Mercurial > hg > CbC > CbC_llvm
diff clang/lib/Parse/ParseDeclCXX.cpp @ 252:1f2b6ac9f198 llvm-original
LLVM16-1
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Fri, 18 Aug 2023 09:04:13 +0900 |
parents | c4bab56944e8 |
children |
line wrap: on
line diff
--- a/clang/lib/Parse/ParseDeclCXX.cpp Wed Nov 09 17:47:54 2022 +0900 +++ b/clang/lib/Parse/ParseDeclCXX.cpp Fri Aug 18 09:04:13 2023 +0900 @@ -19,14 +19,17 @@ #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TokenKinds.h" +#include "clang/Lex/LiteralSupport.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/TimeProfiler.h" +#include <optional> using namespace clang; @@ -227,7 +230,7 @@ UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident, - T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl); + T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl, false); PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl, NamespaceLoc, "parsing namespace"); @@ -254,9 +257,10 @@ if (index == InnerNSs.size()) { while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { - ParsedAttributes Attrs(AttrFactory); - MaybeParseCXX11Attributes(Attrs); - ParseExternalDeclaration(Attrs); + ParsedAttributes DeclAttrs(AttrFactory); + MaybeParseCXX11Attributes(DeclAttrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs); } // The caller is what called check -- we are simply calling @@ -274,7 +278,7 @@ Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( getCurScope(), InnerNSs[index].InlineLoc, InnerNSs[index].NamespaceLoc, InnerNSs[index].IdentLoc, InnerNSs[index].Ident, - Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl); + Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl, true); assert(!ImplicitUsingDirectiveDecl && "nested namespace definition cannot define anonymous namespace"); @@ -347,7 +351,7 @@ /// Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { assert(isTokenStringLiteral() && "Not a string literal!"); - ExprResult Lang = ParseStringLiteralExpression(false); + ExprResult Lang = ParseUnevaluatedStringLiteralExpression(); ParseScope LinkageScope(this, Scope::DeclScope); Decl *LinkageSpec = @@ -358,7 +362,11 @@ Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation()); ParsedAttributes DeclAttrs(AttrFactory); - MaybeParseCXX11Attributes(DeclAttrs); + ParsedAttributes DeclSpecAttrs(AttrFactory); + + while (MaybeParseCXX11Attributes(DeclAttrs) || + MaybeParseGNUAttributes(DeclSpecAttrs)) + ; if (Tok.isNot(tok::l_brace)) { // Reset the source range in DS, as the leading "extern" @@ -367,7 +375,7 @@ DS.SetRangeEnd(SourceLocation()); // ... but anyway remember that such an "extern" was seen. DS.setExternInLinkageSpec(true); - ParseExternalDeclaration(DeclAttrs, &DS); + ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs, &DS); return LinkageSpec ? Actions.ActOnFinishLinkageSpecification( getCurScope(), LinkageSpec, SourceLocation()) : nullptr; @@ -407,9 +415,9 @@ break; [[fallthrough]]; default: - ParsedAttributes Attrs(AttrFactory); - MaybeParseCXX11Attributes(Attrs); - ParseExternalDeclaration(Attrs); + ParsedAttributes DeclAttrs(AttrFactory); + MaybeParseCXX11Attributes(DeclAttrs); + ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs); continue; } @@ -422,7 +430,7 @@ : nullptr; } -/// Parse a C++ Modules TS export-declaration. +/// Parse a standard C++ Modules export-declaration. /// /// export-declaration: /// 'export' declaration @@ -439,9 +447,10 @@ if (Tok.isNot(tok::l_brace)) { // FIXME: Factor out a ParseExternalDeclarationWithAttrs. - ParsedAttributes Attrs(AttrFactory); - MaybeParseCXX11Attributes(Attrs); - ParseExternalDeclaration(Attrs); + ParsedAttributes DeclAttrs(AttrFactory); + MaybeParseCXX11Attributes(DeclAttrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs); return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl, SourceLocation()); } @@ -449,18 +458,12 @@ BalancedDelimiterTracker T(*this, tok::l_brace); T.consumeOpen(); - // The Modules TS draft says "An export-declaration shall declare at least one - // entity", but the intent is that it shall contain at least one declaration. - if (Tok.is(tok::r_brace) && getLangOpts().ModulesTS) { - Diag(ExportLoc, diag::err_export_empty) - << SourceRange(ExportLoc, Tok.getLocation()); - } - while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { - ParsedAttributes Attrs(AttrFactory); - MaybeParseCXX11Attributes(Attrs); - ParseExternalDeclaration(Attrs); + ParsedAttributes DeclAttrs(AttrFactory); + MaybeParseCXX11Attributes(DeclAttrs); + ParsedAttributes EmptyDeclSpecAttrs(AttrFactory); + ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs); } T.consumeClose(); @@ -633,6 +636,7 @@ Tok.is(tok::identifier) && (NextToken().is(tok::semi) || NextToken().is(tok::comma) || NextToken().is(tok::ellipsis) || NextToken().is(tok::l_square) || + NextToken().isRegularKeywordAttribute() || NextToken().is(tok::kw___attribute)) && D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() && !D.SS.getScopeRep()->getAsNamespace() && @@ -765,11 +769,15 @@ // If we had any misplaced attributes from earlier, this is where they // should have been written. if (MisplacedAttrs.Range.isValid()) { - Diag(MisplacedAttrs.Range.getBegin(), diag::err_attributes_not_allowed) + auto *FirstAttr = + MisplacedAttrs.empty() ? nullptr : &MisplacedAttrs.front(); + auto &Range = MisplacedAttrs.Range; + (FirstAttr && FirstAttr->isRegularKeywordAttribute() + ? Diag(Range.getBegin(), diag::err_keyword_not_allowed) << FirstAttr + : Diag(Range.getBegin(), diag::err_attributes_not_allowed)) << FixItHint::CreateInsertionFromRange( - Tok.getLocation(), - CharSourceRange::getTokenRange(MisplacedAttrs.Range)) - << FixItHint::CreateRemoval(MisplacedAttrs.Range); + Tok.getLocation(), CharSourceRange::getTokenRange(Range)) + << FixItHint::CreateRemoval(Range); Attrs.takeAllFrom(MisplacedAttrs); } @@ -957,14 +965,16 @@ assert(Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert) && "Not a static_assert declaration"); - // Save the token used for static assertion. - Token SavedTok = Tok; + // Save the token name used for static assertion. + const char *TokName = Tok.getName(); if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11) Diag(Tok, diag::ext_c11_feature) << Tok.getName(); if (Tok.is(tok::kw_static_assert)) { if (!getLangOpts().CPlusPlus) { - if (!getLangOpts().C2x) + if (getLangOpts().C23) + Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName(); + else Diag(Tok, diag::ext_ms_static_assert) << FixItHint::CreateReplacement( Tok.getLocation(), "_Static_assert"); } else @@ -995,7 +1005,7 @@ DiagVal = diag::warn_cxx14_compat_static_assert_no_message; else if (getLangOpts().CPlusPlus) DiagVal = diag::ext_cxx_static_assert_no_message; - else if (getLangOpts().C2x) + else if (getLangOpts().C23) DiagVal = diag::warn_c17_compat_static_assert_no_message; else DiagVal = diag::ext_c_static_assert_no_message; @@ -1007,14 +1017,30 @@ return nullptr; } - if (!isTokenStringLiteral()) { + bool ParseAsExpression = false; + if (getLangOpts().CPlusPlus26) { + for (unsigned I = 0;; ++I) { + const Token &T = GetLookAheadToken(I); + if (T.is(tok::r_paren)) + break; + if (!tokenIsLikeStringLiteral(T, getLangOpts())) { + ParseAsExpression = true; + break; + } + } + } + + if (ParseAsExpression) + AssertMessage = ParseConstantExpressionInExprEvalContext(); + else if (tokenIsLikeStringLiteral(Tok, getLangOpts())) + AssertMessage = ParseUnevaluatedStringLiteralExpression(); + else { Diag(Tok, diag::err_expected_string_literal) << /*Source='static_assert'*/ 1; SkipMalformedDecl(); return nullptr; } - AssertMessage = ParseStringLiteralExpression(); if (AssertMessage.isInvalid()) { SkipMalformedDecl(); return nullptr; @@ -1024,9 +1050,7 @@ T.consumeClose(); DeclEnd = Tok.getLocation(); - // Passing the token used to the error message. - ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert, - SavedTok.getName()); + ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert, TokName); return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, AssertExpr.get(), AssertMessage.get(), @@ -1074,7 +1098,7 @@ // Check for C++1y 'decltype(auto)'. if (Tok.is(tok::kw_auto) && NextToken().is(tok::r_paren)) { // the typename-specifier in a function-style cast expression may - // be 'auto' since C++2b. + // be 'auto' since C++23. Diag(Tok.getLocation(), getLangOpts().CPlusPlus14 ? diag::warn_cxx11_compat_decltype_auto_type_specifier @@ -1369,9 +1393,9 @@ tok::kw___multiple_inheritance, tok::kw___virtual_inheritance)) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + auto Kind = Tok.getKind(); SourceLocation AttrNameLoc = ConsumeToken(); - attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - ParsedAttr::AS_Keyword); + attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind); } } @@ -1382,6 +1406,8 @@ // This switch enumerates the valid "follow" set for type-specifiers. switch (Tok.getKind()) { default: + if (Tok.isRegularKeywordAttribute()) + return true; break; case tok::semi: // struct foo {...} ; case tok::star: // struct foo {...} * P; @@ -1621,6 +1647,7 @@ tok::kw___is_signed, tok::kw___is_standard_layout, tok::kw___is_trivial, + tok::kw___is_trivially_equality_comparable, tok::kw___is_trivially_assignable, tok::kw___is_trivially_constructible, tok::kw___is_trivially_copyable, @@ -1673,6 +1700,9 @@ ColonProtectionRAIIObject X(*this); CXXScopeSpec Spec; + if (TemplateInfo.TemplateParams) + Spec.setTemplateParamLists(*TemplateInfo.TemplateParams); + bool HasValidSpec = true; if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr, /*ObjectHasErrors=*/false, @@ -1835,6 +1865,7 @@ } else if (isClassCompatibleKeyword() && (NextToken().is(tok::l_square) || NextToken().is(tok::kw_alignas) || + NextToken().isRegularKeywordAttribute() || isCXX11VirtSpecifier(NextToken()) != VirtSpecifiers::VS_None)) { // We can't tell if this is a definition or reference // until we skipped the 'final' and C++11 attribute specifiers. @@ -1856,6 +1887,8 @@ ConsumeParen(); if (!SkipUntil(tok::r_paren, StopAtSemi)) break; + } else if (Tok.isRegularKeywordAttribute()) { + ConsumeToken(); } else { break; } @@ -1892,7 +1925,11 @@ // them to the right place. SourceRange AttrRange = Attributes.Range; if (AttrRange.isValid()) { - Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed) + auto *FirstAttr = Attributes.empty() ? nullptr : &Attributes.front(); + auto Loc = AttrRange.getBegin(); + (FirstAttr && FirstAttr->isRegularKeywordAttribute() + ? Diag(Loc, diag::err_keyword_not_allowed) << FirstAttr + : Diag(Loc, diag::err_attributes_not_allowed)) << AttrRange << FixItHint::CreateInsertionFromRange( AttrFixitLoc, CharSourceRange(AttrRange, true)) @@ -1940,6 +1977,7 @@ TUK == Sema::TUK_Declaration) { // This is an explicit instantiation of a class template. ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, + diag::err_keyword_not_allowed, /*DiagnoseEmptyAttrs=*/true); TagOrTempResult = Actions.ActOnExplicitInstantiation( @@ -1956,6 +1994,7 @@ (TUK == Sema::TUK_Friend && TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, + diag::err_keyword_not_allowed, /*DiagnoseEmptyAttrs=*/true); TypeResult = Actions.ActOnTagTemplateIdType( TUK, TagType, StartLoc, SS, TemplateId->TemplateKWLoc, @@ -1995,8 +2034,8 @@ // "template<>", so that we treat this construct as a class // template specialization. FakedParamLists.push_back(Actions.ActOnTemplateParameterList( - 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None, - LAngleLoc, nullptr)); + 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, + std::nullopt, LAngleLoc, nullptr)); TemplateParams = &FakedParamLists; } } @@ -2025,6 +2064,7 @@ } else if (TUK == Sema::TUK_Friend && TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) { ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, + diag::err_keyword_not_allowed, /*DiagnoseEmptyAttrs=*/true); TagOrTempResult = Actions.ActOnTemplatedFriendTag( @@ -2035,6 +2075,7 @@ } else { if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition) ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed, + diag::err_keyword_not_allowed, /* DiagnoseEmptyAttrs=*/true); if (TUK == Sema::TUK_Definition && @@ -2066,7 +2107,7 @@ DSC == DeclSpecContext::DSC_type_specifier, DSC == DeclSpecContext::DSC_template_param || DSC == DeclSpecContext::DSC_template_type_arg, - &SkipBody); + OffsetOfState, &SkipBody); // If ActOnTag said the type was dependent, try again with the // less common call. @@ -2821,6 +2862,7 @@ RecordDecl *AnonRecord = nullptr; Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec( getCurScope(), AS, DS, DeclAttrs, TemplateParams, false, AnonRecord); + Actions.ActOnDefinedDeclarationSpecifier(TheDecl); DS.complete(TheDecl); if (AnonRecord) { Decl *decls[] = {AnonRecord, TheDecl}; @@ -2829,6 +2871,9 @@ return Actions.ConvertDeclToDeclGroup(TheDecl); } + if (DS.hasTagDefinition()) + Actions.ActOnDefinedDeclarationSpecifier(DS.getRepAsDecl()); + ParsingDeclarator DeclaratorInfo(*this, DS, DeclAttrs, DeclaratorContext::Member); if (TemplateInfo.TemplateParams) @@ -3011,12 +3056,14 @@ // // Diagnose attributes that appear in a friend member function declarator: // friend int foo [[]] (); - SmallVector<SourceRange, 4> Ranges; - DeclaratorInfo.getCXX11AttributeRanges(Ranges); - for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(), - E = Ranges.end(); - I != E; ++I) - Diag((*I).getBegin(), diag::err_attributes_not_allowed) << *I; + for (const ParsedAttr &AL : DeclaratorInfo.getAttributes()) + if (AL.isCXX11Attribute() || AL.isRegularKeywordAttribute()) { + auto Loc = AL.getRange().getBegin(); + (AL.isRegularKeywordAttribute() + ? Diag(Loc, diag::err_keyword_not_allowed) << AL + : Diag(Loc, diag::err_attributes_not_allowed)) + << AL.getRange(); + } ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo, TemplateParams); @@ -3184,7 +3231,12 @@ "Data member initializer not starting with '=' or '{'"); EnterExpressionEvaluationContext Context( - Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, D); + Actions, + isa_and_present<FieldDecl>(D) + ? Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed + : Sema::ExpressionEvaluationContext::PotentiallyEvaluated, + D); + Actions.ExprEvalContexts.back().InImmediateEscalatingFunctionContext = true; if (TryConsumeToken(tok::equal, EqualLoc)) { if (Tok.is(tok::kw_delete)) { // In principle, an initializer of '= delete p;' is legal, but it will @@ -3803,7 +3855,6 @@ // Parse the optional expression-list. ExprVector ArgExprs; - CommaLocsTy CommaLocs; auto RunSignatureHelp = [&] { if (TemplateTypeTy.isInvalid()) return QualType(); @@ -3813,8 +3864,7 @@ CalledSignatureHelp = true; return PreferredType; }; - if (Tok.isNot(tok::r_paren) && - ParseExpressionList(ArgExprs, CommaLocs, [&] { + if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, [&] { PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp); })) { @@ -4062,7 +4112,7 @@ Actions.ActOnStartTrailingRequiresClause(getCurScope(), D); - llvm::Optional<Sema::CXXThisScopeRAII> ThisScope; + std::optional<Sema::CXXThisScopeRAII> ThisScope; InitCXXThisScopeForDeclaratorIfRelevant(D, D.getDeclSpec(), ThisScope); TrailingRequiresClause = @@ -4191,7 +4241,7 @@ case tok::code_completion: cutOffParsing(); Actions.CodeCompleteAttribute(getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 - : ParsedAttr::AS_C2x, + : ParsedAttr::AS_C23, Completion, Scope); return nullptr; @@ -4348,21 +4398,21 @@ assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); SourceLocation LParenLoc = Tok.getLocation(); const LangOptions &LO = getLangOpts(); - ParsedAttr::Syntax Syntax = - LO.CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C2x; + ParsedAttr::Form Form = + LO.CPlusPlus ? ParsedAttr::Form::CXX11() : ParsedAttr::Form::C23(); // Try parsing microsoft attributes if (getLangOpts().MicrosoftExt || getLangOpts().HLSL) { if (hasAttribute(AttributeCommonInfo::Syntax::AS_Microsoft, ScopeName, AttrName, getTargetInfo(), getLangOpts())) - Syntax = ParsedAttr::AS_Microsoft; + Form = ParsedAttr::Form::Microsoft(); } // If the attribute isn't known, we will not attempt to parse any // arguments. - if (Syntax != ParsedAttr::AS_Microsoft && + if (Form.getSyntax() != ParsedAttr::AS_Microsoft && !hasAttribute(LO.CPlusPlus ? AttributeCommonInfo::Syntax::AS_CXX11 - : AttributeCommonInfo::Syntax::AS_C2x, + : AttributeCommonInfo::Syntax::AS_C23, ScopeName, AttrName, getTargetInfo(), getLangOpts())) { if (getLangOpts().MicrosoftExt || getLangOpts().HLSL) { } @@ -4376,7 +4426,7 @@ // GNU-scoped attributes have some special cases to handle GNU-specific // behaviors. ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, - ScopeLoc, Syntax, nullptr); + ScopeLoc, Form, nullptr); return true; } @@ -4396,10 +4446,10 @@ // Some Clang-scoped attributes have some special parsing behavior. if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang"))) NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, Syntax); + ScopeName, ScopeLoc, Form); else NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, Syntax); + ScopeName, ScopeLoc, Form); if (!Attrs.empty() && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { @@ -4426,7 +4476,7 @@ return true; } -/// Parse a C++11 or C2x attribute-specifier. +/// Parse a C++11 or C23 attribute-specifier. /// /// [C++11] attribute-specifier: /// '[' '[' attribute-list ']' ']' @@ -4454,16 +4504,33 @@ CachedTokens &OpenMPTokens, SourceLocation *EndLoc) { if (Tok.is(tok::kw_alignas)) { - Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas); + if (getLangOpts().C23) + Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName(); + else + Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas); ParseAlignmentSpecifier(Attrs, EndLoc); return; } + if (Tok.isRegularKeywordAttribute()) { + SourceLocation Loc = Tok.getLocation(); + IdentifierInfo *AttrName = Tok.getIdentifierInfo(); + Attrs.addNew(AttrName, Loc, nullptr, Loc, nullptr, 0, Tok.getKind()); + ConsumeToken(); + return; + } + assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) && "Not a double square bracket attribute list"); SourceLocation OpenLoc = Tok.getLocation(); - Diag(OpenLoc, diag::warn_cxx98_compat_attribute); + if (getLangOpts().CPlusPlus) { + Diag(OpenLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_attribute + : diag::warn_ext_cxx11_attributes); + } else { + Diag(OpenLoc, getLangOpts().C23 ? diag::warn_pre_c23_compat_attributes + : diag::warn_ext_c23_attributes); + } ConsumeBracket(); checkCompoundToken(OpenLoc, tok::l_square, CompoundToken::AttrBegin); @@ -4487,8 +4554,6 @@ Diag(Tok.getLocation(), diag::err_expected) << tok::colon; } - llvm::SmallDenseMap<IdentifierInfo *, SourceLocation, 4> SeenAttrs; - bool AttrParsed = false; while (!Tok.isOneOf(tok::r_square, tok::semi, tok::eof)) { if (AttrParsed) { @@ -4548,7 +4613,8 @@ AttrName, SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc), ScopeName, ScopeLoc, nullptr, 0, - getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C2x); + getLangOpts().CPlusPlus ? ParsedAttr::Form::CXX11() + : ParsedAttr::Form::C23()); AttrParsed = true; } @@ -4574,31 +4640,33 @@ SkipUntil(tok::r_square); } -/// ParseCXX11Attributes - Parse a C++11 or C2x attribute-specifier-seq. +/// ParseCXX11Attributes - Parse a C++11 or C23 attribute-specifier-seq. /// /// attribute-specifier-seq: /// attribute-specifier-seq[opt] attribute-specifier void Parser::ParseCXX11Attributes(ParsedAttributes &Attrs) { - assert(standardAttributesAllowed()); - SourceLocation StartLoc = Tok.getLocation(); SourceLocation EndLoc = StartLoc; do { ParseCXX11AttributeSpecifier(Attrs, &EndLoc); - } while (isCXX11AttributeSpecifier()); + } while (isAllowedCXX11AttributeSpecifier()); Attrs.Range = SourceRange(StartLoc, EndLoc); } void Parser::DiagnoseAndSkipCXX11Attributes() { + auto Keyword = + Tok.isRegularKeywordAttribute() ? Tok.getIdentifierInfo() : nullptr; // Start and end location of an attribute or an attribute list. SourceLocation StartLoc = Tok.getLocation(); SourceLocation EndLoc = SkipCXX11Attributes(); if (EndLoc.isValid()) { SourceRange Range(StartLoc, EndLoc); - Diag(StartLoc, diag::err_attributes_not_allowed) << Range; + (Keyword ? Diag(StartLoc, diag::err_keyword_not_allowed) << Keyword + : Diag(StartLoc, diag::err_attributes_not_allowed)) + << Range; } } @@ -4614,6 +4682,9 @@ T.consumeOpen(); T.skipToEnd(); EndLoc = T.getCloseLocation(); + } else if (Tok.isRegularKeywordAttribute()) { + EndLoc = Tok.getLocation(); + ConsumeToken(); } else { assert(Tok.is(tok::kw_alignas) && "not an attribute specifier"); ConsumeToken(); @@ -4708,7 +4779,7 @@ if (!T.consumeClose()) { Attrs.addNew(UuidIdent, SourceRange(UuidLoc, T.getCloseLocation()), nullptr, SourceLocation(), ArgExprs.data(), ArgExprs.size(), - ParsedAttr::AS_Microsoft); + ParsedAttr::Form::Microsoft()); } } @@ -4764,7 +4835,7 @@ } if (!AttrParsed) { Attrs.addNew(II, NameLoc, nullptr, SourceLocation(), nullptr, 0, - ParsedAttr::AS_Microsoft); + ParsedAttr::Form::Microsoft()); } } }