diff options
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Parse/ParseDecl.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/Parse/ParseDecl.cpp | 391 |
1 files changed, 227 insertions, 164 deletions
diff --git a/gnu/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/gnu/llvm/tools/clang/lib/Parse/ParseDecl.cpp index a4610698c46..127e18439b8 100644 --- a/gnu/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/gnu/llvm/tools/clang/lib/Parse/ParseDecl.cpp @@ -43,13 +43,13 @@ using namespace clang; /// /// Called type-id in C++. TypeResult Parser::ParseTypeName(SourceRange *Range, - Declarator::TheContext Context, + DeclaratorContext Context, AccessSpecifier AS, Decl **OwnedType, ParsedAttributes *Attrs) { DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context); - if (DSC == DSC_normal) - DSC = DSC_type_specifier; + if (DSC == DeclSpecContext::DSC_normal) + DSC = DeclSpecContext::DSC_type_specifier; // Parse the common declaration-specifiers piece. DeclSpec DS(AttrFactory); @@ -912,13 +912,18 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, return; } IdentifierLoc *Platform = ParseIdentifierLoc(); - // Canonicalize platform name from "macosx" to "macos". - if (Platform->Ident && Platform->Ident->getName() == "macosx") - Platform->Ident = PP.getIdentifierInfo("macos"); - // Canonicalize platform name from "macosx_app_extension" to - // "macos_app_extension". - if (Platform->Ident && Platform->Ident->getName() == "macosx_app_extension") - Platform->Ident = PP.getIdentifierInfo("macos_app_extension"); + if (const IdentifierInfo *const Ident = Platform->Ident) { + // Canonicalize platform name from "macosx" to "macos". + if (Ident->getName() == "macosx") + Platform->Ident = PP.getIdentifierInfo("macos"); + // Canonicalize platform name from "macosx_app_extension" to + // "macos_app_extension". + else if (Ident->getName() == "macosx_app_extension") + Platform->Ident = PP.getIdentifierInfo("macos_app_extension"); + else + Platform->Ident = PP.getIdentifierInfo( + AvailabilityAttr::canonicalizePlatformName(Ident->getName())); + } // Parse the ',' following the platform name. if (ExpectAndConsume(tok::comma)) { @@ -1388,7 +1393,9 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, // If the Decl is on a function, add function parameters to the scope. bool HasFunScope = EnterScope && D->isFunctionOrFunctionTemplate(); - ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope, HasFunScope); + ParseScope FnScope( + this, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope, + HasFunScope); if (HasFunScope) Actions.ActOnReenterFunctionContext(Actions.CurScope, D); @@ -1541,21 +1548,27 @@ void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, SourceLocation Loc = Tok.getLocation(); ParseCXX11Attributes(Attrs); CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true); - + // FIXME: use err_attributes_misplaced Diag(Loc, diag::err_attributes_not_allowed) << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange) << FixItHint::CreateRemoval(AttrRange); } -void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs) { - Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed) - << attrs.Range; +void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs, + const SourceLocation CorrectLocation) { + if (CorrectLocation.isValid()) { + CharSourceRange AttrRange(attrs.Range, true); + Diag(CorrectLocation, diag::err_attributes_misplaced) + << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange) + << FixItHint::CreateRemoval(AttrRange); + } else + Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed) << attrs.Range; } void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, unsigned DiagID) { for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) { - if (!Attr->isCXX11Attribute()) + if (!Attr->isCXX11Attribute() && !Attr->isC2xAttribute()) continue; if (Attr->getKind() == AttributeList::UnknownAttribute) Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored) @@ -1626,7 +1639,7 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, /// ParseDeclaration - Parse a full 'declaration', which consists of /// declaration-specifiers, some number of declarators, and a semicolon. -/// 'Context' should be a Declarator::TheContext value. This returns the +/// 'Context' should be a DeclaratorContext value. This returns the /// location of the semicolon in DeclEnd. /// /// declaration: [C99 6.7] @@ -1640,7 +1653,7 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, /// [C++11/C11] static_assert-declaration /// others... [FIXME] /// -Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, +Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs) { ParenBraceBracketBalancer BalancerRAIIObj(*this); @@ -1701,7 +1714,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, /// of a simple-declaration. If we find that we are, we also parse the /// for-range-initializer, and place it here. Parser::DeclGroupPtrTy -Parser::ParseSimpleDeclaration(unsigned Context, +Parser::ParseSimpleDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, ParsedAttributesWithRange &Attrs, bool RequireSemi, ForRangeInit *FRI) { @@ -1740,7 +1753,7 @@ Parser::ParseSimpleDeclaration(unsigned Context, /// Returns true if this might be the start of a declarator, or a common typo /// for a declarator. -bool Parser::MightBeDeclarator(unsigned Context) { +bool Parser::MightBeDeclarator(DeclaratorContext Context) { switch (Tok.getKind()) { case tok::annot_cxxscope: case tok::annot_template_id: @@ -1759,11 +1772,12 @@ bool Parser::MightBeDeclarator(unsigned Context) { return getLangOpts().CPlusPlus; case tok::l_square: // Might be an attribute on an unnamed bit-field. - return Context == Declarator::MemberContext && getLangOpts().CPlusPlus11 && - NextToken().is(tok::l_square); + return Context == DeclaratorContext::MemberContext && + getLangOpts().CPlusPlus11 && NextToken().is(tok::l_square); case tok::colon: // Might be a typo for '::' or an unnamed bit-field. - return Context == Declarator::MemberContext || getLangOpts().CPlusPlus; + return Context == DeclaratorContext::MemberContext || + getLangOpts().CPlusPlus; case tok::identifier: switch (NextToken().getKind()) { @@ -1789,8 +1803,9 @@ bool Parser::MightBeDeclarator(unsigned Context) { // At namespace scope, 'identifier:' is probably a typo for 'identifier::' // and in block scope it's probably a label. Inside a class definition, // this is a bit-field. - return Context == Declarator::MemberContext || - (getLangOpts().CPlusPlus && Context == Declarator::FileContext); + return Context == DeclaratorContext::MemberContext || + (getLangOpts().CPlusPlus && + Context == DeclaratorContext::FileContext); case tok::identifier: // Possible virt-specifier. return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken()); @@ -1889,11 +1904,11 @@ void Parser::SkipMalformedDecl() { /// definition or a group of object declarations, actually parse the /// result. Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, - unsigned Context, + DeclaratorContext Context, SourceLocation *DeclEnd, ForRangeInit *FRI) { // Parse the first declarator. - ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context)); + ParsingDeclarator D(*this, DS, Context); ParseDeclarator(D); // Bail out if the first declarator didn't seem well-formed. @@ -1940,7 +1955,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // Function definitions are only allowed at file scope and in C++ classes. // The C++ inline method definition case is handled elsewhere, so we only // need to handle the file scope definition case. - if (Context == Declarator::FileContext) { + if (Context == DeclaratorContext::FileContext) { if (isStartOfFunctionDefinition(D)) { if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { Diag(Tok, diag::err_function_declared_typedef); @@ -2011,7 +2026,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, if (FirstDecl) DeclsInGroup.push_back(FirstDecl); - bool ExpectSemi = Context != Declarator::ForContext; + bool ExpectSemi = Context != DeclaratorContext::ForContext; // If we don't have a comma, it is either the end of the list (a ';') or an // error, bail out. @@ -2057,7 +2072,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, *DeclEnd = Tok.getLocation(); if (ExpectSemi && - ExpectAndConsumeSemi(Context == Declarator::FileContext + ExpectAndConsumeSemi(Context == DeclaratorContext::FileContext ? diag::err_invalid_token_after_toplevel_declarator : diag::err_expected_semi_declaration)) { // Okay, there was no semicolon and one was expected. If we see a @@ -2124,6 +2139,37 @@ Decl *Parser::ParseDeclarationAfterDeclarator( Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) { + // RAII type used to track whether we're inside an initializer. + struct InitializerScopeRAII { + Parser &P; + Declarator &D; + Decl *ThisDecl; + + InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl) + : P(P), D(D), ThisDecl(ThisDecl) { + if (ThisDecl && P.getLangOpts().CPlusPlus) { + Scope *S = nullptr; + if (D.getCXXScopeSpec().isSet()) { + P.EnterScope(0); + S = P.getCurScope(); + } + P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl); + } + } + ~InitializerScopeRAII() { pop(); } + void pop() { + if (ThisDecl && P.getLangOpts().CPlusPlus) { + Scope *S = nullptr; + if (D.getCXXScopeSpec().isSet()) + S = P.getCurScope(); + P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl); + if (S) + P.ExitScope(); + } + ThisDecl = nullptr; + } + }; + // Inform the current actions module that we just parsed this declarator. Decl *ThisDecl = nullptr; switch (TemplateInfo.Kind) { @@ -2155,7 +2201,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( // FIXME: This check should be for a variable template instantiation only. // Check that this is a valid instantiation - if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { + if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) { // If the declarator-id is not a template-id, issue a diagnostic and // recover by ignoring the 'template' keyword. Diag(Tok, diag::err_template_defn_explicit_instantiation) @@ -2201,10 +2247,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( else Diag(ConsumeToken(), diag::err_default_special_members); } else { - if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) { - EnterScope(0); - Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl); - } + InitializerScopeRAII InitScope(*this, D, ThisDecl); if (Tok.is(tok::code_completion)) { Actions.CodeCompleteInitializer(getCurScope(), ThisDecl); @@ -2227,16 +2270,13 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( FRI->RangeExpr = Init; } - if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) { - Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl); - ExitScope(); - } + InitScope.pop(); if (Init.isInvalid()) { SmallVector<tok::TokenKind, 2> StopTokens; StopTokens.push_back(tok::comma); - if (D.getContext() == Declarator::ForContext || - D.getContext() == Declarator::InitStmtContext) + if (D.getContext() == DeclaratorContext::ForContext || + D.getContext() == DeclaratorContext::InitStmtContext) StopTokens.push_back(tok::r_paren); SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch); Actions.ActOnInitializerError(ThisDecl); @@ -2252,23 +2292,27 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( ExprVector Exprs; CommaLocsTy CommaLocs; - if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) { - EnterScope(0); - Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl); + InitializerScopeRAII InitScope(*this, D, ThisDecl); + + llvm::function_ref<void()> ExprListCompleter; + auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl); + auto ConstructorCompleter = [&, ThisVarDecl] { + Actions.CodeCompleteConstructor( + getCurScope(), ThisVarDecl->getType()->getCanonicalTypeInternal(), + ThisDecl->getLocation(), Exprs); + }; + if (ThisVarDecl) { + // ParseExpressionList can sometimes succeed even when ThisDecl is not + // VarDecl. This is an error and it is reported in a call to + // Actions.ActOnInitializerError(). However, we call + // CodeCompleteConstructor only on VarDecls, falling back to default + // completer in other cases. + ExprListCompleter = ConstructorCompleter; } - if (ParseExpressionList(Exprs, CommaLocs, [&] { - Actions.CodeCompleteConstructor(getCurScope(), - cast<VarDecl>(ThisDecl)->getType()->getCanonicalTypeInternal(), - ThisDecl->getLocation(), Exprs); - })) { + if (ParseExpressionList(Exprs, CommaLocs, ExprListCompleter)) { Actions.ActOnInitializerError(ThisDecl); SkipUntil(tok::r_paren, StopAtSemi); - - if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) { - Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl); - ExitScope(); - } } else { // Match the ')'. T.consumeClose(); @@ -2276,10 +2320,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( assert(!Exprs.empty() && Exprs.size()-1 == CommaLocs.size() && "Unexpected number of commas!"); - if (getLangOpts().CPlusPlus && D.getCXXScopeSpec().isSet()) { - Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl); - ExitScope(); - } + InitScope.pop(); ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(), T.getCloseLocation(), @@ -2292,17 +2333,11 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( // Parse C++0x braced-init-list. Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); - if (D.getCXXScopeSpec().isSet()) { - EnterScope(0); - Actions.ActOnCXXEnterDeclInitializer(getCurScope(), ThisDecl); - } + InitializerScopeRAII InitScope(*this, D, ThisDecl); ExprResult Init(ParseBraceInitializer()); - if (D.getCXXScopeSpec().isSet()) { - Actions.ActOnCXXExitDeclInitializer(getCurScope(), ThisDecl); - ExitScope(); - } + InitScope.pop(); if (Init.isInvalid()) { Actions.ActOnInitializerError(ThisDecl); @@ -2364,7 +2399,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS, } // Issue diagnostic and remove constexpr specfier if present. - if (DS.isConstexprSpecified() && DSC != DSC_condition) { + if (DS.isConstexprSpecified() && DSC != DeclSpecContext::DSC_condition) { Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr); DS.ClearConstexprSpec(); } @@ -2453,7 +2488,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // classes. if (ParsedType T = Actions.ActOnMSVCUnknownTypeName( *Tok.getIdentifierInfo(), Tok.getLocation(), - DSC == DSC_template_type_arg)) { + DSC == DeclSpecContext::DSC_template_type_arg)) { const char *PrevSpec; unsigned DiagID; DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T, @@ -2507,18 +2542,20 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // Parse this as a tag as if the missing tag were present. if (TagKind == tok::kw_enum) - ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSC_normal); + ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, + DeclSpecContext::DSC_normal); else ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS, - /*EnteringContext*/ false, DSC_normal, Attrs); + /*EnteringContext*/ false, + DeclSpecContext::DSC_normal, Attrs); return true; } } // Determine whether this identifier could plausibly be the name of something // being declared (with a missing type). - if (!isTypeSpecifier(DSC) && - (!SS || DSC == DSC_top_level || DSC == DSC_class)) { + if (!isTypeSpecifier(DSC) && (!SS || DSC == DeclSpecContext::DSC_top_level || + DSC == DeclSpecContext::DSC_class)) { // Look ahead to the next token to try to figure out what this declaration // was supposed to be. switch (NextToken().getKind()) { @@ -2542,7 +2579,8 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // If we're in a context where we could be declaring a constructor, // check whether this is a constructor declaration with a bogus name. - if (DSC == DSC_class || (DSC == DSC_top_level && SS)) { + if (DSC == DeclSpecContext::DSC_class || + (DSC == DeclSpecContext::DSC_top_level && SS)) { IdentifierInfo *II = Tok.getIdentifierInfo(); if (Actions.isCurrentClassNameTypo(II, SS)) { Diag(Loc, diag::err_constructor_bad_name) @@ -2622,23 +2660,23 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, /// context. /// /// \param Context the declarator context, which is one of the -/// Declarator::TheContext enumerator values. +/// DeclaratorContext enumerator values. Parser::DeclSpecContext -Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) { - if (Context == Declarator::MemberContext) - return DSC_class; - if (Context == Declarator::FileContext) - return DSC_top_level; - if (Context == Declarator::TemplateParamContext) - return DSC_template_param; - if (Context == Declarator::TemplateTypeArgContext) - return DSC_template_type_arg; - if (Context == Declarator::TrailingReturnContext) - return DSC_trailing; - if (Context == Declarator::AliasDeclContext || - Context == Declarator::AliasTemplateContext) - return DSC_alias_declaration; - return DSC_normal; +Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) { + if (Context == DeclaratorContext::MemberContext) + return DeclSpecContext::DSC_class; + if (Context == DeclaratorContext::FileContext) + return DeclSpecContext::DSC_top_level; + if (Context == DeclaratorContext::TemplateParamContext) + return DeclSpecContext::DSC_template_param; + if (Context == DeclaratorContext::TemplateTypeArgContext) + return DeclSpecContext::DSC_template_type_arg; + if (Context == DeclaratorContext::TrailingReturnContext) + return DeclSpecContext::DSC_trailing; + if (Context == DeclaratorContext::AliasDeclContext || + Context == DeclaratorContext::AliasTemplateContext) + return DeclSpecContext::DSC_alias_declaration; + return DeclSpecContext::DSC_normal; } /// ParseAlignArgument - Parse the argument to an alignment-specifier. @@ -2718,7 +2756,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, LateParsedAttrList *LateAttrs) { assert(DS.hasTagDefinition() && "shouldn't call this"); - bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level); + bool EnteringContext = (DSContext == DeclSpecContext::DSC_class || + DSContext == DeclSpecContext::DSC_top_level); if (getLangOpts().CPlusPlus && Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype, @@ -2852,7 +2891,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DS.SetRangeEnd(SourceLocation()); } - bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level); + bool EnteringContext = (DSContext == DeclSpecContext::DSC_class || + DSContext == DeclSpecContext::DSC_top_level); bool AttrsLastTime = false; ParsedAttributesWithRange attrs(AttrFactory); // We use Sema's policy to get bool macros right. @@ -2898,7 +2938,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::l_square: case tok::kw_alignas: - if (!getLangOpts().CPlusPlus11 || !isCXX11AttributeSpecifier()) + if (!standardAttributesAllowed() || !isCXX11AttributeSpecifier()) goto DoneWithDeclSpec; ProhibitAttributes(attrs); @@ -2922,8 +2962,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, Scope::FunctionPrototypeScope | Scope::AtCatchScope)) == 0; bool AllowNestedNameSpecifiers - = DSContext == DSC_top_level || - (DSContext == DSC_class && DS.isFriendSpecified()); + = DSContext == DeclSpecContext::DSC_top_level || + (DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified()); Actions.CodeCompleteDeclSpec(getCurScope(), DS, AllowNonIdentifiers, @@ -2934,9 +2974,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, 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) + CCC = DSContext == DeclSpecContext::DSC_class ? Sema::PCC_MemberTemplate + : Sema::PCC_Template; + else if (DSContext == DeclSpecContext::DSC_class) CCC = Sema::PCC_Class; else if (CurParsedObjCImpl) CCC = Sema::PCC_ObjCImplementation; @@ -2980,10 +3020,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // To improve diagnostics for this case, parse the declaration as a // constructor (and reject the extra template arguments later). TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next); - if ((DSContext == DSC_top_level || DSContext == DSC_class) && + if ((DSContext == DeclSpecContext::DSC_top_level || + DSContext == DeclSpecContext::DSC_class) && TemplateId->Name && Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) && - isConstructorDeclarator(/*Unqualified*/false)) { + isConstructorDeclarator(/*Unqualified*/ false)) { // The user meant this to be an out-of-line constructor // definition, but template arguments are not allowed // there. Just allow this as a constructor; we'll @@ -3022,7 +3063,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Check whether this is a constructor declaration. If we're in a // context where the identifier could be a class name, and it has the // shape of a constructor declaration, process it as one. - if ((DSContext == DSC_top_level || DSContext == DSC_class) && + if ((DSContext == DeclSpecContext::DSC_top_level || + DSContext == DeclSpecContext::DSC_class) && Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(), &SS) && isConstructorDeclarator(/*Unqualified*/ false)) @@ -3160,7 +3202,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (DS.isTypeAltiVecVector()) goto DoneWithDeclSpec; - if (DSContext == DSC_objc_method_result && isObjCInstancetype()) { + if (DSContext == DeclSpecContext::DSC_objc_method_result && + isObjCInstancetype()) { ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc); assert(TypeRep); isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, @@ -3194,15 +3237,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // If we're in a context where the identifier could be a class name, // check whether this is a constructor declaration. - if (getLangOpts().CPlusPlus && DSContext == DSC_class && + if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class && Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) && isConstructorDeclarator(/*Unqualified*/true)) goto DoneWithDeclSpec; // Likewise, if this is a context where the identifier could be a template // name, check whether this is a deduction guide declaration. - if (getLangOpts().CPlusPlus1z && - (DSContext == DSC_class || DSContext == DSC_top_level) && + if (getLangOpts().CPlusPlus17 && + (DSContext == DeclSpecContext::DSC_class || + DSContext == DeclSpecContext::DSC_top_level) && Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(), Tok.getLocation()) && isConstructorDeclarator(/*Unqualified*/ true, @@ -3248,7 +3292,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // If we're in a context where the template-id could be a // constructor name or specialization, check whether this is a // constructor declaration. - if (getLangOpts().CPlusPlus && DSContext == DSC_class && + if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class && Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) && isConstructorDeclarator(TemplateId->SS.isEmpty())) goto DoneWithDeclSpec; @@ -3418,7 +3462,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // friend case tok::kw_friend: - if (DSContext == DSC_class) + if (DSContext == DeclSpecContext::DSC_class) isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); else { PrevSpec = ""; // not actually used by the diagnostic @@ -3437,11 +3481,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID); break; - // concept - case tok::kw_concept: - isInvalid = DS.SetConceptSpec(Loc, PrevSpec, DiagID); - break; - // type-specifier case tok::kw_short: isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, @@ -3503,6 +3542,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw__Float16: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec, + DiagID, Policy); + break; case tok::kw___float128: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy); @@ -3747,7 +3790,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, /// semicolon. /// /// struct-declaration: -/// specifier-qualifier-list struct-declarator-list +/// [C2x] attributes-specifier-seq[opt] +/// specifier-qualifier-list struct-declarator-list /// [GNU] __extension__ struct-declaration /// [GNU] specifier-qualifier-list /// struct-declarator-list: @@ -3771,6 +3815,11 @@ void Parser::ParseStructDeclaration( return ParseStructDeclaration(DS, FieldsCallback); } + // Parse leading attributes. + ParsedAttributesWithRange Attrs(AttrFactory); + MaybeParseCXX11Attributes(Attrs); + DS.takeAttributesFrom(Attrs); + // Parse the common specifier-qualifiers-list piece. ParseSpecifierQualifierList(DS); @@ -4032,7 +4081,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag); // Enum definitions should not be parsed in a trailing-return-type. - bool AllowDeclaration = DSC != DSC_trailing; + bool AllowDeclaration = DSC != DeclSpecContext::DSC_trailing; bool AllowFixedUnderlyingType = AllowDeclaration && (getLangOpts().CPlusPlus11 || getLangOpts().MicrosoftExt || @@ -4258,14 +4307,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, bool IsDependent = false; const char *PrevSpec = nullptr; unsigned DiagID; - Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, - StartLoc, SS, Name, NameLoc, attrs.getList(), - AS, DS.getModulePrivateSpecLoc(), TParams, - Owned, IsDependent, ScopedEnumKWLoc, - IsScopedUsingClassTag, BaseType, - DSC == DSC_type_specifier, - DSC == DSC_template_param || - DSC == DSC_template_type_arg, &SkipBody); + Decl *TagDecl = Actions.ActOnTag( + getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc, + attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned, + IsDependent, ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType, + DSC == DeclSpecContext::DSC_type_specifier, + DSC == DeclSpecContext::DSC_template_param || + DSC == DeclSpecContext::DSC_template_type_arg, + &SkipBody); if (SkipBody.ShouldSkip) { assert(TUK == Sema::TUK_Definition && "can only skip a definition"); @@ -4381,9 +4430,11 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseGNUAttributes(attrs); ProhibitAttributes(attrs); // GNU-style attributes are prohibited. - if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) { - if (!getLangOpts().CPlusPlus1z) - Diag(Tok.getLocation(), diag::warn_cxx14_compat_attribute) + if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) { + if (getLangOpts().CPlusPlus) + Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 + ? diag::warn_cxx14_compat_ns_enum_attribute + : diag::ext_ns_enum_attribute) << 1 /*enumerator*/; ParseCXX11Attributes(attrs); } @@ -4506,6 +4557,7 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: @@ -4581,6 +4633,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: @@ -4737,6 +4790,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: case tok::kw__Bool: @@ -4783,9 +4837,6 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::annot_decltype: case tok::kw_constexpr: - // C++ Concepts TS - concept - case tok::kw_concept: - // C11 _Atomic case tok::kw__Atomic: return true; @@ -4990,7 +5041,7 @@ void Parser::ParseTypeQualifierListOpt( DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed, bool IdentifierRequired, Optional<llvm::function_ref<void()>> CodeCompletionHandler) { - if (getLangOpts().CPlusPlus11 && (AttrReqs & AR_CXX11AttributesParsed) && + if (standardAttributesAllowed() && (AttrReqs & AR_CXX11AttributesParsed) && isCXX11AttributeSpecifier()) { ParsedAttributesWithRange attrs(AttrFactory); ParseCXX11Attributes(attrs); @@ -5135,7 +5186,7 @@ void Parser::ParseDeclarator(Declarator &D) { } static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, - unsigned TheContext) { + DeclaratorContext TheContext) { if (Kind == tok::star || Kind == tok::caret) return true; @@ -5154,8 +5205,9 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, // (The same thing can in theory happen after a trailing-return-type, but // since those are a C++11 feature, there is no rejects-valid issue there.) if (Kind == tok::ampamp) - return Lang.CPlusPlus11 || (TheContext != Declarator::ConversionIdContext && - TheContext != Declarator::CXXNewContext); + return Lang.CPlusPlus11 || + (TheContext != DeclaratorContext::ConversionIdContext && + TheContext != DeclaratorContext::CXXNewContext); return false; } @@ -5209,8 +5261,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, (Tok.is(tok::identifier) && (NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) || Tok.is(tok::annot_cxxscope))) { - bool EnteringContext = D.getContext() == Declarator::FileContext || - D.getContext() == Declarator::MemberContext; + bool EnteringContext = + D.getContext() == DeclaratorContext::FileContext || + D.getContext() == DeclaratorContext::MemberContext; CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, nullptr, EnteringContext); @@ -5276,9 +5329,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // GNU attributes are not allowed here in a new-type-id, but Declspec and // C++11 attributes are allowed. unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed | - ((D.getContext() != Declarator::CXXNewContext) - ? AR_GNUAttributesParsed - : AR_GNUAttributesParsedAndRejected); + ((D.getContext() != DeclaratorContext::CXXNewContext) + ? AR_GNUAttributesParsed + : AR_GNUAttributesParsedAndRejected); ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier()); D.ExtendWithDeclSpec(DS); @@ -5430,15 +5483,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in // this context it is a bitfield. Also in range-based for statement colon // may delimit for-range-declaration. - ColonProtectionRAIIObject X(*this, - D.getContext() == Declarator::MemberContext || - (D.getContext() == Declarator::ForContext && - getLangOpts().CPlusPlus11)); + ColonProtectionRAIIObject X( + *this, D.getContext() == DeclaratorContext::MemberContext || + (D.getContext() == DeclaratorContext::ForContext && + getLangOpts().CPlusPlus11)); // ParseDeclaratorInternal might already have parsed the scope. if (D.getCXXScopeSpec().isEmpty()) { - bool EnteringContext = D.getContext() == Declarator::FileContext || - D.getContext() == Declarator::MemberContext; + bool EnteringContext = + D.getContext() == DeclaratorContext::FileContext || + D.getContext() == DeclaratorContext::MemberContext; ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), nullptr, EnteringContext); } @@ -5467,9 +5521,9 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // been expanded or contains auto; otherwise, it is parsed as part of the // parameter-declaration-clause. if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() && - !((D.getContext() == Declarator::PrototypeContext || - D.getContext() == Declarator::LambdaExprParameterContext || - D.getContext() == Declarator::BlockLiteralContext) && + !((D.getContext() == DeclaratorContext::PrototypeContext || + D.getContext() == DeclaratorContext::LambdaExprParameterContext || + D.getContext() == DeclaratorContext::BlockLiteralContext) && NextToken().is(tok::r_paren) && !D.hasGroupingParens() && !Actions.containsUnexpandedParameterPacks(D) && @@ -5501,14 +5555,15 @@ void Parser::ParseDirectDeclarator(Declarator &D) { AllowDeductionGuide = false; } else if (D.getCXXScopeSpec().isSet()) { AllowConstructorName = - (D.getContext() == Declarator::FileContext || - D.getContext() == Declarator::MemberContext); + (D.getContext() == DeclaratorContext::FileContext || + D.getContext() == DeclaratorContext::MemberContext); AllowDeductionGuide = false; } else { - AllowConstructorName = (D.getContext() == Declarator::MemberContext); + AllowConstructorName = + (D.getContext() == DeclaratorContext::MemberContext); AllowDeductionGuide = - (D.getContext() == Declarator::FileContext || - D.getContext() == Declarator::MemberContext); + (D.getContext() == DeclaratorContext::FileContext || + D.getContext() == DeclaratorContext::MemberContext); } SourceLocation TemplateKWLoc; @@ -5564,15 +5619,15 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // An identifier within parens is unlikely to be intended to be anything // other than a name being "declared". DiagnoseIdentifier = true; - else if (D.getContext() == Declarator::TemplateTypeArgContext) + else if (D.getContext() == DeclaratorContext::TemplateTypeArgContext) // T<int N> is an accidental identifier; T<int N indicates a missing '>'. DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater); - else if (D.getContext() == Declarator::AliasDeclContext || - D.getContext() == Declarator::AliasTemplateContext) + else if (D.getContext() == DeclaratorContext::AliasDeclContext || + D.getContext() == DeclaratorContext::AliasTemplateContext) // The most likely error is that the ';' was forgotten. DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi); - else if (D.getContext() == Declarator::TrailingReturnContext && + else if (D.getContext() == DeclaratorContext::TrailingReturnContext && !isCXX11VirtSpecifier(Tok)) DiagnoseIdentifier = NextToken().isOneOf( tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try); @@ -5619,7 +5674,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { LLVM_BUILTIN_TRAP; if (Tok.is(tok::l_square)) return ParseMisplacedBracketDeclarator(D); - if (D.getContext() == Declarator::MemberContext) { + if (D.getContext() == DeclaratorContext::MemberContext) { // Objective-C++: Detect C++ keywords and try to prevent further errors by // treating these keyword as valid member names. if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus && @@ -5927,7 +5982,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, SmallVector<SourceRange, 2> DynamicExceptionRanges; ExprResult NoexceptExpr; CachedTokens *ExceptionSpecTokens = nullptr; - ParsedAttributes FnAttrs(AttrFactory); + ParsedAttributesWithRange FnAttrs(AttrFactory); TypeResult TrailingReturnType; /* LocalEndLoc is the end location for the local FunctionTypeLoc. @@ -5948,6 +6003,11 @@ void Parser::ParseFunctionDeclarator(Declarator &D, RParenLoc = Tracker.getCloseLocation(); LocalEndLoc = RParenLoc; EndLoc = RParenLoc; + + // If there are attributes following the identifier list, parse them and + // prohibit them. + MaybeParseCXX11Attributes(FnAttrs); + ProhibitAttributes(FnAttrs); } else { if (Tok.isNot(tok::r_paren)) ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, @@ -5955,7 +6015,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D, else if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); - HasProto = ParamInfo.size() || getLangOpts().CPlusPlus; + HasProto = ParamInfo.size() || getLangOpts().CPlusPlus + || getLangOpts().OpenCL; // If we have the closing ')', eat it. Tracker.consumeClose(); @@ -5996,9 +6057,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D, bool IsCXX11MemberFunction = getLangOpts().CPlusPlus11 && D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && - (D.getContext() == Declarator::MemberContext + (D.getContext() == DeclaratorContext::MemberContext ? !D.getDeclSpec().isFriendSpecified() - : D.getContext() == Declarator::FileContext && + : D.getContext() == DeclaratorContext::FileContext && D.getCXXScopeSpec().isValid() && Actions.CurContext->isRecord()); Sema::CXXThisScopeRAII ThisScope(Actions, @@ -6053,6 +6114,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D, TrailingReturnType = ParseTrailingReturnType(Range); EndLoc = Range.getEnd(); } + } else if (standardAttributesAllowed()) { + MaybeParseCXX11Attributes(FnAttrs); } } @@ -6261,10 +6324,10 @@ void Parser::ParseParameterDeclarationClause( // Parse the declarator. This is "PrototypeContext" or // "LambdaExprParameterContext", because we must accept either // 'declarator' or 'abstract-declarator' here. - Declarator ParmDeclarator(DS, - D.getContext() == Declarator::LambdaExprContext ? - Declarator::LambdaExprParameterContext : - Declarator::PrototypeContext); + Declarator ParmDeclarator( + DS, D.getContext() == DeclaratorContext::LambdaExprContext + ? DeclaratorContext::LambdaExprParameterContext + : DeclaratorContext::PrototypeContext); ParseDeclarator(ParmDeclarator); // Parse GNU attributes, if present. @@ -6307,7 +6370,7 @@ void Parser::ParseParameterDeclarationClause( SourceLocation EqualLoc = Tok.getLocation(); // Parse the default argument - if (D.getContext() == Declarator::MemberContext) { + if (D.getContext() == DeclaratorContext::MemberContext) { // If we're inside a class definition, cache the tokens // corresponding to the default argument. We'll actually parse // them when we see the end of the class definition. |
