diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp | 681 |
1 files changed, 415 insertions, 266 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index 555fcf0..5a7fc7e 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -29,13 +29,14 @@ using namespace clang; /// specifier-qualifier-list abstract-declarator[opt] /// /// Called type-id in C++. -TypeResult Parser::ParseTypeName(SourceRange *Range) { +TypeResult Parser::ParseTypeName(SourceRange *Range, + Declarator::TheContext Context) { // Parse the common declaration-specifiers piece. DeclSpec DS; ParseSpecifierQualifierList(DS); // Parse the abstract-declarator, if present. - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + Declarator DeclaratorInfo(DS, Context); ParseDeclarator(DeclaratorInfo); if (Range) *Range = DeclaratorInfo.getSourceRange(); @@ -82,21 +83,20 @@ TypeResult Parser::ParseTypeName(SourceRange *Range) { /// attributes are very simple in practice. Until we find a bug, I don't see /// a pressing need to implement the 2 token lookahead. -AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { +void Parser::ParseGNUAttributes(ParsedAttributes &attrs, + SourceLocation *endLoc) { assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!"); - AttributeList *CurrAttr = 0; - while (Tok.is(tok::kw___attribute)) { ConsumeToken(); if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "attribute")) { SkipUntil(tok::r_paren, true); // skip until ) or ; - return CurrAttr; + return; } if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) { SkipUntil(tok::r_paren, true); // skip until ) or ; - return CurrAttr; + return; } // Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") )) while (Tok.is(tok::identifier) || isDeclarationSpecifier() || @@ -122,8 +122,8 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { if (Tok.is(tok::r_paren)) { // __attribute__(( mode(byte) )) ConsumeParen(); // ignore the right paren loc for now - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, - ParmName, ParmLoc, 0, 0, CurrAttr); + attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, + ParmName, ParmLoc, 0, 0)); } else if (Tok.is(tok::comma)) { ConsumeToken(); // __attribute__(( format(printf, 1, 2) )) @@ -146,10 +146,9 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { } if (ArgExprsOk && Tok.is(tok::r_paren)) { ConsumeParen(); // ignore the right paren loc for now - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, + attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, ParmName, ParmLoc, - ArgExprs.take(), ArgExprs.size(), - CurrAttr); + ArgExprs.take(), ArgExprs.size())); } } } else { // not an identifier @@ -158,8 +157,8 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { // parse a possibly empty comma separated list of expressions // __attribute__(( nonnull() )) ConsumeParen(); // ignore the right paren loc for now - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0, CurrAttr); + attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, + 0, SourceLocation(), 0, 0)); break; case tok::kw_char: case tok::kw_wchar_t: @@ -174,10 +173,12 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { case tok::kw_float: case tok::kw_double: case tok::kw_void: - case tok::kw_typeof: - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0, CurrAttr); - if (CurrAttr->getKind() == AttributeList::AT_IBOutletCollection) + case tok::kw_typeof: { + AttributeList *attr + = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, + 0, SourceLocation(), 0, 0); + attrs.add(attr); + if (attr->getKind() == AttributeList::AT_IBOutletCollection) Diag(Tok, diag::err_iboutletcollection_builtintype); // If it's a builtin type name, eat it and expect a rparen // __attribute__(( vec_type_hint(char) )) @@ -185,6 +186,7 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { if (Tok.is(tok::r_paren)) ConsumeParen(); break; + } default: // __attribute__(( aligned(16) )) ExprVector ArgExprs(Actions); @@ -207,17 +209,16 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { // Match the ')'. if (ArgExprsOk && Tok.is(tok::r_paren)) { ConsumeParen(); // ignore the right paren loc for now - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, - AttrNameLoc, 0, SourceLocation(), ArgExprs.take(), - ArgExprs.size(), - CurrAttr); + attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, + AttrNameLoc, 0, SourceLocation(), + ArgExprs.take(), ArgExprs.size())); } break; } } } else { - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0, CurrAttr); + attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, + 0, SourceLocation(), 0, 0)); } } if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) @@ -226,10 +227,9 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) { SkipUntil(tok::r_paren, false); } - if (EndLoc) - *EndLoc = Loc; + if (endLoc) + *endLoc = Loc; } - return CurrAttr; } /// ParseMicrosoftDeclSpec - Parse an __declspec construct @@ -241,14 +241,14 @@ AttributeList *Parser::ParseGNUAttributes(SourceLocation *EndLoc) { /// extended-decl-modifier[opt] /// extended-decl-modifier extended-decl-modifier-seq -AttributeList* Parser::ParseMicrosoftDeclSpec(AttributeList *CurrAttr) { +void Parser::ParseMicrosoftDeclSpec(ParsedAttributes &attrs) { assert(Tok.is(tok::kw___declspec) && "Not a declspec!"); ConsumeToken(); if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "declspec")) { SkipUntil(tok::r_paren, true); // skip until ) or ; - return CurrAttr; + return; } while (Tok.getIdentifierInfo()) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); @@ -260,23 +260,22 @@ AttributeList* Parser::ParseMicrosoftDeclSpec(AttributeList *CurrAttr) { ExprResult ArgExpr(ParseAssignmentExpression()); if (!ArgExpr.isInvalid()) { Expr *ExprList = ArgExpr.take(); - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), &ExprList, 1, - CurrAttr, true); + attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, + SourceLocation(), &ExprList, 1, true)); } if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) SkipUntil(tok::r_paren, false); } else { - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0, CurrAttr, true); + attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, + 0, SourceLocation(), 0, 0, true)); } } if (ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) SkipUntil(tok::r_paren, false); - return CurrAttr; + return; } -AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) { +void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { // Treat these like attributes // FIXME: Allow Sema to distinguish between these and real attributes! while (Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___stdcall) || @@ -287,21 +286,34 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) { if (Tok.is(tok::kw___ptr64) || Tok.is(tok::kw___w64)) // FIXME: Support these properly! continue; - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, CurrAttr, true); + attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, + SourceLocation(), 0, 0, true)); } - return CurrAttr; } -AttributeList* Parser::ParseBorlandTypeAttributes(AttributeList *CurrAttr) { +void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) { // Treat these like attributes while (Tok.is(tok::kw___pascal)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, - SourceLocation(), 0, 0, CurrAttr, true); + attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, 0, + SourceLocation(), 0, 0, true)); + } +} + +void Parser::ParseOpenCLAttributes(ParsedAttributes &attrs) { + // Treat these like attributes + while (Tok.is(tok::kw___kernel)) { + SourceLocation AttrNameLoc = ConsumeToken(); + attrs.add(AttrFactory.Create(PP.getIdentifierInfo("opencl_kernel_function"), + AttrNameLoc, 0, AttrNameLoc, 0, + SourceLocation(), 0, 0, false)); } - return CurrAttr; +} + +void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { + Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed) + << attrs.Range; } /// ParseDeclaration - Parse a full 'declaration', which consists of @@ -320,48 +332,43 @@ AttributeList* Parser::ParseBorlandTypeAttributes(AttributeList *CurrAttr) { /// [C++0x] static_assert-declaration /// others... [FIXME] /// -Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, +Parser::DeclGroupPtrTy Parser::ParseDeclaration(StmtVector &Stmts, + unsigned Context, SourceLocation &DeclEnd, - CXX0XAttributeList Attr) { + ParsedAttributesWithRange &attrs) { ParenBraceBracketBalancer BalancerRAIIObj(*this); Decl *SingleDecl = 0; switch (Tok.getKind()) { case tok::kw_template: case tok::kw_export: - if (Attr.HasAttr) - Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed) - << Attr.Range; + ProhibitAttributes(attrs); SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd); break; case tok::kw_inline: // Could be the start of an inline namespace. Allowed as an ext in C++03. if (getLang().CPlusPlus && NextToken().is(tok::kw_namespace)) { - if (Attr.HasAttr) - Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed) - << Attr.Range; + ProhibitAttributes(attrs); SourceLocation InlineLoc = ConsumeToken(); SingleDecl = ParseNamespace(Context, DeclEnd, InlineLoc); break; } - return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList, true); + return ParseSimpleDeclaration(Stmts, Context, DeclEnd, attrs, + true); case tok::kw_namespace: - if (Attr.HasAttr) - Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed) - << Attr.Range; + ProhibitAttributes(attrs); SingleDecl = ParseNamespace(Context, DeclEnd); break; case tok::kw_using: - SingleDecl = ParseUsingDirectiveOrDeclaration(Context, DeclEnd, Attr); + SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), + DeclEnd, attrs); break; case tok::kw_static_assert: - if (Attr.HasAttr) - Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed) - << Attr.Range; + ProhibitAttributes(attrs); SingleDecl = ParseStaticAssertDeclaration(DeclEnd); break; default: - return ParseSimpleDeclaration(Context, DeclEnd, Attr.AttrList, true); + return ParseSimpleDeclaration(Stmts, Context, DeclEnd, attrs, true); } // This routine returns a DeclGroup, if the thing we parsed only contains a @@ -376,16 +383,19 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, /// /// If RequireSemi is false, this does not check for a ';' at the end of the /// declaration. If it is true, it checks for and eats it. -Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, +Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(StmtVector &Stmts, + unsigned Context, SourceLocation &DeclEnd, - AttributeList *Attr, + ParsedAttributes &attrs, bool RequireSemi) { // Parse the common declaration-specifiers piece. ParsingDeclSpec DS(*this); - if (Attr) - DS.AddAttributes(Attr); + DS.takeAttributesFrom(attrs); ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, - getDeclSpecContextFromDeclaratorContext(Context)); + getDeclSpecContextFromDeclaratorContext(Context)); + StmtResult R = Actions.ActOnVlaStmt(DS); + if (R.isUsable()) + Stmts.push_back(R.release()); // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' @@ -474,11 +484,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // short __attribute__((common)) var; -> declspec // short var __attribute__((common)); -> declarator // short x, __attribute__((common)) var; -> declarator - if (Tok.is(tok::kw___attribute)) { - SourceLocation Loc; - AttributeList *AttrList = ParseGNUAttributes(&Loc); - D.AddAttributes(AttrList, Loc); - } + MaybeParseGNUAttributes(D); ParseDeclarator(D); @@ -547,12 +553,7 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D, D.SetRangeEnd(Loc); } - // If attributes are present, parse them. - if (Tok.is(tok::kw___attribute)) { - SourceLocation Loc; - AttributeList *AttrList = ParseGNUAttributes(&Loc); - D.AddAttributes(AttrList, Loc); - } + MaybeParseGNUAttributes(D); // Inform the current actions module that we just parsed this declarator. Decl *ThisDecl = 0; @@ -586,11 +587,19 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D, } } + bool TypeContainsAuto = + D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; + // Parse declarator '=' initializer. - if (Tok.is(tok::equal)) { + if (isTokenEqualOrMistypedEqualEqual( + diag::err_invalid_equalequal_after_declarator)) { ConsumeToken(); - if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) { + if (Tok.is(tok::kw_delete)) { SourceLocation DelLoc = ConsumeToken(); + + if (!getLang().CPlusPlus0x) + Diag(DelLoc, diag::warn_deleted_function_accepted_as_extension); + Actions.SetDeclDeleted(ThisDecl, DelLoc); } else { if (getLang().CPlusPlus && D.getCXXScopeSpec().isSet()) { @@ -616,7 +625,8 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D, SkipUntil(tok::comma, true, true); Actions.ActOnInitializerError(ThisDecl); } else - Actions.AddInitializerToDecl(ThisDecl, Init.take()); + Actions.AddInitializerToDecl(ThisDecl, Init.take(), + /*DirectInit=*/false, TypeContainsAuto); } } else if (Tok.is(tok::l_paren)) { // Parse C++ direct initializer: '(' expression-list ')' @@ -650,12 +660,11 @@ Decl *Parser::ParseDeclarationAfterDeclarator(Declarator &D, Actions.AddCXXDirectInitializerToDecl(ThisDecl, LParenLoc, move_arg(Exprs), - CommaLocs.data(), RParenLoc); + RParenLoc, + TypeContainsAuto); } } else { - bool TypeContainsUndeducedAuto = - D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; - Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsUndeducedAuto); + Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsAuto); } return ThisDecl; @@ -675,7 +684,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) { // Validate declspec for type-name. unsigned Specs = DS.getParsedSpecifiers(); if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() && - !DS.getAttributes()) + !DS.hasAttributes()) Diag(Tok, diag::err_typename_requires_specqual); // Issue diagnostic and remove storage class if present. @@ -868,6 +877,7 @@ Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) { /// [C99] 'inline' /// [C++] 'virtual' /// [C++] 'explicit' +/// [OpenCL] '__kernel' /// 'friend': [C++ dcl.friend] /// 'constexpr': [C++0x dcl.constexpr] @@ -877,6 +887,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext) { DS.SetRangeStart(Tok.getLocation()); + DS.SetRangeEnd(Tok.getLocation()); while (1) { bool isInvalid = false; const char *PrevSpec = 0; @@ -905,13 +916,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, = DSContext == DSC_top_level || (DSContext == DSC_class && DS.isFriendSpecified()); - Actions.CodeCompleteDeclarator(getCurScope(), AllowNonIdentifiers, - AllowNestedNameSpecifiers); + Actions.CodeCompleteDeclSpec(getCurScope(), DS, + AllowNonIdentifiers, + AllowNestedNameSpecifiers); ConsumeCodeCompletionToken(); return; } - if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) + if (getCurScope()->getFnParent() || getCurScope()->getBlockParent()) + CCC = Sema::PCC_LocalDeclarationSpecifiers; + else if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) CCC = DSContext == DSC_class? Sema::PCC_MemberTemplate : Sema::PCC_Template; else if (DSContext == DSC_class) @@ -1005,7 +1019,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ConsumeToken(); // The C++ scope. if (Tok.getAnnotationValue()) { ParsedType T = getTypeAnnotation(Tok); - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, + Tok.getAnnotationEndLoc(), PrevSpec, DiagID, T); } else @@ -1080,20 +1095,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id' // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an - // Objective-C interface. If we don't have Objective-C or a '<', this is - // just a normal reference to a typedef name. - if (!Tok.is(tok::less) || !getLang().ObjC1) - continue; - - SourceLocation LAngleLoc, EndProtoLoc; - llvm::SmallVector<Decl *, 8> ProtocolDecl; - llvm::SmallVector<SourceLocation, 8> ProtocolLocs; - ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false, - LAngleLoc, EndProtoLoc); - DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(), - ProtocolLocs.data(), LAngleLoc); - - DS.SetRangeEnd(EndProtoLoc); + // Objective-C interface. + if (Tok.is(tok::less) && getLang().ObjC1) + ParseObjCProtocolQualifiers(DS); + continue; } @@ -1150,21 +1155,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Objective-C supports syntax of the form 'id<proto1,proto2>' where 'id' // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an - // Objective-C interface. If we don't have Objective-C or a '<', this is - // just a normal reference to a typedef name. - if (!Tok.is(tok::less) || !getLang().ObjC1) - continue; - - SourceLocation LAngleLoc, EndProtoLoc; - llvm::SmallVector<Decl *, 8> ProtocolDecl; - llvm::SmallVector<SourceLocation, 8> ProtocolLocs; - ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false, - LAngleLoc, EndProtoLoc); - DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(), - ProtocolLocs.data(), LAngleLoc); - - DS.SetRangeEnd(EndProtoLoc); - + // Objective-C interface. + if (Tok.is(tok::less) && getLang().ObjC1) + ParseObjCProtocolQualifiers(DS); + // Need to support trailing type qualifiers (e.g. "id<p> const"). // If a type specifier follows, it will be diagnosed elsewhere. continue; @@ -1196,12 +1190,12 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // GNU attributes support. case tok::kw___attribute: - DS.AddAttributes(ParseGNUAttributes()); + ParseGNUAttributes(DS.getAttributes()); continue; // Microsoft declspec support. case tok::kw___declspec: - DS.AddAttributes(ParseMicrosoftDeclSpec()); + ParseMicrosoftDeclSpec(DS.getAttributes()); continue; // Microsoft single token adornments. @@ -1215,34 +1209,39 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: - DS.AddAttributes(ParseMicrosoftTypeAttributes()); + ParseMicrosoftTypeAttributes(DS.getAttributes()); continue; // Borland single token adornments. case tok::kw___pascal: - DS.AddAttributes(ParseBorlandTypeAttributes()); + ParseBorlandTypeAttributes(DS.getAttributes()); + continue; + + // OpenCL single token adornments. + case tok::kw___kernel: + ParseOpenCLAttributes(DS.getAttributes()); continue; // storage-class-specifier case tok::kw_typedef: isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec, - DiagID); + DiagID, getLang()); break; case tok::kw_extern: if (DS.isThreadSpecified()) Diag(Tok, diag::ext_thread_before) << "extern"; isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec, - DiagID); + DiagID, getLang()); break; case tok::kw___private_extern__: isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc, - PrevSpec, DiagID); + PrevSpec, DiagID, getLang()); break; case tok::kw_static: if (DS.isThreadSpecified()) Diag(Tok, diag::ext_thread_before) << "static"; isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec, - DiagID); + DiagID, getLang()); break; case tok::kw_auto: if (getLang().CPlusPlus0x) @@ -1250,15 +1249,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DiagID); else isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec, - DiagID); + DiagID, getLang()); break; case tok::kw_register: isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec, - DiagID); + DiagID, getLang()); break; case tok::kw_mutable: isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec, - DiagID); + DiagID, getLang()); break; case tok::kw___thread: isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID); @@ -1354,8 +1353,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, break; case tok::kw_bool: case tok::kw__Bool: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, - DiagID); + if (Tok.is(tok::kw_bool) && + DS.getTypeSpecType() != DeclSpec::TST_unspecified && + DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { + PrevSpec = ""; // Not used by the diagnostic. + DiagID = diag::err_bool_redeclaration; + isInvalid = true; + } else { + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, + DiagID); + } break; case tok::kw__Decimal32: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec, @@ -1432,23 +1439,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (DS.hasTypeSpecifier() || !getLang().ObjC1) goto DoneWithDeclSpec; - { - SourceLocation LAngleLoc, EndProtoLoc; - llvm::SmallVector<Decl *, 8> ProtocolDecl; - llvm::SmallVector<SourceLocation, 8> ProtocolLocs; - ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false, - LAngleLoc, EndProtoLoc); - DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(), - ProtocolLocs.data(), LAngleLoc); - DS.SetRangeEnd(EndProtoLoc); - + if (!ParseObjCProtocolQualifiers(DS)) Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id) << FixItHint::CreateInsertion(Loc, "id") - << SourceRange(Loc, EndProtoLoc); - // Need to support trailing type qualifiers (e.g. "id<p> const"). - // If a type specifier follows, it will be diagnosed elsewhere. - continue; - } + << SourceRange(Loc, DS.getSourceRange().getEnd()); + + // Need to support trailing type qualifiers (e.g. "id<p> const"). + // If a type specifier follows, it will be diagnosed elsewhere. + continue; } // If the specifier wasn't legal, issue a diagnostic. if (isInvalid) { @@ -1552,7 +1550,8 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, // simple-type-specifier: case tok::annot_typename: { if (ParsedType T = getTypeAnnotation(Tok)) { - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, + Tok.getAnnotationEndLoc(), PrevSpec, DiagID, T); } else DS.SetTypeSpecError(); @@ -1563,18 +1562,9 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, // is a specific typedef and 'itf<proto1,proto2>' where 'itf' is an // Objective-C interface. If we don't have Objective-C or a '<', this is // just a normal reference to a typedef name. - if (!Tok.is(tok::less) || !getLang().ObjC1) - return true; - - SourceLocation LAngleLoc, EndProtoLoc; - llvm::SmallVector<Decl *, 8> ProtocolDecl; - llvm::SmallVector<SourceLocation, 8> ProtocolLocs; - ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false, - LAngleLoc, EndProtoLoc); - DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(), - ProtocolLocs.data(), LAngleLoc); - - DS.SetRangeEnd(EndProtoLoc); + if (Tok.is(tok::less) && getLang().ObjC1) + ParseObjCProtocolQualifiers(DS); + return true; } @@ -1706,11 +1696,11 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, case tok::kw___stdcall: case tok::kw___fastcall: case tok::kw___thiscall: - DS.AddAttributes(ParseMicrosoftTypeAttributes()); + ParseMicrosoftTypeAttributes(DS.getAttributes()); return true; case tok::kw___pascal: - DS.AddAttributes(ParseBorlandTypeAttributes()); + ParseBorlandTypeAttributes(DS.getAttributes()); return true; default: @@ -1756,7 +1746,6 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { } // Parse the common specifier-qualifiers-list piece. - SourceLocation DSStart = Tok.getLocation(); ParseSpecifierQualifierList(DS); // If there are no declarators, this is a free-standing declaration @@ -1773,11 +1762,8 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { FieldDeclarator DeclaratorInfo(DS); // Attributes are only allowed here on successive declarators. - if (!FirstDeclarator && Tok.is(tok::kw___attribute)) { - SourceLocation Loc; - AttributeList *AttrList = ParseGNUAttributes(&Loc); - DeclaratorInfo.D.AddAttributes(AttrList, Loc); - } + if (!FirstDeclarator) + MaybeParseGNUAttributes(DeclaratorInfo.D); /// struct-declarator: declarator /// struct-declarator: declarator[opt] ':' constant-expression @@ -1797,11 +1783,7 @@ ParseStructDeclaration(DeclSpec &DS, FieldCallback &Fields) { } // If attributes exist after the declarator, parse them. - if (Tok.is(tok::kw___attribute)) { - SourceLocation Loc; - AttributeList *AttrList = ParseGNUAttributes(&Loc); - DeclaratorInfo.D.AddAttributes(AttrList, Loc); - } + MaybeParseGNUAttributes(DeclaratorInfo.D); // We're done with this declarator; invoke the callback. Decl *D = Fields.invoke(DeclaratorInfo); @@ -1922,20 +1904,18 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); - llvm::OwningPtr<AttributeList> AttrList; + ParsedAttributes attrs; // If attributes exist after struct contents, parse them. - if (Tok.is(tok::kw___attribute)) - AttrList.reset(ParseGNUAttributes()); + MaybeParseGNUAttributes(attrs); Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls.data(), FieldDecls.size(), LBraceLoc, RBraceLoc, - AttrList.get()); + attrs.getList()); StructScope.Exit(); Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, RBraceLoc); } - /// ParseEnumSpecifier /// enum-specifier: [C99 6.7.2.2] /// 'enum' identifier[opt] '{' enumerator-list '}' @@ -1945,6 +1925,21 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, /// 'enum' identifier /// [GNU] 'enum' attributes[opt] identifier /// +/// [C++0x] enum-head '{' enumerator-list[opt] '}' +/// [C++0x] enum-head '{' enumerator-list ',' '}' +/// +/// enum-head: [C++0x] +/// enum-key attributes[opt] identifier[opt] enum-base[opt] +/// enum-key attributes[opt] nested-name-specifier identifier enum-base[opt] +/// +/// enum-key: [C++0x] +/// 'enum' +/// 'enum' 'class' +/// 'enum' 'struct' +/// +/// enum-base: [C++0x] +/// ':' type-specifier-seq +/// /// [C++] elaborated-type-specifier: /// [C++] 'enum' '::'[opt] nested-name-specifier[opt] identifier /// @@ -1958,10 +1953,9 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, ConsumeCodeCompletionToken(); } - llvm::OwningPtr<AttributeList> Attr; // If attributes exist after tag, parse them. - if (Tok.is(tok::kw___attribute)) - Attr.reset(ParseGNUAttributes()); + ParsedAttributes attrs; + MaybeParseGNUAttributes(attrs); CXXScopeSpec &SS = DS.getTypeSpecScope(); if (getLang().CPlusPlus) { @@ -1979,6 +1973,16 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, } } + bool IsScopedEnum = false; + bool IsScopedUsingClassTag = false; + + if (getLang().CPlusPlus0x && + (Tok.is(tok::kw_class) || Tok.is(tok::kw_struct))) { + IsScopedEnum = true; + IsScopedUsingClassTag = Tok.is(tok::kw_class); + ConsumeToken(); + } + // Must have either 'enum name' or 'enum {...}'. if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace)) { Diag(Tok, diag::err_expected_ident_lbrace); @@ -1996,6 +2000,69 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, NameLoc = ConsumeToken(); } + if (!Name && IsScopedEnum) { + // C++0x 7.2p2: The optional identifier shall not be omitted in the + // declaration of a scoped enumeration. + Diag(Tok, diag::err_scoped_enum_missing_identifier); + IsScopedEnum = false; + IsScopedUsingClassTag = false; + } + + TypeResult BaseType; + + // Parse the fixed underlying type. + if (getLang().CPlusPlus0x && Tok.is(tok::colon)) { + bool PossibleBitfield = false; + if (getCurScope()->getFlags() & Scope::ClassScope) { + // If we're in class scope, this can either be an enum declaration with + // an underlying type, or a declaration of a bitfield member. We try to + // use a simple disambiguation scheme first to catch the common cases + // (integer literal, sizeof); if it's still ambiguous, we then consider + // anything that's a simple-type-specifier followed by '(' as an + // expression. This suffices because function types are not valid + // underlying types anyway. + TPResult TPR = isExpressionOrTypeSpecifierSimple(NextToken().getKind()); + // If the next token starts an expression, we know we're parsing a + // bit-field. This is the common case. + if (TPR == TPResult::True()) + PossibleBitfield = true; + // If the next token starts a type-specifier-seq, it may be either a + // a fixed underlying type or the start of a function-style cast in C++; + // lookahead one more token to see if it's obvious that we have a + // fixed underlying type. + else if (TPR == TPResult::False() && + GetLookAheadToken(2).getKind() == tok::semi) { + // Consume the ':'. + ConsumeToken(); + } else { + // We have the start of a type-specifier-seq, so we have to perform + // tentative parsing to determine whether we have an expression or a + // type. + TentativeParsingAction TPA(*this); + + // Consume the ':'. + ConsumeToken(); + + if (isCXXDeclarationSpecifier() != TPResult::True()) { + // We'll parse this as a bitfield later. + PossibleBitfield = true; + TPA.Revert(); + } else { + // We have a type-specifier-seq. + TPA.Commit(); + } + } + } else { + // Consume the ':'. + ConsumeToken(); + } + + if (!PossibleBitfield) { + SourceRange Range; + BaseType = ParseTypeName(&Range); + } + } + // There are three options here. If we have 'enum foo;', then this is a // forward declaration. If we have 'enum foo {...' then this is a // definition. Otherwise we have something like 'enum foo xyz', a reference. @@ -2029,10 +2096,12 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, const char *PrevSpec = 0; unsigned DiagID; Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, - StartLoc, SS, Name, NameLoc, Attr.get(), + StartLoc, SS, Name, NameLoc, attrs.getList(), AS, MultiTemplateParamsArg(Actions), - Owned, IsDependent); + Owned, IsDependent, IsScopedEnum, + IsScopedUsingClassTag, BaseType); + if (IsDependent) { // This enum has a dependent nested-name-specifier. Handle it as a // dependent tag. @@ -2109,6 +2178,10 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { IdentifierInfo *Ident = Tok.getIdentifierInfo(); SourceLocation IdentLoc = ConsumeToken(); + // If attributes exist after the enumerator, parse them. + ParsedAttributes attrs; + MaybeParseGNUAttributes(attrs); + SourceLocation EqualLoc; ExprResult AssignedVal; if (Tok.is(tok::equal)) { @@ -2122,11 +2195,19 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { Decl *EnumConstDecl = Actions.ActOnEnumConstant(getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, - EqualLoc, + attrs.getList(), EqualLoc, AssignedVal.release()); EnumConstantDecls.push_back(EnumConstDecl); LastEnumConstDecl = EnumConstDecl; + if (Tok.is(tok::identifier)) { + // We're missing a comma between enumerators. + SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation); + Diag(Loc, diag::err_enumerator_list_missing_comma) + << FixItHint::CreateInsertion(Loc, ", "); + continue; + } + if (Tok.isNot(tok::comma)) break; SourceLocation CommaLoc = ConsumeToken(); @@ -2141,14 +2222,13 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { // Eat the }. SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); - llvm::OwningPtr<AttributeList> Attr; // If attributes exist after the identifier list, parse them. - if (Tok.is(tok::kw___attribute)) - Attr.reset(ParseGNUAttributes()); // FIXME: where do they do? + ParsedAttributes attrs; + MaybeParseGNUAttributes(attrs); Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl, EnumConstantDecls.data(), EnumConstantDecls.size(), - getCurScope(), Attr.get()); + getCurScope(), attrs.getList()); EnumScope.Exit(); Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, RBraceLoc); @@ -2296,7 +2376,10 @@ bool Parser::isTypeSpecifierQualifier() { /// isDeclarationSpecifier() - Return true if the current token is part of a /// declaration specifier. -bool Parser::isDeclarationSpecifier() { +/// +/// \param DisambiguatingWithExpression True to indicate that the purpose of +/// this check is to disambiguate between an expression and a declaration. +bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { switch (Tok.getKind()) { default: return false; @@ -2314,6 +2397,16 @@ bool Parser::isDeclarationSpecifier() { return true; if (Tok.is(tok::identifier)) return false; + + // If we're in Objective-C and we have an Objective-C class type followed + // by an identifier and then either ':' or ']', in a place where an + // expression is permitted, then this is probably a class message send + // missing the initial '['. In this case, we won't consider this to be + // the start of a declaration. + if (DisambiguatingWithExpression && + isStartOfObjCClassMessageMissingOpenBracket()) + return false; + return isDeclarationSpecifier(); case tok::coloncolon: // ::foo::bar @@ -2441,6 +2534,10 @@ bool Parser::isConstructorDeclarator() { if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS)) DeclScopeObj.EnterDeclaratorScope(); + // Optionally skip Microsoft attributes. + ParsedAttributes Attrs; + MaybeParseMicrosoftAttributes(Attrs); + // Check whether the next token(s) are part of a declaration // specifier, in which case we have the start of a parameter and, // therefore, we know that this is a constructor. @@ -2466,9 +2563,10 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool CXX0XAttributesAllowed) { if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { SourceLocation Loc = Tok.getLocation(); - CXX0XAttributeList Attr = ParseCXX0XAttributes(); + ParsedAttributesWithRange attrs; + ParseCXX0XAttributes(attrs); if (CXX0XAttributesAllowed) - DS.AddAttributes(Attr.AttrList); + DS.takeAttributesFrom(attrs); else Diag(Loc, diag::err_attributes_not_allowed); } @@ -2504,19 +2602,19 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, case tok::kw___fastcall: case tok::kw___thiscall: if (VendorAttributesAllowed) { - DS.AddAttributes(ParseMicrosoftTypeAttributes()); + ParseMicrosoftTypeAttributes(DS.getAttributes()); continue; } goto DoneWithTypeQuals; case tok::kw___pascal: if (VendorAttributesAllowed) { - DS.AddAttributes(ParseBorlandTypeAttributes()); + ParseBorlandTypeAttributes(DS.getAttributes()); continue; } goto DoneWithTypeQuals; case tok::kw___attribute: if (VendorAttributesAllowed) { - DS.AddAttributes(ParseGNUAttributes()); + ParseGNUAttributes(DS.getAttributes()); continue; // do *not* consume the next token! } // otherwise, FALL THROUGH! @@ -2602,7 +2700,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Sema will have to catch (syntactically invalid) pointers into global // scope. It has to catch pointers into namespace scope anyway. D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(), - Loc, DS.TakeAttributes()), + Loc, DS.takeAttributes()), /* Don't replace range end. */SourceLocation()); return; } @@ -2636,12 +2734,12 @@ void Parser::ParseDeclaratorInternal(Declarator &D, if (Kind == tok::star) // Remember that we parsed a pointer type, and remember the type-quals. D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc, - DS.TakeAttributes()), + DS.takeAttributes()), SourceLocation()); else // Remember that we parsed a Block type, and remember the type-quals. D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), - Loc, DS.TakeAttributes()), + Loc, DS.takeAttributes()), SourceLocation()); } else { // Is a reference @@ -2650,7 +2748,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Complain about rvalue references in C++03, but then go on and build // the declarator. if (Kind == tok::ampamp && !getLang().CPlusPlus0x) - Diag(Loc, diag::err_rvalue_reference); + Diag(Loc, diag::ext_rvalue_reference); // C++ 8.3.2p1: cv-qualified references are ill-formed except when the // cv-qualifiers are introduced through the use of a typedef or of a @@ -2693,7 +2791,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Remember that we parsed a reference type. It doesn't have type-quals. D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc, - DS.TakeAttributes(), + DS.takeAttributes(), Kind == tok::amp), SourceLocation()); } @@ -2718,7 +2816,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, /// [C++] declarator-id /// /// declarator-id: [C++ 8] -/// id-expression +/// '...'[opt] id-expression /// '::'[opt] nested-name-specifier[opt] type-name /// /// id-expression: [C++ 5.1] @@ -2748,6 +2846,20 @@ void Parser::ParseDirectDeclarator(Declarator &D) { DeclScopeObj.EnterDeclaratorScope(); } + // C++0x [dcl.fct]p14: + // There is a syntactic ambiguity when an ellipsis occurs at the end + // of a parameter-declaration-clause without a preceding comma. In + // this case, the ellipsis is parsed as part of the + // abstract-declarator if the type of the parameter names a template + // parameter pack that has not been expanded; otherwise, it is parsed + // as part of the parameter-declaration-clause. + if (Tok.is(tok::ellipsis) && + !((D.getContext() == Declarator::PrototypeContext || + D.getContext() == Declarator::BlockLiteralContext) && + NextToken().is(tok::r_paren) && + !Actions.containsUnexpandedParameterPacks(D))) + D.setEllipsisLoc(ConsumeToken()); + if (Tok.is(tok::identifier) || Tok.is(tok::kw_operator) || Tok.is(tok::annot_template_id) || Tok.is(tok::tilde)) { // We found something that indicates the start of an unqualified-id. @@ -2830,12 +2942,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { "Haven't past the location of the identifier yet?"); // Don't parse attributes unless we have an identifier. - if (D.getIdentifier() && getLang().CPlusPlus0x - && isCXX0XAttributeSpecifier(true)) { - SourceLocation AttrEndLoc; - CXX0XAttributeList Attr = ParseCXX0XAttributes(); - D.AddAttributes(Attr.AttrList, AttrEndLoc); - } + if (D.getIdentifier()) + MaybeParseCXX0XAttributes(D); while (1) { if (Tok.is(tok::l_paren)) { @@ -2849,7 +2957,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { if (!isCXXFunctionDeclarator(warnIfAmbiguous)) break; } - ParseFunctionDeclarator(ConsumeParen(), D); + ParsedAttributes attrs; + ParseFunctionDeclarator(ConsumeParen(), D, attrs); } else if (Tok.is(tok::l_square)) { ParseBracketDeclarator(D); } else { @@ -2885,10 +2994,10 @@ void Parser::ParseParenDeclarator(Declarator &D) { // In either case, we need to eat any attributes to be able to determine what // sort of paren this is. // - llvm::OwningPtr<AttributeList> AttrList; + ParsedAttributes attrs; bool RequiresArg = false; if (Tok.is(tok::kw___attribute)) { - AttrList.reset(ParseGNUAttributes()); + ParseGNUAttributes(attrs); // We require that the argument list (if this is a non-grouping paren) be // present even if the attribute list was empty. @@ -2898,12 +3007,11 @@ void Parser::ParseParenDeclarator(Declarator &D) { if (Tok.is(tok::kw___cdecl) || Tok.is(tok::kw___stdcall) || Tok.is(tok::kw___thiscall) || Tok.is(tok::kw___fastcall) || Tok.is(tok::kw___w64) || Tok.is(tok::kw___ptr64)) { - AttrList.reset(ParseMicrosoftTypeAttributes(AttrList.take())); + ParseMicrosoftTypeAttributes(attrs); } // Eat any Borland extensions. - if (Tok.is(tok::kw___pascal)) { - AttrList.reset(ParseBorlandTypeAttributes(AttrList.take())); - } + if (Tok.is(tok::kw___pascal)) + ParseBorlandTypeAttributes(attrs); // If we haven't past the identifier yet (or where the identifier would be // stored, if this is an abstract declarator), then this is probably just @@ -2932,15 +3040,15 @@ void Parser::ParseParenDeclarator(Declarator &D) { if (isGrouping) { bool hadGroupingParens = D.hasGroupingParens(); D.setGroupingParens(true); - if (AttrList) - D.AddAttributes(AttrList.take(), SourceLocation()); + if (!attrs.empty()) + D.addAttributes(attrs.getList(), SourceLocation()); ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); // Match the ')'. - SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, StartLoc); + SourceLocation EndLoc = MatchRHSPunctuation(tok::r_paren, StartLoc); + D.AddTypeInfo(DeclaratorChunk::getParen(StartLoc, EndLoc), EndLoc); D.setGroupingParens(hadGroupingParens); - D.SetRangeEnd(Loc); return; } @@ -2950,7 +3058,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { // ParseFunctionDeclarator to handle of argument list. D.SetIdentifier(0, Tok.getLocation()); - ParseFunctionDeclarator(StartLoc, D, AttrList.take(), RequiresArg); + ParseFunctionDeclarator(StartLoc, D, attrs, RequiresArg); } /// ParseFunctionDeclarator - We are after the identifier and have parsed the @@ -2982,37 +3090,51 @@ void Parser::ParseParenDeclarator(Declarator &D) { /// '=' assignment-expression /// [GNU] declaration-specifiers abstract-declarator[opt] attributes /// -/// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]" -/// and "exception-specification[opt]". +/// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]", +/// C++0x "ref-qualifier[opt]" and "exception-specification[opt]". /// void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, - AttributeList *AttrList, + ParsedAttributes &attrs, bool RequiresArg) { // lparen is already consumed! assert(D.isPastIdentifier() && "Should not call before identifier!"); + ParsedType TrailingReturnType; + // This parameter list may be empty. if (Tok.is(tok::r_paren)) { - if (RequiresArg) { + if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); - delete AttrList; - } SourceLocation RParenLoc = ConsumeParen(); // Eat the closing ')'. SourceLocation EndLoc = RParenLoc; // cv-qualifier-seq[opt]. DeclSpec DS; + SourceLocation RefQualifierLoc; + bool RefQualifierIsLValueRef = true; bool hasExceptionSpec = false; SourceLocation ThrowLoc; bool hasAnyExceptionSpec = false; llvm::SmallVector<ParsedType, 2> Exceptions; llvm::SmallVector<SourceRange, 2> ExceptionRanges; if (getLang().CPlusPlus) { + MaybeParseCXX0XAttributes(attrs); + ParseTypeQualifierListOpt(DS, false /*no attributes*/); if (!DS.getSourceRange().getEnd().isInvalid()) EndLoc = DS.getSourceRange().getEnd(); + // Parse ref-qualifier[opt] + if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::ext_ref_qualifier); + + RefQualifierIsLValueRef = Tok.is(tok::amp); + RefQualifierLoc = ConsumeToken(); + EndLoc = RefQualifierLoc; + } + // Parse exception-specification[opt]. if (Tok.is(tok::kw_throw)) { hasExceptionSpec = true; @@ -3022,21 +3144,30 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, assert(Exceptions.size() == ExceptionRanges.size() && "Produced different number of exception types and ranges."); } + + // Parse trailing-return-type. + if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) { + TrailingReturnType = ParseTrailingReturnType().get(); + } } // Remember that we parsed a function type, and remember the attributes. // int() -> no prototype, no '...'. - D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/getLang().CPlusPlus, + D.AddTypeInfo(DeclaratorChunk::getFunction(attrs, + /*prototype*/getLang().CPlusPlus, /*variadic*/ false, SourceLocation(), /*arglist*/ 0, 0, DS.getTypeQualifiers(), + RefQualifierIsLValueRef, + RefQualifierLoc, hasExceptionSpec, ThrowLoc, hasAnyExceptionSpec, Exceptions.data(), ExceptionRanges.data(), Exceptions.size(), - LParenLoc, RParenLoc, D), + LParenLoc, RParenLoc, D, + TrailingReturnType), EndLoc); return; } @@ -3048,10 +3179,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, if (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename)) { // K&R identifier lists can't have typedefs as identifiers, per // C99 6.7.5.3p11. - if (RequiresArg) { + if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); - delete AttrList; - } // Identifier list. Note that '(' identifier-list ')' is only allowed for // normal declarators, not for abstract-declarators. Get the first @@ -3101,17 +3230,20 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, break; } - SourceLocation DSStart = Tok.getLocation(); - // Parse the declaration-specifiers. // Just use the ParsingDeclaration "scope" of the declarator. DeclSpec DS; + + // Skip any Microsoft attributes before a param. + if (getLang().Microsoft && Tok.is(tok::l_square)) + ParseMicrosoftAttributes(DS.getAttributes()); + + SourceLocation DSStart = Tok.getLocation(); // If the caller parsed attributes for the first argument, add them now. - if (AttrList) { - DS.AddAttributes(AttrList); - AttrList = 0; // Only apply the attributes to the first parameter. - } + // Take them so that we only apply the attributes to the first parameter. + DS.takeAttributesFrom(attrs); + ParseDeclarationSpecifiers(DS); // Parse the declarator. This is "PrototypeContext", because we must @@ -3120,11 +3252,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, ParseDeclarator(ParmDecl); // Parse GNU attributes, if present. - if (Tok.is(tok::kw___attribute)) { - SourceLocation Loc; - AttributeList *AttrList = ParseGNUAttributes(&Loc); - ParmDecl.AddAttributes(AttrList, Loc); - } + MaybeParseGNUAttributes(ParmDecl); // Remember this parsed parameter in ParamInfo. IdentifierInfo *ParmII = ParmDecl.getIdentifier(); @@ -3184,6 +3312,11 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // Consume the '='. ConsumeToken(); + // The argument isn't actually potentially evaluated unless it is + // used. + EnterExpressionEvaluationContext Eval(Actions, + Sema::PotentiallyEvaluatedIfUsed); + ExprResult DefArgResult(ParseAssignmentExpression()); if (DefArgResult.isInvalid()) { Actions.ActOnParamDefaultArgumentError(Param); @@ -3222,14 +3355,13 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, ConsumeToken(); } - // Leave prototype scope. - PrototypeScope.Exit(); - // If we have the closing ')', eat it. SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); SourceLocation EndLoc = RParenLoc; DeclSpec DS; + SourceLocation RefQualifierLoc; + bool RefQualifierIsLValueRef = true; bool hasExceptionSpec = false; SourceLocation ThrowLoc; bool hasAnyExceptionSpec = false; @@ -3237,11 +3369,23 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, llvm::SmallVector<SourceRange, 2> ExceptionRanges; if (getLang().CPlusPlus) { + MaybeParseCXX0XAttributes(attrs); + // Parse cv-qualifier-seq[opt]. ParseTypeQualifierListOpt(DS, false /*no attributes*/); if (!DS.getSourceRange().getEnd().isInvalid()) EndLoc = DS.getSourceRange().getEnd(); + // Parse ref-qualifier[opt] + if (Tok.is(tok::amp) || Tok.is(tok::ampamp)) { + if (!getLang().CPlusPlus0x) + Diag(Tok, diag::ext_ref_qualifier); + + RefQualifierIsLValueRef = Tok.is(tok::amp); + RefQualifierLoc = ConsumeToken(); + EndLoc = RefQualifierLoc; + } + // Parse exception-specification[opt]. if (Tok.is(tok::kw_throw)) { hasExceptionSpec = true; @@ -3251,19 +3395,34 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, assert(Exceptions.size() == ExceptionRanges.size() && "Produced different number of exception types and ranges."); } + + // Parse trailing-return-type. + if (getLang().CPlusPlus0x && Tok.is(tok::arrow)) { + TrailingReturnType = ParseTrailingReturnType().get(); + } } + // FIXME: We should leave the prototype scope before parsing the exception + // specification, and then reenter it when parsing the trailing return type. + + // Leave prototype scope. + PrototypeScope.Exit(); + // Remember that we parsed a function type, and remember the attributes. - D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic, + D.AddTypeInfo(DeclaratorChunk::getFunction(attrs, + /*proto*/true, IsVariadic, EllipsisLoc, ParamInfo.data(), ParamInfo.size(), DS.getTypeQualifiers(), + RefQualifierIsLValueRef, + RefQualifierLoc, hasExceptionSpec, ThrowLoc, hasAnyExceptionSpec, Exceptions.data(), ExceptionRanges.data(), Exceptions.size(), - LParenLoc, RParenLoc, D), + LParenLoc, RParenLoc, D, + TrailingReturnType), EndLoc); } @@ -3333,10 +3492,12 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, // Remember that we parsed a function type, and remember the attributes. This // function type is always a K&R style function type, which is not varargs and // has no prototype. - D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false, + D.AddTypeInfo(DeclaratorChunk::getFunction(ParsedAttributes(), + /*proto*/false, /*varargs*/false, SourceLocation(), &ParamInfo[0], ParamInfo.size(), /*TypeQuals*/0, + true, SourceLocation(), /*exception*/false, SourceLocation(), false, 0, 0, 0, LParenLoc, RLoc, D), @@ -3355,15 +3516,12 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // This code does a fast path to handle some of the most obvious cases. if (Tok.getKind() == tok::r_square) { SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); - //FIXME: Use these - CXX0XAttributeList Attr; - if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier(true)) { - Attr = ParseCXX0XAttributes(); - } + ParsedAttributes attrs; + MaybeParseCXX0XAttributes(attrs); // Remember that we parsed the empty array type. ExprResult NumElements; - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0, + D.AddTypeInfo(DeclaratorChunk::getArray(0, attrs, false, false, 0, StartLoc, EndLoc), EndLoc); return; @@ -3374,18 +3532,12 @@ void Parser::ParseBracketDeclarator(Declarator &D) { ConsumeToken(); SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); - //FIXME: Use these - CXX0XAttributeList Attr; - if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { - Attr = ParseCXX0XAttributes(); - } - - // If there was an error parsing the assignment-expression, recover. - if (ExprRes.isInvalid()) - ExprRes.release(); // Deallocate expr, just use []. + ParsedAttributes attrs; + MaybeParseCXX0XAttributes(attrs); // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, ExprRes.release(), + D.AddTypeInfo(DeclaratorChunk::getArray(0, attrs, false, 0, + ExprRes.release(), StartLoc, EndLoc), EndLoc); return; @@ -3446,14 +3598,11 @@ void Parser::ParseBracketDeclarator(Declarator &D) { SourceLocation EndLoc = MatchRHSPunctuation(tok::r_square, StartLoc); - //FIXME: Use these - CXX0XAttributeList Attr; - if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { - Attr = ParseCXX0XAttributes(); - } + ParsedAttributes attrs; + MaybeParseCXX0XAttributes(attrs); // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), + D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), attrs, StaticLoc.isValid(), isStar, NumElements.release(), StartLoc, EndLoc), |