diff options
Diffstat (limited to 'lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 189 |
1 files changed, 122 insertions, 67 deletions
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 3f22ad4ddaba2..6436e3dfc7631 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -65,7 +65,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteNamespaceDecl(getCurScope()); cutOffParsing(); - return DeclGroupPtrTy(); + return nullptr; } SourceLocation IdentLoc; @@ -109,7 +109,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context, Diag(Tok, diag::err_expected) << tok::identifier; // Skip to end of the definition and eat the ';'. SkipUntil(tok::semi); - return DeclGroupPtrTy(); + return nullptr; } if (attrLoc.isValid()) Diag(attrLoc, diag::err_unexpected_namespace_attributes_alias); @@ -126,7 +126,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context, Diag(Tok, diag::err_expected) << tok::l_brace; else Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace; - return DeclGroupPtrTy(); + return nullptr; } if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() || @@ -134,7 +134,7 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context, getCurScope()->getFnParent()) { Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope); SkipUntil(tok::r_brace); - return DeclGroupPtrTy(); + return nullptr; } if (ExtraIdent.empty()) { @@ -267,7 +267,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, CXXScopeSpec SS; // Parse (optional) nested-name-specifier. - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false); if (SS.isInvalid() || Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_namespace_name); @@ -442,7 +442,7 @@ Decl *Parser::ParseUsingDirective(unsigned Context, CXXScopeSpec SS; // Parse (optional) nested-name-specifier. - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false); IdentifierInfo *NamespcName = nullptr; SourceLocation IdentLoc = SourceLocation(); @@ -517,7 +517,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, // Parse nested-name-specifier. IdentifierInfo *LastII = nullptr; - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false, + ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false, /*MayBePseudoDtor=*/nullptr, /*IsTypename=*/false, /*LastII=*/&LastII); @@ -554,7 +554,7 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, /*AllowDestructorName=*/true, /*AllowConstructorName=*/!(Tok.is(tok::identifier) && NextToken().is(tok::equal)), - ParsedType(), TemplateKWLoc, Name)) { + nullptr, TemplateKWLoc, Name)) { SkipUntil(tok::semi); return nullptr; } @@ -944,7 +944,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // Parse optional nested-name-specifier CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false); BaseLoc = Tok.getLocation(); @@ -1006,8 +1006,8 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, if (!Template) { TemplateArgList TemplateArgs; SourceLocation LAngleLoc, RAngleLoc; - ParseTemplateIdAfterTemplateName(TemplateTy(), IdLoc, SS, - true, LAngleLoc, TemplateArgs, RAngleLoc); + ParseTemplateIdAfterTemplateName(nullptr, IdLoc, SS, true, LAngleLoc, + TemplateArgs, RAngleLoc); return true; } @@ -1037,11 +1037,10 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, // We have an identifier; check whether it is actually a type. IdentifierInfo *CorrectedII = nullptr; - ParsedType Type = Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true, - false, ParsedType(), - /*IsCtorOrDtorName=*/false, - /*NonTrivialTypeSourceInfo=*/true, - &CorrectedII); + ParsedType Type = + Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, true, false, nullptr, + /*IsCtorOrDtorName=*/false, + /*NonTrivialTypeSourceInfo=*/true, &CorrectedII); if (!Type) { Diag(IdLoc, diag::err_expected_class_name); return true; @@ -1101,9 +1100,25 @@ bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) { // FIXME: we should emit semantic diagnostic when declaration // attribute is in type attribute position. case tok::kw___attribute: // struct foo __attribute__((used)) x; + case tok::annot_pragma_pack: // struct foo {...} _Pragma(pack(pop)); + // struct foo {...} _Pragma(section(...)); + case tok::annot_pragma_ms_pragma: + // struct foo {...} _Pragma(vtordisp(pop)); + case tok::annot_pragma_ms_vtordisp: + // struct foo {...} _Pragma(pointers_to_members(...)); + case tok::annot_pragma_ms_pointers_to_members: return true; case tok::colon: return CouldBeBitfield; // enum E { ... } : 2; + // Microsoft compatibility + case tok::kw___cdecl: // struct foo {...} __cdecl x; + case tok::kw___fastcall: // struct foo {...} __fastcall x; + case tok::kw___stdcall: // struct foo {...} __stdcall x; + case tok::kw___thiscall: // struct foo {...} __thiscall x; + case tok::kw___vectorcall: // struct foo {...} __vectorcall x; + // We will diagnose these calling-convention specifiers on non-function + // declarations later, so claim they are valid after a type specifier. + return getLangOpts().MicrosoftExt; // Type qualifiers case tok::kw_const: // struct foo {...} const x; case tok::kw_volatile: // struct foo {...} volatile x; @@ -1261,6 +1276,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, Tok.isOneOf(tok::kw___is_abstract, tok::kw___is_arithmetic, tok::kw___is_array, + tok::kw___is_assignable, tok::kw___is_base_of, tok::kw___is_class, tok::kw___is_complete_type, @@ -1352,7 +1368,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, CXXScopeSpec Spec; bool HasValidSpec = true; - if (ParseOptionalCXXScopeSpecifier(Spec, ParsedType(), EnteringContext)) { + if (ParseOptionalCXXScopeSpecifier(Spec, nullptr, EnteringContext)) { DS.SetTypeSpecError(); HasValidSpec = false; } @@ -1381,9 +1397,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // a class (or template thereof). TemplateArgList TemplateArgs; SourceLocation LAngleLoc, RAngleLoc; - if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, SS, - true, LAngleLoc, - TemplateArgs, RAngleLoc)) { + if (ParseTemplateIdAfterTemplateName( + nullptr, NameLoc, SS, true, LAngleLoc, TemplateArgs, RAngleLoc)) { // We couldn't parse the template argument list at all, so don't // try to give any location information for the list. LAngleLoc = RAngleLoc = SourceLocation(); @@ -1396,7 +1411,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Strip off the last template parameter list if it was empty, since // we've removed its template argument list. if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) { - if (TemplateParams && TemplateParams->size() > 1) { + if (TemplateParams->size() > 1) { TemplateParams->pop_back(); } else { TemplateParams = nullptr; @@ -1663,7 +1678,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // template specialization. FakedParamLists.push_back(Actions.ActOnTemplateParameterList( 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None, - LAngleLoc)); + LAngleLoc, nullptr)); TemplateParams = &FakedParamLists; } } @@ -2253,7 +2268,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ConsumeToken(); SkipUntil(tok::r_brace, StopAtSemi); - return DeclGroupPtrTy(); + return nullptr; } // Turn on colon protection early, while parsing declspec, although there is @@ -2282,28 +2297,28 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (isAccessDecl) { // Collect the scope specifier token we annotated earlier. CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), + ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false); if (SS.isInvalid()) { SkipUntil(tok::semi); - return DeclGroupPtrTy(); + return nullptr; } // Try to parse an unqualified-id. SourceLocation TemplateKWLoc; UnqualifiedId Name; - if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), - TemplateKWLoc, Name)) { + if (ParseUnqualifiedId(SS, false, true, true, nullptr, TemplateKWLoc, + Name)) { SkipUntil(tok::semi); - return DeclGroupPtrTy(); + return nullptr; } // TODO: recover from mistakenly-qualified operator declarations. if (ExpectAndConsume(tok::semi, diag::err_expected_after, "access declaration")) { SkipUntil(tok::semi); - return DeclGroupPtrTy(); + return nullptr; } return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration( @@ -2361,7 +2376,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::kw_namespace)) { Diag(UsingLoc, diag::err_using_namespace_in_class); SkipUntil(tok::semi, StopBeforeMatch); - return DeclGroupPtrTy(); + return nullptr; } SourceLocation DeclEnd; // Otherwise, it must be a using-declaration or an alias-declaration. @@ -2391,7 +2406,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate && DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_class, &CommonLateParsedAttrs)) - return DeclGroupPtrTy(); + return nullptr; MultiTemplateParamsArg TemplateParams( TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() @@ -2402,10 +2417,15 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (DS.isFriendSpecified()) ProhibitAttributes(FnAttrs); - Decl *TheDecl = - Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS, TemplateParams); + RecordDecl *AnonRecord = nullptr; + Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec( + getCurScope(), AS, DS, TemplateParams, false, AnonRecord); DS.complete(TheDecl); - return DeclGroupPtrTy::make(DeclGroupRef(TheDecl)); + if (AnonRecord) { + Decl* decls[] = {AnonRecord, TheDecl}; + return Actions.BuildDeclaratorGroup(decls, /*TypeMayContainAuto=*/false); + } + return Actions.ConvertDeclToDeclGroup(TheDecl); } ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext); @@ -2446,7 +2466,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (ParseCXXMemberDeclaratorBeforeInitializer( DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) { TryConsumeToken(tok::semi); - return DeclGroupPtrTy(); + return nullptr; } // Check for a member function definition. @@ -2495,7 +2515,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Consume the optional ';' TryConsumeToken(tok::semi); - return DeclGroupPtrTy(); + return nullptr; } if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { @@ -2698,7 +2718,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); // If we stopped at a ';', eat it. TryConsumeToken(tok::semi); - return DeclGroupPtrTy(); + return nullptr; } return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup); @@ -2825,49 +2845,49 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( if (getLangOpts().MicrosoftExt && Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) { ParseMicrosoftIfExistsClassDeclaration(TagType, AS); - return DeclGroupPtrTy(); + return nullptr; } // Check for extraneous top-level semicolon. if (Tok.is(tok::semi)) { ConsumeExtraSemi(InsideStruct, TagType); - return DeclGroupPtrTy(); + return nullptr; } if (Tok.is(tok::annot_pragma_vis)) { HandlePragmaVisibility(); - return DeclGroupPtrTy(); + return nullptr; } if (Tok.is(tok::annot_pragma_pack)) { HandlePragmaPack(); - return DeclGroupPtrTy(); + return nullptr; } if (Tok.is(tok::annot_pragma_align)) { HandlePragmaAlign(); - return DeclGroupPtrTy(); + return nullptr; } if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) { HandlePragmaMSPointersToMembers(); - return DeclGroupPtrTy(); + return nullptr; } if (Tok.is(tok::annot_pragma_ms_pragma)) { HandlePragmaMSPragma(); - return DeclGroupPtrTy(); + return nullptr; } if (Tok.is(tok::annot_pragma_ms_vtordisp)) { HandlePragmaMSVtorDisp(); - return DeclGroupPtrTy(); + return nullptr; } // If we see a namespace here, a close brace was missing somewhere. if (Tok.is(tok::kw_namespace)) { DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl)); - return DeclGroupPtrTy(); + return nullptr; } AccessSpecifier NewAS = getAccessSpecifierIfPresent(); @@ -2903,11 +2923,12 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( AccessAttrs.clear(); } - return DeclGroupPtrTy(); + return nullptr; } if (Tok.is(tok::annot_pragma_openmp)) - return ParseOpenMPDeclarativeDirective(); + return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, AccessAttrs, TagType, + TagDecl); // Parse all the comma separated declarators. return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList()); @@ -3122,8 +3143,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, } if (TagDecl) - Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, - T.getCloseLocation()); + Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); // Leave the class scope. ParsingDef.Pop(); @@ -3189,28 +3209,30 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { Actions.CodeCompleteConstructorInitializer(ConstructorDecl, MemInitializers); return cutOffParsing(); - } else { - MemInitResult MemInit = ParseMemInitializer(ConstructorDecl); - if (!MemInit.isInvalid()) - MemInitializers.push_back(MemInit.get()); - else - AnyErrors = true; } - + + MemInitResult MemInit = ParseMemInitializer(ConstructorDecl); + if (!MemInit.isInvalid()) + MemInitializers.push_back(MemInit.get()); + else + AnyErrors = true; + if (Tok.is(tok::comma)) ConsumeToken(); else if (Tok.is(tok::l_brace)) break; - // If the next token looks like a base or member initializer, assume that - // we're just missing a comma. - else if (Tok.isOneOf(tok::identifier, tok::coloncolon)) { + // If the previous initializer was valid and the next token looks like a + // base or member initializer, assume that we're just missing a comma. + else if (!MemInit.isInvalid() && + Tok.isOneOf(tok::identifier, tok::coloncolon)) { SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation); Diag(Loc, diag::err_ctor_init_missing_comma) << FixItHint::CreateInsertion(Loc, ", "); } else { // Skip over garbage, until we get to '{'. Don't eat the '{'. - Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace - << tok::comma; + if (!MemInit.isInvalid()) + Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace + << tok::comma; SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); break; } @@ -3235,7 +3257,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) { MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { // parse '::'[opt] nested-name-specifier[opt] CXXScopeSpec SS; - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); + ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false); ParsedType TemplateTypeTy; if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); @@ -3397,10 +3419,11 @@ Parser::tryParseExceptionSpecification(bool Delayed, NoexceptExpr = ParseConstantExpression(); T.consumeClose(); // The argument must be contextually convertible to bool. We use - // ActOnBooleanCondition for this purpose. + // CheckBooleanCondition for this purpose. + // FIXME: Add a proper Sema entry point for this. if (!NoexceptExpr.isInvalid()) { - NoexceptExpr = Actions.ActOnBooleanCondition(getCurScope(), KeywordLoc, - NoexceptExpr.get()); + NoexceptExpr = + Actions.CheckBooleanCondition(KeywordLoc, NoexceptExpr.get()); NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation()); } else { NoexceptType = EST_None; @@ -3630,7 +3653,10 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, case AttributeList::AT_FallThrough: case AttributeList::AT_CXX11NoReturn: return true; - + case AttributeList::AT_WarnUnusedResult: + return !ScopeName && AttrName->getName().equals("nodiscard"); + case AttributeList::AT_Unused:
+ return !ScopeName && AttrName->getName().equals("maybe_unused");
default: return false; } @@ -3689,6 +3715,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, // The attribute was allowed to have arguments, but none were provided // even though the attribute parsed successfully. This is an error. Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName; + Attr->setInvalid(true); } else if (!Attr->getMaxArgs()) { // The attribute parsed successfully, but was not allowed to have any // arguments. It doesn't matter whether any were provided -- the @@ -3696,6 +3723,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments) << AttrName << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc)); + Attr->setInvalid(true); } } } @@ -3742,6 +3770,23 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, ConsumeBracket(); ConsumeBracket(); + SourceLocation CommonScopeLoc; + IdentifierInfo *CommonScopeName = nullptr; + if (Tok.is(tok::kw_using)) { + Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z + ? diag::warn_cxx14_compat_using_attribute_ns + : diag::ext_using_attribute_ns); + ConsumeToken(); + + CommonScopeName = TryParseCXX11AttributeIdentifier(CommonScopeLoc); + if (!CommonScopeName) { + Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; + SkipUntil(tok::r_square, tok::colon, StopBeforeMatch); + } + if (!TryConsumeToken(tok::colon) && CommonScopeName) + Diag(Tok.getLocation(), diag::err_expected) << tok::colon; + } + llvm::SmallDenseMap<IdentifierInfo*, SourceLocation, 4> SeenAttrs; while (Tok.isNot(tok::r_square)) { @@ -3770,6 +3815,16 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, } } + if (CommonScopeName) { + if (ScopeName) { + Diag(ScopeLoc, diag::err_using_attribute_ns_conflict) + << SourceRange(CommonScopeLoc); + } else { + ScopeName = CommonScopeName; + ScopeLoc = CommonScopeLoc; + } + } + bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName); bool AttrParsed = false; |