diff options
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 858 |
1 files changed, 519 insertions, 339 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 4a3532c..b56c331 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -69,10 +69,10 @@ Action::TypeResult Parser::ParseTypeName(SourceRange *Range) { /// typespec /// typequal /// storageclass -/// +/// /// FIXME: The GCC grammar/code for this construct implies we need two -/// token lookahead. Comment from gcc: "If they start with an identifier -/// which is followed by a comma or close parenthesis, then the arguments +/// token lookahead. Comment from gcc: "If they start with an identifier +/// which is followed by a comma or close parenthesis, then the arguments /// start with that identifier; otherwise they are an expression list." /// /// At the moment, I am not doing 2 token lookahead. I am also unaware of @@ -82,9 +82,9 @@ Action::TypeResult Parser::ParseTypeName(SourceRange *Range) { AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { assert(Tok.is(tok::kw___attribute) && "Not an attribute list!"); - + AttributeList *CurrAttr = 0; - + while (Tok.is(tok::kw___attribute)) { ConsumeToken(); if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, @@ -99,8 +99,8 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { // Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") )) while (Tok.is(tok::identifier) || isDeclarationSpecifier() || Tok.is(tok::comma)) { - - if (Tok.is(tok::comma)) { + + if (Tok.is(tok::comma)) { // allows for empty/non-empty attributes. ((__vector_size__(16),,,,)) ConsumeToken(); continue; @@ -108,26 +108,26 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { // we have an identifier or declaration specifier (const, int, etc.) IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); - + // check if we have a "paramterized" attribute if (Tok.is(tok::l_paren)) { ConsumeParen(); // ignore the left paren loc for now - + if (Tok.is(tok::identifier)) { IdentifierInfo *ParmName = Tok.getIdentifierInfo(); SourceLocation ParmLoc = ConsumeToken(); - - if (Tok.is(tok::r_paren)) { + + if (Tok.is(tok::r_paren)) { // __attribute__(( mode(byte) )) ConsumeParen(); // ignore the right paren loc for now - CurrAttr = new AttributeList(AttrName, AttrNameLoc, + CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName, ParmLoc, 0, 0, CurrAttr); } else if (Tok.is(tok::comma)) { ConsumeToken(); // __attribute__(( format(printf, 1, 2) )) ExprVector ArgExprs(Actions); bool ArgExprsOk = true; - + // now parse the non-empty comma separated list of expressions while (1) { OwningExprResult ArgExpr(ParseAssignmentExpression()); @@ -144,7 +144,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { } if (ArgExprsOk && Tok.is(tok::r_paren)) { ConsumeParen(); // ignore the right paren loc for now - CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName, + CurrAttr = new AttributeList(AttrName, AttrNameLoc, ParmName, ParmLoc, ArgExprs.take(), ArgExprs.size(), CurrAttr); } } @@ -154,11 +154,13 @@ AttributeList *Parser::ParseAttributes(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, + CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, SourceLocation(), 0, 0, CurrAttr); break; case tok::kw_char: case tok::kw_wchar_t: + case tok::kw_char16_t: + case tok::kw_char32_t: case tok::kw_bool: case tok::kw_short: case tok::kw_int: @@ -172,7 +174,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { // If it's a builtin type name, eat it and expect a rparen // __attribute__(( vec_type_hint(char) )) ConsumeToken(); - CurrAttr = new AttributeList(AttrName, AttrNameLoc, + CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, SourceLocation(), 0, 0, CurrAttr); if (Tok.is(tok::r_paren)) ConsumeParen(); @@ -181,7 +183,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { // __attribute__(( aligned(16) )) ExprVector ArgExprs(Actions); bool ArgExprsOk = true; - + // now parse the list of expressions while (1) { OwningExprResult ArgExpr(ParseAssignmentExpression()); @@ -207,7 +209,7 @@ AttributeList *Parser::ParseAttributes(SourceLocation *EndLoc) { } } } else { - CurrAttr = new AttributeList(AttrName, AttrNameLoc, + CurrAttr = new AttributeList(AttrName, AttrNameLoc, 0, SourceLocation(), 0, 0, CurrAttr); } } @@ -320,7 +322,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, default: return ParseSimpleDeclaration(Context, DeclEnd); } - + // This routine returns a DeclGroup, if the thing we parsed only contains a // single decl, convert it now. return Actions.ConvertDeclToDeclGroup(SingleDecl); @@ -339,7 +341,7 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, // Parse the common declaration-specifiers piece. DeclSpec DS; ParseDeclarationSpecifiers(DS); - + // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { @@ -347,25 +349,25 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(unsigned Context, DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS); return Actions.ConvertDeclToDeclGroup(TheDecl); } - + Declarator DeclaratorInfo(DS, (Declarator::TheContext)Context); ParseDeclarator(DeclaratorInfo); - + DeclGroupPtrTy DG = ParseInitDeclaratorListAfterFirstDeclarator(DeclaratorInfo); DeclEnd = Tok.getLocation(); - + // If the client wants to check what comes after the declaration, just return // immediately without checking anything! if (!RequireSemi) return DG; - + if (Tok.is(tok::semi)) { ConsumeToken(); return DG; } - - Diag(Tok, diag::err_expected_semi_declation); + + Diag(Tok, diag::err_expected_semi_declaration); // Skip to end of block or statement SkipUntil(tok::r_brace, true, true); if (Tok.is(tok::semi)) @@ -404,27 +406,50 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D, SkipUntil(tok::semi, true, true); return DeclPtrTy(); } - + D.setAsmLabel(AsmLabel.release()); D.SetRangeEnd(Loc); } - + // If attributes are present, parse them. if (Tok.is(tok::kw___attribute)) { SourceLocation Loc; AttributeList *AttrList = ParseAttributes(&Loc); D.AddAttributes(AttrList, Loc); } - + // Inform the current actions module that we just parsed this declarator. - DeclPtrTy ThisDecl = TemplateInfo.TemplateParams? - Actions.ActOnTemplateDeclarator(CurScope, + DeclPtrTy ThisDecl; + switch (TemplateInfo.Kind) { + case ParsedTemplateInfo::NonTemplate: + ThisDecl = Actions.ActOnDeclarator(CurScope, D); + break; + + case ParsedTemplateInfo::Template: + case ParsedTemplateInfo::ExplicitSpecialization: + ThisDecl = Actions.ActOnTemplateDeclarator(CurScope, Action::MultiTemplateParamsArg(Actions, TemplateInfo.TemplateParams->data(), TemplateInfo.TemplateParams->size()), - D) - : Actions.ActOnDeclarator(CurScope, D); - + D); + break; + + case ParsedTemplateInfo::ExplicitInstantiation: { + Action::DeclResult ThisRes + = Actions.ActOnExplicitInstantiation(CurScope, + TemplateInfo.ExternLoc, + TemplateInfo.TemplateLoc, + D); + if (ThisRes.isInvalid()) { + SkipUntil(tok::semi, true, true); + return DeclPtrTy(); + } + + ThisDecl = ThisRes.get(); + break; + } + } + // Parse declarator '=' initializer. if (Tok.is(tok::equal)) { ConsumeToken(); @@ -444,7 +469,7 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D, SkipUntil(tok::semi, true, true); return DeclPtrTy(); } - Actions.AddInitializerToDecl(ThisDecl, Actions.FullExpr(Init)); + Actions.AddInitializerToDecl(ThisDecl, move(Init)); } } else if (Tok.is(tok::l_paren)) { // Parse C++ direct initializer: '(' expression-list ')' @@ -465,7 +490,9 @@ Parser::DeclPtrTy Parser::ParseDeclarationAfterDeclarator(Declarator &D, CommaLocs.data(), RParenLoc); } } else { - Actions.ActOnUninitializedDecl(ThisDecl); + bool TypeContainsUndeducedAuto = + D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto; + Actions.ActOnUninitializedDecl(ThisDecl, TypeContainsUndeducedAuto); } return ThisDecl; @@ -488,25 +515,25 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { // Declarators may be grouped together ("int X, *Y, Z();"). Remember the decls // that we parse together here. llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup; - + // At this point, we know that it is not a function definition. Parse the // rest of the init-declarator-list. while (1) { DeclPtrTy ThisDecl = ParseDeclarationAfterDeclarator(D); if (ThisDecl.get()) DeclsInGroup.push_back(ThisDecl); - + // If we don't have a comma, it is either the end of the list (a ';') or an // error, bail out. if (Tok.isNot(tok::comma)) break; - + // Consume the comma. ConsumeToken(); - + // Parse the next declarator. D.clear(); - + // Accept attributes in an init-declarator. In the first declarator in a // declaration, these would be part of the declspec. In subsequent // declarators, they become part of the declarator itself, so that they @@ -519,10 +546,10 @@ ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D) { AttributeList *AttrList = ParseAttributes(&Loc); D.AddAttributes(AttrList, Loc); } - + ParseDeclarator(D); } - + return Actions.FinalizeDeclaratorGroup(CurScope, D.getDeclSpec(), DeclsInGroup.data(), DeclsInGroup.size()); @@ -538,13 +565,13 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) { /// specifier-qualifier-list is a subset of declaration-specifiers. Just /// parse declaration-specifiers and complain about extra stuff. ParseDeclarationSpecifiers(DS); - + // Validate declspec for type-name. unsigned Specs = DS.getParsedSpecifiers(); if (Specs == DeclSpec::PQ_None && !DS.getNumProtocolQualifiers() && !DS.getAttributes()) Diag(Tok, diag::err_typename_requires_specqual); - + // Issue diagnostic and remove storage class if present. if (Specs & DeclSpec::PQ_StorageClassSpecifier) { if (DS.getStorageClassSpecLoc().isValid()) @@ -553,7 +580,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS) { Diag(DS.getThreadSpecLoc(), diag::err_typename_invalid_storageclass); DS.ClearStorageClassSpecs(); } - + // Issue diagnostic and remove function specfier if present. if (Specs & DeclSpec::PQ_FunctionSpecifier) { if (DS.isInlineSpecified()) @@ -604,7 +631,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS) { assert(Tok.is(tok::identifier) && "should have identifier"); - + SourceLocation Loc = Tok.getLocation(); // If we see an identifier that is not a type name, we normally would // parse it as the identifer being declared. However, when a typename @@ -619,7 +646,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // next token is obviously invalid for a type. Parse these as a case // with an invalid type specifier. assert(!DS.hasTypeSpecifier() && "Type specifier checked above"); - + // Since we know that this either implicit int (which is rare) or an // error, we'd do lookahead to try to do better recovery. if (isValidAfterIdentifierInDeclarator(NextToken())) { @@ -628,7 +655,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // identifier in the declarator. return false; } - + // Otherwise, if we don't consume this token, we are going to emit an // error anyway. Try to recover from various common problems. Check // to see if this was a reference to a tag name without a tag specified. @@ -638,7 +665,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, if (SS == 0) { const char *TagName = 0; tok::TokenKind TagKind = tok::unknown; - + switch (Actions.isTagName(*Tok.getIdentifierInfo(), CurScope)) { default: break; case DeclSpec::TST_enum: TagName="enum" ;TagKind=tok::kw_enum ;break; @@ -646,12 +673,12 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, case DeclSpec::TST_struct:TagName="struct";TagKind=tok::kw_struct;break; case DeclSpec::TST_class: TagName="class" ;TagKind=tok::kw_class ;break; } - + if (TagName) { Diag(Loc, diag::err_use_of_tag_name_without_tag) << Tok.getIdentifierInfo() << TagName << CodeModificationHint::CreateInsertion(Tok.getLocation(),TagName); - + // Parse this as a tag as if the missing tag were present. if (TagKind == tok::kw_enum) ParseEnumSpecifier(Loc, DS, AS); @@ -660,19 +687,43 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, return true; } } - - // Since this is almost certainly an invalid type name, emit a - // diagnostic that says it, eat the token, and mark the declspec as - // invalid. - SourceRange R; - if (SS) R = SS->getRange(); - - Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R; + + // This is almost certainly an invalid type name. Let the action emit a + // diagnostic and attempt to recover. + Action::TypeTy *T = 0; + if (Actions.DiagnoseUnknownTypeName(*Tok.getIdentifierInfo(), Loc, + CurScope, SS, T)) { + // The action emitted a diagnostic, so we don't have to. + if (T) { + // The action has suggested that the type T could be used. Set that as + // the type in the declaration specifiers, consume the would-be type + // name token, and we're done. + const char *PrevSpec; + unsigned DiagID; + DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T, + false); + DS.SetRangeEnd(Tok.getLocation()); + ConsumeToken(); + + // There may be other declaration specifiers after this. + return true; + } + + // Fall through; the action had no suggestion for us. + } else { + // The action did not emit a diagnostic, so emit one now. + SourceRange R; + if (SS) R = SS->getRange(); + Diag(Loc, diag::err_unknown_typename) << Tok.getIdentifierInfo() << R; + } + + // Mark this as an error. const char *PrevSpec; - DS.SetTypeSpecType(DeclSpec::TST_error, Loc, PrevSpec); + unsigned DiagID; + DS.SetTypeSpecType(DeclSpec::TST_error, Loc, PrevSpec, DiagID); DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); - + // TODO: Could inject an invalid typedef decl in an enclosing scope to // avoid rippling error messages on subsequent uses of the same type, // could be useful if #include was forgotten. @@ -703,24 +754,32 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, /// void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, - AccessSpecifier AS) { + AccessSpecifier AS, + DeclSpecContext DSContext) { + if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteOrdinaryName(CurScope); + ConsumeToken(); + } + DS.SetRangeStart(Tok.getLocation()); while (1) { - int isInvalid = false; + bool isInvalid = false; const char *PrevSpec = 0; + unsigned DiagID = 0; + SourceLocation Loc = Tok.getLocation(); switch (Tok.getKind()) { - default: + default: DoneWithDeclSpec: // If this is not a declaration specifier token, we're done reading decl // specifiers. First verify that DeclSpec's are consistent. DS.Finish(Diags, PP); return; - + case tok::coloncolon: // ::foo::bar // Annotate C++ scope specifiers. If we get one, loop. - if (TryAnnotateCXXScopeToken()) + if (TryAnnotateCXXScopeToken(true)) continue; goto DoneWithDeclSpec; @@ -730,18 +789,31 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // We are looking for a qualified typename. Token Next = NextToken(); - if (Next.is(tok::annot_template_id) && + if (Next.is(tok::annot_template_id) && static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue()) ->Kind == TNK_Type_template) { // We have a qualified template-id, e.g., N::A<int> CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS); - assert(Tok.is(tok::annot_template_id) && + ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true); + assert(Tok.is(tok::annot_template_id) && "ParseOptionalCXXScopeSpecifier not working"); AnnotateTemplateIdTokenAsType(&SS); continue; } + if (Next.is(tok::annot_typename)) { + // FIXME: is this scope-specifier getting dropped? + ConsumeToken(); // the scope-specifier + if (Tok.getAnnotationValue()) + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, + PrevSpec, DiagID, + Tok.getAnnotationValue()); + else + DS.SetTypeSpecError(); + DS.SetRangeEnd(Tok.getAnnotationEndLoc()); + ConsumeToken(); // The typename + } + if (Next.isNot(tok::identifier)) goto DoneWithDeclSpec; @@ -763,66 +835,69 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // If the referenced identifier is not a type, then this declspec is // erroneous: We already checked about that it has no type specifier, and // C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the - // typename. + // typename. if (TypeRep == 0) { ConsumeToken(); // Eat the scope spec so the identifier is current. if (ParseImplicitInt(DS, &SS, TemplateInfo, AS)) continue; goto DoneWithDeclSpec; } - + ConsumeToken(); // The C++ scope. isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - TypeRep); + DiagID, TypeRep); if (isInvalid) break; - + DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); // The typename. continue; } - + case tok::annot_typename: { if (Tok.getAnnotationValue()) isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - Tok.getAnnotationValue()); + DiagID, Tok.getAnnotationValue()); else DS.SetTypeSpecError(); DS.SetRangeEnd(Tok.getAnnotationEndLoc()); ConsumeToken(); // The typename - + // 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 EndProtoLoc; + + SourceLocation LAngleLoc, EndProtoLoc; llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl; - ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc); - DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size()); - + llvm::SmallVector<SourceLocation, 8> ProtocolLocs; + ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false, + LAngleLoc, EndProtoLoc); + DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(), + ProtocolLocs.data(), LAngleLoc); + DS.SetRangeEnd(EndProtoLoc); continue; } - + // typedef-name case tok::identifier: { // In C++, check to see if this is a scope specifier like foo::bar::, if // so handle it as such. This is important for ctor parsing. - if (getLang().CPlusPlus && TryAnnotateCXXScopeToken()) + if (getLang().CPlusPlus && TryAnnotateCXXScopeToken(true)) continue; - + // This identifier can only be a typedef name if we haven't already seen // a type-specifier. Without this check we misparse: // typedef int X; struct Y { short X; }; as 'short int'. if (DS.hasTypeSpecifier()) goto DoneWithDeclSpec; - + // It has to be available as a typedef too! - TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(), + TypeTy *TypeRep = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), CurScope); // If this is not a typedef name, don't parse it as part of the declspec, @@ -836,16 +911,19 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // being defined and the next token is a '(', then this is a // constructor declaration. We're done with the decl-specifiers // and will treat this token as an identifier. - if (getLang().CPlusPlus && CurScope->isClassScope() && - Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope) && + if (getLang().CPlusPlus && + (CurScope->isClassScope() || + (CurScope->isTemplateParamScope() && + CurScope->getParent()->isClassScope())) && + Actions.isCurrentClassName(*Tok.getIdentifierInfo(), CurScope) && NextToken().getKind() == tok::l_paren) goto DoneWithDeclSpec; isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - TypeRep); + DiagID, TypeRep); if (isInvalid) break; - + DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); // The identifier @@ -855,12 +933,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // just a normal reference to a typedef name. if (!Tok.is(tok::less) || !getLang().ObjC1) continue; - - SourceLocation EndProtoLoc; + + SourceLocation LAngleLoc, EndProtoLoc; llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl; - ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc); - DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size()); - + llvm::SmallVector<SourceLocation, 8> ProtocolLocs; + ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false, + LAngleLoc, EndProtoLoc); + DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(), + ProtocolLocs.data(), LAngleLoc); + DS.SetRangeEnd(EndProtoLoc); // Need to support trailing type qualifiers (e.g. "id<p> const"). @@ -870,7 +951,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // type-name case tok::annot_template_id: { - TemplateIdAnnotation *TemplateId + TemplateIdAnnotation *TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); if (TemplateId->Kind != TNK_Type_template) { // This template-id does not refer to a type name, so we're @@ -893,7 +974,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___declspec: DS.AddAttributes(ParseMicrosoftDeclSpec()); continue; - + // Microsoft single token adornments. case tok::kw___forceinline: // FIXME: Add handling here! @@ -909,106 +990,144 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // storage-class-specifier case tok::kw_typedef: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_typedef, Loc, PrevSpec, + DiagID); break; case tok::kw_extern: if (DS.isThreadSpecified()) Diag(Tok, diag::ext_thread_before) << "extern"; - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_extern, Loc, PrevSpec, + DiagID); break; case tok::kw___private_extern__: isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_private_extern, Loc, - PrevSpec); + PrevSpec, DiagID); break; case tok::kw_static: if (DS.isThreadSpecified()) Diag(Tok, diag::ext_thread_before) << "static"; - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_static, Loc, PrevSpec, + DiagID); break; case tok::kw_auto: if (getLang().CPlusPlus0x) - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, + DiagID); else - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_auto, Loc, PrevSpec, + DiagID); break; case tok::kw_register: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_register, Loc, PrevSpec, + DiagID); break; case tok::kw_mutable: - isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec); + isInvalid = DS.SetStorageClassSpec(DeclSpec::SCS_mutable, Loc, PrevSpec, + DiagID); break; case tok::kw___thread: - isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec)*2; + isInvalid = DS.SetStorageClassSpecThread(Loc, PrevSpec, DiagID); break; - + // function-specifier case tok::kw_inline: - isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec); + isInvalid = DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID); break; case tok::kw_virtual: - isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec); + isInvalid = DS.SetFunctionSpecVirtual(Loc, PrevSpec, DiagID); break; case tok::kw_explicit: - isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec); + isInvalid = DS.SetFunctionSpecExplicit(Loc, PrevSpec, DiagID); break; // friend case tok::kw_friend: - isInvalid = DS.SetFriendSpec(Loc, PrevSpec); + if (DSContext == DSC_class) + isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); + else { + PrevSpec = ""; // not actually used by the diagnostic + DiagID = diag::err_friend_invalid_in_context; + isInvalid = true; + } break; - + // type-specifier case tok::kw_short: - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, + DiagID); break; case tok::kw_long: if (DS.getTypeSpecWidth() != DeclSpec::TSW_long) - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, + DiagID); else - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, + DiagID); break; case tok::kw_signed: - isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, + DiagID); break; case tok::kw_unsigned: - isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, + DiagID); break; case tok::kw__Complex: - isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec, + DiagID); break; case tok::kw__Imaginary: - isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec, + DiagID); break; case tok::kw_void: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, + DiagID); break; case tok::kw_char: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, + DiagID); break; case tok::kw_int: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, + DiagID); break; case tok::kw_float: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, + DiagID); break; case tok::kw_double: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, + DiagID); break; case tok::kw_wchar_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, + DiagID); + break; + case tok::kw_char16_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, + DiagID); + break; + case tok::kw_char32_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, + DiagID); break; case tok::kw_bool: case tok::kw__Bool: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, + DiagID); break; case tok::kw__Decimal32: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec, + DiagID); break; case tok::kw__Decimal64: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec, + DiagID); break; case tok::kw__Decimal128: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec, + DiagID); break; // class-specifier: @@ -1029,15 +1148,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // cv-qualifier: case tok::kw_const: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec,getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID, + getLang()); break; case tok::kw_volatile: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, - getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, + getLang()); break; case tok::kw_restrict: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, - getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, + getLang()); break; // C++ typename-specifier: @@ -1061,12 +1181,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // but we support it. if (DS.hasTypeSpecifier() || !getLang().ObjC1) goto DoneWithDeclSpec; - + { - SourceLocation EndProtoLoc; + SourceLocation LAngleLoc, EndProtoLoc; llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl; - ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc); - DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size()); + llvm::SmallVector<SourceLocation, 8> ProtocolLocs; + ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false, + LAngleLoc, EndProtoLoc); + DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(), + ProtocolLocs.data(), LAngleLoc); DS.SetRangeEnd(EndProtoLoc); Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id) @@ -1077,12 +1200,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; } } - // If the specifier combination wasn't legal, issue a diagnostic. + // If the specifier wasn't legal, issue a diagnostic. if (isInvalid) { assert(PrevSpec && "Method did not return previous specifier!"); - // Pick between error or extwarn. - unsigned DiagID = isInvalid == 1 ? diag::err_invalid_decl_spec_combination - : diag::ext_duplicate_declspec; + assert(DiagID); Diag(Tok, DiagID) << PrevSpec; } DS.SetRangeEnd(Tok.getLocation()); @@ -1133,8 +1254,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, /// [OBJC] class-name objc-protocol-refs[opt] [TODO] /// [OBJC] typedef-name objc-protocol-refs[opt] [TODO] /// [C++0x] 'decltype' ( expression ) -bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, +bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, bool& isInvalid, const char *&PrevSpec, + unsigned &DiagID, const ParsedTemplateInfo &TemplateInfo) { SourceLocation Loc = Tok.getLocation(); @@ -1144,98 +1266,117 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. if (TryAnnotateTypeOrScopeToken()) - return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, TemplateInfo); + return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, + TemplateInfo); // Otherwise, not a type specifier. return false; case tok::coloncolon: // ::foo::bar if (NextToken().is(tok::kw_new) || // ::new NextToken().is(tok::kw_delete)) // ::delete return false; - + // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. if (TryAnnotateTypeOrScopeToken()) - return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, TemplateInfo); + return ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID, + TemplateInfo); // Otherwise, not a type specifier. return false; - + // simple-type-specifier: case tok::annot_typename: { if (Tok.getAnnotationValue()) isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, - Tok.getAnnotationValue()); + DiagID, Tok.getAnnotationValue()); else DS.SetTypeSpecError(); DS.SetRangeEnd(Tok.getAnnotationEndLoc()); ConsumeToken(); // The typename - + // 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) return true; - - SourceLocation EndProtoLoc; + + SourceLocation LAngleLoc, EndProtoLoc; llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl; - ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc); - DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size()); - + llvm::SmallVector<SourceLocation, 8> ProtocolLocs; + ParseObjCProtocolReferences(ProtocolDecl, ProtocolLocs, false, + LAngleLoc, EndProtoLoc); + DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size(), + ProtocolLocs.data(), LAngleLoc); + DS.SetRangeEnd(EndProtoLoc); return true; } case tok::kw_short: - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID); break; case tok::kw_long: if (DS.getTypeSpecWidth() != DeclSpec::TSW_long) - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, + DiagID); else - isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_longlong, Loc, PrevSpec, + DiagID); break; case tok::kw_signed: - isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID); break; case tok::kw_unsigned: - isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, + DiagID); break; case tok::kw__Complex: - isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec, + DiagID); break; case tok::kw__Imaginary: - isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec, + DiagID); break; case tok::kw_void: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID); break; case tok::kw_char: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID); break; case tok::kw_int: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID); break; case tok::kw_float: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID); break; case tok::kw_double: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID); break; case tok::kw_wchar_t: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID); + break; + case tok::kw_char16_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID); + break; + case tok::kw_char32_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID); break; case tok::kw_bool: case tok::kw__Bool: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID); break; case tok::kw__Decimal32: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec, + DiagID); break; case tok::kw__Decimal64: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec, + DiagID); break; case tok::kw__Decimal128: - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec, + DiagID); break; // class-specifier: @@ -1257,15 +1398,15 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, // cv-qualifier: case tok::kw_const: isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, - getLang())*2; + DiagID, getLang()); break; case tok::kw_volatile: isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, - getLang())*2; + DiagID, getLang()); break; case tok::kw_restrict: isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, - getLang())*2; + DiagID, getLang()); break; // GNU typeof support. @@ -1277,13 +1418,13 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, case tok::kw_decltype: ParseDecltypeSpecifier(DS); return true; - + // C++0x auto support. case tok::kw_auto: if (!getLang().CPlusPlus0x) return false; - isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec, DiagID); break; case tok::kw___ptr64: case tok::kw___w64: @@ -1302,8 +1443,6 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, if (isInvalid) { assert(PrevSpec && "Method did not return previous specifier!"); // Pick between error or extwarn. - unsigned DiagID = isInvalid == 1 ? diag::err_invalid_decl_spec_combination - : diag::ext_duplicate_declspec; Diag(Tok, DiagID) << PrevSpec; } DS.SetRangeEnd(Tok.getLocation()); @@ -1337,11 +1476,11 @@ ParseStructDeclaration(DeclSpec &DS, ConsumeToken(); return ParseStructDeclaration(DS, 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 // specifier. Let the actions module cope with it. if (Tok.is(tok::semi)) { @@ -1353,12 +1492,12 @@ ParseStructDeclaration(DeclSpec &DS, Fields.push_back(FieldDeclarator(DS)); while (1) { FieldDeclarator &DeclaratorInfo = Fields.back(); - + /// struct-declarator: declarator /// struct-declarator: declarator[opt] ':' constant-expression if (Tok.isNot(tok::colon)) ParseDeclarator(DeclaratorInfo.D); - + if (Tok.is(tok::colon)) { ConsumeToken(); OwningExprResult Res(ParseConstantExpression()); @@ -1410,9 +1549,9 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions, PP.getSourceManager(), "parsing struct/union body"); - + SourceLocation LBraceLoc = ConsumeBrace(); - + ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope); Actions.ActOnTagStartDefinition(CurScope, TagDecl); @@ -1428,7 +1567,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, // While we still have something to read, read the declarations in the struct. while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { // Each iteration of this loop reads one struct-declaration. - + // Check for extraneous top-level semicolon. if (Tok.is(tok::semi)) { Diag(Tok, diag::ext_extra_struct_semi) @@ -1442,14 +1581,23 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, FieldDeclarators.clear(); if (!Tok.is(tok::at)) { ParseStructDeclaration(DS, FieldDeclarators); - + // Convert them all to fields. for (unsigned i = 0, e = FieldDeclarators.size(); i != e; ++i) { FieldDeclarator &FD = FieldDeclarators[i]; + DeclPtrTy Field; // Install the declarator into the current TagDecl. - DeclPtrTy Field = Actions.ActOnField(CurScope, TagDecl, - DS.getSourceRange().getBegin(), - FD.D, FD.BitfieldSize); + if (FD.D.getExtension()) { + // Silences extension warnings + ExtensionRAIIObject O(Diags); + Field = Actions.ActOnField(CurScope, TagDecl, + DS.getSourceRange().getBegin(), + FD.D, FD.BitfieldSize); + } else { + Field = Actions.ActOnField(CurScope, TagDecl, + DS.getSourceRange().getBegin(), + FD.D, FD.BitfieldSize); + } FieldDecls.push_back(Field); } } else { // Handle @defs @@ -1467,12 +1615,12 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, continue; } llvm::SmallVector<DeclPtrTy, 16> Fields; - Actions.ActOnDefs(CurScope, TagDecl, Tok.getLocation(), + Actions.ActOnDefs(CurScope, TagDecl, Tok.getLocation(), Tok.getIdentifierInfo(), Fields); FieldDecls.insert(FieldDecls.end(), Fields.begin(), Fields.end()); ConsumeToken(); ExpectAndConsume(tok::r_paren, diag::err_expected_rparen); - } + } if (Tok.is(tok::semi)) { ConsumeToken(); @@ -1485,9 +1633,9 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, SkipUntil(tok::r_brace, true, true); } } - + SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); - + AttributeList *AttrList = 0; // If attributes exist after struct contents, parse them. if (Tok.is(tok::kw___attribute)) @@ -1498,7 +1646,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, LBraceLoc, RBraceLoc, AttrList); StructScope.Exit(); - Actions.ActOnTagFinishDefinition(CurScope, TagDecl); + Actions.ActOnTagFinishDefinition(CurScope, TagDecl, RBraceLoc); } @@ -1517,14 +1665,19 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, AccessSpecifier AS) { // Parse the tag portion of this. - + if (Tok.is(tok::code_completion)) { + // Code completion for an enum name. + Actions.CodeCompleteTag(CurScope, DeclSpec::TST_enum); + ConsumeToken(); + } + AttributeList *Attr = 0; // If attributes exist after tag, parse them. if (Tok.is(tok::kw___attribute)) Attr = ParseAttributes(); CXXScopeSpec SS; - if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS)) { + if (getLang().CPlusPlus && ParseOptionalCXXScopeSpecifier(SS, 0, false)) { if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); if (Tok.isNot(tok::l_brace)) { @@ -1535,16 +1688,16 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, } } } - + // Must have either 'enum name' or 'enum {...}'. if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace)) { Diag(Tok, diag::err_expected_ident_lbrace); - + // Skip the rest of this declarator, up until the comma or semicolon. SkipUntil(tok::comma, true); return; } - + // If an identifier is present, consume and remember it. IdentifierInfo *Name = 0; SourceLocation NameLoc; @@ -1552,7 +1705,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, Name = Tok.getIdentifierInfo(); NameLoc = ConsumeToken(); } - + // 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. @@ -1561,26 +1714,30 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // enum foo {..}; void bar() { enum foo; } <- new foo in bar. // enum foo {..}; void bar() { enum foo x; } <- use of old foo. // - Action::TagKind TK; + Action::TagUseKind TUK; if (Tok.is(tok::l_brace)) - TK = Action::TK_Definition; + TUK = Action::TUK_Definition; else if (Tok.is(tok::semi)) - TK = Action::TK_Declaration; + TUK = Action::TUK_Declaration; else - TK = Action::TK_Reference; + TUK = Action::TUK_Reference; bool Owned = false; - DeclPtrTy TagDecl = Actions.ActOnTag(CurScope, DeclSpec::TST_enum, TK, + bool IsDependent = false; + DeclPtrTy TagDecl = Actions.ActOnTag(CurScope, DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc, Attr, AS, - Owned); - + Action::MultiTemplateParamsArg(Actions), + Owned, IsDependent); + assert(!IsDependent && "didn't expect dependent enum"); + if (Tok.is(tok::l_brace)) ParseEnumBody(StartLoc, TagDecl); - + // TODO: semantic analysis on the declspec for enums. const char *PrevSpec = 0; - if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, PrevSpec, + unsigned DiagID; + if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc, PrevSpec, DiagID, TagDecl.getAs<void>(), Owned)) - Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + Diag(StartLoc, DiagID) << PrevSpec; } /// ParseEnumBody - Parse a {} enclosed enumerator-list. @@ -1599,20 +1756,20 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) { Actions.ActOnTagStartDefinition(CurScope, EnumDecl); SourceLocation LBraceLoc = ConsumeBrace(); - + // C does not allow an empty enumerator-list, C++ does [dcl.enum]. if (Tok.is(tok::r_brace) && !getLang().CPlusPlus) Diag(Tok, diag::ext_empty_struct_union_enum) << "enum"; - + llvm::SmallVector<DeclPtrTy, 32> EnumConstantDecls; DeclPtrTy LastEnumConstDecl; - + // Parse the enumerator-list. while (Tok.is(tok::identifier)) { IdentifierInfo *Ident = Tok.getIdentifierInfo(); SourceLocation IdentLoc = ConsumeToken(); - + SourceLocation EqualLoc; OwningExprResult AssignedVal(Actions); if (Tok.is(tok::equal)) { @@ -1621,7 +1778,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) { if (AssignedVal.isInvalid()) SkipUntil(tok::comma, tok::r_brace, true, true); } - + // Install the enumerator constant into EnumDecl. DeclPtrTy EnumConstDecl = Actions.ActOnEnumConstant(CurScope, EnumDecl, LastEnumConstDecl, @@ -1630,31 +1787,32 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, DeclPtrTy EnumDecl) { AssignedVal.release()); EnumConstantDecls.push_back(EnumConstDecl); LastEnumConstDecl = EnumConstDecl; - + if (Tok.isNot(tok::comma)) break; SourceLocation CommaLoc = ConsumeToken(); - - if (Tok.isNot(tok::identifier) && + + if (Tok.isNot(tok::identifier) && !(getLang().C99 || getLang().CPlusPlus0x)) Diag(CommaLoc, diag::ext_enumerator_list_comma) << getLang().CPlusPlus << CodeModificationHint::CreateRemoval((SourceRange(CommaLoc))); } - + // Eat the }. SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc); - Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl, - EnumConstantDecls.data(), EnumConstantDecls.size()); - - Action::AttrTy *AttrList = 0; + AttributeList *Attr = 0; // If attributes exist after the identifier list, parse them. if (Tok.is(tok::kw___attribute)) - AttrList = ParseAttributes(); // FIXME: where do they do? + Attr = ParseAttributes(); + + Actions.ActOnEnumBody(StartLoc, LBraceLoc, RBraceLoc, EnumDecl, + EnumConstantDecls.data(), EnumConstantDecls.size(), + CurScope, Attr); EnumScope.Exit(); - Actions.ActOnTagFinishDefinition(CurScope, EnumDecl); + Actions.ActOnTagFinishDefinition(CurScope, EnumDecl, RBraceLoc); } /// isTypeSpecifierQualifier - Return true if the current token could be the @@ -1675,7 +1833,7 @@ bool Parser::isTypeQualifier() const { bool Parser::isTypeSpecifierQualifier() { switch (Tok.getKind()) { default: return false; - + case tok::identifier: // foo::bar case tok::kw_typename: // typename T::type // Annotate typenames and C++ scope specifiers. If we get one, just @@ -1696,12 +1854,12 @@ bool Parser::isTypeSpecifierQualifier() { return isTypeSpecifierQualifier(); // Otherwise, not a type specifier. return false; - + // GNU attributes support. case tok::kw___attribute: // GNU typeof support. case tok::kw_typeof: - + // type-specifiers case tok::kw_short: case tok::kw_long: @@ -1712,6 +1870,8 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw_void: case tok::kw_char: case tok::kw_wchar_t: + case tok::kw_char16_t: + case tok::kw_char32_t: case tok::kw_int: case tok::kw_float: case tok::kw_double: @@ -1720,14 +1880,14 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw__Decimal32: case tok::kw__Decimal64: case tok::kw__Decimal128: - + // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: case tok::kw_union: // enum-specifier case tok::kw_enum: - + // type-qualifier case tok::kw_const: case tok::kw_volatile: @@ -1736,11 +1896,11 @@ bool Parser::isTypeSpecifierQualifier() { // typedef-name case tok::annot_typename: return true; - + // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'. case tok::less: return getLang().ObjC1; - + case tok::kw___cdecl: case tok::kw___stdcall: case tok::kw___fastcall: @@ -1755,7 +1915,7 @@ bool Parser::isTypeSpecifierQualifier() { bool Parser::isDeclarationSpecifier() { switch (Tok.getKind()) { default: return false; - + case tok::identifier: // foo::bar // Unfortunate hack to support "Class.factoryMethod" notation. if (getLang().ObjC1 && NextToken().is(tok::period)) @@ -1773,14 +1933,14 @@ bool Parser::isDeclarationSpecifier() { if (NextToken().is(tok::kw_new) || // ::new NextToken().is(tok::kw_delete)) // ::delete return false; - + // Annotate typenames and C++ scope specifiers. If we get one, just // recurse to handle whatever we get. if (TryAnnotateTypeOrScopeToken()) return isDeclarationSpecifier(); // Otherwise, not a declaration specifier. return false; - + // storage-class-specifier case tok::kw_typedef: case tok::kw_extern: @@ -1789,7 +1949,7 @@ bool Parser::isDeclarationSpecifier() { case tok::kw_auto: case tok::kw_register: case tok::kw___thread: - + // type-specifiers case tok::kw_short: case tok::kw_long: @@ -1800,6 +1960,9 @@ bool Parser::isDeclarationSpecifier() { case tok::kw_void: case tok::kw_char: case tok::kw_wchar_t: + case tok::kw_char16_t: + case tok::kw_char32_t: + case tok::kw_int: case tok::kw_float: case tok::kw_double: @@ -1808,14 +1971,14 @@ bool Parser::isDeclarationSpecifier() { case tok::kw__Decimal32: case tok::kw__Decimal64: case tok::kw__Decimal128: - + // struct-or-union-specifier (C99) or class-specifier (C++) case tok::kw_class: case tok::kw_struct: case tok::kw_union: // enum-specifier case tok::kw_enum: - + // type-qualifier case tok::kw_const: case tok::kw_volatile: @@ -1831,15 +1994,15 @@ bool Parser::isDeclarationSpecifier() { // GNU typeof support. case tok::kw_typeof: - + // GNU attributes. case tok::kw___attribute: return true; - + // GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'. case tok::less: return getLang().ObjC1; - + case tok::kw___declspec: case tok::kw___cdecl: case tok::kw___stdcall: @@ -1861,22 +2024,23 @@ bool Parser::isDeclarationSpecifier() { /// void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) { while (1) { - int isInvalid = false; + bool isInvalid = false; const char *PrevSpec = 0; + unsigned DiagID = 0; SourceLocation Loc = Tok.getLocation(); switch (Tok.getKind()) { case tok::kw_const: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, - getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID, + getLang()); break; case tok::kw_volatile: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, - getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID, + getLang()); break; case tok::kw_restrict: - isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, - getLang())*2; + isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID, + getLang()); break; case tok::kw___w64: case tok::kw___ptr64: @@ -1905,9 +2069,6 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed) { // If the specifier combination wasn't legal, issue a diagnostic. if (isInvalid) { assert(PrevSpec && "Method did not return previous specifier!"); - // Pick between error or extwarn. - unsigned DiagID = isInvalid == 1 ? diag::err_invalid_decl_spec_combination - : diag::ext_duplicate_declspec; Diag(Tok, DiagID) << PrevSpec; } ConsumeToken(); @@ -1947,6 +2108,8 @@ void Parser::ParseDeclarator(Declarator &D) { void Parser::ParseDeclaratorInternal(Declarator &D, DirectDeclParseFunction DirectDeclParser) { + if (Diags.hasAllExtensionsSilenced()) + D.setExtension(); // C++ member pointers start with a '::' or a nested-name. // Member pointers get special handling, since there's no place for the // scope spec in the generic path below. @@ -1954,8 +2117,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, (Tok.is(tok::coloncolon) || Tok.is(tok::identifier) || Tok.is(tok::annot_cxxscope))) { CXXScopeSpec SS; - if (ParseOptionalCXXScopeSpecifier(SS)) { - if(Tok.isNot(tok::star)) { + if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true)) { + if (Tok.isNot(tok::star)) { // The scope spec really belongs to the direct-declarator. D.getCXXScopeSpec() = SS; if (DirectDeclParser) @@ -2013,7 +2176,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, SourceLocation()); else // Remember that we parsed a Block type, and remember the type-quals. - D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), + D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), Loc, DS.TakeAttributes()), SourceLocation()); } else { @@ -2095,13 +2258,13 @@ void Parser::ParseDeclaratorInternal(Declarator &D, /// /// id-expression: [C++ 5.1] /// unqualified-id -/// qualified-id [TODO] +/// qualified-id /// /// unqualified-id: [C++ 5.1] -/// identifier +/// identifier /// operator-function-id -/// conversion-function-id [TODO] -/// '~' class-name +/// conversion-function-id +/// '~' class-name /// template-id /// void Parser::ParseDirectDeclarator(Declarator &D) { @@ -2111,7 +2274,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { if (D.mayHaveIdentifier()) { // ParseDeclaratorInternal might already have parsed the scope. bool afterCXXScope = D.getCXXScopeSpec().isSet() || - ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec()); + ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), /*ObjectType=*/0, + true); if (afterCXXScope) { // Change the declaration context for name lookup, until this function // is exited (and the declarator has been parsed). @@ -2122,11 +2286,12 @@ void Parser::ParseDirectDeclarator(Declarator &D) { assert(Tok.getIdentifierInfo() && "Not an identifier?"); // If this identifier is the name of the current class, it's a - // constructor name. + // constructor name. if (!D.getDeclSpec().hasTypeSpecifier() && Actions.isCurrentClassName(*Tok.getIdentifierInfo(),CurScope)) { + CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0; D.setConstructor(Actions.getTypeName(*Tok.getIdentifierInfo(), - Tok.getLocation(), CurScope), + Tok.getLocation(), CurScope, SS), Tok.getLocation()); // This is a normal identifier. } else @@ -2134,18 +2299,10 @@ void Parser::ParseDirectDeclarator(Declarator &D) { ConsumeToken(); goto PastIdentifier; } else if (Tok.is(tok::annot_template_id)) { - TemplateIdAnnotation *TemplateId + TemplateIdAnnotation *TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); - // FIXME: Could this template-id name a constructor? - - // FIXME: This is an egregious hack, where we silently ignore - // the specialization (which should be a function template - // specialization name) and use the name instead. This hack - // will go away when we have support for function - // specializations. - D.SetIdentifier(TemplateId->Name, Tok.getLocation()); - TemplateId->Destroy(); + D.setTemplateId(TemplateId); ConsumeToken(); goto PastIdentifier; } else if (Tok.is(tok::kw_operator)) { @@ -2167,17 +2324,18 @@ void Parser::ParseDirectDeclarator(Declarator &D) { } else if (Tok.is(tok::tilde)) { // This should be a C++ destructor. SourceLocation TildeLoc = ConsumeToken(); - if (Tok.is(tok::identifier)) { + if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id)) { // FIXME: Inaccurate. SourceLocation NameLoc = Tok.getLocation(); SourceLocation EndLoc; - TypeResult Type = ParseClassName(EndLoc); + CXXScopeSpec *SS = afterCXXScope? &D.getCXXScopeSpec() : 0; + TypeResult Type = ParseClassName(EndLoc, SS, true); if (Type.isInvalid()) D.SetIdentifier(0, TildeLoc); else D.setDestructor(Type.get(), TildeLoc, NameLoc); } else { - Diag(Tok, diag::err_expected_class_name); + Diag(Tok, diag::err_destructor_class_name); D.SetIdentifier(0, TildeLoc); } goto PastIdentifier; @@ -2222,11 +2380,11 @@ void Parser::ParseDirectDeclarator(Declarator &D) { D.SetIdentifier(0, Tok.getLocation()); D.setInvalidType(true); } - + PastIdentifier: assert(D.isPastIdentifier() && "Haven't past the location of the identifier yet?"); - + while (1) { if (Tok.is(tok::l_paren)) { // The paren may be part of a C++ direct initializer, eg. "int x(1);". @@ -2250,7 +2408,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { /// ParseParenDeclarator - We parsed the declarator D up to a paren. This is /// only called before the identifier, so these are most likely just grouping -/// parens for precedence. If we find that these are actually function +/// parens for precedence. If we find that these are actually function /// parameter parens in an abstract-declarator, we call ParseFunctionDeclarator. /// /// direct-declarator: @@ -2264,7 +2422,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { void Parser::ParseParenDeclarator(Declarator &D) { SourceLocation StartLoc = ConsumeParen(); assert(!D.isPastIdentifier() && "Should be called before passing identifier"); - + // Eat any attributes before we look at whether this is a grouping or function // declarator paren. If this is a grouping paren, the attribute applies to // the type being built up, for example: @@ -2279,7 +2437,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { bool RequiresArg = false; if (Tok.is(tok::kw___attribute)) { AttrList = ParseAttributes(); - + // We require that the argument list (if this is a non-grouping paren) be // present even if the attribute list was empty. RequiresArg = true; @@ -2290,13 +2448,13 @@ void Parser::ParseParenDeclarator(Declarator &D) { Tok.is(tok::kw___ptr64)) { AttrList = ParseMicrosoftTypeAttributes(AttrList); } - + // 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 // grouping parens. However, if this could be an abstract-declarator, then // this could also be the start of function arguments (consider 'void()'). bool isGrouping; - + if (!D.mayOmitIdentifier()) { // If this can't be an abstract-declarator, this *must* be a grouping // paren, because we haven't seen the identifier yet. @@ -2311,7 +2469,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { // Otherwise, this is a grouping paren, e.g. 'int (*X)' or 'int(X)'. isGrouping = true; } - + // If this is a grouping paren, handle: // direct-declarator: '(' declarator ')' // direct-declarator: '(' attributes declarator ')' @@ -2329,7 +2487,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { D.SetRangeEnd(Loc); return; } - + // Okay, if this wasn't a grouping paren, it must be the start of a function // argument list. Recognize that this declarator will never have an // identifier (and remember where it would have been), then call into @@ -2353,6 +2511,7 @@ void Parser::ParseParenDeclarator(Declarator &D) { /// parameter-type-list: [C99 6.7.5] /// parameter-list /// parameter-list ',' '...' +/// [C++] parameter-list '...' /// /// parameter-list: [C99 6.7.5] /// parameter-declaration @@ -2375,7 +2534,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, bool RequiresArg) { // lparen is already consumed! assert(D.isPastIdentifier() && "Should not call before identifier!"); - + // This parameter list may be empty. if (Tok.is(tok::r_paren)) { if (RequiresArg) { @@ -2383,7 +2542,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, delete AttrList; } - SourceLocation Loc = ConsumeParen(); // Eat the closing ')'. + SourceLocation RParenLoc = ConsumeParen(); // Eat the closing ')'. + SourceLocation EndLoc = RParenLoc; // cv-qualifier-seq[opt]. DeclSpec DS; @@ -2395,13 +2555,13 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, if (getLang().CPlusPlus) { ParseTypeQualifierListOpt(DS, false /*no attributes*/); if (!DS.getSourceRange().getEnd().isInvalid()) - Loc = DS.getSourceRange().getEnd(); + EndLoc = DS.getSourceRange().getEnd(); // Parse exception-specification[opt]. if (Tok.is(tok::kw_throw)) { hasExceptionSpec = true; ThrowLoc = Tok.getLocation(); - ParseExceptionSpecification(Loc, Exceptions, ExceptionRanges, + ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges, hasAnyExceptionSpec); assert(Exceptions.size() == ExceptionRanges.size() && "Produced different number of exception types and ranges."); @@ -2420,8 +2580,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, Exceptions.data(), ExceptionRanges.data(), Exceptions.size(), - LParenLoc, D), - Loc); + LParenLoc, RParenLoc, D), + EndLoc); return; } @@ -2440,9 +2600,9 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, return ParseFunctionDeclaratorIdentifierList(LParenLoc, D); } } - + // Finally, a normal, non-empty parameter type list. - + // Build up an array of information about the parsed arguments. llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; @@ -2450,7 +2610,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // function prototype scope, including parameter declarators. ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope|Scope::DeclScope); - + bool IsVariadic = false; SourceLocation EllipsisLoc; while (1) { @@ -2459,9 +2619,9 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, EllipsisLoc = ConsumeToken(); // Consume the ellipsis. break; } - + SourceLocation DSStart = Tok.getLocation(); - + // Parse the declaration-specifiers. DeclSpec DS; @@ -2471,7 +2631,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, AttrList = 0; // Only apply the attributes to the first parameter. } ParseDeclarationSpecifiers(DS); - + // Parse the declarator. This is "PrototypeContext", because we must // accept either 'declarator' or 'abstract-declarator' here. Declarator ParmDecl(DS, Declarator::PrototypeContext); @@ -2483,10 +2643,10 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, AttributeList *AttrList = ParseAttributes(&Loc); ParmDecl.AddAttributes(AttrList, Loc); } - + // Remember this parsed parameter in ParamInfo. IdentifierInfo *ParmII = ParmDecl.getIdentifier(); - + // DefArgToks is used when the parsing of default arguments needs // to be delayed. CachedTokens *DefArgToks = 0; @@ -2500,7 +2660,7 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, } else { // Otherwise, we have something. Add it and let semantic analysis try // to grok it and add the result to the ParamInfo we are building. - + // Inform the actions module about the parameter declarator, so it gets // added to the current scope. DeclPtrTy Param = Actions.ActOnParamDeclarator(CurScope, ParmDecl); @@ -2521,18 +2681,18 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // FIXME: Can we use a smart pointer for Toks? DefArgToks = new CachedTokens; - if (!ConsumeAndStoreUntil(tok::comma, tok::r_paren, *DefArgToks, + if (!ConsumeAndStoreUntil(tok::comma, tok::r_paren, *DefArgToks, tok::semi, false)) { delete DefArgToks; DefArgToks = 0; Actions.ActOnParamDefaultArgumentError(Param); } else - Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc, + Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc, (*DefArgToks)[1].getLocation()); } else { // Consume the '='. ConsumeToken(); - + OwningExprResult DefArgResult(ParseAssignmentExpression()); if (DefArgResult.isInvalid()) { Actions.ActOnParamDefaultArgumentError(Param); @@ -2544,24 +2704,39 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, } } } - - ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, - ParmDecl.getIdentifierLoc(), Param, + + ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII, + ParmDecl.getIdentifierLoc(), Param, DefArgToks)); } // If the next token is a comma, consume it and keep reading arguments. - if (Tok.isNot(tok::comma)) break; - + if (Tok.isNot(tok::comma)) { + if (Tok.is(tok::ellipsis)) { + IsVariadic = true; + EllipsisLoc = ConsumeToken(); // Consume the ellipsis. + + if (!getLang().CPlusPlus) { + // We have ellipsis without a preceding ',', which is ill-formed + // in C. Complain and provide the fix. + Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis) + << CodeModificationHint::CreateInsertion(EllipsisLoc, ", "); + } + } + + break; + } + // Consume the comma. ConsumeToken(); } - + // Leave prototype scope. PrototypeScope.Exit(); - + // If we have the closing ')', eat it. - SourceLocation Loc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + SourceLocation EndLoc = RParenLoc; DeclSpec DS; bool hasExceptionSpec = false; @@ -2573,13 +2748,13 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // Parse cv-qualifier-seq[opt]. ParseTypeQualifierListOpt(DS, false /*no attributes*/); if (!DS.getSourceRange().getEnd().isInvalid()) - Loc = DS.getSourceRange().getEnd(); + EndLoc = DS.getSourceRange().getEnd(); // Parse exception-specification[opt]. if (Tok.is(tok::kw_throw)) { hasExceptionSpec = true; ThrowLoc = Tok.getLocation(); - ParseExceptionSpecification(Loc, Exceptions, ExceptionRanges, + ParseExceptionSpecification(EndLoc, Exceptions, ExceptionRanges, hasAnyExceptionSpec); assert(Exceptions.size() == ExceptionRanges.size() && "Produced different number of exception types and ranges."); @@ -2595,8 +2770,9 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, hasAnyExceptionSpec, Exceptions.data(), ExceptionRanges.data(), - Exceptions.size(), LParenLoc, D), - Loc); + Exceptions.size(), + LParenLoc, RParenLoc, D), + EndLoc); } /// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator @@ -2612,7 +2788,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, // Build up an array of information about the parsed arguments. llvm::SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo; llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar; - + // If there was no identifier specified for the declarator, either we are in // an abstract-declarator, or we are in a parameter declarator which was found // to be abstract. In abstract-declarators, identifier lists are not valid: @@ -2626,13 +2802,13 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, ParamInfo.push_back(DeclaratorChunk::ParamInfo(Tok.getIdentifierInfo(), Tok.getLocation(), DeclPtrTy())); - + ConsumeToken(); // eat the first identifier. - + while (Tok.is(tok::comma)) { // Eat the comma. ConsumeToken(); - + // If this isn't an identifier, report the error and skip until ')'. if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); @@ -2645,7 +2821,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, // Reject 'typedef int y; int test(x, y)', but continue parsing. if (Actions.getTypeName(*ParmII, Tok.getLocation(), CurScope)) Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII; - + // Verify that the argument identifier has not already been mentioned. if (!ParamsSoFar.insert(ParmII)) { Diag(Tok, diag::err_param_redefinition) << ParmII; @@ -2655,7 +2831,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, Tok.getLocation(), DeclPtrTy())); } - + // Eat the identifier. ConsumeToken(); } @@ -2672,7 +2848,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, /*TypeQuals*/0, /*exception*/false, SourceLocation(), false, 0, 0, 0, - LParenLoc, D), + LParenLoc, RLoc, D), RLoc); } @@ -2683,14 +2859,15 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, /// [C99] direct-declarator '[' type-qual-list[opt] '*' ']' void Parser::ParseBracketDeclarator(Declarator &D) { SourceLocation StartLoc = ConsumeBracket(); - + // C array syntax has many features, but by-far the most common is [] and [4]. // 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); // Remember that we parsed the empty array type. OwningExprResult NumElements(Actions); - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0, StartLoc), + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, 0, + StartLoc, EndLoc), EndLoc); return; } else if (Tok.getKind() == tok::numeric_constant && @@ -2704,33 +2881,33 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // If there was an error parsing the assignment-expression, recover. if (ExprRes.isInvalid()) ExprRes.release(); // Deallocate expr, just use []. - + // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, - ExprRes.release(), StartLoc), + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, 0, ExprRes.release(), + StartLoc, EndLoc), EndLoc); return; } - + // If valid, this location is the position where we read the 'static' keyword. SourceLocation StaticLoc; if (Tok.is(tok::kw_static)) StaticLoc = ConsumeToken(); - + // If there is a type-qualifier-list, read it now. // Type qualifiers in an array subscript are a C99 feature. DeclSpec DS; ParseTypeQualifierListOpt(DS, false /*no attributes*/); - + // If we haven't already read 'static', check to see if there is one after the // type-qualifier-list. if (!StaticLoc.isValid() && Tok.is(tok::kw_static)) StaticLoc = ConsumeToken(); - + // Handle "direct-declarator [ type-qual-list[opt] * ]". bool isStar = false; OwningExprResult NumElements(Actions); - + // Handle the case where we have '[*]' as the array size. However, a leading // star could be the start of an expression, for example 'X[*p + 4]'. Verify // the the token after the star is a ']'. Since stars in arrays are @@ -2748,7 +2925,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // of assignment-expr. The only difference is that assignment-expr allows // things like '=' and '*='. Sema rejects these in C89 mode because they // are not i-c-e's, so we don't need to distinguish between the two here. - + // Parse the constant-expression or assignment-expression now (depending // on dialect). if (getLang().CPlusPlus) @@ -2756,7 +2933,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { else NumElements = ParseAssignmentExpression(); } - + // If there was an error parsing the assignment-expression, recover. if (NumElements.isInvalid()) { D.setInvalidType(true); @@ -2770,7 +2947,8 @@ void Parser::ParseBracketDeclarator(Declarator &D) { // Remember that we parsed a array type, and remember its features. D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(), isStar, - NumElements.release(), StartLoc), + NumElements.release(), + StartLoc, EndLoc), EndLoc); } @@ -2797,7 +2975,7 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { DS.SetRangeEnd(Tok.getLocation()); else DS.SetRangeEnd(CastRange.getEnd()); - + if (isCastExpr) { if (!CastTy) { DS.SetTypeSpecError(); @@ -2805,10 +2983,11 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { } const char *PrevSpec = 0; + unsigned DiagID; // Check for duplicate type specifiers (e.g. "int typeof(int)"). if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec, - CastTy)) - Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + DiagID, CastTy)) + Diag(StartLoc, DiagID) << PrevSpec; return; } @@ -2819,8 +2998,9 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) { } const char *PrevSpec = 0; + unsigned DiagID; // Check for duplicate type specifiers (e.g. "int typeof(int)"). if (DS.SetTypeSpecType(DeclSpec::TST_typeofExpr, StartLoc, PrevSpec, - Operand.release())) - Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec; + DiagID, Operand.release())) + Diag(StartLoc, DiagID) << PrevSpec; } |