diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2022-07-04 19:20:19 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-08 19:02:26 +0000 |
commit | 81ad626541db97eb356e2c1d4a20eb2a26a766ab (patch) | |
tree | 311b6a8987c32b1e1dcbab65c54cfac3fdb56175 /contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp | |
parent | 5fff09660e06a66bed6482da9c70df328e16bbb6 (diff) | |
parent | 145449b1e420787bb99721a429341fa6be3adfb6 (diff) |
Diffstat (limited to 'contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp | 508 |
1 files changed, 314 insertions, 194 deletions
diff --git a/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp index f21938c81689..2f21b7b2fef0 100644 --- a/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp @@ -10,16 +10,17 @@ // //===----------------------------------------------------------------------===// -#include "clang/Parse/Parser.h" -#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/AttributeCommonInfo.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/TargetInfo.h" #include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Parser.h" +#include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" @@ -40,10 +41,8 @@ using namespace clang; /// specifier-qualifier-list abstract-declarator[opt] /// /// Called type-id in C++. -TypeResult Parser::ParseTypeName(SourceRange *Range, - DeclaratorContext Context, - AccessSpecifier AS, - Decl **OwnedType, +TypeResult Parser::ParseTypeName(SourceRange *Range, DeclaratorContext Context, + AccessSpecifier AS, Decl **OwnedType, ParsedAttributes *Attrs) { DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context); if (DSC == DeclSpecContext::DSC_normal) @@ -58,7 +57,7 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr; // Parse the abstract-declarator, if present. - Declarator DeclaratorInfo(DS, Context); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context); ParseDeclarator(DeclaratorInfo); if (Range) *Range = DeclaratorInfo.getSourceRange(); @@ -103,9 +102,7 @@ static bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc, return AttrStartIsInMacro && AttrEndIsInMacro; } -void Parser::ParseAttributes(unsigned WhichAttrKinds, - ParsedAttributesWithRange &Attrs, - SourceLocation *End, +void Parser::ParseAttributes(unsigned WhichAttrKinds, ParsedAttributes &Attrs, LateParsedAttrList *LateAttrs) { bool MoreToParse; do { @@ -113,11 +110,11 @@ void Parser::ParseAttributes(unsigned WhichAttrKinds, // parsed, loop to ensure all specified attribute combinations are parsed. MoreToParse = false; if (WhichAttrKinds & PAKM_CXX11) - MoreToParse |= MaybeParseCXX11Attributes(Attrs, End); + MoreToParse |= MaybeParseCXX11Attributes(Attrs); if (WhichAttrKinds & PAKM_GNU) - MoreToParse |= MaybeParseGNUAttributes(Attrs, End, LateAttrs); + MoreToParse |= MaybeParseGNUAttributes(Attrs, LateAttrs); if (WhichAttrKinds & PAKM_Declspec) - MoreToParse |= MaybeParseMicrosoftDeclSpecs(Attrs, End); + MoreToParse |= MaybeParseMicrosoftDeclSpecs(Attrs); } while (MoreToParse); } @@ -162,15 +159,12 @@ void Parser::ParseAttributes(unsigned WhichAttrKinds, /// ',' or ')' are ignored, otherwise they produce a parse error. /// /// We follow the C++ model, but don't allow junk after the identifier. -void Parser::ParseGNUAttributes(ParsedAttributesWithRange &Attrs, - SourceLocation *EndLoc, +void Parser::ParseGNUAttributes(ParsedAttributes &Attrs, LateParsedAttrList *LateAttrs, Declarator *D) { assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!"); - SourceLocation StartLoc = Tok.getLocation(), Loc; - - if (!EndLoc) - EndLoc = &Loc; + SourceLocation StartLoc = Tok.getLocation(); + SourceLocation EndLoc = StartLoc; while (Tok.is(tok::kw___attribute)) { SourceLocation AttrTokLoc = ConsumeToken(); @@ -214,7 +208,7 @@ void Parser::ParseGNUAttributes(ParsedAttributesWithRange &Attrs, // Handle "parameterized" attributes if (!LateAttrs || !isAttributeLateParsed(*AttrName)) { - ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, nullptr, + ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, &EndLoc, nullptr, SourceLocation(), ParsedAttr::AS_GNU, D); continue; } @@ -247,8 +241,7 @@ void Parser::ParseGNUAttributes(ParsedAttributesWithRange &Attrs, SourceLocation Loc = Tok.getLocation(); if (ExpectAndConsume(tok::r_paren)) SkipUntil(tok::r_paren, StopAtSemi); - if (EndLoc) - *EndLoc = Loc; + EndLoc = Loc; // If this was declared in a macro, attach the macro IdentifierInfo to the // parsed attribute. @@ -270,7 +263,7 @@ void Parser::ParseGNUAttributes(ParsedAttributesWithRange &Attrs, } } - Attrs.Range = SourceRange(StartLoc, *EndLoc); + Attrs.Range = SourceRange(StartLoc, EndLoc); } /// Determine whether the given attribute has an identifier argument. @@ -300,6 +293,15 @@ static bool attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo &II) { #undef CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST } +/// Determine if an attribute accepts parameter packs. +static bool attributeAcceptsExprPack(const IdentifierInfo &II) { +#define CLANG_ATTR_ACCEPTS_EXPR_PACK + return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) +#include "clang/Parse/AttrParserStringSwitches.inc" + .Default(false); +#undef CLANG_ATTR_ACCEPTS_EXPR_PACK +} + /// Determine whether the given attribute parses a type argument. static bool attributeIsTypeArgAttr(const IdentifierInfo &II) { #define CLANG_ATTR_TYPE_ARG_LIST @@ -331,7 +333,6 @@ IdentifierLoc *Parser::ParseIdentifierLoc() { void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, - SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) { @@ -366,6 +367,8 @@ unsigned Parser::ParseAttributeArgsCommon( bool ChangeKWThisToIdent = attributeTreatsKeywordThisAsIdentifier(*AttrName); bool AttributeIsTypeArgAttr = attributeIsTypeArgAttr(*AttrName); + bool AttributeHasVariadicIdentifierArg = + attributeHasVariadicIdentifierArg(*AttrName); // Interpret "kw_this" as an identifier if the attributed requests it. if (ChangeKWThisToIdent && Tok.is(tok::kw_this)) @@ -374,8 +377,8 @@ unsigned Parser::ParseAttributeArgsCommon( ArgsVector ArgExprs; if (Tok.is(tok::identifier)) { // If this attribute wants an 'identifier' argument, make it so. - bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName) || - attributeHasVariadicIdentifierArg(*AttrName); + bool IsIdentifierArg = AttributeHasVariadicIdentifierArg || + attributeHasIdentifierArg(*AttrName); ParsedAttr::Kind AttrKind = ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax); @@ -397,42 +400,81 @@ unsigned Parser::ParseAttributeArgsCommon( if (!ArgExprs.empty()) ConsumeToken(); - // Parse the non-empty comma-separated list of expressions. - do { - // Interpret "kw_this" as an identifier if the attributed requests it. - if (ChangeKWThisToIdent && Tok.is(tok::kw_this)) - Tok.setKind(tok::identifier); + if (AttributeIsTypeArgAttr) { + // FIXME: Multiple type arguments are not implemented. + TypeResult T = ParseTypeName(); + if (T.isInvalid()) { + SkipUntil(tok::r_paren, StopAtSemi); + return 0; + } + if (T.isUsable()) + TheParsedType = T.get(); + } else if (AttributeHasVariadicIdentifierArg) { + // Parse variadic identifier arg. This can either consume identifiers or + // expressions. Variadic identifier args do not support parameter packs + // because those are typically used for attributes with enumeration + // arguments, and those enumerations are not something the user could + // express via a pack. + do { + // Interpret "kw_this" as an identifier if the attributed requests it. + if (ChangeKWThisToIdent && Tok.is(tok::kw_this)) + Tok.setKind(tok::identifier); + + ExprResult ArgExpr; + if (Tok.is(tok::identifier)) { + ArgExprs.push_back(ParseIdentifierLoc()); + } else { + bool Uneval = attributeParsedArgsUnevaluated(*AttrName); + EnterExpressionEvaluationContext Unevaluated( + Actions, + Uneval ? Sema::ExpressionEvaluationContext::Unevaluated + : Sema::ExpressionEvaluationContext::ConstantEvaluated); - ExprResult ArgExpr; - if (AttributeIsTypeArgAttr) { - TypeResult T = ParseTypeName(); - if (T.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return 0; + ExprResult ArgExpr( + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); + + if (ArgExpr.isInvalid()) { + SkipUntil(tok::r_paren, StopAtSemi); + return 0; + } + ArgExprs.push_back(ArgExpr.get()); } - if (T.isUsable()) - TheParsedType = T.get(); - break; // FIXME: Multiple type arguments are not implemented. - } else if (Tok.is(tok::identifier) && - attributeHasVariadicIdentifierArg(*AttrName)) { - ArgExprs.push_back(ParseIdentifierLoc()); - } else { - bool Uneval = attributeParsedArgsUnevaluated(*AttrName); - EnterExpressionEvaluationContext Unevaluated( - Actions, - Uneval ? Sema::ExpressionEvaluationContext::Unevaluated - : Sema::ExpressionEvaluationContext::ConstantEvaluated); - - ExprResult ArgExpr( - Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); - if (ArgExpr.isInvalid()) { + // Eat the comma, move to the next argument + } while (TryConsumeToken(tok::comma)); + } else { + // General case. Parse all available expressions. + bool Uneval = attributeParsedArgsUnevaluated(*AttrName); + EnterExpressionEvaluationContext Unevaluated( + Actions, Uneval + ? Sema::ExpressionEvaluationContext::Unevaluated + : Sema::ExpressionEvaluationContext::ConstantEvaluated); + + CommaLocsTy CommaLocs; + ExprVector ParsedExprs; + if (ParseExpressionList(ParsedExprs, CommaLocs, + llvm::function_ref<void()>(), + /*FailImmediatelyOnInvalidExpr=*/true, + /*EarlyTypoCorrection=*/true)) { + SkipUntil(tok::r_paren, StopAtSemi); + return 0; + } + + // Pack expansion must currently be explicitly supported by an attribute. + for (size_t I = 0; I < ParsedExprs.size(); ++I) { + if (!isa<PackExpansionExpr>(ParsedExprs[I])) + continue; + + if (!attributeAcceptsExprPack(*AttrName)) { + Diag(Tok.getLocation(), + diag::err_attribute_argument_parm_pack_not_supported) + << AttrName; SkipUntil(tok::r_paren, StopAtSemi); return 0; } - ArgExprs.push_back(ArgExpr.get()); } - // Eat the comma, move to the next argument - } while (TryConsumeToken(tok::comma)); + + ArgExprs.insert(ArgExprs.end(), ParsedExprs.begin(), ParsedExprs.end()); + } } SourceLocation RParen = Tok.getLocation(); @@ -456,14 +498,10 @@ unsigned Parser::ParseAttributeArgsCommon( /// Parse the arguments to a parameterized GNU attribute or /// a C++11 attribute in "gnu" namespace. -void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, - SourceLocation *EndLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax, - Declarator *D) { +void Parser::ParseGNUAttributeArgs( + IdentifierInfo *AttrName, SourceLocation AttrNameLoc, + ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax, Declarator *D) { assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); @@ -491,7 +529,7 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, ScopeName, ScopeLoc, Syntax); return; } else if (attributeIsTypeArgAttr(*AttrName)) { - ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, + ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc, Syntax); return; } @@ -555,9 +593,11 @@ unsigned Parser::ParseClangAttributeArgs( bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs) { + unsigned ExistingAttrs = Attrs.size(); + // If the attribute isn't known, we will not attempt to parse any // arguments. - if (!hasAttribute(AttrSyntax::Declspec, nullptr, AttrName, + if (!hasAttribute(AttributeCommonInfo::Syntax::AS_Declspec, nullptr, AttrName, getTargetInfo(), getLangOpts())) { // Eat the left paren, then skip to the ending right paren. ConsumeParen(); @@ -687,7 +727,7 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, // If this attribute's args were parsed, and it was expected to have // arguments but none were provided, emit a diagnostic. - if (!Attrs.empty() && Attrs.begin()->getMaxArgs() && !NumArgs) { + if (ExistingAttrs < Attrs.size() && Attrs.back().getMaxArgs() && !NumArgs) { Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName; return false; } @@ -700,11 +740,13 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, /// [MS] extended-decl-modifier-seq: /// extended-decl-modifier[opt] /// extended-decl-modifier extended-decl-modifier-seq -void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs, - SourceLocation *End) { +void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs) { assert(getLangOpts().DeclSpecKeyword && "__declspec keyword is not enabled"); assert(Tok.is(tok::kw___declspec) && "Not a declspec!"); + SourceLocation StartLoc = Tok.getLocation(); + SourceLocation EndLoc = StartLoc; + while (Tok.is(tok::kw___declspec)) { ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); @@ -767,9 +809,10 @@ void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs, ParsedAttr::AS_Declspec); } T.consumeClose(); - if (End) - *End = T.getCloseLocation(); + EndLoc = T.getCloseLocation(); } + + Attrs.Range = SourceRange(StartLoc, EndLoc); } void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { @@ -855,6 +898,15 @@ void Parser::ParseOpenCLKernelAttributes(ParsedAttributes &attrs) { } } +void Parser::ParseCUDAFunctionAttributes(ParsedAttributes &attrs) { + while (Tok.is(tok::kw___noinline__)) { + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + SourceLocation AttrNameLoc = ConsumeToken(); + attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, + ParsedAttr::AS_Keyword); + } +} + void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = Tok.getLocation(); @@ -1154,7 +1206,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, // Also reject wide string literals. if (StringLiteral *MessageStringLiteral = cast_or_null<StringLiteral>(MessageExpr.get())) { - if (!MessageStringLiteral->isAscii()) { + if (!MessageStringLiteral->isOrdinary()) { Diag(MessageStringLiteral->getSourceRange().getBegin(), diag::err_expected_string_literal) << /*Source='availability attribute'*/ 2; @@ -1379,13 +1431,10 @@ void Parser::ParseExternalSourceSymbolAttribute( /// opt-instance_method: /// Identifier | <empty> /// -void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, - SourceLocation ObjCBridgeRelatedLoc, - ParsedAttributes &attrs, - SourceLocation *endLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - ParsedAttr::Syntax Syntax) { +void Parser::ParseObjCBridgeRelatedAttribute( + IdentifierInfo &ObjCBridgeRelated, SourceLocation ObjCBridgeRelatedLoc, + ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) { // Opening '('. BalancedDelimiterTracker T(*this, tok::l_paren); if (T.consumeOpen()) { @@ -1441,20 +1490,16 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, if (T.consumeClose()) return; - if (endLoc) - *endLoc = T.getCloseLocation(); + if (EndLoc) + *EndLoc = T.getCloseLocation(); // Record this attribute - attrs.addNew(&ObjCBridgeRelated, + Attrs.addNew(&ObjCBridgeRelated, SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()), - ScopeName, ScopeLoc, - RelatedClass, - ClassMethod, - InstanceMethod, + ScopeName, ScopeLoc, RelatedClass, ClassMethod, InstanceMethod, Syntax); } - void Parser::ParseSwiftNewTypeAttribute( IdentifierInfo &AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, @@ -1496,7 +1541,6 @@ void Parser::ParseSwiftNewTypeAttribute( ScopeName, ScopeLoc, Args, llvm::array_lengthof(Args), Syntax); } - void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, @@ -1597,7 +1641,7 @@ bool Parser::DiagnoseProhibitedCXX11Attribute() { /// attribute-specifier in a location where an attribute is not permitted, but /// we know where the attributes ought to be written. Parse them anyway, and /// provide a fixit moving them to the right place. -void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, +void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributes &Attrs, SourceLocation CorrectLocation) { assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) || Tok.is(tok::kw_alignas)); @@ -1623,8 +1667,9 @@ void Parser::DiagnoseProhibitedAttributes( Diag(Range.getBegin(), diag::err_attributes_not_allowed) << Range; } -void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, - unsigned DiagID, bool DiagnoseEmptyAttrs) { +void Parser::ProhibitCXX11Attributes(ParsedAttributes &Attrs, unsigned DiagID, + bool DiagnoseEmptyAttrs, + bool WarnOnUnknownAttrs) { if (DiagnoseEmptyAttrs && Attrs.empty() && Attrs.Range.isValid()) { // An attribute list has been parsed, but it was empty. @@ -1651,17 +1696,18 @@ void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, for (const ParsedAttr &AL : Attrs) { if (!AL.isCXX11Attribute() && !AL.isC2xAttribute()) continue; - if (AL.getKind() == ParsedAttr::UnknownAttribute) - Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) - << AL << AL.getRange(); - else { + if (AL.getKind() == ParsedAttr::UnknownAttribute) { + if (WarnOnUnknownAttrs) + Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) + << AL << AL.getRange(); + } else { Diag(AL.getLoc(), DiagID) << AL; AL.setInvalid(); } } } -void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributesWithRange &Attrs) { +void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributes &Attrs) { for (const ParsedAttr &PA : Attrs) { if (PA.isCXX11Attribute() || PA.isC2xAttribute()) Diag(PA.getLoc(), diag::ext_cxx11_attr_placement) << PA << PA.getRange(); @@ -1675,7 +1721,7 @@ void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributesWithRange &Attrs) { // Also, Microsoft-style [attributes] seem to affect the type instead of the // variable. // This function moves attributes that should apply to the type off DS to Attrs. -void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, +void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributes &Attrs, DeclSpec &DS, Sema::TagUseKind TUK) { if (TUK == Sema::TUK_Reference) @@ -1712,10 +1758,11 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, /// [C++11/C11] static_assert-declaration /// others... [FIXME] /// -Parser::DeclGroupPtrTy -Parser::ParseDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, - ParsedAttributesWithRange &attrs, - SourceLocation *DeclSpecStart) { +Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, + SourceLocation &DeclEnd, + ParsedAttributes &DeclAttrs, + ParsedAttributes &DeclSpecAttrs, + SourceLocation *DeclSpecStart) { ParenBraceBracketBalancer BalancerRAIIObj(*this); // Must temporarily exit the objective-c container scope for // parsing c none objective-c decls. @@ -1725,32 +1772,40 @@ Parser::ParseDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, switch (Tok.getKind()) { case tok::kw_template: case tok::kw_export: - ProhibitAttributes(attrs); - SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd, attrs); + ProhibitAttributes(DeclAttrs); + ProhibitAttributes(DeclSpecAttrs); + SingleDecl = + ParseDeclarationStartingWithTemplate(Context, DeclEnd, DeclAttrs); break; case tok::kw_inline: // Could be the start of an inline namespace. Allowed as an ext in C++03. if (getLangOpts().CPlusPlus && NextToken().is(tok::kw_namespace)) { - ProhibitAttributes(attrs); + ProhibitAttributes(DeclAttrs); + ProhibitAttributes(DeclSpecAttrs); SourceLocation InlineLoc = ConsumeToken(); return ParseNamespace(Context, DeclEnd, InlineLoc); } - return ParseSimpleDeclaration(Context, DeclEnd, attrs, true, nullptr, - DeclSpecStart); + return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs, + true, nullptr, DeclSpecStart); case tok::kw_namespace: - ProhibitAttributes(attrs); + ProhibitAttributes(DeclAttrs); + ProhibitAttributes(DeclSpecAttrs); return ParseNamespace(Context, DeclEnd); - case tok::kw_using: + case tok::kw_using: { + ParsedAttributes Attrs(AttrFactory); + takeAndConcatenateAttrs(DeclAttrs, DeclSpecAttrs, Attrs); return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), - DeclEnd, attrs); + DeclEnd, Attrs); + } case tok::kw_static_assert: case tok::kw__Static_assert: - ProhibitAttributes(attrs); + ProhibitAttributes(DeclAttrs); + ProhibitAttributes(DeclSpecAttrs); SingleDecl = ParseStaticAssertDeclaration(DeclEnd); break; default: - return ParseSimpleDeclaration(Context, DeclEnd, attrs, true, nullptr, - DeclSpecStart); + return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs, + true, nullptr, DeclSpecStart); } // This routine returns a DeclGroup, if the thing we parsed only contains a @@ -1781,10 +1836,16 @@ Parser::ParseDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, /// DeclSpecStart if DeclSpecStart is non-null. Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration( DeclaratorContext Context, SourceLocation &DeclEnd, - ParsedAttributesWithRange &Attrs, bool RequireSemi, ForRangeInit *FRI, - SourceLocation *DeclSpecStart) { + ParsedAttributes &DeclAttrs, ParsedAttributes &DeclSpecAttrs, + bool RequireSemi, ForRangeInit *FRI, SourceLocation *DeclSpecStart) { + // Need to retain these for diagnostics before we add them to the DeclSepc. + ParsedAttributesView OriginalDeclSpecAttrs; + OriginalDeclSpecAttrs.addAll(DeclSpecAttrs.begin(), DeclSpecAttrs.end()); + OriginalDeclSpecAttrs.Range = DeclSpecAttrs.Range; + // Parse the common declaration-specifiers piece. ParsingDeclSpec DS(*this); + DS.takeAttributesFrom(DeclSpecAttrs); DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context); ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, DSContext); @@ -1798,12 +1859,12 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration( // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { - ProhibitAttributes(Attrs); + ProhibitAttributes(DeclAttrs); DeclEnd = Tok.getLocation(); if (RequireSemi) ConsumeToken(); RecordDecl *AnonRecord = nullptr; - Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none, - DS, AnonRecord); + Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec( + getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord); DS.complete(TheDecl); if (AnonRecord) { Decl* decls[] = {AnonRecord, TheDecl}; @@ -1815,8 +1876,7 @@ Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration( if (DeclSpecStart) DS.SetRangeStart(*DeclSpecStart); - DS.takeAttributesFrom(Attrs); - return ParseDeclGroup(DS, Context, &DeclEnd, FRI); + return ParseDeclGroup(DS, Context, DeclAttrs, &DeclEnd, FRI); } /// Returns true if this might be the start of a declarator, or a common typo @@ -1971,10 +2031,16 @@ void Parser::SkipMalformedDecl() { /// result. Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, DeclaratorContext Context, + ParsedAttributes &Attrs, SourceLocation *DeclEnd, ForRangeInit *FRI) { // Parse the first declarator. - ParsingDeclarator D(*this, DS, Context); + // Consume all of the attributes from `Attrs` by moving them to our own local + // list. This ensures that we will not attempt to interpret them as statement + // attributes higher up the callchain. + ParsedAttributes LocalAttrs(AttrFactory); + LocalAttrs.takeAllFrom(Attrs); + ParsingDeclarator D(*this, DS, LocalAttrs, Context); ParseDeclarator(D); // Bail out if the first declarator didn't seem well-formed. @@ -2580,7 +2646,7 @@ static bool isValidAfterIdentifierInDeclarator(const Token &T) { bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, DeclSpecContext DSC, - ParsedAttributesWithRange &Attrs) { + ParsedAttributes &Attrs) { assert(Tok.is(tok::identifier) && "should have identifier"); SourceLocation Loc = Tok.getLocation(); @@ -2602,8 +2668,8 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // error, do lookahead to try to do better recovery. This never applies // within a type specifier. Outside of C++, we allow this even if the // language doesn't "officially" support implicit int -- we support - // implicit int as an extension in C99 and C11. - if (!isTypeSpecifier(DSC) && !getLangOpts().CPlusPlus && + // implicit int as an extension in some language modes. + if (!isTypeSpecifier(DSC) && getLangOpts().isImplicitIntAllowed() && isValidAfterIdentifierInDeclarator(NextToken())) { // If this token is valid for implicit int, e.g. "static x = 4", then // we just avoid eating the identifier, so it will be parsed as the @@ -2825,6 +2891,8 @@ Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) { if (Context == DeclaratorContext::AliasDecl || Context == DeclaratorContext::AliasTemplate) return DeclSpecContext::DSC_alias_declaration; + if (Context == DeclaratorContext::Association) + return DeclSpecContext::DSC_association; return DeclSpecContext::DSC_normal; } @@ -3077,7 +3145,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, bool EnteringContext = (DSContext == DeclSpecContext::DSC_class || DSContext == DeclSpecContext::DSC_top_level); bool AttrsLastTime = false; - ParsedAttributesWithRange attrs(AttrFactory); + ParsedAttributes attrs(AttrFactory); // We use Sema's policy to get bool macros right. PrintingPolicy Policy = Actions.getPrintingPolicy(); while (true) { @@ -3129,10 +3197,30 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (!AttrsLastTime) ProhibitAttributes(attrs); else { - // Reject C++11 attributes that appertain to decl specifiers as - // we don't support any C++11 attributes that appertain to decl - // specifiers. This also conforms to what g++ 4.8 is doing. - ProhibitCXX11Attributes(attrs, diag::err_attribute_not_type_attr); + // Reject C++11 / C2x attributes that aren't type attributes. + for (const ParsedAttr &PA : attrs) { + if (!PA.isCXX11Attribute() && !PA.isC2xAttribute()) + continue; + if (PA.getKind() == ParsedAttr::UnknownAttribute) + // We will warn about the unknown attribute elsewhere (in + // SemaDeclAttr.cpp) + continue; + // GCC ignores this attribute when placed on the DeclSpec in [[]] + // syntax, so we do the same. + if (PA.getKind() == ParsedAttr::AT_VectorSize) { + Diag(PA.getLoc(), diag::warn_attribute_ignored) << PA; + PA.setInvalid(); + continue; + } + // We reject AT_LifetimeBound and AT_AnyX86NoCfCheck, even though they + // are type attributes, because we historically haven't allowed these + // to be used as type attributes in C++11 / C2x syntax. + if (PA.isTypeAttr() && PA.getKind() != ParsedAttr::AT_LifetimeBound && + PA.getKind() != ParsedAttr::AT_AnyX86NoCfCheck) + continue; + Diag(PA.getLoc(), diag::err_attribute_not_type_attr) << PA; + PA.setInvalid(); + } DS.takeAttributesFrom(attrs); } @@ -3321,7 +3409,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; // Eat the scope spec so the identifier is current. ConsumeAnnotationToken(); - ParsedAttributesWithRange Attrs(AttrFactory); + ParsedAttributes Attrs(AttrFactory); if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) { if (!Attrs.empty()) { AttrsLastTime = true; @@ -3482,7 +3570,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; if (Tok.isNot(tok::identifier)) continue; - ParsedAttributesWithRange Attrs(AttrFactory); + ParsedAttributes Attrs(AttrFactory); if (ParseImplicitInt(DS, nullptr, TemplateInfo, AS, DSContext, Attrs)) { if (!Attrs.empty()) { AttrsLastTime = true; @@ -3613,8 +3701,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Attributes support. case tok::kw___attribute: case tok::kw___declspec: - ParseAttributes(PAKM_GNU | PAKM_Declspec, DS.getAttributes(), nullptr, - LateAttrs); + ParseAttributes(PAKM_GNU | PAKM_Declspec, DS.getAttributes(), LateAttrs); continue; // Microsoft single token adornments. @@ -3656,6 +3743,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, ParseOpenCLKernelAttributes(DS.getAttributes()); continue; + // CUDA/HIP single token adornments. + case tok::kw___noinline__: + ParseCUDAFunctionAttributes(DS.getAttributes()); + continue; + // Nullability type specifiers. case tok::kw__Nonnull: case tok::kw__Nullable: @@ -4046,7 +4138,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // These are attributes following class specifiers. // To produce better diagnostic, we parse them when // parsing class specifier. - ParsedAttributesWithRange Attributes(AttrFactory); + ParsedAttributes Attributes(AttrFactory); ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS, EnteringContext, DSContext, Attributes); @@ -4251,9 +4343,8 @@ void Parser::ParseStructDeclaration( } // Parse leading attributes. - ParsedAttributesWithRange Attrs(AttrFactory); + ParsedAttributes Attrs(AttrFactory); MaybeParseCXX11Attributes(Attrs); - DS.takeAttributesFrom(Attrs); // Parse the common specifier-qualifiers-list piece. ParseSpecifierQualifierList(DS); @@ -4261,9 +4352,14 @@ void Parser::ParseStructDeclaration( // If there are no declarators, this is a free-standing declaration // specifier. Let the actions module cope with it. if (Tok.is(tok::semi)) { + // C2x 6.7.2.1p9 : "The optional attribute specifier sequence in a + // member declaration appertains to each of the members declared by the + // member declarator list; it shall not appear if the optional member + // declarator list is omitted." + ProhibitAttributes(Attrs); RecordDecl *AnonRecord = nullptr; - Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none, - DS, AnonRecord); + Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec( + getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord); assert(!AnonRecord && "Did not expect anonymous struct or union here"); DS.complete(TheDecl); return; @@ -4273,7 +4369,7 @@ void Parser::ParseStructDeclaration( bool FirstDeclarator = true; SourceLocation CommaLoc; while (true) { - ParsingFieldDeclarator DeclaratorInfo(*this, DS); + ParsingFieldDeclarator DeclaratorInfo(*this, DS, Attrs); DeclaratorInfo.D.setCommaLoc(CommaLoc); // Attributes are only allowed here on successive declarators. @@ -4371,7 +4467,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) { // Result can be ignored, because it must be always empty. AccessSpecifier AS = AS_none; - ParsedAttributesWithRange Attrs(AttrFactory); + ParsedAttributes Attrs(AttrFactory); (void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs); continue; } @@ -4439,8 +4535,7 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, // If attributes exist after struct contents, parse them. MaybeParseGNUAttributes(attrs); - SmallVector<Decl *, 32> FieldDecls(TagDecl->field_begin(), - TagDecl->field_end()); + SmallVector<Decl *, 32> FieldDecls(TagDecl->fields()); Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls, T.getOpenLocation(), T.getCloseLocation(), attrs); @@ -4490,14 +4585,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, } // If attributes exist after tag, parse them. - ParsedAttributesWithRange attrs(AttrFactory); + ParsedAttributes attrs(AttrFactory); MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs); SourceLocation ScopedEnumKWLoc; bool IsScopedUsingClassTag = false; // In C++11, recognize 'enum class' and 'enum struct'. - if (Tok.isOneOf(tok::kw_class, tok::kw_struct)) { + if (Tok.isOneOf(tok::kw_class, tok::kw_struct) && getLangOpts().CPlusPlus) { Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_scoped_enum : diag::ext_scoped_enum); IsScopedUsingClassTag = Tok.is(tok::kw_class); @@ -4524,7 +4619,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // Determine whether this declaration is permitted to have an enum-base. AllowDefiningTypeSpec AllowEnumSpecifier = - isDefiningTypeSpecifierContext(DSC); + isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus); bool CanBeOpaqueEnumDeclaration = DS.isEmpty() && isOpaqueEnumDeclarationContext(DSC); bool CanHaveEnumBase = (getLangOpts().CPlusPlus11 || getLangOpts().ObjC || @@ -4590,8 +4685,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, TypeResult BaseType; SourceRange BaseRange; - bool CanBeBitfield = (getCurScope()->getFlags() & Scope::ClassScope) && - ScopedEnumKWLoc.isInvalid() && Name; + bool CanBeBitfield = + getCurScope()->isClassScope() && ScopedEnumKWLoc.isInvalid() && Name; // Parse the fixed underlying type. if (Tok.is(tok::colon)) { @@ -4633,7 +4728,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, // declares 'enum E : int; E *p;' not 'enum E : int*; E p;'. DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS, AS, DeclSpecContext::DSC_type_specifier); - Declarator DeclaratorInfo(DS, DeclaratorContext::TypeName); + Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), + DeclaratorContext::TypeName); BaseType = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd()); @@ -4838,7 +4934,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagDecl; ParseEnumBody(StartLoc, D); if (SkipBody.CheckSameAsPrevious && - !Actions.ActOnDuplicateDefinition(DS, TagDecl, SkipBody)) { + !Actions.ActOnDuplicateDefinition(TagDecl, SkipBody)) { DS.SetTypeSpecError(); return; } @@ -4893,7 +4989,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { SourceLocation IdentLoc = ConsumeToken(); // If attributes exist after the enumerator, parse them. - ParsedAttributesWithRange attrs(AttrFactory); + ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) { if (getLangOpts().CPlusPlus) @@ -4987,7 +5083,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { // The next token must be valid after an enum definition. If not, a ';' // was probably forgotten. - bool CanBeBitfield = getCurScope()->getFlags() & Scope::ClassScope; + bool CanBeBitfield = getCurScope()->isClassScope(); if (!isValidAfterTypeSpecifier(CanBeBitfield)) { ExpectAndConsume(tok::semi, diag::err_expected_after, "enum"); // Push this token back into the preprocessor and change our current token @@ -5574,9 +5670,9 @@ void Parser::ParseTypeQualifierListOpt( Optional<llvm::function_ref<void()>> CodeCompletionHandler) { if (standardAttributesAllowed() && (AttrReqs & AR_CXX11AttributesParsed) && isCXX11AttributeSpecifier()) { - ParsedAttributesWithRange attrs(AttrFactory); - ParseCXX11Attributes(attrs); - DS.takeAttributesFrom(attrs); + ParsedAttributes Attrs(AttrFactory); + ParseCXX11Attributes(Attrs); + DS.takeAttributesFrom(Attrs); } SourceLocation EndLoc; @@ -5717,11 +5813,12 @@ void Parser::ParseTypeQualifierListOpt( } /// ParseDeclarator - Parse and verify a newly-initialized declarator. -/// void Parser::ParseDeclarator(Declarator &D) { /// This implements the 'declarator' production in the C grammar, then checks /// for well-formedness and issues diagnostics. - ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); + Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] { + ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); + }); } static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, @@ -5753,7 +5850,7 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, } // Indicates whether the given declarator is a pipe declarator. -static bool isPipeDeclerator(const Declarator &D) { +static bool isPipeDeclarator(const Declarator &D) { const unsigned NumTypes = D.getNumTypeObjects(); for (unsigned Idx = 0; Idx != NumTypes; ++Idx) @@ -5832,7 +5929,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, D.ExtendWithDeclSpec(DS); // Recurse to parse whatever is left. - ParseDeclaratorInternal(D, DirectDeclParser); + Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] { + ParseDeclaratorInternal(D, DirectDeclParser); + }); // Sema will have to catch (syntactically invalid) pointers into global // scope. It has to catch pointers into namespace scope anyway. @@ -5846,7 +5945,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, tok::TokenKind Kind = Tok.getKind(); - if (D.getDeclSpec().isTypeSpecPipe() && !isPipeDeclerator(D)) { + if (D.getDeclSpec().isTypeSpecPipe() && !isPipeDeclarator(D)) { DeclSpec DS(AttrFactory); ParseTypeQualifierListOpt(DS); @@ -5881,7 +5980,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, D.ExtendWithDeclSpec(DS); // Recursively parse the declarator. - ParseDeclaratorInternal(D, DirectDeclParser); + Actions.runWithSufficientStackSpace( + D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); }); if (Kind == tok::star) // Remember that we parsed a pointer type, and remember the type-quals. D.AddTypeInfo(DeclaratorChunk::getPointer( @@ -5926,7 +6026,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D, } // Recursively parse the declarator. - ParseDeclaratorInternal(D, DirectDeclParser); + Actions.runWithSufficientStackSpace( + D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); }); if (D.getNumTypeObjects() > 0) { // C++ [dcl.ref]p4: There shall be no references to references. @@ -6550,9 +6651,9 @@ void Parser::InitCXXThisScopeForDeclaratorIfRelevant( /// declarator D up to a paren, which indicates that we are parsing function /// arguments. /// -/// If FirstArgAttrs is non-null, then the caller parsed those arguments -/// immediately after the open paren - they should be considered to be the -/// first argument of a parameter. +/// If FirstArgAttrs is non-null, then the caller parsed those attributes +/// immediately after the open paren - they will be applied to the DeclSpec +/// of the first parameter. /// /// If RequiresArg is true, then the first argument of the function is required /// to be present and required to not be an identifier list. @@ -6593,7 +6694,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, SmallVector<SourceRange, 2> DynamicExceptionRanges; ExprResult NoexceptExpr; CachedTokens *ExceptionSpecTokens = nullptr; - ParsedAttributesWithRange FnAttrs(AttrFactory); + ParsedAttributes FnAttrs(AttrFactory); TypeResult TrailingReturnType; SourceLocation TrailingReturnTypeLoc; @@ -6627,8 +6728,11 @@ void Parser::ParseFunctionDeclarator(Declarator &D, else if (RequiresArg) Diag(Tok, diag::err_argument_required_after_attribute); - HasProto = ParamInfo.size() || getLangOpts().CPlusPlus - || getLangOpts().OpenCL; + // OpenCL disallows functions without a prototype, but it doesn't enforce + // strict prototypes as in C2x because it allows a function definition to + // have an identifier list. See OpenCL 3.0 6.11/g for more details. + HasProto = ParamInfo.size() || getLangOpts().requiresStrictPrototypes() || + getLangOpts().OpenCL; // If we have the closing ')', eat it. Tracker.consumeClose(); @@ -6719,8 +6823,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, // this in C and not C++, where the decls will continue to live in the // surrounding context. SmallVector<NamedDecl *, 0> DeclsInPrototype; - if (getCurScope()->getFlags() & Scope::FunctionDeclarationScope && - !getLangOpts().CPlusPlus) { + if (getCurScope()->isFunctionDeclarationScope() && !getLangOpts().CPlusPlus) { for (Decl *D : getCurScope()->decls()) { NamedDecl *ND = dyn_cast<NamedDecl>(D); if (!ND || isa<ParmVarDecl>(ND)) @@ -6766,7 +6869,7 @@ bool Parser::ParseRefQualifier(bool &RefQualifierIsLValueRef, /// Note that identifier-lists are only allowed for normal declarators, not for /// abstract-declarators. bool Parser::isFunctionDeclaratorIdentifierList() { - return !getLangOpts().CPlusPlus + return !getLangOpts().requiresStrictPrototypes() && Tok.is(tok::identifier) && !TryAltiVecVectorToken() // K&R identifier lists can't have typedefs as identifiers, per C99 @@ -6800,6 +6903,10 @@ bool Parser::isFunctionDeclaratorIdentifierList() { void Parser::ParseFunctionDeclaratorIdentifierList( Declarator &D, SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo) { + // We should never reach this point in C2x or C++. + assert(!getLangOpts().requiresStrictPrototypes() && + "Cannot parse an identifier list in C2x or C++"); + // 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: @@ -6848,7 +6955,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList( /// /// DeclContext is the context of the declarator being parsed. If FirstArgAttrs /// is non-null, then the caller parsed those attributes immediately after the -/// open paren - they should be considered to be part of the first parameter. +/// open paren - they will be applied to the DeclSpec of the first parameter. /// /// After returning, ParamInfo will hold the parsed parameters. EllipsisLoc will /// be the location of the ellipsis, if any was parsed. @@ -6874,10 +6981,9 @@ void Parser::ParseFunctionDeclaratorIdentifierList( /// [C++11] attribute-specifier-seq parameter-declaration /// void Parser::ParseParameterDeclarationClause( - DeclaratorContext DeclaratorCtx, - ParsedAttributes &FirstArgAttrs, - SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo, - SourceLocation &EllipsisLoc) { + DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs, + SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo, + SourceLocation &EllipsisLoc) { // Avoid exceeding the maximum function scope depth. // See https://bugs.llvm.org/show_bug.cgi?id=19607 @@ -6901,37 +7007,42 @@ void Parser::ParseParameterDeclarationClause( // Just use the ParsingDeclaration "scope" of the declarator. DeclSpec DS(AttrFactory); - // Parse any C++11 attributes. - MaybeParseCXX11Attributes(DS.getAttributes()); + ParsedAttributes ArgDeclAttrs(AttrFactory); + ParsedAttributes ArgDeclSpecAttrs(AttrFactory); - // Skip any Microsoft attributes before a param. - MaybeParseMicrosoftAttributes(DS.getAttributes()); + if (FirstArgAttrs.Range.isValid()) { + // If the caller parsed attributes for the first argument, add them now. + // Take them so that we only apply the attributes to the first parameter. + // We have already started parsing the decl-specifier sequence, so don't + // parse any parameter-declaration pieces that precede it. + ArgDeclSpecAttrs.takeAllFrom(FirstArgAttrs); + } else { + // Parse any C++11 attributes. + MaybeParseCXX11Attributes(ArgDeclAttrs); - SourceLocation DSStart = Tok.getLocation(); + // Skip any Microsoft attributes before a param. + MaybeParseMicrosoftAttributes(ArgDeclSpecAttrs); + } - // If the caller parsed attributes for the first argument, add them now. - // Take them so that we only apply the attributes to the first parameter. - // FIXME: If we can leave the attributes in the token stream somehow, we can - // get rid of a parameter (FirstArgAttrs) and this statement. It might be - // too much hassle. - DS.takeAttributesFrom(FirstArgAttrs); + SourceLocation DSStart = Tok.getLocation(); ParseDeclarationSpecifiers(DS); - + DS.takeAttributesFrom(ArgDeclSpecAttrs); // Parse the declarator. This is "PrototypeContext" or // "LambdaExprParameterContext", because we must accept either // 'declarator' or 'abstract-declarator' here. - Declarator ParmDeclarator( - DS, DeclaratorCtx == DeclaratorContext::RequiresExpr - ? DeclaratorContext::RequiresExpr - : DeclaratorCtx == DeclaratorContext::LambdaExpr - ? DeclaratorContext::LambdaExprParameter - : DeclaratorContext::Prototype); + Declarator ParmDeclarator(DS, ArgDeclAttrs, + DeclaratorCtx == DeclaratorContext::RequiresExpr + ? DeclaratorContext::RequiresExpr + : DeclaratorCtx == DeclaratorContext::LambdaExpr + ? DeclaratorContext::LambdaExprParameter + : DeclaratorContext::Prototype); ParseDeclarator(ParmDeclarator); // Parse GNU attributes, if present. MaybeParseGNUAttributes(ParmDeclarator); + MaybeParseHLSLSemantics(DS.getAttributes()); if (Tok.is(tok::kw_requires)) { // User tried to define a requires clause in a parameter declaration, @@ -7035,8 +7146,16 @@ void Parser::ParseParameterDeclarationClause( if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); DefArgResult = ParseBraceInitializer(); - } else + } else { + if (Tok.is(tok::l_paren) && NextToken().is(tok::l_brace)) { + Diag(Tok, diag::err_stmt_expr_in_default_arg) << 0; + Actions.ActOnParamDefaultArgumentError(Param, EqualLoc); + // Skip the statement expression and continue parsing + SkipUntil(tok::comma, StopBeforeMatch); + continue; + } DefArgResult = ParseAssignmentExpression(); + } DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult); if (DefArgResult.isInvalid()) { Actions.ActOnParamDefaultArgumentError(Param, EqualLoc); @@ -7217,7 +7336,8 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) { assert(!D.mayOmitIdentifier() && "Declarator cannot omit identifier"); SourceLocation StartBracketLoc = Tok.getLocation(); - Declarator TempDeclarator(D.getDeclSpec(), D.getContext()); + Declarator TempDeclarator(D.getDeclSpec(), ParsedAttributesView::none(), + D.getContext()); while (Tok.is(tok::l_square)) { ParseBracketDeclarator(TempDeclarator); |