5100 lines · cpp
1//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the C++ Declaration portions of the Parser interfaces.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ASTContext.h"14#include "clang/AST/DeclTemplate.h"15#include "clang/AST/PrettyDeclStackTrace.h"16#include "clang/Basic/AttributeCommonInfo.h"17#include "clang/Basic/Attributes.h"18#include "clang/Basic/CharInfo.h"19#include "clang/Basic/DiagnosticParse.h"20#include "clang/Basic/TargetInfo.h"21#include "clang/Basic/TokenKinds.h"22#include "clang/Lex/LiteralSupport.h"23#include "clang/Parse/ParseHLSLRootSignature.h"24#include "clang/Parse/Parser.h"25#include "clang/Parse/RAIIObjectsForParser.h"26#include "clang/Sema/DeclSpec.h"27#include "clang/Sema/EnterExpressionEvaluationContext.h"28#include "clang/Sema/ParsedTemplate.h"29#include "clang/Sema/Scope.h"30#include "clang/Sema/SemaCodeCompletion.h"31#include "clang/Sema/SemaHLSL.h"32#include "llvm/Support/TimeProfiler.h"33#include <optional>34 35using namespace clang;36 37Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,38 SourceLocation &DeclEnd,39 SourceLocation InlineLoc) {40 assert(Tok.is(tok::kw_namespace) && "Not a namespace!");41 SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'.42 ObjCDeclContextSwitch ObjCDC(*this);43 44 if (Tok.is(tok::code_completion)) {45 cutOffParsing();46 Actions.CodeCompletion().CodeCompleteNamespaceDecl(getCurScope());47 return nullptr;48 }49 50 SourceLocation IdentLoc;51 IdentifierInfo *Ident = nullptr;52 InnerNamespaceInfoList ExtraNSs;53 SourceLocation FirstNestedInlineLoc;54 55 ParsedAttributes attrs(AttrFactory);56 57 while (MaybeParseGNUAttributes(attrs) || isAllowedCXX11AttributeSpecifier()) {58 if (isAllowedCXX11AttributeSpecifier()) {59 if (getLangOpts().CPlusPlus11)60 Diag(Tok.getLocation(), getLangOpts().CPlusPlus1761 ? diag::warn_cxx14_compat_ns_enum_attribute62 : diag::ext_ns_enum_attribute)63 << 0 /*namespace*/;64 ParseCXX11Attributes(attrs);65 }66 }67 68 if (Tok.is(tok::identifier)) {69 Ident = Tok.getIdentifierInfo();70 IdentLoc = ConsumeToken(); // eat the identifier.71 while (Tok.is(tok::coloncolon) &&72 (NextToken().is(tok::identifier) ||73 (NextToken().is(tok::kw_inline) &&74 GetLookAheadToken(2).is(tok::identifier)))) {75 76 InnerNamespaceInfo Info;77 Info.NamespaceLoc = ConsumeToken();78 79 if (Tok.is(tok::kw_inline)) {80 Info.InlineLoc = ConsumeToken();81 if (FirstNestedInlineLoc.isInvalid())82 FirstNestedInlineLoc = Info.InlineLoc;83 }84 85 Info.Ident = Tok.getIdentifierInfo();86 Info.IdentLoc = ConsumeToken();87 88 ExtraNSs.push_back(Info);89 }90 }91 92 DiagnoseAndSkipCXX11Attributes();93 MaybeParseGNUAttributes(attrs);94 DiagnoseAndSkipCXX11Attributes();95 96 SourceLocation attrLoc = attrs.Range.getBegin();97 98 // A nested namespace definition cannot have attributes.99 if (!ExtraNSs.empty() && attrLoc.isValid())100 Diag(attrLoc, diag::err_unexpected_nested_namespace_attribute);101 102 if (Tok.is(tok::equal)) {103 if (!Ident) {104 Diag(Tok, diag::err_expected) << tok::identifier;105 // Skip to end of the definition and eat the ';'.106 SkipUntil(tok::semi);107 return nullptr;108 }109 if (!ExtraNSs.empty()) {110 Diag(ExtraNSs.front().NamespaceLoc,111 diag::err_unexpected_qualified_namespace_alias)112 << SourceRange(ExtraNSs.front().NamespaceLoc,113 ExtraNSs.back().IdentLoc);114 SkipUntil(tok::semi);115 return nullptr;116 }117 if (attrLoc.isValid())118 Diag(attrLoc, diag::err_unexpected_namespace_attributes_alias);119 if (InlineLoc.isValid())120 Diag(InlineLoc, diag::err_inline_namespace_alias)121 << FixItHint::CreateRemoval(InlineLoc);122 Decl *NSAlias = ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);123 return Actions.ConvertDeclToDeclGroup(NSAlias);124 }125 126 BalancedDelimiterTracker T(*this, tok::l_brace);127 if (T.consumeOpen()) {128 if (Ident)129 Diag(Tok, diag::err_expected) << tok::l_brace;130 else131 Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;132 return nullptr;133 }134 135 if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() ||136 getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() ||137 getCurScope()->getFnParent()) {138 Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope);139 SkipUntil(tok::r_brace);140 return nullptr;141 }142 143 if (ExtraNSs.empty()) {144 // Normal namespace definition, not a nested-namespace-definition.145 } else if (InlineLoc.isValid()) {146 Diag(InlineLoc, diag::err_inline_nested_namespace_definition);147 } else if (getLangOpts().CPlusPlus20) {148 Diag(ExtraNSs[0].NamespaceLoc,149 diag::warn_cxx14_compat_nested_namespace_definition);150 if (FirstNestedInlineLoc.isValid())151 Diag(FirstNestedInlineLoc,152 diag::warn_cxx17_compat_inline_nested_namespace_definition);153 } else if (getLangOpts().CPlusPlus17) {154 Diag(ExtraNSs[0].NamespaceLoc,155 diag::warn_cxx14_compat_nested_namespace_definition);156 if (FirstNestedInlineLoc.isValid())157 Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition);158 } else {159 TentativeParsingAction TPA(*this);160 SkipUntil(tok::r_brace, StopBeforeMatch);161 Token rBraceToken = Tok;162 TPA.Revert();163 164 if (!rBraceToken.is(tok::r_brace)) {165 Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition)166 << SourceRange(ExtraNSs.front().NamespaceLoc,167 ExtraNSs.back().IdentLoc);168 } else {169 std::string NamespaceFix;170 for (const auto &ExtraNS : ExtraNSs) {171 NamespaceFix += " { ";172 if (ExtraNS.InlineLoc.isValid())173 NamespaceFix += "inline ";174 NamespaceFix += "namespace ";175 NamespaceFix += ExtraNS.Ident->getName();176 }177 178 std::string RBraces;179 for (unsigned i = 0, e = ExtraNSs.size(); i != e; ++i)180 RBraces += "} ";181 182 Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition)183 << FixItHint::CreateReplacement(184 SourceRange(ExtraNSs.front().NamespaceLoc,185 ExtraNSs.back().IdentLoc),186 NamespaceFix)187 << FixItHint::CreateInsertion(rBraceToken.getLocation(), RBraces);188 }189 190 // Warn about nested inline namespaces.191 if (FirstNestedInlineLoc.isValid())192 Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition);193 }194 195 // If we're still good, complain about inline namespaces in non-C++0x now.196 if (InlineLoc.isValid())197 Diag(InlineLoc, getLangOpts().CPlusPlus11198 ? diag::warn_cxx98_compat_inline_namespace199 : diag::ext_inline_namespace);200 201 // Enter a scope for the namespace.202 ParseScope NamespaceScope(this, Scope::DeclScope);203 204 UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;205 Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(206 getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident,207 T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl, false);208 209 PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl,210 NamespaceLoc, "parsing namespace");211 212 // Parse the contents of the namespace. This includes parsing recovery on213 // any improperly nested namespaces.214 ParseInnerNamespace(ExtraNSs, 0, InlineLoc, attrs, T);215 216 // Leave the namespace scope.217 NamespaceScope.Exit();218 219 DeclEnd = T.getCloseLocation();220 Actions.ActOnFinishNamespaceDef(NamespcDecl, DeclEnd);221 222 return Actions.ConvertDeclToDeclGroup(NamespcDecl,223 ImplicitUsingDirectiveDecl);224}225 226void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs,227 unsigned int index, SourceLocation &InlineLoc,228 ParsedAttributes &attrs,229 BalancedDelimiterTracker &Tracker) {230 if (index == InnerNSs.size()) {231 while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&232 Tok.isNot(tok::eof)) {233 ParsedAttributes DeclAttrs(AttrFactory);234 MaybeParseCXX11Attributes(DeclAttrs);235 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);236 ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs);237 }238 239 // The caller is what called check -- we are simply calling240 // the close for it.241 Tracker.consumeClose();242 243 return;244 }245 246 // Handle a nested namespace definition.247 // FIXME: Preserve the source information through to the AST rather than248 // desugaring it here.249 ParseScope NamespaceScope(this, Scope::DeclScope);250 UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;251 Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(252 getCurScope(), InnerNSs[index].InlineLoc, InnerNSs[index].NamespaceLoc,253 InnerNSs[index].IdentLoc, InnerNSs[index].Ident,254 Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl, true);255 assert(!ImplicitUsingDirectiveDecl &&256 "nested namespace definition cannot define anonymous namespace");257 258 ParseInnerNamespace(InnerNSs, ++index, InlineLoc, attrs, Tracker);259 260 NamespaceScope.Exit();261 Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation());262}263 264Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,265 SourceLocation AliasLoc,266 IdentifierInfo *Alias,267 SourceLocation &DeclEnd) {268 assert(Tok.is(tok::equal) && "Not equal token");269 270 ConsumeToken(); // eat the '='.271 272 if (Tok.is(tok::code_completion)) {273 cutOffParsing();274 Actions.CodeCompletion().CodeCompleteNamespaceAliasDecl(getCurScope());275 return nullptr;276 }277 278 CXXScopeSpec SS;279 // Parse (optional) nested-name-specifier.280 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,281 /*ObjectHasErrors=*/false,282 /*EnteringContext=*/false,283 /*MayBePseudoDestructor=*/nullptr,284 /*IsTypename=*/false,285 /*LastII=*/nullptr,286 /*OnlyNamespace=*/true);287 288 if (Tok.isNot(tok::identifier)) {289 Diag(Tok, diag::err_expected_namespace_name);290 // Skip to end of the definition and eat the ';'.291 SkipUntil(tok::semi);292 return nullptr;293 }294 295 if (SS.isInvalid()) {296 // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.297 // Skip to end of the definition and eat the ';'.298 SkipUntil(tok::semi);299 return nullptr;300 }301 302 // Parse identifier.303 IdentifierInfo *Ident = Tok.getIdentifierInfo();304 SourceLocation IdentLoc = ConsumeToken();305 306 // Eat the ';'.307 DeclEnd = Tok.getLocation();308 if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name))309 SkipUntil(tok::semi);310 311 return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc,312 Alias, SS, IdentLoc, Ident);313}314 315Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {316 assert(isTokenStringLiteral() && "Not a string literal!");317 ExprResult Lang = ParseUnevaluatedStringLiteralExpression();318 319 ParseScope LinkageScope(this, Scope::DeclScope);320 Decl *LinkageSpec =321 Lang.isInvalid()322 ? nullptr323 : Actions.ActOnStartLinkageSpecification(324 getCurScope(), DS.getSourceRange().getBegin(), Lang.get(),325 Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation());326 327 ParsedAttributes DeclAttrs(AttrFactory);328 ParsedAttributes DeclSpecAttrs(AttrFactory);329 330 while (MaybeParseCXX11Attributes(DeclAttrs) ||331 MaybeParseGNUAttributes(DeclSpecAttrs))332 ;333 334 if (Tok.isNot(tok::l_brace)) {335 // Reset the source range in DS, as the leading "extern"336 // does not really belong to the inner declaration ...337 DS.SetRangeStart(SourceLocation());338 DS.SetRangeEnd(SourceLocation());339 // ... but anyway remember that such an "extern" was seen.340 DS.setExternInLinkageSpec(true);341 ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs, &DS);342 return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(343 getCurScope(), LinkageSpec, SourceLocation())344 : nullptr;345 }346 347 DS.abort();348 349 ProhibitAttributes(DeclAttrs);350 351 BalancedDelimiterTracker T(*this, tok::l_brace);352 T.consumeOpen();353 354 unsigned NestedModules = 0;355 while (true) {356 switch (Tok.getKind()) {357 case tok::annot_module_begin:358 ++NestedModules;359 ParseTopLevelDecl();360 continue;361 362 case tok::annot_module_end:363 if (!NestedModules)364 break;365 --NestedModules;366 ParseTopLevelDecl();367 continue;368 369 case tok::annot_module_include:370 ParseTopLevelDecl();371 continue;372 373 case tok::eof:374 break;375 376 case tok::r_brace:377 if (!NestedModules)378 break;379 [[fallthrough]];380 default:381 ParsedAttributes DeclAttrs(AttrFactory);382 ParsedAttributes DeclSpecAttrs(AttrFactory);383 while (MaybeParseCXX11Attributes(DeclAttrs) ||384 MaybeParseGNUAttributes(DeclSpecAttrs))385 ;386 ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs);387 continue;388 }389 390 break;391 }392 393 T.consumeClose();394 return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(395 getCurScope(), LinkageSpec, T.getCloseLocation())396 : nullptr;397}398 399Decl *Parser::ParseExportDeclaration() {400 assert(Tok.is(tok::kw_export));401 SourceLocation ExportLoc = ConsumeToken();402 403 if (Tok.is(tok::code_completion)) {404 cutOffParsing();405 Actions.CodeCompletion().CodeCompleteOrdinaryName(406 getCurScope(), PP.isIncrementalProcessingEnabled()407 ? SemaCodeCompletion::PCC_TopLevelOrExpression408 : SemaCodeCompletion::PCC_Namespace);409 return nullptr;410 }411 412 ParseScope ExportScope(this, Scope::DeclScope);413 Decl *ExportDecl = Actions.ActOnStartExportDecl(414 getCurScope(), ExportLoc,415 Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation());416 417 if (Tok.isNot(tok::l_brace)) {418 // FIXME: Factor out a ParseExternalDeclarationWithAttrs.419 ParsedAttributes DeclAttrs(AttrFactory);420 MaybeParseCXX11Attributes(DeclAttrs);421 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);422 ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs);423 return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl,424 SourceLocation());425 }426 427 BalancedDelimiterTracker T(*this, tok::l_brace);428 T.consumeOpen();429 430 while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&431 Tok.isNot(tok::eof)) {432 ParsedAttributes DeclAttrs(AttrFactory);433 MaybeParseCXX11Attributes(DeclAttrs);434 ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);435 ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs);436 }437 438 T.consumeClose();439 return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl,440 T.getCloseLocation());441}442 443Parser::DeclGroupPtrTy Parser::ParseUsingDirectiveOrDeclaration(444 DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,445 SourceLocation &DeclEnd, ParsedAttributes &Attrs) {446 assert(Tok.is(tok::kw_using) && "Not using token");447 ObjCDeclContextSwitch ObjCDC(*this);448 449 // Eat 'using'.450 SourceLocation UsingLoc = ConsumeToken();451 452 if (Tok.is(tok::code_completion)) {453 cutOffParsing();454 Actions.CodeCompletion().CodeCompleteUsing(getCurScope());455 return nullptr;456 }457 458 // Consume unexpected 'template' keywords.459 while (Tok.is(tok::kw_template)) {460 SourceLocation TemplateLoc = ConsumeToken();461 Diag(TemplateLoc, diag::err_unexpected_template_after_using)462 << FixItHint::CreateRemoval(TemplateLoc);463 }464 465 // 'using namespace' means this is a using-directive.466 if (Tok.is(tok::kw_namespace)) {467 // Template parameters are always an error here.468 if (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate) {469 SourceRange R = TemplateInfo.getSourceRange();470 Diag(UsingLoc, diag::err_templated_using_directive_declaration)471 << 0 /* directive */ << R << FixItHint::CreateRemoval(R);472 }473 474 Decl *UsingDir = ParseUsingDirective(Context, UsingLoc, DeclEnd, Attrs);475 return Actions.ConvertDeclToDeclGroup(UsingDir);476 }477 478 // Otherwise, it must be a using-declaration or an alias-declaration.479 return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd, Attrs,480 AS_none);481}482 483Decl *Parser::ParseUsingDirective(DeclaratorContext Context,484 SourceLocation UsingLoc,485 SourceLocation &DeclEnd,486 ParsedAttributes &attrs) {487 assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");488 489 // Eat 'namespace'.490 SourceLocation NamespcLoc = ConsumeToken();491 492 if (Tok.is(tok::code_completion)) {493 cutOffParsing();494 Actions.CodeCompletion().CodeCompleteUsingDirective(getCurScope());495 return nullptr;496 }497 498 CXXScopeSpec SS;499 // Parse (optional) nested-name-specifier.500 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,501 /*ObjectHasErrors=*/false,502 /*EnteringContext=*/false,503 /*MayBePseudoDestructor=*/nullptr,504 /*IsTypename=*/false,505 /*LastII=*/nullptr,506 /*OnlyNamespace=*/true);507 508 IdentifierInfo *NamespcName = nullptr;509 SourceLocation IdentLoc = SourceLocation();510 511 // Parse namespace-name.512 if (Tok.isNot(tok::identifier)) {513 Diag(Tok, diag::err_expected_namespace_name);514 // If there was invalid namespace name, skip to end of decl, and eat ';'.515 SkipUntil(tok::semi);516 // FIXME: Are there cases, when we would like to call ActOnUsingDirective?517 return nullptr;518 }519 520 if (SS.isInvalid()) {521 // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.522 // Skip to end of the definition and eat the ';'.523 SkipUntil(tok::semi);524 return nullptr;525 }526 527 // Parse identifier.528 NamespcName = Tok.getIdentifierInfo();529 IdentLoc = ConsumeToken();530 531 // Parse (optional) attributes (most likely GNU strong-using extension).532 bool GNUAttr = false;533 if (Tok.is(tok::kw___attribute)) {534 GNUAttr = true;535 ParseGNUAttributes(attrs);536 }537 538 // Eat ';'.539 DeclEnd = Tok.getLocation();540 if (ExpectAndConsume(tok::semi,541 GNUAttr ? diag::err_expected_semi_after_attribute_list542 : diag::err_expected_semi_after_namespace_name))543 SkipUntil(tok::semi);544 545 return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS,546 IdentLoc, NamespcName, attrs);547}548 549bool Parser::ParseUsingDeclarator(DeclaratorContext Context,550 UsingDeclarator &D) {551 D.clear();552 553 // Ignore optional 'typename'.554 // FIXME: This is wrong; we should parse this as a typename-specifier.555 TryConsumeToken(tok::kw_typename, D.TypenameLoc);556 557 if (Tok.is(tok::kw___super)) {558 Diag(Tok.getLocation(), diag::err_super_in_using_declaration);559 return true;560 }561 562 // Parse nested-name-specifier.563 const IdentifierInfo *LastII = nullptr;564 if (ParseOptionalCXXScopeSpecifier(D.SS, /*ObjectType=*/nullptr,565 /*ObjectHasErrors=*/false,566 /*EnteringContext=*/false,567 /*MayBePseudoDtor=*/nullptr,568 /*IsTypename=*/false,569 /*LastII=*/&LastII,570 /*OnlyNamespace=*/false,571 /*InUsingDeclaration=*/true))572 573 return true;574 if (D.SS.isInvalid())575 return true;576 577 // Parse the unqualified-id. We allow parsing of both constructor and578 // destructor names and allow the action module to diagnose any semantic579 // errors.580 //581 // C++11 [class.qual]p2:582 // [...] in a using-declaration that is a member-declaration, if the name583 // specified after the nested-name-specifier is the same as the identifier584 // or the simple-template-id's template-name in the last component of the585 // nested-name-specifier, the name is [...] considered to name the586 // constructor.587 if (getLangOpts().CPlusPlus11 && Context == DeclaratorContext::Member &&588 Tok.is(tok::identifier) &&589 (NextToken().is(tok::semi) || NextToken().is(tok::comma) ||590 NextToken().is(tok::ellipsis) || NextToken().is(tok::l_square) ||591 NextToken().isRegularKeywordAttribute() ||592 NextToken().is(tok::kw___attribute)) &&593 D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&594 D.SS.getScopeRep().getKind() != NestedNameSpecifier::Kind::Namespace) {595 SourceLocation IdLoc = ConsumeToken();596 ParsedType Type =597 Actions.getInheritingConstructorName(D.SS, IdLoc, *LastII);598 D.Name.setConstructorName(Type, IdLoc, IdLoc);599 } else {600 if (ParseUnqualifiedId(601 D.SS, /*ObjectType=*/nullptr,602 /*ObjectHadErrors=*/false, /*EnteringContext=*/false,603 /*AllowDestructorName=*/true,604 /*AllowConstructorName=*/605 !(Tok.is(tok::identifier) && NextToken().is(tok::equal)),606 /*AllowDeductionGuide=*/false, nullptr, D.Name))607 return true;608 }609 610 if (TryConsumeToken(tok::ellipsis, D.EllipsisLoc))611 Diag(Tok.getLocation(), getLangOpts().CPlusPlus17612 ? diag::warn_cxx17_compat_using_declaration_pack613 : diag::ext_using_declaration_pack);614 615 return false;616}617 618Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration(619 DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,620 SourceLocation UsingLoc, SourceLocation &DeclEnd,621 ParsedAttributes &PrefixAttrs, AccessSpecifier AS) {622 SourceLocation UELoc;623 bool InInitStatement = Context == DeclaratorContext::SelectionInit ||624 Context == DeclaratorContext::ForInit;625 626 if (TryConsumeToken(tok::kw_enum, UELoc) && !InInitStatement) {627 // C++20 using-enum628 Diag(UELoc, getLangOpts().CPlusPlus20629 ? diag::warn_cxx17_compat_using_enum_declaration630 : diag::ext_using_enum_declaration);631 632 DiagnoseCXX11AttributeExtension(PrefixAttrs);633 634 if (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate) {635 SourceRange R = TemplateInfo.getSourceRange();636 Diag(UsingLoc, diag::err_templated_using_directive_declaration)637 << 1 /* declaration */ << R << FixItHint::CreateRemoval(R);638 SkipUntil(tok::semi);639 return nullptr;640 }641 CXXScopeSpec SS;642 if (ParseOptionalCXXScopeSpecifier(SS, /*ParsedType=*/nullptr,643 /*ObectHasErrors=*/false,644 /*EnteringConttext=*/false,645 /*MayBePseudoDestructor=*/nullptr,646 /*IsTypename=*/true,647 /*IdentifierInfo=*/nullptr,648 /*OnlyNamespace=*/false,649 /*InUsingDeclaration=*/true)) {650 SkipUntil(tok::semi);651 return nullptr;652 }653 654 if (Tok.is(tok::code_completion)) {655 cutOffParsing();656 Actions.CodeCompletion().CodeCompleteUsing(getCurScope());657 return nullptr;658 }659 660 Decl *UED = nullptr;661 662 // FIXME: identifier and annot_template_id handling is very similar to663 // ParseBaseTypeSpecifier. It should be factored out into a function.664 if (Tok.is(tok::identifier)) {665 IdentifierInfo *IdentInfo = Tok.getIdentifierInfo();666 SourceLocation IdentLoc = ConsumeToken();667 668 ParsedType Type = Actions.getTypeName(669 *IdentInfo, IdentLoc, getCurScope(), &SS, /*isClassName=*/true,670 /*HasTrailingDot=*/false,671 /*ObjectType=*/nullptr, /*IsCtorOrDtorName=*/false,672 /*WantNontrivialTypeSourceInfo=*/true);673 674 UED = Actions.ActOnUsingEnumDeclaration(675 getCurScope(), AS, UsingLoc, UELoc, IdentLoc, *IdentInfo, Type, SS);676 } else if (Tok.is(tok::annot_template_id)) {677 TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);678 679 if (TemplateId->mightBeType()) {680 AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No,681 /*IsClassName=*/true);682 683 assert(Tok.is(tok::annot_typename) && "template-id -> type failed");684 TypeResult Type = getTypeAnnotation(Tok);685 SourceRange Loc = Tok.getAnnotationRange();686 ConsumeAnnotationToken();687 688 UED = Actions.ActOnUsingEnumDeclaration(getCurScope(), AS, UsingLoc,689 UELoc, Loc, *TemplateId->Name,690 Type.get(), SS);691 } else {692 Diag(Tok.getLocation(), diag::err_using_enum_not_enum)693 << TemplateId->Name->getName()694 << SourceRange(TemplateId->TemplateNameLoc, TemplateId->RAngleLoc);695 }696 } else {697 Diag(Tok.getLocation(), diag::err_using_enum_expect_identifier)698 << Tok.is(tok::kw_enum);699 SkipUntil(tok::semi);700 return nullptr;701 }702 703 if (!UED) {704 SkipUntil(tok::semi);705 return nullptr;706 }707 708 DeclEnd = Tok.getLocation();709 if (ExpectAndConsume(tok::semi, diag::err_expected_after,710 "using-enum declaration"))711 SkipUntil(tok::semi);712 713 return Actions.ConvertDeclToDeclGroup(UED);714 }715 716 // Check for misplaced attributes before the identifier in an717 // alias-declaration.718 ParsedAttributes MisplacedAttrs(AttrFactory);719 MaybeParseCXX11Attributes(MisplacedAttrs);720 721 if (InInitStatement && Tok.isNot(tok::identifier))722 return nullptr;723 724 UsingDeclarator D;725 bool InvalidDeclarator = ParseUsingDeclarator(Context, D);726 727 ParsedAttributes Attrs(AttrFactory);728 MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);729 730 // If we had any misplaced attributes from earlier, this is where they731 // should have been written.732 if (MisplacedAttrs.Range.isValid()) {733 auto *FirstAttr =734 MisplacedAttrs.empty() ? nullptr : &MisplacedAttrs.front();735 auto &Range = MisplacedAttrs.Range;736 (FirstAttr && FirstAttr->isRegularKeywordAttribute()737 ? Diag(Range.getBegin(), diag::err_keyword_not_allowed) << FirstAttr738 : Diag(Range.getBegin(), diag::err_attributes_not_allowed))739 << FixItHint::CreateInsertionFromRange(740 Tok.getLocation(), CharSourceRange::getTokenRange(Range))741 << FixItHint::CreateRemoval(Range);742 Attrs.takeAllPrependingFrom(MisplacedAttrs);743 }744 745 // Maybe this is an alias-declaration.746 if (Tok.is(tok::equal) || InInitStatement) {747 if (InvalidDeclarator) {748 SkipUntil(tok::semi);749 return nullptr;750 }751 752 ProhibitAttributes(PrefixAttrs);753 754 Decl *DeclFromDeclSpec = nullptr;755 Scope *CurScope = getCurScope();756 if (CurScope)757 CurScope->setFlags(Scope::ScopeFlags::TypeAliasScope |758 CurScope->getFlags());759 760 Decl *AD = ParseAliasDeclarationAfterDeclarator(761 TemplateInfo, UsingLoc, D, DeclEnd, AS, Attrs, &DeclFromDeclSpec);762 763 if (!AD)764 return nullptr;765 766 return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec);767 }768 769 DiagnoseCXX11AttributeExtension(PrefixAttrs);770 771 // Diagnose an attempt to declare a templated using-declaration.772 // In C++11, alias-declarations can be templates:773 // template <...> using id = type;774 if (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate) {775 SourceRange R = TemplateInfo.getSourceRange();776 Diag(UsingLoc, diag::err_templated_using_directive_declaration)777 << 1 /* declaration */ << R << FixItHint::CreateRemoval(R);778 779 // Unfortunately, we have to bail out instead of recovering by780 // ignoring the parameters, just in case the nested name specifier781 // depends on the parameters.782 return nullptr;783 }784 785 SmallVector<Decl *, 8> DeclsInGroup;786 while (true) {787 // Parse (optional) attributes.788 MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);789 DiagnoseCXX11AttributeExtension(Attrs);790 Attrs.prepend(PrefixAttrs.begin(), PrefixAttrs.end());791 792 if (InvalidDeclarator)793 SkipUntil(tok::comma, tok::semi, StopBeforeMatch);794 else {795 // "typename" keyword is allowed for identifiers only,796 // because it may be a type definition.797 if (D.TypenameLoc.isValid() &&798 D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {799 Diag(D.Name.getSourceRange().getBegin(),800 diag::err_typename_identifiers_only)801 << FixItHint::CreateRemoval(SourceRange(D.TypenameLoc));802 // Proceed parsing, but discard the typename keyword.803 D.TypenameLoc = SourceLocation();804 }805 806 Decl *UD = Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc,807 D.TypenameLoc, D.SS, D.Name,808 D.EllipsisLoc, Attrs);809 if (UD)810 DeclsInGroup.push_back(UD);811 }812 813 if (!TryConsumeToken(tok::comma))814 break;815 816 // Parse another using-declarator.817 Attrs.clear();818 InvalidDeclarator = ParseUsingDeclarator(Context, D);819 }820 821 if (DeclsInGroup.size() > 1)822 Diag(Tok.getLocation(),823 getLangOpts().CPlusPlus17824 ? diag::warn_cxx17_compat_multi_using_declaration825 : diag::ext_multi_using_declaration);826 827 // Eat ';'.828 DeclEnd = Tok.getLocation();829 if (ExpectAndConsume(tok::semi, diag::err_expected_after,830 !Attrs.empty() ? "attributes list"831 : UELoc.isValid() ? "using-enum declaration"832 : "using declaration"))833 SkipUntil(tok::semi);834 835 return Actions.BuildDeclaratorGroup(DeclsInGroup);836}837 838Decl *Parser::ParseAliasDeclarationAfterDeclarator(839 const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,840 UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS,841 ParsedAttributes &Attrs, Decl **OwnedType) {842 if (ExpectAndConsume(tok::equal)) {843 SkipUntil(tok::semi);844 return nullptr;845 }846 847 Diag(Tok.getLocation(), getLangOpts().CPlusPlus11848 ? diag::warn_cxx98_compat_alias_declaration849 : diag::ext_alias_declaration);850 851 // Type alias templates cannot be specialized.852 int SpecKind = -1;853 if (TemplateInfo.Kind == ParsedTemplateKind::Template &&854 D.Name.getKind() == UnqualifiedIdKind::IK_TemplateId)855 SpecKind = 0;856 if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitSpecialization)857 SpecKind = 1;858 if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation)859 SpecKind = 2;860 if (SpecKind != -1) {861 SourceRange Range;862 if (SpecKind == 0)863 Range = SourceRange(D.Name.TemplateId->LAngleLoc,864 D.Name.TemplateId->RAngleLoc);865 else866 Range = TemplateInfo.getSourceRange();867 Diag(Range.getBegin(), diag::err_alias_declaration_specialization)868 << SpecKind << Range;869 SkipUntil(tok::semi);870 return nullptr;871 }872 873 // Name must be an identifier.874 if (D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {875 Diag(D.Name.StartLocation, diag::err_alias_declaration_not_identifier);876 // No removal fixit: can't recover from this.877 SkipUntil(tok::semi);878 return nullptr;879 } else if (D.TypenameLoc.isValid())880 Diag(D.TypenameLoc, diag::err_alias_declaration_not_identifier)881 << FixItHint::CreateRemoval(882 SourceRange(D.TypenameLoc, D.SS.isNotEmpty() ? D.SS.getEndLoc()883 : D.TypenameLoc));884 else if (D.SS.isNotEmpty())885 Diag(D.SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)886 << FixItHint::CreateRemoval(D.SS.getRange());887 if (D.EllipsisLoc.isValid())888 Diag(D.EllipsisLoc, diag::err_alias_declaration_pack_expansion)889 << FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc));890 891 Decl *DeclFromDeclSpec = nullptr;892 TypeResult TypeAlias =893 ParseTypeName(nullptr,894 TemplateInfo.Kind != ParsedTemplateKind::NonTemplate ? DeclaratorContext::AliasTemplate895 : DeclaratorContext::AliasDecl,896 AS, &DeclFromDeclSpec, &Attrs);897 if (OwnedType)898 *OwnedType = DeclFromDeclSpec;899 900 // Eat ';'.901 DeclEnd = Tok.getLocation();902 if (ExpectAndConsume(tok::semi, diag::err_expected_after,903 !Attrs.empty() ? "attributes list"904 : "alias declaration"))905 SkipUntil(tok::semi);906 907 TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;908 MultiTemplateParamsArg TemplateParamsArg(909 TemplateParams ? TemplateParams->data() : nullptr,910 TemplateParams ? TemplateParams->size() : 0);911 return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,912 UsingLoc, D.Name, Attrs, TypeAlias,913 DeclFromDeclSpec);914}915 916static FixItHint getStaticAssertNoMessageFixIt(const Expr *AssertExpr,917 SourceLocation EndExprLoc) {918 if (const auto *BO = dyn_cast_or_null<BinaryOperator>(AssertExpr)) {919 if (BO->getOpcode() == BO_LAnd &&920 isa<StringLiteral>(BO->getRHS()->IgnoreImpCasts()))921 return FixItHint::CreateReplacement(BO->getOperatorLoc(), ",");922 }923 return FixItHint::CreateInsertion(EndExprLoc, ", \"\"");924}925 926Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) {927 assert(Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert) &&928 "Not a static_assert declaration");929 930 // Save the token name used for static assertion.931 const char *TokName = Tok.getName();932 933 if (Tok.is(tok::kw__Static_assert))934 diagnoseUseOfC11Keyword(Tok);935 else if (Tok.is(tok::kw_static_assert)) {936 if (!getLangOpts().CPlusPlus) {937 if (getLangOpts().C23)938 Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();939 } else940 Diag(Tok, diag::warn_cxx98_compat_static_assert);941 }942 943 SourceLocation StaticAssertLoc = ConsumeToken();944 945 BalancedDelimiterTracker T(*this, tok::l_paren);946 if (T.consumeOpen()) {947 Diag(Tok, diag::err_expected) << tok::l_paren;948 SkipMalformedDecl();949 return nullptr;950 }951 952 EnterExpressionEvaluationContext ConstantEvaluated(953 Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);954 ExprResult AssertExpr(ParseConstantExpressionInExprEvalContext());955 if (AssertExpr.isInvalid()) {956 SkipMalformedDecl();957 return nullptr;958 }959 960 ExprResult AssertMessage;961 if (Tok.is(tok::r_paren)) {962 unsigned DiagVal;963 if (getLangOpts().CPlusPlus17)964 DiagVal = diag::warn_cxx14_compat_static_assert_no_message;965 else if (getLangOpts().CPlusPlus)966 DiagVal = diag::ext_cxx_static_assert_no_message;967 else if (getLangOpts().C23)968 DiagVal = diag::warn_c17_compat_static_assert_no_message;969 else970 DiagVal = diag::ext_c_static_assert_no_message;971 Diag(Tok, DiagVal) << getStaticAssertNoMessageFixIt(AssertExpr.get(),972 Tok.getLocation());973 } else {974 if (ExpectAndConsume(tok::comma)) {975 SkipUntil(tok::semi);976 return nullptr;977 }978 979 bool ParseAsExpression = false;980 if (getLangOpts().CPlusPlus11) {981 for (unsigned I = 0;; ++I) {982 const Token &T = GetLookAheadToken(I);983 if (T.is(tok::r_paren))984 break;985 if (!tokenIsLikeStringLiteral(T, getLangOpts()) || T.hasUDSuffix()) {986 ParseAsExpression = true;987 break;988 }989 }990 }991 992 if (ParseAsExpression) {993 Diag(Tok,994 getLangOpts().CPlusPlus26995 ? diag::warn_cxx20_compat_static_assert_user_generated_message996 : diag::ext_cxx_static_assert_user_generated_message);997 AssertMessage = ParseConstantExpressionInExprEvalContext();998 } else if (tokenIsLikeStringLiteral(Tok, getLangOpts()))999 AssertMessage = ParseUnevaluatedStringLiteralExpression();1000 else {1001 Diag(Tok, diag::err_expected_string_literal)1002 << /*Source='static_assert'*/ 1;1003 SkipMalformedDecl();1004 return nullptr;1005 }1006 1007 if (AssertMessage.isInvalid()) {1008 SkipMalformedDecl();1009 return nullptr;1010 }1011 }1012 1013 if (T.consumeClose())1014 return nullptr;1015 1016 DeclEnd = Tok.getLocation();1017 ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert, TokName);1018 1019 return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, AssertExpr.get(),1020 AssertMessage.get(),1021 T.getCloseLocation());1022}1023 1024SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {1025 assert(Tok.isOneOf(tok::kw_decltype, tok::annot_decltype) &&1026 "Not a decltype specifier");1027 1028 ExprResult Result;1029 SourceLocation StartLoc = Tok.getLocation();1030 SourceLocation EndLoc;1031 1032 if (Tok.is(tok::annot_decltype)) {1033 Result = getExprAnnotation(Tok);1034 EndLoc = Tok.getAnnotationEndLoc();1035 // Unfortunately, we don't know the LParen source location as the annotated1036 // token doesn't have it.1037 DS.setTypeArgumentRange(SourceRange(SourceLocation(), EndLoc));1038 ConsumeAnnotationToken();1039 if (Result.isInvalid()) {1040 DS.SetTypeSpecError();1041 return EndLoc;1042 }1043 } else {1044 if (Tok.getIdentifierInfo()->isStr("decltype"))1045 Diag(Tok, diag::warn_cxx98_compat_decltype);1046 1047 ConsumeToken();1048 1049 BalancedDelimiterTracker T(*this, tok::l_paren);1050 if (T.expectAndConsume(diag::err_expected_lparen_after, "decltype",1051 tok::r_paren)) {1052 DS.SetTypeSpecError();1053 return T.getOpenLocation() == Tok.getLocation() ? StartLoc1054 : T.getOpenLocation();1055 }1056 1057 // Check for C++1y 'decltype(auto)'.1058 if (Tok.is(tok::kw_auto) && NextToken().is(tok::r_paren)) {1059 // the typename-specifier in a function-style cast expression may1060 // be 'auto' since C++23.1061 Diag(Tok.getLocation(),1062 getLangOpts().CPlusPlus141063 ? diag::warn_cxx11_compat_decltype_auto_type_specifier1064 : diag::ext_decltype_auto_type_specifier);1065 ConsumeToken();1066 } else {1067 // Parse the expression1068 1069 // C++11 [dcl.type.simple]p4:1070 // The operand of the decltype specifier is an unevaluated operand.1071 EnterExpressionEvaluationContext Unevaluated(1072 Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,1073 Sema::ExpressionEvaluationContextRecord::EK_Decltype);1074 Result = ParseExpression();1075 if (Result.isInvalid()) {1076 DS.SetTypeSpecError();1077 if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {1078 EndLoc = ConsumeParen();1079 } else {1080 if (PP.isBacktrackEnabled() && Tok.is(tok::semi)) {1081 // Backtrack to get the location of the last token before the semi.1082 PP.RevertCachedTokens(2);1083 ConsumeToken(); // the semi.1084 EndLoc = ConsumeAnyToken();1085 assert(Tok.is(tok::semi));1086 } else {1087 EndLoc = Tok.getLocation();1088 }1089 }1090 return EndLoc;1091 }1092 1093 Result = Actions.ActOnDecltypeExpression(Result.get());1094 }1095 1096 // Match the ')'1097 T.consumeClose();1098 DS.setTypeArgumentRange(T.getRange());1099 if (T.getCloseLocation().isInvalid()) {1100 DS.SetTypeSpecError();1101 // FIXME: this should return the location of the last token1102 // that was consumed (by "consumeClose()")1103 return T.getCloseLocation();1104 }1105 1106 if (Result.isInvalid()) {1107 DS.SetTypeSpecError();1108 return T.getCloseLocation();1109 }1110 1111 EndLoc = T.getCloseLocation();1112 }1113 assert(!Result.isInvalid());1114 1115 const char *PrevSpec = nullptr;1116 unsigned DiagID;1117 const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();1118 // Check for duplicate type specifiers (e.g. "int decltype(a)").1119 if (Result.get() ? DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc,1120 PrevSpec, DiagID, Result.get(), Policy)1121 : DS.SetTypeSpecType(DeclSpec::TST_decltype_auto, StartLoc,1122 PrevSpec, DiagID, Policy)) {1123 Diag(StartLoc, DiagID) << PrevSpec;1124 DS.SetTypeSpecError();1125 }1126 return EndLoc;1127}1128 1129void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,1130 SourceLocation StartLoc,1131 SourceLocation EndLoc) {1132 // make sure we have a token we can turn into an annotation token1133 if (PP.isBacktrackEnabled()) {1134 PP.RevertCachedTokens(1);1135 } else1136 PP.EnterToken(Tok, /*IsReinject*/ true);1137 1138 Tok.setKind(tok::annot_decltype);1139 setExprAnnotation(Tok,1140 DS.getTypeSpecType() == TST_decltype ? DS.getRepAsExpr()1141 : DS.getTypeSpecType() == TST_decltype_auto ? ExprResult()1142 : ExprError());1143 Tok.setAnnotationEndLoc(EndLoc);1144 Tok.setLocation(StartLoc);1145 PP.AnnotateCachedTokens(Tok);1146}1147 1148SourceLocation Parser::ParsePackIndexingType(DeclSpec &DS) {1149 assert(Tok.isOneOf(tok::annot_pack_indexing_type, tok::identifier) &&1150 "Expected an identifier");1151 1152 TypeResult Type;1153 SourceLocation StartLoc;1154 SourceLocation EllipsisLoc;1155 const char *PrevSpec;1156 unsigned DiagID;1157 const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();1158 1159 if (Tok.is(tok::annot_pack_indexing_type)) {1160 StartLoc = Tok.getLocation();1161 SourceLocation EndLoc;1162 Type = getTypeAnnotation(Tok);1163 EndLoc = Tok.getAnnotationEndLoc();1164 // Unfortunately, we don't know the LParen source location as the annotated1165 // token doesn't have it.1166 DS.setTypeArgumentRange(SourceRange(SourceLocation(), EndLoc));1167 ConsumeAnnotationToken();1168 if (Type.isInvalid()) {1169 DS.SetTypeSpecError();1170 return EndLoc;1171 }1172 DS.SetTypeSpecType(DeclSpec::TST_typename_pack_indexing, StartLoc, PrevSpec,1173 DiagID, Type, Policy);1174 return EndLoc;1175 }1176 if (!NextToken().is(tok::ellipsis) ||1177 !GetLookAheadToken(2).is(tok::l_square)) {1178 DS.SetTypeSpecError();1179 return Tok.getEndLoc();1180 }1181 1182 ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),1183 Tok.getLocation(), getCurScope());1184 if (!Ty) {1185 DS.SetTypeSpecError();1186 return Tok.getEndLoc();1187 }1188 Type = Ty;1189 1190 StartLoc = ConsumeToken();1191 EllipsisLoc = ConsumeToken();1192 BalancedDelimiterTracker T(*this, tok::l_square);1193 T.consumeOpen();1194 ExprResult IndexExpr = ParseConstantExpression();1195 T.consumeClose();1196 1197 DS.SetRangeStart(StartLoc);1198 DS.SetRangeEnd(T.getCloseLocation());1199 1200 if (!IndexExpr.isUsable()) {1201 ASTContext &C = Actions.getASTContext();1202 IndexExpr = IntegerLiteral::Create(C, C.MakeIntValue(0, C.getSizeType()),1203 C.getSizeType(), SourceLocation());1204 }1205 1206 DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, PrevSpec, DiagID, Type,1207 Policy);1208 DS.SetPackIndexingExpr(EllipsisLoc, IndexExpr.get());1209 return T.getCloseLocation();1210}1211 1212void Parser::AnnotateExistingIndexedTypeNamePack(ParsedType T,1213 SourceLocation StartLoc,1214 SourceLocation EndLoc) {1215 // make sure we have a token we can turn into an annotation token1216 if (PP.isBacktrackEnabled()) {1217 PP.RevertCachedTokens(1);1218 if (!T) {1219 // We encountered an error in parsing 'decltype(...)' so lets annotate all1220 // the tokens in the backtracking cache - that we likely had to skip over1221 // to get to a token that allows us to resume parsing, such as a1222 // semi-colon.1223 EndLoc = PP.getLastCachedTokenLocation();1224 }1225 } else1226 PP.EnterToken(Tok, /*IsReinject*/ true);1227 1228 Tok.setKind(tok::annot_pack_indexing_type);1229 setTypeAnnotation(Tok, T);1230 Tok.setAnnotationEndLoc(EndLoc);1231 Tok.setLocation(StartLoc);1232 PP.AnnotateCachedTokens(Tok);1233}1234 1235DeclSpec::TST Parser::TypeTransformTokToDeclSpec() {1236 switch (Tok.getKind()) {1237#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \1238 case tok::kw___##Trait: \1239 return DeclSpec::TST_##Trait;1240#include "clang/Basic/TransformTypeTraits.def"1241 default:1242 llvm_unreachable("passed in an unhandled type transformation built-in");1243 }1244}1245 1246bool Parser::MaybeParseTypeTransformTypeSpecifier(DeclSpec &DS) {1247 if (!NextToken().is(tok::l_paren)) {1248 Tok.setKind(tok::identifier);1249 return false;1250 }1251 DeclSpec::TST TypeTransformTST = TypeTransformTokToDeclSpec();1252 SourceLocation StartLoc = ConsumeToken();1253 1254 BalancedDelimiterTracker T(*this, tok::l_paren);1255 if (T.expectAndConsume(diag::err_expected_lparen_after, Tok.getName(),1256 tok::r_paren))1257 return true;1258 1259 TypeResult Result = ParseTypeName();1260 if (Result.isInvalid()) {1261 SkipUntil(tok::r_paren, StopAtSemi);1262 return true;1263 }1264 1265 T.consumeClose();1266 if (T.getCloseLocation().isInvalid())1267 return true;1268 1269 const char *PrevSpec = nullptr;1270 unsigned DiagID;1271 if (DS.SetTypeSpecType(TypeTransformTST, StartLoc, PrevSpec, DiagID,1272 Result.get(),1273 Actions.getASTContext().getPrintingPolicy()))1274 Diag(StartLoc, DiagID) << PrevSpec;1275 DS.setTypeArgumentRange(T.getRange());1276 return true;1277}1278 1279TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,1280 SourceLocation &EndLocation) {1281 // Ignore attempts to use typename1282 if (Tok.is(tok::kw_typename)) {1283 Diag(Tok, diag::err_expected_class_name_not_template)1284 << FixItHint::CreateRemoval(Tok.getLocation());1285 ConsumeToken();1286 }1287 1288 // Parse optional nested-name-specifier1289 CXXScopeSpec SS;1290 if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,1291 /*ObjectHasErrors=*/false,1292 /*EnteringContext=*/false))1293 return true;1294 1295 BaseLoc = Tok.getLocation();1296 1297 // Parse decltype-specifier1298 // tok == kw_decltype is just error recovery, it can only happen when SS1299 // isn't empty1300 if (Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) {1301 if (SS.isNotEmpty())1302 Diag(SS.getBeginLoc(), diag::err_unexpected_scope_on_base_decltype)1303 << FixItHint::CreateRemoval(SS.getRange());1304 // Fake up a Declarator to use with ActOnTypeName.1305 DeclSpec DS(AttrFactory);1306 1307 EndLocation = ParseDecltypeSpecifier(DS);1308 1309 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),1310 DeclaratorContext::TypeName);1311 return Actions.ActOnTypeName(DeclaratorInfo);1312 }1313 1314 if (Tok.is(tok::annot_pack_indexing_type)) {1315 DeclSpec DS(AttrFactory);1316 ParsePackIndexingType(DS);1317 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),1318 DeclaratorContext::TypeName);1319 return Actions.ActOnTypeName(DeclaratorInfo);1320 }1321 1322 // Check whether we have a template-id that names a type.1323 // FIXME: identifier and annot_template_id handling in ParseUsingDeclaration1324 // work very similarly. It should be refactored into a separate function.1325 if (Tok.is(tok::annot_template_id)) {1326 TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);1327 if (TemplateId->mightBeType()) {1328 AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No,1329 /*IsClassName=*/true);1330 1331 assert(Tok.is(tok::annot_typename) && "template-id -> type failed");1332 TypeResult Type = getTypeAnnotation(Tok);1333 EndLocation = Tok.getAnnotationEndLoc();1334 ConsumeAnnotationToken();1335 return Type;1336 }1337 1338 // Fall through to produce an error below.1339 }1340 1341 if (Tok.isNot(tok::identifier)) {1342 Diag(Tok, diag::err_expected_class_name);1343 return true;1344 }1345 1346 IdentifierInfo *Id = Tok.getIdentifierInfo();1347 SourceLocation IdLoc = ConsumeToken();1348 1349 if (Tok.is(tok::less)) {1350 // It looks the user intended to write a template-id here, but the1351 // template-name was wrong. Try to fix that.1352 // FIXME: Invoke ParseOptionalCXXScopeSpecifier in a "'template' is neither1353 // required nor permitted" mode, and do this there.1354 TemplateNameKind TNK = TNK_Non_template;1355 TemplateTy Template;1356 if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(), &SS,1357 Template, TNK)) {1358 Diag(IdLoc, diag::err_unknown_template_name) << Id;1359 }1360 1361 // Form the template name1362 UnqualifiedId TemplateName;1363 TemplateName.setIdentifier(Id, IdLoc);1364 1365 // Parse the full template-id, then turn it into a type.1366 if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),1367 TemplateName))1368 return true;1369 if (Tok.is(tok::annot_template_id) &&1370 takeTemplateIdAnnotation(Tok)->mightBeType())1371 AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No,1372 /*IsClassName=*/true);1373 1374 // If we didn't end up with a typename token, there's nothing more we1375 // can do.1376 if (Tok.isNot(tok::annot_typename))1377 return true;1378 1379 // Retrieve the type from the annotation token, consume that token, and1380 // return.1381 EndLocation = Tok.getAnnotationEndLoc();1382 TypeResult Type = getTypeAnnotation(Tok);1383 ConsumeAnnotationToken();1384 return Type;1385 }1386 1387 // We have an identifier; check whether it is actually a type.1388 IdentifierInfo *CorrectedII = nullptr;1389 ParsedType Type = Actions.getTypeName(1390 *Id, IdLoc, getCurScope(), &SS, /*isClassName=*/true, false, nullptr,1391 /*IsCtorOrDtorName=*/false,1392 /*WantNontrivialTypeSourceInfo=*/true,1393 /*IsClassTemplateDeductionContext=*/false, ImplicitTypenameContext::No,1394 &CorrectedII);1395 if (!Type) {1396 Diag(IdLoc, diag::err_expected_class_name);1397 return true;1398 }1399 1400 // Consume the identifier.1401 EndLocation = IdLoc;1402 1403 // Fake up a Declarator to use with ActOnTypeName.1404 DeclSpec DS(AttrFactory);1405 DS.SetRangeStart(IdLoc);1406 DS.SetRangeEnd(EndLocation);1407 DS.getTypeSpecScope() = SS;1408 1409 const char *PrevSpec = nullptr;1410 unsigned DiagID;1411 DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type,1412 Actions.getASTContext().getPrintingPolicy());1413 1414 Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),1415 DeclaratorContext::TypeName);1416 return Actions.ActOnTypeName(DeclaratorInfo);1417}1418 1419void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {1420 while (Tok.isOneOf(tok::kw___single_inheritance,1421 tok::kw___multiple_inheritance,1422 tok::kw___virtual_inheritance)) {1423 IdentifierInfo *AttrName = Tok.getIdentifierInfo();1424 auto Kind = Tok.getKind();1425 SourceLocation AttrNameLoc = ConsumeToken();1426 attrs.addNew(AttrName, AttrNameLoc, AttributeScopeInfo(), nullptr, 0, Kind);1427 }1428}1429 1430void Parser::ParseNullabilityClassAttributes(ParsedAttributes &attrs) {1431 while (Tok.is(tok::kw__Nullable)) {1432 IdentifierInfo *AttrName = Tok.getIdentifierInfo();1433 auto Kind = Tok.getKind();1434 SourceLocation AttrNameLoc = ConsumeToken();1435 attrs.addNew(AttrName, AttrNameLoc, AttributeScopeInfo(), nullptr, 0, Kind);1436 }1437}1438 1439bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) {1440 // This switch enumerates the valid "follow" set for type-specifiers.1441 switch (Tok.getKind()) {1442 default:1443 if (Tok.isRegularKeywordAttribute())1444 return true;1445 break;1446 case tok::semi: // struct foo {...} ;1447 case tok::star: // struct foo {...} * P;1448 case tok::amp: // struct foo {...} & R = ...1449 case tok::ampamp: // struct foo {...} && R = ...1450 case tok::identifier: // struct foo {...} V ;1451 case tok::r_paren: //(struct foo {...} ) {4}1452 case tok::coloncolon: // struct foo {...} :: a::b;1453 case tok::annot_cxxscope: // struct foo {...} a:: b;1454 case tok::annot_typename: // struct foo {...} a ::b;1455 case tok::annot_template_id: // struct foo {...} a<int> ::b;1456 case tok::kw_decltype: // struct foo {...} decltype (a)::b;1457 case tok::l_paren: // struct foo {...} ( x);1458 case tok::comma: // __builtin_offsetof(struct foo{...} ,1459 case tok::kw_operator: // struct foo operator ++() {...}1460 case tok::kw___declspec: // struct foo {...} __declspec(...)1461 case tok::l_square: // void f(struct f [ 3])1462 case tok::ellipsis: // void f(struct f ... [Ns])1463 // FIXME: we should emit semantic diagnostic when declaration1464 // attribute is in type attribute position.1465 case tok::kw___attribute: // struct foo __attribute__((used)) x;1466 case tok::annot_pragma_pack: // struct foo {...} _Pragma(pack(pop));1467 // struct foo {...} _Pragma(section(...));1468 case tok::annot_pragma_ms_pragma:1469 // struct foo {...} _Pragma(vtordisp(pop));1470 case tok::annot_pragma_ms_vtordisp:1471 // struct foo {...} _Pragma(pointers_to_members(...));1472 case tok::annot_pragma_ms_pointers_to_members:1473 return true;1474 case tok::colon:1475 return CouldBeBitfield || // enum E { ... } : 2;1476 ColonIsSacred; // _Generic(..., enum E : 2);1477 // Microsoft compatibility1478 case tok::kw___cdecl: // struct foo {...} __cdecl x;1479 case tok::kw___fastcall: // struct foo {...} __fastcall x;1480 case tok::kw___stdcall: // struct foo {...} __stdcall x;1481 case tok::kw___thiscall: // struct foo {...} __thiscall x;1482 case tok::kw___vectorcall: // struct foo {...} __vectorcall x;1483 // We will diagnose these calling-convention specifiers on non-function1484 // declarations later, so claim they are valid after a type specifier.1485 return getLangOpts().MicrosoftExt;1486 // Type qualifiers1487 case tok::kw_const: // struct foo {...} const x;1488 case tok::kw_volatile: // struct foo {...} volatile x;1489 case tok::kw_restrict: // struct foo {...} restrict x;1490 case tok::kw__Atomic: // struct foo {...} _Atomic x;1491 case tok::kw___unaligned: // struct foo {...} __unaligned *x;1492 // Function specifiers1493 // Note, no 'explicit'. An explicit function must be either a conversion1494 // operator or a constructor. Either way, it can't have a return type.1495 case tok::kw_inline: // struct foo inline f();1496 case tok::kw_virtual: // struct foo virtual f();1497 case tok::kw_friend: // struct foo friend f();1498 // Storage-class specifiers1499 case tok::kw_static: // struct foo {...} static x;1500 case tok::kw_extern: // struct foo {...} extern x;1501 case tok::kw_typedef: // struct foo {...} typedef x;1502 case tok::kw_register: // struct foo {...} register x;1503 case tok::kw_auto: // struct foo {...} auto x;1504 case tok::kw_mutable: // struct foo {...} mutable x;1505 case tok::kw_thread_local: // struct foo {...} thread_local x;1506 case tok::kw_constexpr: // struct foo {...} constexpr x;1507 case tok::kw_consteval: // struct foo {...} consteval x;1508 case tok::kw_constinit: // struct foo {...} constinit x;1509 // As shown above, type qualifiers and storage class specifiers absolutely1510 // can occur after class specifiers according to the grammar. However,1511 // almost no one actually writes code like this. If we see one of these,1512 // it is much more likely that someone missed a semi colon and the1513 // type/storage class specifier we're seeing is part of the *next*1514 // intended declaration, as in:1515 //1516 // struct foo { ... }1517 // typedef int X;1518 //1519 // We'd really like to emit a missing semicolon error instead of emitting1520 // an error on the 'int' saying that you can't have two type specifiers in1521 // the same declaration of X. Because of this, we look ahead past this1522 // token to see if it's a type specifier. If so, we know the code is1523 // otherwise invalid, so we can produce the expected semi error.1524 if (!isKnownToBeTypeSpecifier(NextToken()))1525 return true;1526 break;1527 case tok::r_brace: // struct bar { struct foo {...} }1528 // Missing ';' at end of struct is accepted as an extension in C mode.1529 if (!getLangOpts().CPlusPlus)1530 return true;1531 break;1532 case tok::greater:1533 // template<class T = class X>1534 return getLangOpts().CPlusPlus;1535 }1536 return false;1537}1538 1539void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,1540 SourceLocation StartLoc, DeclSpec &DS,1541 ParsedTemplateInfo &TemplateInfo,1542 AccessSpecifier AS, bool EnteringContext,1543 DeclSpecContext DSC,1544 ParsedAttributes &Attributes) {1545 DeclSpec::TST TagType;1546 if (TagTokKind == tok::kw_struct)1547 TagType = DeclSpec::TST_struct;1548 else if (TagTokKind == tok::kw___interface)1549 TagType = DeclSpec::TST_interface;1550 else if (TagTokKind == tok::kw_class)1551 TagType = DeclSpec::TST_class;1552 else {1553 assert(TagTokKind == tok::kw_union && "Not a class specifier");1554 TagType = DeclSpec::TST_union;1555 }1556 1557 if (Tok.is(tok::code_completion)) {1558 // Code completion for a struct, class, or union name.1559 cutOffParsing();1560 Actions.CodeCompletion().CodeCompleteTag(getCurScope(), TagType);1561 return;1562 }1563 1564 // C++20 [temp.class.spec] 13.7.5/101565 // The usual access checking rules do not apply to non-dependent names1566 // used to specify template arguments of the simple-template-id of the1567 // partial specialization.1568 // C++20 [temp.spec] 13.9/6:1569 // The usual access checking rules do not apply to names in a declaration1570 // of an explicit instantiation or explicit specialization...1571 const bool shouldDelayDiagsInTag =1572 (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate);1573 SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);1574 1575 ParsedAttributes attrs(AttrFactory);1576 // If attributes exist after tag, parse them.1577 for (;;) {1578 MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);1579 // Parse inheritance specifiers.1580 if (Tok.isOneOf(tok::kw___single_inheritance,1581 tok::kw___multiple_inheritance,1582 tok::kw___virtual_inheritance)) {1583 ParseMicrosoftInheritanceClassAttributes(attrs);1584 continue;1585 }1586 if (Tok.is(tok::kw__Nullable)) {1587 ParseNullabilityClassAttributes(attrs);1588 continue;1589 }1590 break;1591 }1592 1593 // Source location used by FIXIT to insert misplaced1594 // C++11 attributes1595 SourceLocation AttrFixitLoc = Tok.getLocation();1596 1597 if (TagType == DeclSpec::TST_struct && Tok.isNot(tok::identifier) &&1598 !Tok.isAnnotation() && Tok.getIdentifierInfo() &&1599 Tok.isOneOf(1600#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,1601#include "clang/Basic/TransformTypeTraits.def"1602 tok::kw___is_abstract,1603 tok::kw___is_aggregate,1604 tok::kw___is_arithmetic,1605 tok::kw___is_array,1606 tok::kw___is_assignable,1607 tok::kw___is_base_of,1608 tok::kw___is_bounded_array,1609 tok::kw___is_class,1610 tok::kw___is_complete_type,1611 tok::kw___is_compound,1612 tok::kw___is_const,1613 tok::kw___is_constructible,1614 tok::kw___is_convertible,1615 tok::kw___is_convertible_to,1616 tok::kw___is_destructible,1617 tok::kw___is_empty,1618 tok::kw___is_enum,1619 tok::kw___is_floating_point,1620 tok::kw___is_final,1621 tok::kw___is_function,1622 tok::kw___is_fundamental,1623 tok::kw___is_integral,1624 tok::kw___is_interface_class,1625 tok::kw___is_literal,1626 tok::kw___is_lvalue_expr,1627 tok::kw___is_lvalue_reference,1628 tok::kw___is_member_function_pointer,1629 tok::kw___is_member_object_pointer,1630 tok::kw___is_member_pointer,1631 tok::kw___is_nothrow_assignable,1632 tok::kw___is_nothrow_constructible,1633 tok::kw___is_nothrow_convertible,1634 tok::kw___is_nothrow_destructible,1635 tok::kw___is_object,1636 tok::kw___is_pod,1637 tok::kw___is_pointer,1638 tok::kw___is_polymorphic,1639 tok::kw___is_reference,1640 tok::kw___is_rvalue_expr,1641 tok::kw___is_rvalue_reference,1642 tok::kw___is_same,1643 tok::kw___is_scalar,1644 tok::kw___is_scoped_enum,1645 tok::kw___is_sealed,1646 tok::kw___is_signed,1647 tok::kw___is_standard_layout,1648 tok::kw___is_trivial,1649 tok::kw___is_trivially_equality_comparable,1650 tok::kw___is_trivially_assignable,1651 tok::kw___is_trivially_constructible,1652 tok::kw___is_trivially_copyable,1653 tok::kw___is_unbounded_array,1654 tok::kw___is_union,1655 tok::kw___is_unsigned,1656 tok::kw___is_void,1657 tok::kw___is_volatile1658 ))1659 // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the1660 // name of struct templates, but some are keywords in GCC >= 4.31661 // and Clang. Therefore, when we see the token sequence "struct1662 // X", make X into a normal identifier rather than a keyword, to1663 // allow libstdc++ 4.2 and libc++ to work properly.1664 TryKeywordIdentFallback(true);1665 1666 struct PreserveAtomicIdentifierInfoRAII {1667 PreserveAtomicIdentifierInfoRAII(Token &Tok, bool Enabled)1668 : AtomicII(nullptr) {1669 if (!Enabled)1670 return;1671 assert(Tok.is(tok::kw__Atomic));1672 AtomicII = Tok.getIdentifierInfo();1673 AtomicII->revertTokenIDToIdentifier();1674 Tok.setKind(tok::identifier);1675 }1676 ~PreserveAtomicIdentifierInfoRAII() {1677 if (!AtomicII)1678 return;1679 AtomicII->revertIdentifierToTokenID(tok::kw__Atomic);1680 }1681 IdentifierInfo *AtomicII;1682 };1683 1684 // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL1685 // implementation for VS2013 uses _Atomic as an identifier for one of the1686 // classes in <atomic>. When we are parsing 'struct _Atomic', don't consider1687 // '_Atomic' to be a keyword. We are careful to undo this so that clang can1688 // use '_Atomic' in its own header files.1689 bool ShouldChangeAtomicToIdentifier = getLangOpts().MSVCCompat &&1690 Tok.is(tok::kw__Atomic) &&1691 TagType == DeclSpec::TST_struct;1692 PreserveAtomicIdentifierInfoRAII AtomicTokenGuard(1693 Tok, ShouldChangeAtomicToIdentifier);1694 1695 // Parse the (optional) nested-name-specifier.1696 CXXScopeSpec &SS = DS.getTypeSpecScope();1697 if (getLangOpts().CPlusPlus) {1698 // "FOO : BAR" is not a potential typo for "FOO::BAR". In this context it1699 // is a base-specifier-list.1700 ColonProtectionRAIIObject X(*this);1701 1702 CXXScopeSpec Spec;1703 if (TemplateInfo.TemplateParams)1704 Spec.setTemplateParamLists(*TemplateInfo.TemplateParams);1705 1706 bool HasValidSpec = true;1707 if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr,1708 /*ObjectHasErrors=*/false,1709 EnteringContext)) {1710 DS.SetTypeSpecError();1711 HasValidSpec = false;1712 }1713 if (Spec.isSet())1714 if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) {1715 Diag(Tok, diag::err_expected) << tok::identifier;1716 HasValidSpec = false;1717 }1718 if (HasValidSpec)1719 SS = Spec;1720 }1721 1722 TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;1723 1724 auto RecoverFromUndeclaredTemplateName = [&](IdentifierInfo *Name,1725 SourceLocation NameLoc,1726 SourceRange TemplateArgRange,1727 bool KnownUndeclared) {1728 Diag(NameLoc, diag::err_explicit_spec_non_template)1729 << (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation)1730 << TagTokKind << Name << TemplateArgRange << KnownUndeclared;1731 1732 // Strip off the last template parameter list if it was empty, since1733 // we've removed its template argument list.1734 if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {1735 if (TemplateParams->size() > 1) {1736 TemplateParams->pop_back();1737 } else {1738 TemplateParams = nullptr;1739 TemplateInfo.Kind = ParsedTemplateKind::NonTemplate;1740 }1741 } else if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation) {1742 // Pretend this is just a forward declaration.1743 TemplateParams = nullptr;1744 TemplateInfo.Kind = ParsedTemplateKind::NonTemplate;1745 TemplateInfo.TemplateLoc = SourceLocation();1746 TemplateInfo.ExternLoc = SourceLocation();1747 }1748 };1749 1750 // Parse the (optional) class name or simple-template-id.1751 IdentifierInfo *Name = nullptr;1752 SourceLocation NameLoc;1753 TemplateIdAnnotation *TemplateId = nullptr;1754 if (Tok.is(tok::identifier)) {1755 Name = Tok.getIdentifierInfo();1756 NameLoc = ConsumeToken();1757 DS.SetRangeEnd(NameLoc);1758 1759 if (Tok.is(tok::less) && getLangOpts().CPlusPlus) {1760 // The name was supposed to refer to a template, but didn't.1761 // Eat the template argument list and try to continue parsing this as1762 // a class (or template thereof).1763 TemplateArgList TemplateArgs;1764 SourceLocation LAngleLoc, RAngleLoc;1765 if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs,1766 RAngleLoc)) {1767 // We couldn't parse the template argument list at all, so don't1768 // try to give any location information for the list.1769 LAngleLoc = RAngleLoc = SourceLocation();1770 }1771 RecoverFromUndeclaredTemplateName(1772 Name, NameLoc, SourceRange(LAngleLoc, RAngleLoc), false);1773 }1774 } else if (Tok.is(tok::annot_template_id)) {1775 TemplateId = takeTemplateIdAnnotation(Tok);1776 NameLoc = ConsumeAnnotationToken();1777 1778 if (TemplateId->Kind == TNK_Undeclared_template) {1779 // Try to resolve the template name to a type template. May update Kind.1780 Actions.ActOnUndeclaredTypeTemplateName(1781 getCurScope(), TemplateId->Template, TemplateId->Kind, NameLoc, Name);1782 if (TemplateId->Kind == TNK_Undeclared_template) {1783 RecoverFromUndeclaredTemplateName(1784 Name, NameLoc,1785 SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc), true);1786 TemplateId = nullptr;1787 }1788 }1789 1790 if (TemplateId && !TemplateId->mightBeType()) {1791 // The template-name in the simple-template-id refers to1792 // something other than a type template. Give an appropriate1793 // error message and skip to the ';'.1794 SourceRange Range(NameLoc);1795 if (SS.isNotEmpty())1796 Range.setBegin(SS.getBeginLoc());1797 1798 // FIXME: Name may be null here.1799 Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)1800 << TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range;1801 1802 DS.SetTypeSpecError();1803 SkipUntil(tok::semi, StopBeforeMatch);1804 return;1805 }1806 }1807 1808 // There are four options here.1809 // - If we are in a trailing return type, this is always just a reference,1810 // and we must not try to parse a definition. For instance,1811 // [] () -> struct S { };1812 // does not define a type.1813 // - If we have 'struct foo {...', 'struct foo :...',1814 // 'struct foo final :' or 'struct foo final {', then this is a definition.1815 // - If we have 'struct foo;', then this is either a forward declaration1816 // or a friend declaration, which have to be treated differently.1817 // - Otherwise we have something like 'struct foo xyz', a reference.1818 //1819 // We also detect these erroneous cases to provide better diagnostic for1820 // C++11 attributes parsing.1821 // - attributes follow class name:1822 // struct foo [[]] {};1823 // - attributes appear before or after 'final':1824 // struct foo [[]] final [[]] {};1825 //1826 // However, in type-specifier-seq's, things look like declarations but are1827 // just references, e.g.1828 // new struct s;1829 // or1830 // &T::operator struct s;1831 // For these, DSC is DeclSpecContext::DSC_type_specifier or1832 // DeclSpecContext::DSC_alias_declaration.1833 1834 // If there are attributes after class name, parse them.1835 MaybeParseCXX11Attributes(Attributes);1836 1837 const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();1838 TagUseKind TUK;1839 1840 // C++26 [class.mem.general]p10: If a name-declaration matches the1841 // syntactic requirements of friend-type-declaration, it is a1842 // friend-type-declaration.1843 if (getLangOpts().CPlusPlus && DS.isFriendSpecifiedFirst() &&1844 Tok.isOneOf(tok::comma, tok::ellipsis))1845 TUK = TagUseKind::Friend;1846 else if (isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus) ==1847 AllowDefiningTypeSpec::No ||1848 (getLangOpts().OpenMP && OpenMPDirectiveParsing))1849 TUK = TagUseKind::Reference;1850 else if (Tok.is(tok::l_brace) ||1851 (DSC != DeclSpecContext::DSC_association &&1852 getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||1853 (isClassCompatibleKeyword() &&1854 (NextToken().is(tok::l_brace) || NextToken().is(tok::colon) ||1855 isClassCompatibleKeyword(NextToken())))) {1856 if (DS.isFriendSpecified()) {1857 // C++ [class.friend]p2:1858 // A class shall not be defined in a friend declaration.1859 Diag(Tok.getLocation(), diag::err_friend_decl_defines_type)1860 << SourceRange(DS.getFriendSpecLoc());1861 1862 // Skip everything up to the semicolon, so that this looks like a proper1863 // friend class (or template thereof) declaration.1864 SkipUntil(tok::semi, StopBeforeMatch);1865 TUK = TagUseKind::Friend;1866 } else {1867 // Okay, this is a class definition.1868 TUK = TagUseKind::Definition;1869 }1870 } else if (isClassCompatibleKeyword() &&1871 (NextToken().is(tok::l_square) ||1872 NextToken().is(tok::kw_alignas) ||1873 NextToken().isRegularKeywordAttribute() ||1874 isCXX11VirtSpecifier(NextToken()) != VirtSpecifiers::VS_None ||1875 isCXX2CTriviallyRelocatableKeyword())) {1876 // We can't tell if this is a definition or reference1877 // until we skipped the 'final' and C++11 attribute specifiers.1878 TentativeParsingAction PA(*this);1879 1880 // Skip the 'final', abstract'... keywords.1881 while (isClassCompatibleKeyword())1882 ConsumeToken();1883 1884 // Skip C++11 attribute specifiers.1885 while (true) {1886 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {1887 ConsumeBracket();1888 if (!SkipUntil(tok::r_square, StopAtSemi))1889 break;1890 } else if (Tok.is(tok::kw_alignas) && NextToken().is(tok::l_paren)) {1891 ConsumeToken();1892 ConsumeParen();1893 if (!SkipUntil(tok::r_paren, StopAtSemi))1894 break;1895 } else if (Tok.isRegularKeywordAttribute()) {1896 bool TakesArgs = doesKeywordAttributeTakeArgs(Tok.getKind());1897 ConsumeToken();1898 if (TakesArgs) {1899 BalancedDelimiterTracker T(*this, tok::l_paren);1900 if (!T.consumeOpen())1901 T.skipToEnd();1902 }1903 } else {1904 break;1905 }1906 }1907 1908 if (Tok.isOneOf(tok::l_brace, tok::colon))1909 TUK = TagUseKind::Definition;1910 else1911 TUK = TagUseKind::Reference;1912 1913 PA.Revert();1914 } else if (!isTypeSpecifier(DSC) &&1915 (Tok.is(tok::semi) ||1916 (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) {1917 TUK = DS.isFriendSpecified() ? TagUseKind::Friend : TagUseKind::Declaration;1918 if (Tok.isNot(tok::semi)) {1919 const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();1920 // A semicolon was missing after this declaration. Diagnose and recover.1921 ExpectAndConsume(tok::semi, diag::err_expected_after,1922 DeclSpec::getSpecifierName(TagType, PPol));1923 PP.EnterToken(Tok, /*IsReinject*/ true);1924 Tok.setKind(tok::semi);1925 }1926 } else1927 TUK = TagUseKind::Reference;1928 1929 // Forbid misplaced attributes. In cases of a reference, we pass attributes1930 // to caller to handle.1931 if (TUK != TagUseKind::Reference) {1932 // If this is not a reference, then the only possible1933 // valid place for C++11 attributes to appear here1934 // is between class-key and class-name. If there are1935 // any attributes after class-name, we try a fixit to move1936 // them to the right place.1937 SourceRange AttrRange = Attributes.Range;1938 if (AttrRange.isValid()) {1939 auto *FirstAttr = Attributes.empty() ? nullptr : &Attributes.front();1940 auto Loc = AttrRange.getBegin();1941 (FirstAttr && FirstAttr->isRegularKeywordAttribute()1942 ? Diag(Loc, diag::err_keyword_not_allowed) << FirstAttr1943 : Diag(Loc, diag::err_attributes_not_allowed))1944 << AttrRange1945 << FixItHint::CreateInsertionFromRange(1946 AttrFixitLoc, CharSourceRange(AttrRange, true))1947 << FixItHint::CreateRemoval(AttrRange);1948 1949 // Recover by adding misplaced attributes to the attribute list1950 // of the class so they can be applied on the class later.1951 attrs.takeAllAppendingFrom(Attributes);1952 }1953 }1954 1955 if (!Name && !TemplateId &&1956 (DS.getTypeSpecType() == DeclSpec::TST_error ||1957 TUK != TagUseKind::Definition)) {1958 if (DS.getTypeSpecType() != DeclSpec::TST_error) {1959 // We have a declaration or reference to an anonymous class.1960 Diag(StartLoc, diag::err_anon_type_definition)1961 << DeclSpec::getSpecifierName(TagType, Policy);1962 }1963 1964 // If we are parsing a definition and stop at a base-clause, continue on1965 // until the semicolon. Continuing from the comma will just trick us into1966 // thinking we are seeing a variable declaration.1967 if (TUK == TagUseKind::Definition && Tok.is(tok::colon))1968 SkipUntil(tok::semi, StopBeforeMatch);1969 else1970 SkipUntil(tok::comma, StopAtSemi);1971 return;1972 }1973 1974 // Create the tag portion of the class or class template.1975 DeclResult TagOrTempResult = true; // invalid1976 TypeResult TypeResult = true; // invalid1977 1978 bool Owned = false;1979 SkipBodyInfo SkipBody;1980 if (TemplateId) {1981 // Explicit specialization, class template partial specialization,1982 // or explicit instantiation.1983 ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),1984 TemplateId->NumArgs);1985 if (TemplateId->isInvalid()) {1986 // Can't build the declaration.1987 } else if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation &&1988 TUK == TagUseKind::Declaration) {1989 // This is an explicit instantiation of a class template.1990 ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,1991 diag::err_keyword_not_allowed,1992 /*DiagnoseEmptyAttrs=*/true);1993 1994 TagOrTempResult = Actions.ActOnExplicitInstantiation(1995 getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc,1996 TagType, StartLoc, SS, TemplateId->Template,1997 TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr,1998 TemplateId->RAngleLoc, attrs);1999 2000 // Friend template-ids are treated as references unless2001 // they have template headers, in which case they're ill-formed2002 // (FIXME: "template <class T> friend class A<T>::B<int>;").2003 // We diagnose this error in ActOnClassTemplateSpecialization.2004 } else if (TUK == TagUseKind::Reference ||2005 (TUK == TagUseKind::Friend &&2006 TemplateInfo.Kind == ParsedTemplateKind::NonTemplate)) {2007 ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,2008 diag::err_keyword_not_allowed,2009 /*DiagnoseEmptyAttrs=*/true);2010 TypeResult = Actions.ActOnTagTemplateIdType(2011 TUK, TagType, StartLoc, SS, TemplateId->TemplateKWLoc,2012 TemplateId->Template, TemplateId->TemplateNameLoc,2013 TemplateId->LAngleLoc, TemplateArgsPtr, TemplateId->RAngleLoc);2014 } else {2015 // This is an explicit specialization or a class template2016 // partial specialization.2017 TemplateParameterLists FakedParamLists;2018 if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation) {2019 // This looks like an explicit instantiation, because we have2020 // something like2021 //2022 // template class Foo<X>2023 //2024 // but it actually has a definition. Most likely, this was2025 // meant to be an explicit specialization, but the user forgot2026 // the '<>' after 'template'.2027 // It this is friend declaration however, since it cannot have a2028 // template header, it is most likely that the user meant to2029 // remove the 'template' keyword.2030 assert((TUK == TagUseKind::Definition || TUK == TagUseKind::Friend) &&2031 "Expected a definition here");2032 2033 if (TUK == TagUseKind::Friend) {2034 Diag(DS.getFriendSpecLoc(), diag::err_friend_explicit_instantiation);2035 TemplateParams = nullptr;2036 } else {2037 SourceLocation LAngleLoc =2038 PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);2039 Diag(TemplateId->TemplateNameLoc,2040 diag::err_explicit_instantiation_with_definition)2041 << SourceRange(TemplateInfo.TemplateLoc)2042 << FixItHint::CreateInsertion(LAngleLoc, "<>");2043 2044 // Create a fake template parameter list that contains only2045 // "template<>", so that we treat this construct as a class2046 // template specialization.2047 FakedParamLists.push_back(Actions.ActOnTemplateParameterList(2048 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, {},2049 LAngleLoc, nullptr));2050 TemplateParams = &FakedParamLists;2051 }2052 }2053 2054 // Build the class template specialization.2055 TagOrTempResult = Actions.ActOnClassTemplateSpecialization(2056 getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(),2057 SS, *TemplateId, attrs,2058 MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0]2059 : nullptr,2060 TemplateParams ? TemplateParams->size() : 0),2061 &SkipBody);2062 }2063 } else if (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation &&2064 TUK == TagUseKind::Declaration) {2065 // Explicit instantiation of a member of a class template2066 // specialization, e.g.,2067 //2068 // template struct Outer<int>::Inner;2069 //2070 ProhibitAttributes(attrs);2071 2072 TagOrTempResult = Actions.ActOnExplicitInstantiation(2073 getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc,2074 TagType, StartLoc, SS, Name, NameLoc, attrs);2075 } else if (TUK == TagUseKind::Friend &&2076 TemplateInfo.Kind != ParsedTemplateKind::NonTemplate) {2077 ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,2078 diag::err_keyword_not_allowed,2079 /*DiagnoseEmptyAttrs=*/true);2080 2081 // Consume '...' first so we error on the ',' after it if there is one.2082 SourceLocation EllipsisLoc;2083 TryConsumeToken(tok::ellipsis, EllipsisLoc);2084 2085 // CWG 2917: In a template-declaration whose declaration is a2086 // friend-type-declaration, the friend-type-specifier-list shall2087 // consist of exactly one friend-type-specifier.2088 //2089 // Essentially, the following is obviously nonsense, so disallow it:2090 //2091 // template <typename>2092 // friend class S, int;2093 //2094 if (Tok.is(tok::comma)) {2095 Diag(Tok.getLocation(),2096 diag::err_friend_template_decl_multiple_specifiers);2097 SkipUntil(tok::semi, StopBeforeMatch);2098 }2099 2100 TagOrTempResult = Actions.ActOnTemplatedFriendTag(2101 getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name,2102 NameLoc, EllipsisLoc, attrs,2103 MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr,2104 TemplateParams ? TemplateParams->size() : 0));2105 } else {2106 if (TUK != TagUseKind::Declaration && TUK != TagUseKind::Definition)2107 ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,2108 diag::err_keyword_not_allowed,2109 /* DiagnoseEmptyAttrs=*/true);2110 2111 if (TUK == TagUseKind::Definition &&2112 TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation) {2113 // If the declarator-id is not a template-id, issue a diagnostic and2114 // recover by ignoring the 'template' keyword.2115 Diag(Tok, diag::err_template_defn_explicit_instantiation)2116 << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);2117 TemplateParams = nullptr;2118 }2119 2120 bool IsDependent = false;2121 2122 // Don't pass down template parameter lists if this is just a tag2123 // reference. For example, we don't need the template parameters here:2124 // template <class T> class A *makeA(T t);2125 MultiTemplateParamsArg TParams;2126 if (TUK != TagUseKind::Reference && TemplateParams)2127 TParams =2128 MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size());2129 2130 stripTypeAttributesOffDeclSpec(attrs, DS, TUK);2131 2132 // Declaration or definition of a class type2133 TagOrTempResult = Actions.ActOnTag(2134 getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs, AS,2135 DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent,2136 SourceLocation(), false, clang::TypeResult(),2137 DSC == DeclSpecContext::DSC_type_specifier,2138 DSC == DeclSpecContext::DSC_template_param ||2139 DSC == DeclSpecContext::DSC_template_type_arg,2140 OffsetOfState, &SkipBody);2141 2142 // If ActOnTag said the type was dependent, try again with the2143 // less common call.2144 if (IsDependent) {2145 assert(TUK == TagUseKind::Reference || TUK == TagUseKind::Friend);2146 TypeResult = Actions.ActOnDependentTag(getCurScope(), TagType, TUK, SS,2147 Name, StartLoc, NameLoc);2148 }2149 }2150 2151 // If this is an elaborated type specifier in function template,2152 // and we delayed diagnostics before,2153 // just merge them into the current pool.2154 if (shouldDelayDiagsInTag) {2155 diagsFromTag.done();2156 if (TUK == TagUseKind::Reference &&2157 TemplateInfo.Kind == ParsedTemplateKind::Template)2158 diagsFromTag.redelay();2159 }2160 2161 // If there is a body, parse it and inform the actions module.2162 if (TUK == TagUseKind::Definition) {2163 assert(Tok.is(tok::l_brace) ||2164 (getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||2165 isClassCompatibleKeyword());2166 if (SkipBody.ShouldSkip)2167 SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType,2168 TagOrTempResult.get());2169 else if (getLangOpts().CPlusPlus)2170 ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType,2171 TagOrTempResult.get());2172 else {2173 Decl *D =2174 SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get();2175 // Parse the definition body.2176 ParseStructUnionBody(StartLoc, TagType, cast<RecordDecl>(D));2177 if (SkipBody.CheckSameAsPrevious &&2178 !Actions.ActOnDuplicateDefinition(getCurScope(),2179 TagOrTempResult.get(), SkipBody)) {2180 DS.SetTypeSpecError();2181 return;2182 }2183 }2184 }2185 2186 if (!TagOrTempResult.isInvalid())2187 // Delayed processing of attributes.2188 Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs);2189 2190 const char *PrevSpec = nullptr;2191 unsigned DiagID;2192 bool Result;2193 if (!TypeResult.isInvalid()) {2194 Result = DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc,2195 NameLoc.isValid() ? NameLoc : StartLoc,2196 PrevSpec, DiagID, TypeResult.get(), Policy);2197 } else if (!TagOrTempResult.isInvalid()) {2198 Result = DS.SetTypeSpecType(2199 TagType, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec,2200 DiagID, TagOrTempResult.get(), Owned, Policy);2201 } else {2202 DS.SetTypeSpecError();2203 return;2204 }2205 2206 if (Result)2207 Diag(StartLoc, DiagID) << PrevSpec;2208 2209 // At this point, we've successfully parsed a class-specifier in 'definition'2210 // form (e.g. "struct foo { int x; }". While we could just return here, we're2211 // going to look at what comes after it to improve error recovery. If an2212 // impossible token occurs next, we assume that the programmer forgot a ; at2213 // the end of the declaration and recover that way.2214 //2215 // Also enforce C++ [temp]p3:2216 // In a template-declaration which defines a class, no declarator2217 // is permitted.2218 //2219 // After a type-specifier, we don't expect a semicolon. This only happens in2220 // C, since definitions are not permitted in this context in C++.2221 if (TUK == TagUseKind::Definition &&2222 (getLangOpts().CPlusPlus || !isTypeSpecifier(DSC)) &&2223 (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate || !isValidAfterTypeSpecifier(false))) {2224 if (Tok.isNot(tok::semi)) {2225 const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();2226 ExpectAndConsume(tok::semi, diag::err_expected_after,2227 DeclSpec::getSpecifierName(TagType, PPol));2228 // Push this token back into the preprocessor and change our current token2229 // to ';' so that the rest of the code recovers as though there were an2230 // ';' after the definition.2231 PP.EnterToken(Tok, /*IsReinject=*/true);2232 Tok.setKind(tok::semi);2233 }2234 }2235}2236 2237void Parser::ParseBaseClause(Decl *ClassDecl) {2238 assert(Tok.is(tok::colon) && "Not a base clause");2239 ConsumeToken();2240 2241 // Build up an array of parsed base specifiers.2242 SmallVector<CXXBaseSpecifier *, 8> BaseInfo;2243 2244 while (true) {2245 // Parse a base-specifier.2246 BaseResult Result = ParseBaseSpecifier(ClassDecl);2247 if (!Result.isUsable()) {2248 // Skip the rest of this base specifier, up until the comma or2249 // opening brace.2250 SkipUntil(tok::comma, tok::l_brace, StopAtSemi | StopBeforeMatch);2251 } else {2252 // Add this to our array of base specifiers.2253 BaseInfo.push_back(Result.get());2254 }2255 2256 // If the next token is a comma, consume it and keep reading2257 // base-specifiers.2258 if (!TryConsumeToken(tok::comma))2259 break;2260 }2261 2262 // Attach the base specifiers2263 Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo);2264}2265 2266BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {2267 bool IsVirtual = false;2268 SourceLocation StartLoc = Tok.getLocation();2269 2270 ParsedAttributes Attributes(AttrFactory);2271 MaybeParseCXX11Attributes(Attributes);2272 2273 // Parse the 'virtual' keyword.2274 if (TryConsumeToken(tok::kw_virtual))2275 IsVirtual = true;2276 2277 CheckMisplacedCXX11Attribute(Attributes, StartLoc);2278 2279 // Parse an (optional) access specifier.2280 AccessSpecifier Access = getAccessSpecifierIfPresent();2281 if (Access != AS_none) {2282 ConsumeToken();2283 if (getLangOpts().HLSL)2284 Diag(Tok.getLocation(), diag::ext_hlsl_access_specifiers);2285 }2286 2287 CheckMisplacedCXX11Attribute(Attributes, StartLoc);2288 2289 // Parse the 'virtual' keyword (again!), in case it came after the2290 // access specifier.2291 if (Tok.is(tok::kw_virtual)) {2292 SourceLocation VirtualLoc = ConsumeToken();2293 if (IsVirtual) {2294 // Complain about duplicate 'virtual'2295 Diag(VirtualLoc, diag::err_dup_virtual)2296 << FixItHint::CreateRemoval(VirtualLoc);2297 }2298 2299 IsVirtual = true;2300 }2301 2302 if (getLangOpts().HLSL && IsVirtual)2303 Diag(Tok.getLocation(), diag::err_hlsl_virtual_inheritance);2304 2305 CheckMisplacedCXX11Attribute(Attributes, StartLoc);2306 2307 // Parse the class-name.2308 2309 // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL2310 // implementation for VS2013 uses _Atomic as an identifier for one of the2311 // classes in <atomic>. Treat '_Atomic' to be an identifier when we are2312 // parsing the class-name for a base specifier.2313 if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) &&2314 NextToken().is(tok::less))2315 Tok.setKind(tok::identifier);2316 2317 SourceLocation EndLocation;2318 SourceLocation BaseLoc;2319 TypeResult BaseType = ParseBaseTypeSpecifier(BaseLoc, EndLocation);2320 if (BaseType.isInvalid())2321 return true;2322 2323 // Parse the optional ellipsis (for a pack expansion). The ellipsis is2324 // actually part of the base-specifier-list grammar productions, but we2325 // parse it here for convenience.2326 SourceLocation EllipsisLoc;2327 TryConsumeToken(tok::ellipsis, EllipsisLoc);2328 2329 // Find the complete source range for the base-specifier.2330 SourceRange Range(StartLoc, EndLocation);2331 2332 // Notify semantic analysis that we have parsed a complete2333 // base-specifier.2334 return Actions.ActOnBaseSpecifier(ClassDecl, Range, Attributes, IsVirtual,2335 Access, BaseType.get(), BaseLoc,2336 EllipsisLoc);2337}2338 2339AccessSpecifier Parser::getAccessSpecifierIfPresent() const {2340 switch (Tok.getKind()) {2341 default:2342 return AS_none;2343 case tok::kw_private:2344 return AS_private;2345 case tok::kw_protected:2346 return AS_protected;2347 case tok::kw_public:2348 return AS_public;2349 }2350}2351 2352void Parser::HandleMemberFunctionDeclDelays(Declarator &DeclaratorInfo,2353 Decl *ThisDecl) {2354 DeclaratorChunk::FunctionTypeInfo &FTI = DeclaratorInfo.getFunctionTypeInfo();2355 // If there was a late-parsed exception-specification, we'll need a2356 // late parse2357 bool NeedLateParse = FTI.getExceptionSpecType() == EST_Unparsed;2358 2359 if (!NeedLateParse) {2360 // Look ahead to see if there are any default args2361 for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) {2362 const auto *Param = cast<ParmVarDecl>(FTI.Params[ParamIdx].Param);2363 if (Param->hasUnparsedDefaultArg()) {2364 NeedLateParse = true;2365 break;2366 }2367 }2368 }2369 2370 if (NeedLateParse) {2371 // Push this method onto the stack of late-parsed method2372 // declarations.2373 auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);2374 getCurrentClass().LateParsedDeclarations.push_back(LateMethod);2375 2376 // Push tokens for each parameter. Those that do not have defaults will be2377 // NULL. We need to track all the parameters so that we can push them into2378 // scope for later parameters and perhaps for the exception specification.2379 LateMethod->DefaultArgs.reserve(FTI.NumParams);2380 for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx)2381 LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument(2382 FTI.Params[ParamIdx].Param,2383 std::move(FTI.Params[ParamIdx].DefaultArgTokens)));2384 2385 // Stash the exception-specification tokens in the late-pased method.2386 if (FTI.getExceptionSpecType() == EST_Unparsed) {2387 LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;2388 FTI.ExceptionSpecTokens = nullptr;2389 }2390 }2391}2392 2393VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const {2394 if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier))2395 return VirtSpecifiers::VS_None;2396 2397 const IdentifierInfo *II = Tok.getIdentifierInfo();2398 2399 // Initialize the contextual keywords.2400 if (!Ident_final) {2401 Ident_final = &PP.getIdentifierTable().get("final");2402 if (getLangOpts().GNUKeywords)2403 Ident_GNU_final = &PP.getIdentifierTable().get("__final");2404 if (getLangOpts().MicrosoftExt) {2405 Ident_sealed = &PP.getIdentifierTable().get("sealed");2406 Ident_abstract = &PP.getIdentifierTable().get("abstract");2407 }2408 Ident_override = &PP.getIdentifierTable().get("override");2409 }2410 2411 if (II == Ident_override)2412 return VirtSpecifiers::VS_Override;2413 2414 if (II == Ident_sealed)2415 return VirtSpecifiers::VS_Sealed;2416 2417 if (II == Ident_abstract)2418 return VirtSpecifiers::VS_Abstract;2419 2420 if (II == Ident_final)2421 return VirtSpecifiers::VS_Final;2422 2423 if (II == Ident_GNU_final)2424 return VirtSpecifiers::VS_GNU_Final;2425 2426 return VirtSpecifiers::VS_None;2427}2428 2429void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS,2430 bool IsInterface,2431 SourceLocation FriendLoc) {2432 while (true) {2433 VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();2434 if (Specifier == VirtSpecifiers::VS_None)2435 return;2436 2437 if (FriendLoc.isValid()) {2438 Diag(Tok.getLocation(), diag::err_friend_decl_spec)2439 << VirtSpecifiers::getSpecifierName(Specifier)2440 << FixItHint::CreateRemoval(Tok.getLocation())2441 << SourceRange(FriendLoc, FriendLoc);2442 ConsumeToken();2443 continue;2444 }2445 2446 // C++ [class.mem]p8:2447 // A virt-specifier-seq shall contain at most one of each virt-specifier.2448 const char *PrevSpec = nullptr;2449 if (VS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec))2450 Diag(Tok.getLocation(), diag::err_duplicate_virt_specifier)2451 << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation());2452 2453 if (IsInterface && (Specifier == VirtSpecifiers::VS_Final ||2454 Specifier == VirtSpecifiers::VS_Sealed)) {2455 Diag(Tok.getLocation(), diag::err_override_control_interface)2456 << VirtSpecifiers::getSpecifierName(Specifier);2457 } else if (Specifier == VirtSpecifiers::VS_Sealed) {2458 Diag(Tok.getLocation(), diag::ext_ms_sealed_keyword);2459 } else if (Specifier == VirtSpecifiers::VS_Abstract) {2460 Diag(Tok.getLocation(), diag::ext_ms_abstract_keyword);2461 } else if (Specifier == VirtSpecifiers::VS_GNU_Final) {2462 Diag(Tok.getLocation(), diag::ext_warn_gnu_final);2463 } else {2464 Diag(Tok.getLocation(),2465 getLangOpts().CPlusPlus112466 ? diag::warn_cxx98_compat_override_control_keyword2467 : diag::ext_override_control_keyword)2468 << VirtSpecifiers::getSpecifierName(Specifier);2469 }2470 ConsumeToken();2471 }2472}2473 2474bool Parser::isCXX11FinalKeyword() const {2475 VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();2476 return Specifier == VirtSpecifiers::VS_Final ||2477 Specifier == VirtSpecifiers::VS_GNU_Final ||2478 Specifier == VirtSpecifiers::VS_Sealed;2479}2480 2481bool Parser::isCXX2CTriviallyRelocatableKeyword(Token Tok) const {2482 if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier))2483 return false;2484 if (!Ident_trivially_relocatable_if_eligible)2485 Ident_trivially_relocatable_if_eligible =2486 &PP.getIdentifierTable().get("trivially_relocatable_if_eligible");2487 IdentifierInfo *II = Tok.getIdentifierInfo();2488 return II == Ident_trivially_relocatable_if_eligible;2489}2490 2491bool Parser::isCXX2CTriviallyRelocatableKeyword() const {2492 return isCXX2CTriviallyRelocatableKeyword(Tok);2493}2494 2495void Parser::ParseCXX2CTriviallyRelocatableSpecifier(SourceLocation &TRS) {2496 assert(isCXX2CTriviallyRelocatableKeyword() &&2497 "expected a trivially_relocatable specifier");2498 2499 Diag(Tok.getLocation(), getLangOpts().CPlusPlus262500 ? diag::warn_relocatable_keyword2501 : diag::ext_relocatable_keyword)2502 << /*relocatable*/ 0;2503 2504 TRS = ConsumeToken();2505}2506 2507bool Parser::isCXX2CReplaceableKeyword(Token Tok) const {2508 if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier))2509 return false;2510 if (!Ident_replaceable_if_eligible)2511 Ident_replaceable_if_eligible =2512 &PP.getIdentifierTable().get("replaceable_if_eligible");2513 IdentifierInfo *II = Tok.getIdentifierInfo();2514 return II == Ident_replaceable_if_eligible;2515}2516 2517bool Parser::isCXX2CReplaceableKeyword() const {2518 return isCXX2CReplaceableKeyword(Tok);2519}2520 2521void Parser::ParseCXX2CReplaceableSpecifier(SourceLocation &MRS) {2522 assert(isCXX2CReplaceableKeyword() &&2523 "expected a replaceable_if_eligible specifier");2524 2525 Diag(Tok.getLocation(), getLangOpts().CPlusPlus262526 ? diag::warn_relocatable_keyword2527 : diag::ext_relocatable_keyword)2528 << /*replaceable*/ 1;2529 2530 MRS = ConsumeToken();2531}2532 2533bool Parser::isClassCompatibleKeyword(Token Tok) const {2534 if (isCXX2CTriviallyRelocatableKeyword(Tok) || isCXX2CReplaceableKeyword(Tok))2535 return true;2536 VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);2537 return Specifier == VirtSpecifiers::VS_Final ||2538 Specifier == VirtSpecifiers::VS_GNU_Final ||2539 Specifier == VirtSpecifiers::VS_Sealed ||2540 Specifier == VirtSpecifiers::VS_Abstract;2541}2542 2543bool Parser::isClassCompatibleKeyword() const {2544 return isClassCompatibleKeyword(Tok);2545}2546 2547/// Parse a C++ member-declarator up to, but not including, the optional2548/// brace-or-equal-initializer or pure-specifier.2549bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(2550 Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize,2551 LateParsedAttrList &LateParsedAttrs) {2552 // member-declarator:2553 // declarator virt-specifier-seq[opt] pure-specifier[opt]2554 // declarator requires-clause2555 // declarator brace-or-equal-initializer[opt]2556 // identifier attribute-specifier-seq[opt] ':' constant-expression2557 // brace-or-equal-initializer[opt]2558 // ':' constant-expression2559 //2560 // NOTE: the latter two productions are a proposed bugfix rather than the2561 // current grammar rules as of C++20.2562 if (Tok.isNot(tok::colon))2563 ParseDeclarator(DeclaratorInfo);2564 else2565 DeclaratorInfo.SetIdentifier(nullptr, Tok.getLocation());2566 2567 if (getLangOpts().HLSL)2568 MaybeParseHLSLAnnotations(DeclaratorInfo, nullptr,2569 /*CouldBeBitField*/ true);2570 2571 if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) {2572 assert(DeclaratorInfo.isPastIdentifier() &&2573 "don't know where identifier would go yet?");2574 BitfieldSize = ParseConstantExpression();2575 if (BitfieldSize.isInvalid())2576 SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);2577 } else if (Tok.is(tok::kw_requires)) {2578 ParseTrailingRequiresClause(DeclaratorInfo);2579 } else {2580 ParseOptionalCXX11VirtSpecifierSeq(2581 VS, getCurrentClass().IsInterface,2582 DeclaratorInfo.getDeclSpec().getFriendSpecLoc());2583 if (!VS.isUnset())2584 MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo,2585 VS);2586 }2587 2588 // If a simple-asm-expr is present, parse it.2589 if (Tok.is(tok::kw_asm)) {2590 SourceLocation Loc;2591 ExprResult AsmLabel(ParseSimpleAsm(/*ForAsmLabel*/ true, &Loc));2592 if (AsmLabel.isInvalid())2593 SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);2594 2595 DeclaratorInfo.setAsmLabel(AsmLabel.get());2596 DeclaratorInfo.SetRangeEnd(Loc);2597 }2598 2599 // If attributes exist after the declarator, but before an '{', parse them.2600 // However, this does not apply for [[]] attributes (which could show up2601 // before or after the __attribute__ attributes).2602 DiagnoseAndSkipCXX11Attributes();2603 MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);2604 DiagnoseAndSkipCXX11Attributes();2605 2606 // For compatibility with code written to older Clang, also accept a2607 // virt-specifier *after* the GNU attributes.2608 if (BitfieldSize.isUnset() && VS.isUnset()) {2609 ParseOptionalCXX11VirtSpecifierSeq(2610 VS, getCurrentClass().IsInterface,2611 DeclaratorInfo.getDeclSpec().getFriendSpecLoc());2612 if (!VS.isUnset()) {2613 // If we saw any GNU-style attributes that are known to GCC followed by a2614 // virt-specifier, issue a GCC-compat warning.2615 for (const ParsedAttr &AL : DeclaratorInfo.getAttributes())2616 if (AL.isKnownToGCC() && !AL.isCXX11Attribute())2617 Diag(AL.getLoc(), diag::warn_gcc_attribute_location);2618 2619 MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo,2620 VS);2621 }2622 }2623 2624 // If this has neither a name nor a bit width, something has gone seriously2625 // wrong. Skip until the semi-colon or }.2626 if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) {2627 // If so, skip until the semi-colon or a }.2628 SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);2629 return true;2630 }2631 return false;2632}2633 2634void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(2635 Declarator &D, VirtSpecifiers &VS) {2636 DeclSpec DS(AttrFactory);2637 2638 // GNU-style and C++11 attributes are not allowed here, but they will be2639 // handled by the caller. Diagnose everything else.2640 ParseTypeQualifierListOpt(2641 DS, AR_NoAttributesParsed, /*AtomicOrPtrauthAllowed=*/false,2642 /*IdentifierRequired=*/false, [&]() {2643 Actions.CodeCompletion().CodeCompleteFunctionQualifiers(DS, D, &VS);2644 });2645 D.ExtendWithDeclSpec(DS);2646 2647 if (D.isFunctionDeclarator()) {2648 auto &Function = D.getFunctionTypeInfo();2649 if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {2650 auto DeclSpecCheck = [&](DeclSpec::TQ TypeQual, StringRef FixItName,2651 SourceLocation SpecLoc) {2652 FixItHint Insertion;2653 auto &MQ = Function.getOrCreateMethodQualifiers();2654 if (!(MQ.getTypeQualifiers() & TypeQual)) {2655 std::string Name(FixItName.data());2656 Name += " ";2657 Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);2658 MQ.SetTypeQual(TypeQual, SpecLoc);2659 }2660 Diag(SpecLoc, diag::err_declspec_after_virtspec)2661 << FixItName2662 << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())2663 << FixItHint::CreateRemoval(SpecLoc) << Insertion;2664 };2665 DS.forEachQualifier(DeclSpecCheck);2666 }2667 2668 // Parse ref-qualifiers.2669 bool RefQualifierIsLValueRef = true;2670 SourceLocation RefQualifierLoc;2671 if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) {2672 const char *Name = (RefQualifierIsLValueRef ? "& " : "&& ");2673 FixItHint Insertion =2674 FixItHint::CreateInsertion(VS.getFirstLocation(), Name);2675 Function.RefQualifierIsLValueRef = RefQualifierIsLValueRef;2676 Function.RefQualifierLoc = RefQualifierLoc;2677 2678 Diag(RefQualifierLoc, diag::err_declspec_after_virtspec)2679 << (RefQualifierIsLValueRef ? "&" : "&&")2680 << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())2681 << FixItHint::CreateRemoval(RefQualifierLoc) << Insertion;2682 D.SetRangeEnd(RefQualifierLoc);2683 }2684 }2685}2686 2687Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration(2688 AccessSpecifier AS, ParsedAttributes &AccessAttrs,2689 ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) {2690 assert(getLangOpts().CPlusPlus &&2691 "ParseCXXClassMemberDeclaration should only be called in C++ mode");2692 if (Tok.is(tok::at)) {2693 if (getLangOpts().ObjC && NextToken().isObjCAtKeyword(tok::objc_defs))2694 Diag(Tok, diag::err_at_defs_cxx);2695 else2696 Diag(Tok, diag::err_at_in_class);2697 2698 ConsumeToken();2699 SkipUntil(tok::r_brace, StopAtSemi);2700 return nullptr;2701 }2702 2703 // Turn on colon protection early, while parsing declspec, although there is2704 // nothing to protect there. It prevents from false errors if error recovery2705 // incorrectly determines where the declspec ends, as in the example:2706 // struct A { enum class B { C }; };2707 // const int C = 4;2708 // struct D { A::B : C; };2709 ColonProtectionRAIIObject X(*this);2710 2711 // Access declarations.2712 bool MalformedTypeSpec = false;2713 if (TemplateInfo.Kind == ParsedTemplateKind::NonTemplate &&2714 Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw___super)) {2715 if (TryAnnotateCXXScopeToken())2716 MalformedTypeSpec = true;2717 2718 bool isAccessDecl;2719 if (Tok.isNot(tok::annot_cxxscope))2720 isAccessDecl = false;2721 else if (NextToken().is(tok::identifier))2722 isAccessDecl = GetLookAheadToken(2).is(tok::semi);2723 else2724 isAccessDecl = NextToken().is(tok::kw_operator);2725 2726 if (isAccessDecl) {2727 // Collect the scope specifier token we annotated earlier.2728 CXXScopeSpec SS;2729 ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,2730 /*ObjectHasErrors=*/false,2731 /*EnteringContext=*/false);2732 2733 if (SS.isInvalid()) {2734 SkipUntil(tok::semi);2735 return nullptr;2736 }2737 2738 // Try to parse an unqualified-id.2739 SourceLocation TemplateKWLoc;2740 UnqualifiedId Name;2741 if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,2742 /*ObjectHadErrors=*/false, false, true, true,2743 false, &TemplateKWLoc, Name)) {2744 SkipUntil(tok::semi);2745 return nullptr;2746 }2747 2748 // TODO: recover from mistakenly-qualified operator declarations.2749 if (ExpectAndConsume(tok::semi, diag::err_expected_after,2750 "access declaration")) {2751 SkipUntil(tok::semi);2752 return nullptr;2753 }2754 2755 // FIXME: We should do something with the 'template' keyword here.2756 return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration(2757 getCurScope(), AS, /*UsingLoc*/ SourceLocation(),2758 /*TypenameLoc*/ SourceLocation(), SS, Name,2759 /*EllipsisLoc*/ SourceLocation(),2760 /*AttrList*/ ParsedAttributesView())));2761 }2762 }2763 2764 // static_assert-declaration. A templated static_assert declaration is2765 // diagnosed in Parser::ParseDeclarationAfterTemplate.2766 if (TemplateInfo.Kind == ParsedTemplateKind::NonTemplate &&2767 Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {2768 SourceLocation DeclEnd;2769 return DeclGroupPtrTy::make(2770 DeclGroupRef(ParseStaticAssertDeclaration(DeclEnd)));2771 }2772 2773 if (Tok.is(tok::kw_template)) {2774 assert(!TemplateInfo.TemplateParams &&2775 "Nested template improperly parsed?");2776 ObjCDeclContextSwitch ObjCDC(*this);2777 SourceLocation DeclEnd;2778 return ParseTemplateDeclarationOrSpecialization(DeclaratorContext::Member,2779 DeclEnd, AccessAttrs, AS);2780 }2781 2782 // Handle: member-declaration ::= '__extension__' member-declaration2783 if (Tok.is(tok::kw___extension__)) {2784 // __extension__ silences extension warnings in the subexpression.2785 ExtensionRAIIObject O(Diags); // Use RAII to do this.2786 ConsumeToken();2787 return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,2788 TemplateDiags);2789 }2790 2791 ParsedAttributes DeclAttrs(AttrFactory);2792 // Optional C++11 attribute-specifier2793 MaybeParseCXX11Attributes(DeclAttrs);2794 2795 // The next token may be an OpenMP pragma annotation token. That would2796 // normally be handled from ParseCXXClassMemberDeclarationWithPragmas, but in2797 // this case, it came from an *attribute* rather than a pragma. Handle it now.2798 if (Tok.is(tok::annot_attr_openmp))2799 return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, DeclAttrs);2800 2801 if (Tok.is(tok::kw_using)) {2802 // Eat 'using'.2803 SourceLocation UsingLoc = ConsumeToken();2804 2805 // Consume unexpected 'template' keywords.2806 while (Tok.is(tok::kw_template)) {2807 SourceLocation TemplateLoc = ConsumeToken();2808 Diag(TemplateLoc, diag::err_unexpected_template_after_using)2809 << FixItHint::CreateRemoval(TemplateLoc);2810 }2811 2812 if (Tok.is(tok::kw_namespace)) {2813 Diag(UsingLoc, diag::err_using_namespace_in_class);2814 SkipUntil(tok::semi, StopBeforeMatch);2815 return nullptr;2816 }2817 SourceLocation DeclEnd;2818 // Otherwise, it must be a using-declaration or an alias-declaration.2819 return ParseUsingDeclaration(DeclaratorContext::Member, TemplateInfo,2820 UsingLoc, DeclEnd, DeclAttrs, AS);2821 }2822 2823 ParsedAttributes DeclSpecAttrs(AttrFactory);2824 // Hold late-parsed attributes so we can attach a Decl to them later.2825 LateParsedAttrList CommonLateParsedAttrs;2826 2827 while (MaybeParseCXX11Attributes(DeclAttrs) ||2828 MaybeParseGNUAttributes(DeclSpecAttrs, &CommonLateParsedAttrs) ||2829 MaybeParseMicrosoftAttributes(DeclSpecAttrs))2830 ;2831 2832 SourceLocation DeclStart;2833 if (DeclAttrs.Range.isValid()) {2834 DeclStart = DeclSpecAttrs.Range.isInvalid()2835 ? DeclAttrs.Range.getBegin()2836 : std::min(DeclAttrs.Range.getBegin(),2837 DeclSpecAttrs.Range.getBegin());2838 } else {2839 DeclStart = DeclSpecAttrs.Range.getBegin();2840 }2841 2842 // decl-specifier-seq:2843 // Parse the common declaration-specifiers piece.2844 ParsingDeclSpec DS(*this, TemplateDiags);2845 DS.takeAttributesAppendingingFrom(DeclSpecAttrs);2846 2847 if (MalformedTypeSpec)2848 DS.SetTypeSpecError();2849 2850 // Turn off usual access checking for templates explicit specialization2851 // and instantiation.2852 // C++20 [temp.spec] 13.9/6.2853 // This disables the access checking rules for member function template2854 // explicit instantiation and explicit specialization.2855 bool IsTemplateSpecOrInst =2856 (TemplateInfo.Kind == ParsedTemplateKind::ExplicitInstantiation ||2857 TemplateInfo.Kind == ParsedTemplateKind::ExplicitSpecialization);2858 SuppressAccessChecks diagsFromTag(*this, IsTemplateSpecOrInst);2859 2860 ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DeclSpecContext::DSC_class,2861 &CommonLateParsedAttrs);2862 2863 if (IsTemplateSpecOrInst)2864 diagsFromTag.done();2865 2866 // Turn off colon protection that was set for declspec.2867 X.restore();2868 2869 if (DeclStart.isValid())2870 DS.SetRangeStart(DeclStart);2871 2872 // If we had a free-standing type definition with a missing semicolon, we2873 // may get this far before the problem becomes obvious.2874 if (DS.hasTagDefinition() &&2875 TemplateInfo.Kind == ParsedTemplateKind::NonTemplate &&2876 DiagnoseMissingSemiAfterTagDefinition(DS, AS, DeclSpecContext::DSC_class,2877 &CommonLateParsedAttrs))2878 return nullptr;2879 2880 MultiTemplateParamsArg TemplateParams(2881 TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data()2882 : nullptr,2883 TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);2884 2885 if (TryConsumeToken(tok::semi)) {2886 if (DS.isFriendSpecified())2887 ProhibitAttributes(DeclAttrs);2888 2889 RecordDecl *AnonRecord = nullptr;2890 Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(2891 getCurScope(), AS, DS, DeclAttrs, TemplateParams, false, AnonRecord);2892 Actions.ActOnDefinedDeclarationSpecifier(TheDecl);2893 DS.complete(TheDecl);2894 if (AnonRecord) {2895 Decl *decls[] = {AnonRecord, TheDecl};2896 return Actions.BuildDeclaratorGroup(decls);2897 }2898 return Actions.ConvertDeclToDeclGroup(TheDecl);2899 }2900 2901 if (DS.hasTagDefinition())2902 Actions.ActOnDefinedDeclarationSpecifier(DS.getRepAsDecl());2903 2904 // Handle C++26's variadic friend declarations. These don't even have2905 // declarators, so we get them out of the way early here.2906 if (DS.isFriendSpecifiedFirst() && Tok.isOneOf(tok::comma, tok::ellipsis)) {2907 Diag(Tok.getLocation(), getLangOpts().CPlusPlus262908 ? diag::warn_cxx23_variadic_friends2909 : diag::ext_variadic_friends);2910 2911 SourceLocation FriendLoc = DS.getFriendSpecLoc();2912 SmallVector<Decl *> Decls;2913 2914 // Handles a single friend-type-specifier.2915 auto ParsedFriendDecl = [&](ParsingDeclSpec &DeclSpec) {2916 SourceLocation VariadicLoc;2917 TryConsumeToken(tok::ellipsis, VariadicLoc);2918 2919 RecordDecl *AnonRecord = nullptr;2920 Decl *D = Actions.ParsedFreeStandingDeclSpec(2921 getCurScope(), AS, DeclSpec, DeclAttrs, TemplateParams, false,2922 AnonRecord, VariadicLoc);2923 DeclSpec.complete(D);2924 if (!D) {2925 SkipUntil(tok::semi, tok::r_brace);2926 return true;2927 }2928 2929 Decls.push_back(D);2930 return false;2931 };2932 2933 if (ParsedFriendDecl(DS))2934 return nullptr;2935 2936 while (TryConsumeToken(tok::comma)) {2937 ParsingDeclSpec DeclSpec(*this, TemplateDiags);2938 const char *PrevSpec = nullptr;2939 unsigned DiagId = 0;2940 DeclSpec.SetFriendSpec(FriendLoc, PrevSpec, DiagId);2941 ParseDeclarationSpecifiers(DeclSpec, TemplateInfo, AS,2942 DeclSpecContext::DSC_class, nullptr);2943 if (ParsedFriendDecl(DeclSpec))2944 return nullptr;2945 }2946 2947 ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt,2948 "friend declaration");2949 2950 return Actions.BuildDeclaratorGroup(Decls);2951 }2952 2953 // Befriending a concept is invalid and would already fail if2954 // we did nothing here, but this allows us to issue a more2955 // helpful diagnostic.2956 if (Tok.is(tok::kw_concept)) {2957 Diag(2958 Tok.getLocation(),2959 DS.isFriendSpecified() || NextToken().is(tok::kw_friend)2960 ? llvm::to_underlying(diag::err_friend_concept)2961 : llvm::to_underlying(2962 diag::2963 err_concept_decls_may_only_appear_in_global_namespace_scope));2964 SkipUntil(tok::semi, tok::r_brace, StopBeforeMatch);2965 return nullptr;2966 }2967 2968 ParsingDeclarator DeclaratorInfo(*this, DS, DeclAttrs,2969 DeclaratorContext::Member);2970 if (TemplateInfo.TemplateParams)2971 DeclaratorInfo.setTemplateParameterLists(TemplateParams);2972 VirtSpecifiers VS;2973 2974 // Hold late-parsed attributes so we can attach a Decl to them later.2975 LateParsedAttrList LateParsedAttrs;2976 2977 SourceLocation EqualLoc;2978 SourceLocation PureSpecLoc;2979 2980 auto TryConsumePureSpecifier = [&](bool AllowDefinition) {2981 if (Tok.isNot(tok::equal))2982 return false;2983 2984 auto &Zero = NextToken();2985 SmallString<8> Buffer;2986 if (Zero.isNot(tok::numeric_constant) ||2987 PP.getSpelling(Zero, Buffer) != "0")2988 return false;2989 2990 auto &After = GetLookAheadToken(2);2991 if (!After.isOneOf(tok::semi, tok::comma) &&2992 !(AllowDefinition &&2993 After.isOneOf(tok::l_brace, tok::colon, tok::kw_try)))2994 return false;2995 2996 EqualLoc = ConsumeToken();2997 PureSpecLoc = ConsumeToken();2998 return true;2999 };3000 3001 SmallVector<Decl *, 8> DeclsInGroup;3002 ExprResult BitfieldSize;3003 ExprResult TrailingRequiresClause;3004 bool ExpectSemi = true;3005 3006 // C++20 [temp.spec] 13.9/6.3007 // This disables the access checking rules for member function template3008 // explicit instantiation and explicit specialization.3009 SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);3010 3011 // Parse the first declarator.3012 if (ParseCXXMemberDeclaratorBeforeInitializer(3013 DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) {3014 TryConsumeToken(tok::semi);3015 return nullptr;3016 }3017 3018 if (IsTemplateSpecOrInst)3019 SAC.done();3020 3021 // Check for a member function definition.3022 if (BitfieldSize.isUnset()) {3023 // MSVC permits pure specifier on inline functions defined at class scope.3024 // Hence check for =0 before checking for function definition.3025 if (getLangOpts().MicrosoftExt && DeclaratorInfo.isDeclarationOfFunction())3026 TryConsumePureSpecifier(/*AllowDefinition*/ true);3027 3028 FunctionDefinitionKind DefinitionKind = FunctionDefinitionKind::Declaration;3029 // function-definition:3030 //3031 // In C++11, a non-function declarator followed by an open brace is a3032 // braced-init-list for an in-class member initialization, not an3033 // erroneous function definition.3034 if (Tok.is(tok::l_brace) && !getLangOpts().CPlusPlus11) {3035 DefinitionKind = FunctionDefinitionKind::Definition;3036 } else if (DeclaratorInfo.isFunctionDeclarator()) {3037 if (Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try)) {3038 DefinitionKind = FunctionDefinitionKind::Definition;3039 } else if (Tok.is(tok::equal)) {3040 const Token &KW = NextToken();3041 if (KW.is(tok::kw_default))3042 DefinitionKind = FunctionDefinitionKind::Defaulted;3043 else if (KW.is(tok::kw_delete))3044 DefinitionKind = FunctionDefinitionKind::Deleted;3045 else if (KW.is(tok::code_completion)) {3046 cutOffParsing();3047 Actions.CodeCompletion().CodeCompleteAfterFunctionEquals(3048 DeclaratorInfo);3049 return nullptr;3050 }3051 }3052 }3053 DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind);3054 3055 // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains3056 // to a friend declaration, that declaration shall be a definition.3057 if (DeclaratorInfo.isFunctionDeclarator() &&3058 DefinitionKind == FunctionDefinitionKind::Declaration &&3059 DS.isFriendSpecified()) {3060 // Diagnose attributes that appear before decl specifier:3061 // [[]] friend int foo();3062 ProhibitAttributes(DeclAttrs);3063 }3064 3065 if (DefinitionKind != FunctionDefinitionKind::Declaration) {3066 if (!DeclaratorInfo.isFunctionDeclarator()) {3067 Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params);3068 ConsumeBrace();3069 SkipUntil(tok::r_brace);3070 3071 // Consume the optional ';'3072 TryConsumeToken(tok::semi);3073 3074 return nullptr;3075 }3076 3077 if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {3078 Diag(DeclaratorInfo.getIdentifierLoc(),3079 diag::err_function_declared_typedef);3080 3081 // Recover by treating the 'typedef' as spurious.3082 DS.ClearStorageClassSpecs();3083 }3084 3085 Decl *FunDecl = ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo,3086 TemplateInfo, VS, PureSpecLoc);3087 3088 if (FunDecl) {3089 for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) {3090 CommonLateParsedAttrs[i]->addDecl(FunDecl);3091 }3092 for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {3093 LateParsedAttrs[i]->addDecl(FunDecl);3094 }3095 }3096 LateParsedAttrs.clear();3097 3098 // Consume the ';' - it's optional unless we have a delete or default3099 if (Tok.is(tok::semi))3100 ConsumeExtraSemi(ExtraSemiKind::AfterMemberFunctionDefinition);3101 3102 return DeclGroupPtrTy::make(DeclGroupRef(FunDecl));3103 }3104 }3105 3106 // member-declarator-list:3107 // member-declarator3108 // member-declarator-list ',' member-declarator3109 3110 while (true) {3111 InClassInitStyle HasInClassInit = ICIS_NoInit;3112 bool HasStaticInitializer = false;3113 if (Tok.isOneOf(tok::equal, tok::l_brace) && PureSpecLoc.isInvalid()) {3114 // DRXXXX: Anonymous bit-fields cannot have a brace-or-equal-initializer.3115 if (BitfieldSize.isUsable() && !DeclaratorInfo.hasName()) {3116 // Diagnose the error and pretend there is no in-class initializer.3117 Diag(Tok, diag::err_anon_bitfield_member_init);3118 SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);3119 } else if (DeclaratorInfo.isDeclarationOfFunction()) {3120 // It's a pure-specifier.3121 if (!TryConsumePureSpecifier(/*AllowFunctionDefinition*/ false))3122 // Parse it as an expression so that Sema can diagnose it.3123 HasStaticInitializer = true;3124 } else if (DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=3125 DeclSpec::SCS_static &&3126 DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=3127 DeclSpec::SCS_typedef &&3128 !DS.isFriendSpecified() &&3129 TemplateInfo.Kind == ParsedTemplateKind::NonTemplate) {3130 // It's a default member initializer.3131 if (BitfieldSize.get())3132 Diag(Tok, getLangOpts().CPlusPlus203133 ? diag::warn_cxx17_compat_bitfield_member_init3134 : diag::ext_bitfield_member_init);3135 HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit;3136 } else {3137 HasStaticInitializer = true;3138 }3139 }3140 3141 // NOTE: If Sema is the Action module and declarator is an instance field,3142 // this call will *not* return the created decl; It will return null.3143 // See Sema::ActOnCXXMemberDeclarator for details.3144 3145 NamedDecl *ThisDecl = nullptr;3146 if (DS.isFriendSpecified()) {3147 // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains3148 // to a friend declaration, that declaration shall be a definition.3149 //3150 // Diagnose attributes that appear in a friend member function declarator:3151 // friend int foo [[]] ();3152 for (const ParsedAttr &AL : DeclaratorInfo.getAttributes())3153 if (AL.isCXX11Attribute() || AL.isRegularKeywordAttribute()) {3154 auto Loc = AL.getRange().getBegin();3155 (AL.isRegularKeywordAttribute()3156 ? Diag(Loc, diag::err_keyword_not_allowed) << AL3157 : Diag(Loc, diag::err_attributes_not_allowed))3158 << AL.getRange();3159 }3160 3161 ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,3162 TemplateParams);3163 } else {3164 ThisDecl = Actions.ActOnCXXMemberDeclarator(3165 getCurScope(), AS, DeclaratorInfo, TemplateParams, BitfieldSize.get(),3166 VS, HasInClassInit);3167 3168 if (VarTemplateDecl *VT =3169 ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : nullptr)3170 // Re-direct this decl to refer to the templated decl so that we can3171 // initialize it.3172 ThisDecl = VT->getTemplatedDecl();3173 3174 if (ThisDecl)3175 Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs);3176 }3177 3178 // Error recovery might have converted a non-static member into a static3179 // member.3180 if (HasInClassInit != ICIS_NoInit &&3181 DeclaratorInfo.getDeclSpec().getStorageClassSpec() ==3182 DeclSpec::SCS_static) {3183 HasInClassInit = ICIS_NoInit;3184 HasStaticInitializer = true;3185 }3186 3187 if (PureSpecLoc.isValid() && VS.getAbstractLoc().isValid()) {3188 Diag(PureSpecLoc, diag::err_duplicate_virt_specifier) << "abstract";3189 }3190 if (ThisDecl && PureSpecLoc.isValid())3191 Actions.ActOnPureSpecifier(ThisDecl, PureSpecLoc);3192 else if (ThisDecl && VS.getAbstractLoc().isValid())3193 Actions.ActOnPureSpecifier(ThisDecl, VS.getAbstractLoc());3194 3195 // Handle the initializer.3196 if (HasInClassInit != ICIS_NoInit) {3197 // The initializer was deferred; parse it and cache the tokens.3198 Diag(Tok, getLangOpts().CPlusPlus113199 ? diag::warn_cxx98_compat_nonstatic_member_init3200 : diag::ext_nonstatic_member_init);3201 3202 if (DeclaratorInfo.isArrayOfUnknownBound()) {3203 // C++11 [dcl.array]p3: An array bound may also be omitted when the3204 // declarator is followed by an initializer.3205 //3206 // A brace-or-equal-initializer for a member-declarator is not an3207 // initializer in the grammar, so this is ill-formed.3208 Diag(Tok, diag::err_incomplete_array_member_init);3209 SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);3210 3211 // Avoid later warnings about a class member of incomplete type.3212 if (ThisDecl)3213 ThisDecl->setInvalidDecl();3214 } else3215 ParseCXXNonStaticMemberInitializer(ThisDecl);3216 } else if (HasStaticInitializer) {3217 // Normal initializer.3218 ExprResult Init = ParseCXXMemberInitializer(3219 ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);3220 3221 if (Init.isInvalid()) {3222 if (ThisDecl)3223 Actions.ActOnUninitializedDecl(ThisDecl);3224 SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);3225 } else if (ThisDecl)3226 Actions.AddInitializerToDecl(ThisDecl, Init.get(),3227 EqualLoc.isInvalid());3228 } else if (ThisDecl && DeclaratorInfo.isStaticMember())3229 // No initializer.3230 Actions.ActOnUninitializedDecl(ThisDecl);3231 3232 if (ThisDecl) {3233 if (!ThisDecl->isInvalidDecl()) {3234 // Set the Decl for any late parsed attributes3235 for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i)3236 CommonLateParsedAttrs[i]->addDecl(ThisDecl);3237 3238 for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i)3239 LateParsedAttrs[i]->addDecl(ThisDecl);3240 }3241 Actions.FinalizeDeclaration(ThisDecl);3242 DeclsInGroup.push_back(ThisDecl);3243 3244 if (DeclaratorInfo.isFunctionDeclarator() &&3245 DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=3246 DeclSpec::SCS_typedef)3247 HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl);3248 }3249 LateParsedAttrs.clear();3250 3251 DeclaratorInfo.complete(ThisDecl);3252 3253 // If we don't have a comma, it is either the end of the list (a ';')3254 // or an error, bail out.3255 SourceLocation CommaLoc;3256 if (!TryConsumeToken(tok::comma, CommaLoc))3257 break;3258 3259 if (Tok.isAtStartOfLine() &&3260 !MightBeDeclarator(DeclaratorContext::Member)) {3261 // This comma was followed by a line-break and something which can't be3262 // the start of a declarator. The comma was probably a typo for a3263 // semicolon.3264 Diag(CommaLoc, diag::err_expected_semi_declaration)3265 << FixItHint::CreateReplacement(CommaLoc, ";");3266 ExpectSemi = false;3267 break;3268 }3269 3270 // C++23 [temp.pre]p5:3271 // In a template-declaration, explicit specialization, or explicit3272 // instantiation the init-declarator-list in the declaration shall3273 // contain at most one declarator.3274 if (TemplateInfo.Kind != ParsedTemplateKind::NonTemplate &&3275 DeclaratorInfo.isFirstDeclarator()) {3276 Diag(CommaLoc, diag::err_multiple_template_declarators)3277 << TemplateInfo.Kind;3278 }3279 3280 // Parse the next declarator.3281 DeclaratorInfo.clear();3282 VS.clear();3283 BitfieldSize = ExprResult(/*Invalid=*/false);3284 EqualLoc = PureSpecLoc = SourceLocation();3285 DeclaratorInfo.setCommaLoc(CommaLoc);3286 3287 // GNU attributes are allowed before the second and subsequent declarator.3288 // However, this does not apply for [[]] attributes (which could show up3289 // before or after the __attribute__ attributes).3290 DiagnoseAndSkipCXX11Attributes();3291 MaybeParseGNUAttributes(DeclaratorInfo);3292 DiagnoseAndSkipCXX11Attributes();3293 3294 if (ParseCXXMemberDeclaratorBeforeInitializer(3295 DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs))3296 break;3297 }3298 3299 if (ExpectSemi &&3300 ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) {3301 // Skip to end of block or statement.3302 SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);3303 // If we stopped at a ';', eat it.3304 TryConsumeToken(tok::semi);3305 return nullptr;3306 }3307 3308 return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);3309}3310 3311ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,3312 SourceLocation &EqualLoc) {3313 assert(Tok.isOneOf(tok::equal, tok::l_brace) &&3314 "Data member initializer not starting with '=' or '{'");3315 3316 bool IsFieldInitialization = isa_and_present<FieldDecl>(D);3317 3318 EnterExpressionEvaluationContext Context(3319 Actions,3320 IsFieldInitialization3321 ? Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed3322 : Sema::ExpressionEvaluationContext::PotentiallyEvaluated,3323 D);3324 3325 // CWG27603326 // Default member initializers used to initialize a base or member subobject3327 // [...] are considered to be part of the function body3328 Actions.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =3329 IsFieldInitialization;3330 3331 if (TryConsumeToken(tok::equal, EqualLoc)) {3332 if (Tok.is(tok::kw_delete)) {3333 // In principle, an initializer of '= delete p;' is legal, but it will3334 // never type-check. It's better to diagnose it as an ill-formed3335 // expression than as an ill-formed deleted non-function member. An3336 // initializer of '= delete p, foo' will never be parsed, because a3337 // top-level comma always ends the initializer expression.3338 const Token &Next = NextToken();3339 if (IsFunction || Next.isOneOf(tok::semi, tok::comma, tok::eof)) {3340 if (IsFunction)3341 Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)3342 << 1 /* delete */;3343 else3344 Diag(ConsumeToken(), diag::err_deleted_non_function);3345 SkipDeletedFunctionBody();3346 return ExprError();3347 }3348 } else if (Tok.is(tok::kw_default)) {3349 if (IsFunction)3350 Diag(Tok, diag::err_default_delete_in_multiple_declaration)3351 << 0 /* default */;3352 else3353 Diag(ConsumeToken(), diag::err_default_special_members)3354 << getLangOpts().CPlusPlus20;3355 return ExprError();3356 }3357 }3358 if (const auto *PD = dyn_cast_or_null<MSPropertyDecl>(D)) {3359 Diag(Tok, diag::err_ms_property_initializer) << PD;3360 return ExprError();3361 }3362 return ParseInitializer(D);3363}3364 3365void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,3366 SourceLocation AttrFixitLoc,3367 unsigned TagType, Decl *TagDecl) {3368 // Skip the optional 'final' keyword.3369 while (isClassCompatibleKeyword())3370 ConsumeToken();3371 3372 // Diagnose any C++11 attributes after 'final' keyword.3373 // We deliberately discard these attributes.3374 ParsedAttributes Attrs(AttrFactory);3375 CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);3376 3377 // This can only happen if we had malformed misplaced attributes;3378 // we only get called if there is a colon or left-brace after the3379 // attributes.3380 if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_brace))3381 return;3382 3383 // Skip the base clauses. This requires actually parsing them, because3384 // otherwise we can't be sure where they end (a left brace may appear3385 // within a template argument).3386 if (Tok.is(tok::colon)) {3387 // Enter the scope of the class so that we can correctly parse its bases.3388 ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope);3389 ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true,3390 TagType == DeclSpec::TST_interface);3391 auto OldContext =3392 Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl);3393 3394 // Parse the bases but don't attach them to the class.3395 ParseBaseClause(nullptr);3396 3397 Actions.ActOnTagFinishSkippedDefinition(OldContext);3398 3399 if (!Tok.is(tok::l_brace)) {3400 Diag(PP.getLocForEndOfToken(PrevTokLocation),3401 diag::err_expected_lbrace_after_base_specifiers);3402 return;3403 }3404 }3405 3406 // Skip the body.3407 assert(Tok.is(tok::l_brace));3408 BalancedDelimiterTracker T(*this, tok::l_brace);3409 T.consumeOpen();3410 T.skipToEnd();3411 3412 // Parse and discard any trailing attributes.3413 if (Tok.is(tok::kw___attribute)) {3414 ParsedAttributes Attrs(AttrFactory);3415 MaybeParseGNUAttributes(Attrs);3416 }3417}3418 3419Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(3420 AccessSpecifier &AS, ParsedAttributes &AccessAttrs, DeclSpec::TST TagType,3421 Decl *TagDecl) {3422 ParenBraceBracketBalancer BalancerRAIIObj(*this);3423 3424 switch (Tok.getKind()) {3425 case tok::kw___if_exists:3426 case tok::kw___if_not_exists:3427 ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, AS);3428 return nullptr;3429 3430 case tok::semi:3431 // Check for extraneous top-level semicolon.3432 ConsumeExtraSemi(ExtraSemiKind::InsideStruct, TagType);3433 return nullptr;3434 3435 // Handle pragmas that can appear as member declarations.3436 case tok::annot_pragma_vis:3437 HandlePragmaVisibility();3438 return nullptr;3439 case tok::annot_pragma_pack:3440 HandlePragmaPack();3441 return nullptr;3442 case tok::annot_pragma_align:3443 HandlePragmaAlign();3444 return nullptr;3445 case tok::annot_pragma_ms_pointers_to_members:3446 HandlePragmaMSPointersToMembers();3447 return nullptr;3448 case tok::annot_pragma_ms_pragma:3449 HandlePragmaMSPragma();3450 return nullptr;3451 case tok::annot_pragma_ms_vtordisp:3452 HandlePragmaMSVtorDisp();3453 return nullptr;3454 case tok::annot_pragma_dump:3455 HandlePragmaDump();3456 return nullptr;3457 3458 case tok::kw_namespace:3459 // If we see a namespace here, a close brace was missing somewhere.3460 DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));3461 return nullptr;3462 3463 case tok::kw_private:3464 // FIXME: We don't accept GNU attributes on access specifiers in OpenCL mode3465 // yet.3466 if (getLangOpts().OpenCL && !NextToken().is(tok::colon)) {3467 ParsedTemplateInfo TemplateInfo;3468 return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo);3469 }3470 [[fallthrough]];3471 case tok::kw_public:3472 case tok::kw_protected: {3473 if (getLangOpts().HLSL)3474 Diag(Tok.getLocation(), diag::ext_hlsl_access_specifiers);3475 AccessSpecifier NewAS = getAccessSpecifierIfPresent();3476 assert(NewAS != AS_none);3477 // Current token is a C++ access specifier.3478 AS = NewAS;3479 SourceLocation ASLoc = Tok.getLocation();3480 unsigned TokLength = Tok.getLength();3481 ConsumeToken();3482 AccessAttrs.clear();3483 MaybeParseGNUAttributes(AccessAttrs);3484 3485 SourceLocation EndLoc;3486 if (TryConsumeToken(tok::colon, EndLoc)) {3487 } else if (TryConsumeToken(tok::semi, EndLoc)) {3488 Diag(EndLoc, diag::err_expected)3489 << tok::colon << FixItHint::CreateReplacement(EndLoc, ":");3490 } else {3491 EndLoc = ASLoc.getLocWithOffset(TokLength);3492 Diag(EndLoc, diag::err_expected)3493 << tok::colon << FixItHint::CreateInsertion(EndLoc, ":");3494 }3495 3496 // The Microsoft extension __interface does not permit non-public3497 // access specifiers.3498 if (TagType == DeclSpec::TST_interface && AS != AS_public) {3499 Diag(ASLoc, diag::err_access_specifier_interface) << (AS == AS_protected);3500 }3501 3502 if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, AccessAttrs)) {3503 // found another attribute than only annotations3504 AccessAttrs.clear();3505 }3506 3507 return nullptr;3508 }3509 3510 case tok::annot_attr_openmp:3511 case tok::annot_pragma_openmp:3512 return ParseOpenMPDeclarativeDirectiveWithExtDecl(3513 AS, AccessAttrs, /*Delayed=*/true, TagType, TagDecl);3514 case tok::annot_pragma_openacc:3515 return ParseOpenACCDirectiveDecl(AS, AccessAttrs, TagType, TagDecl);3516 3517 default:3518 if (tok::isPragmaAnnotation(Tok.getKind())) {3519 Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl)3520 << DeclSpec::getSpecifierName(3521 TagType, Actions.getASTContext().getPrintingPolicy());3522 ConsumeAnnotationToken();3523 return nullptr;3524 }3525 ParsedTemplateInfo TemplateInfo;3526 return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo);3527 }3528}3529 3530void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,3531 SourceLocation AttrFixitLoc,3532 ParsedAttributes &Attrs,3533 unsigned TagType, Decl *TagDecl) {3534 assert((TagType == DeclSpec::TST_struct ||3535 TagType == DeclSpec::TST_interface ||3536 TagType == DeclSpec::TST_union || TagType == DeclSpec::TST_class) &&3537 "Invalid TagType!");3538 3539 llvm::TimeTraceScope TimeScope("ParseClass", [&]() {3540 if (auto *TD = dyn_cast_or_null<NamedDecl>(TagDecl))3541 return TD->getQualifiedNameAsString();3542 return std::string("<anonymous>");3543 });3544 3545 PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,3546 "parsing struct/union/class body");3547 3548 // Determine whether this is a non-nested class. Note that local3549 // classes are *not* considered to be nested classes.3550 bool NonNestedClass = true;3551 if (!ClassStack.empty()) {3552 for (const Scope *S = getCurScope(); S; S = S->getParent()) {3553 if (S->isClassScope()) {3554 // We're inside a class scope, so this is a nested class.3555 NonNestedClass = false;3556 3557 // The Microsoft extension __interface does not permit nested classes.3558 if (getCurrentClass().IsInterface) {3559 Diag(RecordLoc, diag::err_invalid_member_in_interface)3560 << /*ErrorType=*/63561 << (isa<NamedDecl>(TagDecl)3562 ? cast<NamedDecl>(TagDecl)->getQualifiedNameAsString()3563 : "(anonymous)");3564 }3565 break;3566 }3567 3568 if (S->isFunctionScope())3569 // If we're in a function or function template then this is a local3570 // class rather than a nested class.3571 break;3572 }3573 }3574 3575 // Enter a scope for the class.3576 ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope);3577 3578 // Note that we are parsing a new (potentially-nested) class definition.3579 ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass,3580 TagType == DeclSpec::TST_interface);3581 3582 if (TagDecl)3583 Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);3584 3585 SourceLocation FinalLoc;3586 SourceLocation AbstractLoc;3587 bool IsFinalSpelledSealed = false;3588 bool IsAbstract = false;3589 SourceLocation TriviallyRelocatable;3590 SourceLocation Replaceable;3591 3592 // Parse the optional 'final' keyword.3593 if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {3594 while (true) {3595 VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);3596 if (Specifier == VirtSpecifiers::VS_None) {3597 if (isCXX2CTriviallyRelocatableKeyword(Tok)) {3598 if (TriviallyRelocatable.isValid()) {3599 auto Skipped = Tok;3600 ConsumeToken();3601 Diag(Skipped, diag::err_duplicate_class_relocation_specifier)3602 << /*trivial_relocatable*/ 0 << TriviallyRelocatable;3603 } else {3604 ParseCXX2CTriviallyRelocatableSpecifier(TriviallyRelocatable);3605 }3606 continue;3607 }3608 if (isCXX2CReplaceableKeyword(Tok)) {3609 if (Replaceable.isValid()) {3610 auto Skipped = Tok;3611 ConsumeToken();3612 Diag(Skipped, diag::err_duplicate_class_relocation_specifier)3613 << /*replaceable*/ 1 << Replaceable;3614 } else {3615 ParseCXX2CReplaceableSpecifier(Replaceable);3616 }3617 continue;3618 }3619 break;3620 }3621 if (isCXX11FinalKeyword()) {3622 if (FinalLoc.isValid()) {3623 auto Skipped = ConsumeToken();3624 Diag(Skipped, diag::err_duplicate_class_virt_specifier)3625 << VirtSpecifiers::getSpecifierName(Specifier);3626 } else {3627 FinalLoc = ConsumeToken();3628 if (Specifier == VirtSpecifiers::VS_Sealed)3629 IsFinalSpelledSealed = true;3630 }3631 } else {3632 if (AbstractLoc.isValid()) {3633 auto Skipped = ConsumeToken();3634 Diag(Skipped, diag::err_duplicate_class_virt_specifier)3635 << VirtSpecifiers::getSpecifierName(Specifier);3636 } else {3637 AbstractLoc = ConsumeToken();3638 IsAbstract = true;3639 }3640 }3641 if (TagType == DeclSpec::TST_interface)3642 Diag(FinalLoc, diag::err_override_control_interface)3643 << VirtSpecifiers::getSpecifierName(Specifier);3644 else if (Specifier == VirtSpecifiers::VS_Final)3645 Diag(FinalLoc, getLangOpts().CPlusPlus113646 ? diag::warn_cxx98_compat_override_control_keyword3647 : diag::ext_override_control_keyword)3648 << VirtSpecifiers::getSpecifierName(Specifier);3649 else if (Specifier == VirtSpecifiers::VS_Sealed)3650 Diag(FinalLoc, diag::ext_ms_sealed_keyword);3651 else if (Specifier == VirtSpecifiers::VS_Abstract)3652 Diag(AbstractLoc, diag::ext_ms_abstract_keyword);3653 else if (Specifier == VirtSpecifiers::VS_GNU_Final)3654 Diag(FinalLoc, diag::ext_warn_gnu_final);3655 }3656 assert((FinalLoc.isValid() || AbstractLoc.isValid() ||3657 TriviallyRelocatable.isValid() || Replaceable.isValid()) &&3658 "not a class definition");3659 3660 // Parse any C++11 attributes after 'final' keyword.3661 // These attributes are not allowed to appear here,3662 // and the only possible place for them to appertain3663 // to the class would be between class-key and class-name.3664 CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);3665 3666 // ParseClassSpecifier() does only a superficial check for attributes before3667 // deciding to call this method. For example, for3668 // `class C final alignas ([l) {` it will decide that this looks like a3669 // misplaced attribute since it sees `alignas '(' ')'`. But the actual3670 // attribute parsing code will try to parse the '[' as a constexpr lambda3671 // and consume enough tokens that the alignas parsing code will eat the3672 // opening '{'. So bail out if the next token isn't one we expect.3673 if (!Tok.is(tok::colon) && !Tok.is(tok::l_brace)) {3674 if (TagDecl)3675 Actions.ActOnTagDefinitionError(getCurScope(), TagDecl);3676 return;3677 }3678 }3679 3680 if (Tok.is(tok::colon)) {3681 ParseScope InheritanceScope(this, getCurScope()->getFlags() |3682 Scope::ClassInheritanceScope);3683 3684 ParseBaseClause(TagDecl);3685 if (!Tok.is(tok::l_brace)) {3686 bool SuggestFixIt = false;3687 SourceLocation BraceLoc = PP.getLocForEndOfToken(PrevTokLocation);3688 if (Tok.isAtStartOfLine()) {3689 switch (Tok.getKind()) {3690 case tok::kw_private:3691 case tok::kw_protected:3692 case tok::kw_public:3693 SuggestFixIt = NextToken().getKind() == tok::colon;3694 break;3695 case tok::kw_static_assert:3696 case tok::r_brace:3697 case tok::kw_using:3698 // base-clause can have simple-template-id; 'template' can't be there3699 case tok::kw_template:3700 SuggestFixIt = true;3701 break;3702 case tok::identifier:3703 SuggestFixIt = isConstructorDeclarator(true);3704 break;3705 default:3706 SuggestFixIt = isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);3707 break;3708 }3709 }3710 DiagnosticBuilder LBraceDiag =3711 Diag(BraceLoc, diag::err_expected_lbrace_after_base_specifiers);3712 if (SuggestFixIt) {3713 LBraceDiag << FixItHint::CreateInsertion(BraceLoc, " {");3714 // Try recovering from missing { after base-clause.3715 PP.EnterToken(Tok, /*IsReinject*/ true);3716 Tok.setKind(tok::l_brace);3717 } else {3718 if (TagDecl)3719 Actions.ActOnTagDefinitionError(getCurScope(), TagDecl);3720 return;3721 }3722 }3723 }3724 3725 assert(Tok.is(tok::l_brace));3726 BalancedDelimiterTracker T(*this, tok::l_brace);3727 T.consumeOpen();3728 3729 if (TagDecl)3730 Actions.ActOnStartCXXMemberDeclarations(3731 getCurScope(), TagDecl, FinalLoc, IsFinalSpelledSealed, IsAbstract,3732 TriviallyRelocatable, Replaceable, T.getOpenLocation());3733 3734 // C++ 11p3: Members of a class defined with the keyword class are private3735 // by default. Members of a class defined with the keywords struct or union3736 // are public by default.3737 // HLSL: In HLSL members of a class are public by default.3738 AccessSpecifier CurAS;3739 if (TagType == DeclSpec::TST_class && !getLangOpts().HLSL)3740 CurAS = AS_private;3741 else3742 CurAS = AS_public;3743 ParsedAttributes AccessAttrs(AttrFactory);3744 3745 if (TagDecl) {3746 // While we still have something to read, read the member-declarations.3747 while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&3748 Tok.isNot(tok::eof)) {3749 // Each iteration of this loop reads one member-declaration.3750 ParseCXXClassMemberDeclarationWithPragmas(3751 CurAS, AccessAttrs, static_cast<DeclSpec::TST>(TagType), TagDecl);3752 MaybeDestroyTemplateIds();3753 }3754 T.consumeClose();3755 } else {3756 SkipUntil(tok::r_brace);3757 }3758 3759 // If attributes exist after class contents, parse them.3760 ParsedAttributes attrs(AttrFactory);3761 MaybeParseGNUAttributes(attrs);3762 3763 if (TagDecl)3764 Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl,3765 T.getOpenLocation(),3766 T.getCloseLocation(), attrs);3767 3768 // C++11 [class.mem]p2:3769 // Within the class member-specification, the class is regarded as complete3770 // within function bodies, default arguments, exception-specifications, and3771 // brace-or-equal-initializers for non-static data members (including such3772 // things in nested classes).3773 if (TagDecl && NonNestedClass) {3774 // We are not inside a nested class. This class and its nested classes3775 // are complete and we can parse the delayed portions of method3776 // declarations and the lexed inline method definitions, along with any3777 // delayed attributes.3778 3779 SourceLocation SavedPrevTokLocation = PrevTokLocation;3780 ParseLexedPragmas(getCurrentClass());3781 ParseLexedAttributes(getCurrentClass());3782 ParseLexedMethodDeclarations(getCurrentClass());3783 3784 // We've finished with all pending member declarations.3785 Actions.ActOnFinishCXXMemberDecls();3786 3787 ParseLexedMemberInitializers(getCurrentClass());3788 ParseLexedMethodDefs(getCurrentClass());3789 PrevTokLocation = SavedPrevTokLocation;3790 3791 // We've finished parsing everything, including default argument3792 // initializers.3793 Actions.ActOnFinishCXXNonNestedClass();3794 }3795 3796 if (TagDecl)3797 Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange());3798 3799 // Leave the class scope.3800 ParsingDef.Pop();3801 ClassScope.Exit();3802}3803 3804void Parser::DiagnoseUnexpectedNamespace(NamedDecl *D) {3805 assert(Tok.is(tok::kw_namespace));3806 3807 // FIXME: Suggest where the close brace should have gone by looking3808 // at indentation changes within the definition body.3809 Diag(D->getLocation(), diag::err_missing_end_of_definition) << D;3810 Diag(Tok.getLocation(), diag::note_missing_end_of_definition_before) << D;3811 3812 // Push '};' onto the token stream to recover.3813 PP.EnterToken(Tok, /*IsReinject*/ true);3814 3815 Tok.startToken();3816 Tok.setLocation(PP.getLocForEndOfToken(PrevTokLocation));3817 Tok.setKind(tok::semi);3818 PP.EnterToken(Tok, /*IsReinject*/ true);3819 3820 Tok.setKind(tok::r_brace);3821}3822 3823void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {3824 assert(Tok.is(tok::colon) &&3825 "Constructor initializer always starts with ':'");3826 3827 // Poison the SEH identifiers so they are flagged as illegal in constructor3828 // initializers.3829 PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true);3830 SourceLocation ColonLoc = ConsumeToken();3831 3832 SmallVector<CXXCtorInitializer *, 4> MemInitializers;3833 bool AnyErrors = false;3834 3835 do {3836 if (Tok.is(tok::code_completion)) {3837 cutOffParsing();3838 Actions.CodeCompletion().CodeCompleteConstructorInitializer(3839 ConstructorDecl, MemInitializers);3840 return;3841 }3842 3843 MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);3844 if (!MemInit.isInvalid())3845 MemInitializers.push_back(MemInit.get());3846 else3847 AnyErrors = true;3848 3849 if (Tok.is(tok::comma))3850 ConsumeToken();3851 else if (Tok.is(tok::l_brace))3852 break;3853 // If the previous initializer was valid and the next token looks like a3854 // base or member initializer, assume that we're just missing a comma.3855 else if (!MemInit.isInvalid() &&3856 Tok.isOneOf(tok::identifier, tok::coloncolon)) {3857 SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation);3858 Diag(Loc, diag::err_ctor_init_missing_comma)3859 << FixItHint::CreateInsertion(Loc, ", ");3860 } else {3861 // Skip over garbage, until we get to '{'. Don't eat the '{'.3862 if (!MemInit.isInvalid())3863 Diag(Tok.getLocation(), diag::err_expected_either)3864 << tok::l_brace << tok::comma;3865 SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);3866 break;3867 }3868 } while (true);3869 3870 Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc, MemInitializers,3871 AnyErrors);3872}3873 3874MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {3875 // parse '::'[opt] nested-name-specifier[opt]3876 CXXScopeSpec SS;3877 if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,3878 /*ObjectHasErrors=*/false,3879 /*EnteringContext=*/false))3880 return true;3881 3882 // : identifier3883 IdentifierInfo *II = nullptr;3884 SourceLocation IdLoc = Tok.getLocation();3885 // : declype(...)3886 DeclSpec DS(AttrFactory);3887 // : template_name<...>3888 TypeResult TemplateTypeTy;3889 3890 if (Tok.is(tok::identifier)) {3891 // Get the identifier. This may be a member name or a class name,3892 // but we'll let the semantic analysis determine which it is.3893 II = Tok.getIdentifierInfo();3894 ConsumeToken();3895 } else if (Tok.is(tok::annot_decltype)) {3896 // Get the decltype expression, if there is one.3897 // Uses of decltype will already have been converted to annot_decltype by3898 // ParseOptionalCXXScopeSpecifier at this point.3899 // FIXME: Can we get here with a scope specifier?3900 ParseDecltypeSpecifier(DS);3901 } else if (Tok.is(tok::annot_pack_indexing_type)) {3902 // Uses of T...[N] will already have been converted to3903 // annot_pack_indexing_type by ParseOptionalCXXScopeSpecifier at this point.3904 ParsePackIndexingType(DS);3905 } else {3906 TemplateIdAnnotation *TemplateId = Tok.is(tok::annot_template_id)3907 ? takeTemplateIdAnnotation(Tok)3908 : nullptr;3909 if (TemplateId && TemplateId->mightBeType()) {3910 AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No,3911 /*IsClassName=*/true);3912 assert(Tok.is(tok::annot_typename) && "template-id -> type failed");3913 TemplateTypeTy = getTypeAnnotation(Tok);3914 ConsumeAnnotationToken();3915 } else {3916 Diag(Tok, diag::err_expected_member_or_base_name);3917 return true;3918 }3919 }3920 3921 // Parse the '('.3922 if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {3923 Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);3924 3925 // FIXME: Add support for signature help inside initializer lists.3926 ExprResult InitList = ParseBraceInitializer();3927 if (InitList.isInvalid())3928 return true;3929 3930 SourceLocation EllipsisLoc;3931 TryConsumeToken(tok::ellipsis, EllipsisLoc);3932 3933 if (TemplateTypeTy.isInvalid())3934 return true;3935 return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,3936 TemplateTypeTy.get(), DS, IdLoc,3937 InitList.get(), EllipsisLoc);3938 } else if (Tok.is(tok::l_paren)) {3939 BalancedDelimiterTracker T(*this, tok::l_paren);3940 T.consumeOpen();3941 3942 // Parse the optional expression-list.3943 ExprVector ArgExprs;3944 auto RunSignatureHelp = [&] {3945 if (TemplateTypeTy.isInvalid())3946 return QualType();3947 QualType PreferredType =3948 Actions.CodeCompletion().ProduceCtorInitMemberSignatureHelp(3949 ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II,3950 T.getOpenLocation(), /*Braced=*/false);3951 CalledSignatureHelp = true;3952 return PreferredType;3953 };3954 if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, [&] {3955 PreferredType.enterFunctionArgument(Tok.getLocation(),3956 RunSignatureHelp);3957 })) {3958 if (PP.isCodeCompletionReached() && !CalledSignatureHelp)3959 RunSignatureHelp();3960 SkipUntil(tok::r_paren, StopAtSemi);3961 return true;3962 }3963 3964 T.consumeClose();3965 3966 SourceLocation EllipsisLoc;3967 TryConsumeToken(tok::ellipsis, EllipsisLoc);3968 3969 if (TemplateTypeTy.isInvalid())3970 return true;3971 return Actions.ActOnMemInitializer(3972 ConstructorDecl, getCurScope(), SS, II, TemplateTypeTy.get(), DS, IdLoc,3973 T.getOpenLocation(), ArgExprs, T.getCloseLocation(), EllipsisLoc);3974 }3975 3976 if (TemplateTypeTy.isInvalid())3977 return true;3978 3979 if (getLangOpts().CPlusPlus11)3980 return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace;3981 else3982 return Diag(Tok, diag::err_expected) << tok::l_paren;3983}3984 3985ExceptionSpecificationType Parser::tryParseExceptionSpecification(3986 bool Delayed, SourceRange &SpecificationRange,3987 SmallVectorImpl<ParsedType> &DynamicExceptions,3988 SmallVectorImpl<SourceRange> &DynamicExceptionRanges,3989 ExprResult &NoexceptExpr, CachedTokens *&ExceptionSpecTokens) {3990 ExceptionSpecificationType Result = EST_None;3991 ExceptionSpecTokens = nullptr;3992 3993 // Handle delayed parsing of exception-specifications.3994 if (Delayed) {3995 if (Tok.isNot(tok::kw_throw) && Tok.isNot(tok::kw_noexcept))3996 return EST_None;3997 3998 // Consume and cache the starting token.3999 bool IsNoexcept = Tok.is(tok::kw_noexcept);4000 Token StartTok = Tok;4001 SpecificationRange = SourceRange(ConsumeToken());4002 4003 // Check for a '('.4004 if (!Tok.is(tok::l_paren)) {4005 // If this is a bare 'noexcept', we're done.4006 if (IsNoexcept) {4007 Diag(Tok, diag::warn_cxx98_compat_noexcept_decl);4008 NoexceptExpr = nullptr;4009 return EST_BasicNoexcept;4010 }4011 4012 Diag(Tok, diag::err_expected_lparen_after) << "throw";4013 return EST_DynamicNone;4014 }4015 4016 // Cache the tokens for the exception-specification.4017 ExceptionSpecTokens = new CachedTokens;4018 ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept'4019 ExceptionSpecTokens->push_back(Tok); // '('4020 SpecificationRange.setEnd(ConsumeParen()); // '('4021 4022 ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens,4023 /*StopAtSemi=*/true,4024 /*ConsumeFinalToken=*/true);4025 SpecificationRange.setEnd(ExceptionSpecTokens->back().getLocation());4026 4027 return EST_Unparsed;4028 }4029 4030 // See if there's a dynamic specification.4031 if (Tok.is(tok::kw_throw)) {4032 Result = ParseDynamicExceptionSpecification(4033 SpecificationRange, DynamicExceptions, DynamicExceptionRanges);4034 assert(DynamicExceptions.size() == DynamicExceptionRanges.size() &&4035 "Produced different number of exception types and ranges.");4036 }4037 4038 // If there's no noexcept specification, we're done.4039 if (Tok.isNot(tok::kw_noexcept))4040 return Result;4041 4042 Diag(Tok, diag::warn_cxx98_compat_noexcept_decl);4043 4044 // If we already had a dynamic specification, parse the noexcept for,4045 // recovery, but emit a diagnostic and don't store the results.4046 SourceRange NoexceptRange;4047 ExceptionSpecificationType NoexceptType = EST_None;4048 4049 SourceLocation KeywordLoc = ConsumeToken();4050 if (Tok.is(tok::l_paren)) {4051 // There is an argument.4052 BalancedDelimiterTracker T(*this, tok::l_paren);4053 T.consumeOpen();4054 4055 EnterExpressionEvaluationContext ConstantEvaluated(4056 Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);4057 NoexceptExpr = ParseConstantExpressionInExprEvalContext();4058 4059 T.consumeClose();4060 if (!NoexceptExpr.isInvalid()) {4061 NoexceptExpr =4062 Actions.ActOnNoexceptSpec(NoexceptExpr.get(), NoexceptType);4063 NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());4064 } else {4065 NoexceptType = EST_BasicNoexcept;4066 }4067 } else {4068 // There is no argument.4069 NoexceptType = EST_BasicNoexcept;4070 NoexceptRange = SourceRange(KeywordLoc, KeywordLoc);4071 }4072 4073 if (Result == EST_None) {4074 SpecificationRange = NoexceptRange;4075 Result = NoexceptType;4076 4077 // If there's a dynamic specification after a noexcept specification,4078 // parse that and ignore the results.4079 if (Tok.is(tok::kw_throw)) {4080 Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification);4081 ParseDynamicExceptionSpecification(NoexceptRange, DynamicExceptions,4082 DynamicExceptionRanges);4083 }4084 } else {4085 Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification);4086 }4087 4088 return Result;4089}4090 4091static void diagnoseDynamicExceptionSpecification(Parser &P, SourceRange Range,4092 bool IsNoexcept) {4093 if (P.getLangOpts().CPlusPlus11) {4094 const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)";4095 P.Diag(Range.getBegin(), P.getLangOpts().CPlusPlus17 && !IsNoexcept4096 ? diag::ext_dynamic_exception_spec4097 : diag::warn_exception_spec_deprecated)4098 << Range;4099 P.Diag(Range.getBegin(), diag::note_exception_spec_deprecated)4100 << Replacement << FixItHint::CreateReplacement(Range, Replacement);4101 }4102}4103 4104ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(4105 SourceRange &SpecificationRange, SmallVectorImpl<ParsedType> &Exceptions,4106 SmallVectorImpl<SourceRange> &Ranges) {4107 assert(Tok.is(tok::kw_throw) && "expected throw");4108 4109 SpecificationRange.setBegin(ConsumeToken());4110 BalancedDelimiterTracker T(*this, tok::l_paren);4111 if (T.consumeOpen()) {4112 Diag(Tok, diag::err_expected_lparen_after) << "throw";4113 SpecificationRange.setEnd(SpecificationRange.getBegin());4114 return EST_DynamicNone;4115 }4116 4117 // Parse throw(...), a Microsoft extension that means "this function4118 // can throw anything".4119 if (Tok.is(tok::ellipsis)) {4120 SourceLocation EllipsisLoc = ConsumeToken();4121 if (!getLangOpts().MicrosoftExt)4122 Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec);4123 T.consumeClose();4124 SpecificationRange.setEnd(T.getCloseLocation());4125 diagnoseDynamicExceptionSpecification(*this, SpecificationRange, false);4126 return EST_MSAny;4127 }4128 4129 // Parse the sequence of type-ids.4130 SourceRange Range;4131 while (Tok.isNot(tok::r_paren)) {4132 TypeResult Res(ParseTypeName(&Range));4133 4134 if (Tok.is(tok::ellipsis)) {4135 // C++0x [temp.variadic]p5:4136 // - In a dynamic-exception-specification (15.4); the pattern is a4137 // type-id.4138 SourceLocation Ellipsis = ConsumeToken();4139 Range.setEnd(Ellipsis);4140 if (!Res.isInvalid())4141 Res = Actions.ActOnPackExpansion(Res.get(), Ellipsis);4142 }4143 4144 if (!Res.isInvalid()) {4145 Exceptions.push_back(Res.get());4146 Ranges.push_back(Range);4147 }4148 4149 if (!TryConsumeToken(tok::comma))4150 break;4151 }4152 4153 T.consumeClose();4154 SpecificationRange.setEnd(T.getCloseLocation());4155 diagnoseDynamicExceptionSpecification(*this, SpecificationRange,4156 Exceptions.empty());4157 return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic;4158}4159 4160TypeResult Parser::ParseTrailingReturnType(SourceRange &Range,4161 bool MayBeFollowedByDirectInit) {4162 assert(Tok.is(tok::arrow) && "expected arrow");4163 4164 ConsumeToken();4165 4166 return ParseTypeName(&Range, MayBeFollowedByDirectInit4167 ? DeclaratorContext::TrailingReturnVar4168 : DeclaratorContext::TrailingReturn);4169}4170 4171void Parser::ParseTrailingRequiresClause(Declarator &D) {4172 assert(Tok.is(tok::kw_requires) && "expected requires");4173 4174 SourceLocation RequiresKWLoc = ConsumeToken();4175 4176 // C++23 [basic.scope.namespace]p1:4177 // For each non-friend redeclaration or specialization whose target scope4178 // is or is contained by the scope, the portion after the declarator-id,4179 // class-head-name, or enum-head-name is also included in the scope.4180 // C++23 [basic.scope.class]p1:4181 // For each non-friend redeclaration or specialization whose target scope4182 // is or is contained by the scope, the portion after the declarator-id,4183 // class-head-name, or enum-head-name is also included in the scope.4184 //4185 // FIXME: We should really be calling ParseTrailingRequiresClause in4186 // ParseDirectDeclarator, when we are already in the declarator scope.4187 // This would also correctly suppress access checks for specializations4188 // and explicit instantiations, which we currently do not do.4189 CXXScopeSpec &SS = D.getCXXScopeSpec();4190 DeclaratorScopeObj DeclScopeObj(*this, SS);4191 if (SS.isValid() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))4192 DeclScopeObj.EnterDeclaratorScope();4193 4194 ExprResult TrailingRequiresClause;4195 ParseScope ParamScope(this, Scope::DeclScope |4196 Scope::FunctionDeclarationScope |4197 Scope::FunctionPrototypeScope);4198 4199 Actions.ActOnStartTrailingRequiresClause(getCurScope(), D);4200 4201 std::optional<Sema::CXXThisScopeRAII> ThisScope;4202 InitCXXThisScopeForDeclaratorIfRelevant(D, D.getDeclSpec(), ThisScope);4203 4204 TrailingRequiresClause =4205 ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true);4206 4207 TrailingRequiresClause =4208 Actions.ActOnFinishTrailingRequiresClause(TrailingRequiresClause);4209 4210 if (!D.isDeclarationOfFunction()) {4211 Diag(RequiresKWLoc,4212 diag::err_requires_clause_on_declarator_not_declaring_a_function);4213 return;4214 }4215 4216 if (TrailingRequiresClause.isInvalid())4217 SkipUntil({tok::l_brace, tok::arrow, tok::kw_try, tok::comma, tok::colon},4218 StopAtSemi | StopBeforeMatch);4219 else4220 D.setTrailingRequiresClause(TrailingRequiresClause.get());4221 4222 // Did the user swap the trailing return type and requires clause?4223 if (D.isFunctionDeclarator() && Tok.is(tok::arrow) &&4224 D.getDeclSpec().getTypeSpecType() == TST_auto) {4225 SourceLocation ArrowLoc = Tok.getLocation();4226 SourceRange Range;4227 TypeResult TrailingReturnType =4228 ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit=*/false);4229 4230 if (!TrailingReturnType.isInvalid()) {4231 Diag(ArrowLoc,4232 diag::err_requires_clause_must_appear_after_trailing_return)4233 << Range;4234 auto &FunctionChunk = D.getFunctionTypeInfo();4235 FunctionChunk.HasTrailingReturnType = TrailingReturnType.isUsable();4236 FunctionChunk.TrailingReturnType = TrailingReturnType.get();4237 FunctionChunk.TrailingReturnTypeLoc = Range.getBegin();4238 } else4239 SkipUntil({tok::equal, tok::l_brace, tok::arrow, tok::kw_try, tok::comma},4240 StopAtSemi | StopBeforeMatch);4241 }4242}4243 4244Sema::ParsingClassState Parser::PushParsingClass(Decl *ClassDecl,4245 bool NonNestedClass,4246 bool IsInterface) {4247 assert((NonNestedClass || !ClassStack.empty()) &&4248 "Nested class without outer class");4249 ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass, IsInterface));4250 return Actions.PushParsingClass();4251}4252 4253void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {4254 for (unsigned I = 0, N = Class->LateParsedDeclarations.size(); I != N; ++I)4255 delete Class->LateParsedDeclarations[I];4256 delete Class;4257}4258 4259void Parser::PopParsingClass(Sema::ParsingClassState state) {4260 assert(!ClassStack.empty() && "Mismatched push/pop for class parsing");4261 4262 Actions.PopParsingClass(state);4263 4264 ParsingClass *Victim = ClassStack.top();4265 ClassStack.pop();4266 if (Victim->TopLevelClass) {4267 // Deallocate all of the nested classes of this class,4268 // recursively: we don't need to keep any of this information.4269 DeallocateParsedClasses(Victim);4270 return;4271 }4272 assert(!ClassStack.empty() && "Missing top-level class?");4273 4274 if (Victim->LateParsedDeclarations.empty()) {4275 // The victim is a nested class, but we will not need to perform4276 // any processing after the definition of this class since it has4277 // no members whose handling was delayed. Therefore, we can just4278 // remove this nested class.4279 DeallocateParsedClasses(Victim);4280 return;4281 }4282 4283 // This nested class has some members that will need to be processed4284 // after the top-level class is completely defined. Therefore, add4285 // it to the list of nested classes within its parent.4286 assert(getCurScope()->isClassScope() &&4287 "Nested class outside of class scope?");4288 ClassStack.top()->LateParsedDeclarations.push_back(4289 new LateParsedClass(this, Victim));4290}4291 4292IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(4293 SourceLocation &Loc, SemaCodeCompletion::AttributeCompletion Completion,4294 const IdentifierInfo *Scope) {4295 switch (Tok.getKind()) {4296 default:4297 // Identifiers and keywords have identifier info attached.4298 if (!Tok.isAnnotation()) {4299 if (IdentifierInfo *II = Tok.getIdentifierInfo()) {4300 Loc = ConsumeToken();4301 return II;4302 }4303 }4304 return nullptr;4305 4306 case tok::code_completion:4307 cutOffParsing();4308 Actions.CodeCompletion().CodeCompleteAttribute(4309 getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C23,4310 Completion, Scope);4311 return nullptr;4312 4313 case tok::numeric_constant: {4314 // If we got a numeric constant, check to see if it comes from a macro that4315 // corresponds to the predefined __clang__ macro. If it does, warn the user4316 // and recover by pretending they said _Clang instead.4317 if (Tok.getLocation().isMacroID()) {4318 SmallString<8> ExpansionBuf;4319 SourceLocation ExpansionLoc =4320 PP.getSourceManager().getExpansionLoc(Tok.getLocation());4321 StringRef Spelling = PP.getSpelling(ExpansionLoc, ExpansionBuf);4322 if (Spelling == "__clang__") {4323 SourceRange TokRange(4324 ExpansionLoc,4325 PP.getSourceManager().getExpansionLoc(Tok.getEndLoc()));4326 Diag(Tok, diag::warn_wrong_clang_attr_namespace)4327 << FixItHint::CreateReplacement(TokRange, "_Clang");4328 Loc = ConsumeToken();4329 return &PP.getIdentifierTable().get("_Clang");4330 }4331 }4332 return nullptr;4333 }4334 4335 case tok::ampamp: // 'and'4336 case tok::pipe: // 'bitor'4337 case tok::pipepipe: // 'or'4338 case tok::caret: // 'xor'4339 case tok::tilde: // 'compl'4340 case tok::amp: // 'bitand'4341 case tok::ampequal: // 'and_eq'4342 case tok::pipeequal: // 'or_eq'4343 case tok::caretequal: // 'xor_eq'4344 case tok::exclaim: // 'not'4345 case tok::exclaimequal: // 'not_eq'4346 // Alternative tokens do not have identifier info, but their spelling4347 // starts with an alphabetical character.4348 SmallString<8> SpellingBuf;4349 SourceLocation SpellingLoc =4350 PP.getSourceManager().getSpellingLoc(Tok.getLocation());4351 StringRef Spelling = PP.getSpelling(SpellingLoc, SpellingBuf);4352 if (isLetter(Spelling[0])) {4353 Loc = ConsumeToken();4354 return &PP.getIdentifierTable().get(Spelling);4355 }4356 return nullptr;4357 }4358}4359 4360void Parser::ParseOpenMPAttributeArgs(const IdentifierInfo *AttrName,4361 CachedTokens &OpenMPTokens) {4362 // Both 'sequence' and 'directive' attributes require arguments, so parse the4363 // open paren for the argument list.4364 BalancedDelimiterTracker T(*this, tok::l_paren);4365 if (T.consumeOpen()) {4366 Diag(Tok, diag::err_expected) << tok::l_paren;4367 return;4368 }4369 4370 if (AttrName->isStr("directive")) {4371 // If the attribute is named `directive`, we can consume its argument list4372 // and push the tokens from it into the cached token stream for a new OpenMP4373 // pragma directive.4374 Token OMPBeginTok;4375 OMPBeginTok.startToken();4376 OMPBeginTok.setKind(tok::annot_attr_openmp);4377 OMPBeginTok.setLocation(Tok.getLocation());4378 OpenMPTokens.push_back(OMPBeginTok);4379 4380 ConsumeAndStoreUntil(tok::r_paren, OpenMPTokens, /*StopAtSemi=*/false,4381 /*ConsumeFinalToken*/ false);4382 Token OMPEndTok;4383 OMPEndTok.startToken();4384 OMPEndTok.setKind(tok::annot_pragma_openmp_end);4385 OMPEndTok.setLocation(Tok.getLocation());4386 OpenMPTokens.push_back(OMPEndTok);4387 } else {4388 assert(AttrName->isStr("sequence") &&4389 "Expected either 'directive' or 'sequence'");4390 // If the attribute is named 'sequence', its argument is a list of one or4391 // more OpenMP attributes (either 'omp::directive' or 'omp::sequence',4392 // where the 'omp::' is optional).4393 do {4394 // We expect to see one of the following:4395 // * An identifier (omp) for the attribute namespace followed by ::4396 // * An identifier (directive) or an identifier (sequence).4397 SourceLocation IdentLoc;4398 const IdentifierInfo *Ident = TryParseCXX11AttributeIdentifier(IdentLoc);4399 4400 // If there is an identifier and it is 'omp', a double colon is required4401 // followed by the actual identifier we're after.4402 if (Ident && Ident->isStr("omp") && !ExpectAndConsume(tok::coloncolon))4403 Ident = TryParseCXX11AttributeIdentifier(IdentLoc);4404 4405 // If we failed to find an identifier (scoped or otherwise), or we found4406 // an unexpected identifier, diagnose.4407 if (!Ident || (!Ident->isStr("directive") && !Ident->isStr("sequence"))) {4408 Diag(Tok.getLocation(), diag::err_expected_sequence_or_directive);4409 SkipUntil(tok::r_paren, StopBeforeMatch);4410 continue;4411 }4412 // We read an identifier. If the identifier is one of the ones we4413 // expected, we can recurse to parse the args.4414 ParseOpenMPAttributeArgs(Ident, OpenMPTokens);4415 4416 // There may be a comma to signal that we expect another directive in the4417 // sequence.4418 } while (TryConsumeToken(tok::comma));4419 }4420 // Parse the closing paren for the argument list.4421 T.consumeClose();4422}4423 4424static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,4425 IdentifierInfo *ScopeName) {4426 switch (4427 ParsedAttr::getParsedKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) {4428 case ParsedAttr::AT_CarriesDependency:4429 case ParsedAttr::AT_Deprecated:4430 case ParsedAttr::AT_FallThrough:4431 case ParsedAttr::AT_CXX11NoReturn:4432 case ParsedAttr::AT_NoUniqueAddress:4433 case ParsedAttr::AT_Likely:4434 case ParsedAttr::AT_Unlikely:4435 return true;4436 case ParsedAttr::AT_WarnUnusedResult:4437 return !ScopeName && AttrName->getName() == "nodiscard";4438 case ParsedAttr::AT_Unused:4439 return !ScopeName && AttrName->getName() == "maybe_unused";4440 default:4441 return false;4442 }4443}4444 4445bool Parser::ParseCXXAssumeAttributeArg(4446 ParsedAttributes &Attrs, IdentifierInfo *AttrName,4447 SourceLocation AttrNameLoc, IdentifierInfo *ScopeName,4448 SourceLocation ScopeLoc, SourceLocation *EndLoc, ParsedAttr::Form Form) {4449 assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");4450 BalancedDelimiterTracker T(*this, tok::l_paren);4451 T.consumeOpen();4452 4453 // [dcl.attr.assume]: The expression is potentially evaluated.4454 EnterExpressionEvaluationContext Unevaluated(4455 Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);4456 4457 TentativeParsingAction TPA(*this);4458 ExprResult Res = ParseConditionalExpression();4459 if (Res.isInvalid()) {4460 TPA.Commit();4461 SkipUntil(tok::r_paren, tok::r_square, StopAtSemi | StopBeforeMatch);4462 if (Tok.is(tok::r_paren))4463 T.consumeClose();4464 return true;4465 }4466 4467 if (!Tok.isOneOf(tok::r_paren, tok::r_square)) {4468 // Emit a better diagnostic if this is an otherwise valid expression that4469 // is not allowed here.4470 TPA.Revert();4471 Res = ParseExpression();4472 if (!Res.isInvalid()) {4473 auto *E = Res.get();4474 Diag(E->getExprLoc(), diag::err_assume_attr_expects_cond_expr)4475 << AttrName << FixItHint::CreateInsertion(E->getBeginLoc(), "(")4476 << FixItHint::CreateInsertion(PP.getLocForEndOfToken(E->getEndLoc()),4477 ")")4478 << E->getSourceRange();4479 }4480 4481 T.consumeClose();4482 return true;4483 }4484 4485 TPA.Commit();4486 ArgsUnion Assumption = Res.get();4487 auto RParen = Tok.getLocation();4488 T.consumeClose();4489 Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen),4490 AttributeScopeInfo(ScopeName, ScopeLoc), &Assumption, 1, Form);4491 4492 if (EndLoc)4493 *EndLoc = RParen;4494 4495 return false;4496}4497 4498bool Parser::ParseCXX11AttributeArgs(4499 IdentifierInfo *AttrName, SourceLocation AttrNameLoc,4500 ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,4501 SourceLocation ScopeLoc, CachedTokens &OpenMPTokens) {4502 assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");4503 SourceLocation LParenLoc = Tok.getLocation();4504 const LangOptions &LO = getLangOpts();4505 ParsedAttr::Form Form =4506 LO.CPlusPlus ? ParsedAttr::Form::CXX11() : ParsedAttr::Form::C23();4507 4508 // Try parsing microsoft attributes4509 if (getLangOpts().MicrosoftExt || getLangOpts().HLSL) {4510 if (hasAttribute(AttributeCommonInfo::Syntax::AS_Microsoft, ScopeName,4511 AttrName, getTargetInfo(), getLangOpts()))4512 Form = ParsedAttr::Form::Microsoft();4513 }4514 4515 if (LO.CPlusPlus) {4516 TentativeParsingAction TPA(*this);4517 bool HasInvalidArgument = false;4518 while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::eof)) {4519 if (Tok.isOneOf(tok::hash, tok::hashhash)) {4520 Diag(Tok.getLocation(), diag::ext_invalid_attribute_argument)4521 << PP.getSpelling(Tok);4522 HasInvalidArgument = true;4523 }4524 ConsumeAnyToken();4525 }4526 4527 if (HasInvalidArgument) {4528 SkipUntil(tok::r_paren);4529 TPA.Commit();4530 return true;4531 }4532 4533 TPA.Revert();4534 }4535 4536 // If the attribute isn't known, we will not attempt to parse any4537 // arguments.4538 if (Form.getSyntax() != ParsedAttr::AS_Microsoft &&4539 !hasAttribute(LO.CPlusPlus ? AttributeCommonInfo::Syntax::AS_CXX114540 : AttributeCommonInfo::Syntax::AS_C23,4541 ScopeName, AttrName, getTargetInfo(), getLangOpts())) {4542 // Eat the left paren, then skip to the ending right paren.4543 ConsumeParen();4544 SkipUntil(tok::r_paren);4545 return false;4546 }4547 4548 if (ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"))) {4549 // GNU-scoped attributes have some special cases to handle GNU-specific4550 // behaviors.4551 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,4552 ScopeLoc, Form, nullptr);4553 return true;4554 }4555 4556 // [[omp::directive]] and [[omp::sequence]] need special handling.4557 if (ScopeName && ScopeName->isStr("omp") &&4558 (AttrName->isStr("directive") || AttrName->isStr("sequence"))) {4559 Diag(AttrNameLoc, getLangOpts().OpenMP >= 514560 ? diag::warn_omp51_compat_attributes4561 : diag::ext_omp_attributes);4562 4563 ParseOpenMPAttributeArgs(AttrName, OpenMPTokens);4564 4565 // We claim that an attribute was parsed and added so that one is not4566 // created for us by the caller.4567 return true;4568 }4569 4570 unsigned NumArgs;4571 // Some Clang-scoped attributes have some special parsing behavior.4572 if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang")))4573 NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc,4574 ScopeName, ScopeLoc, Form);4575 // So does C++23's assume() attribute.4576 else if (!ScopeName && AttrName->isStr("assume")) {4577 if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, nullptr,4578 SourceLocation{}, EndLoc, Form))4579 return true;4580 NumArgs = 1;4581 } else4582 NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,4583 ScopeName, ScopeLoc, Form);4584 4585 if (!Attrs.empty() &&4586 IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {4587 ParsedAttr &Attr = Attrs.back();4588 4589 // Ignore attributes that don't exist for the target.4590 if (!Attr.existsInTarget(getTargetInfo())) {4591 Actions.DiagnoseUnknownAttribute(Attr);4592 Attr.setInvalid(true);4593 return true;4594 }4595 4596 // If the attribute is a standard or built-in attribute and we are4597 // parsing an argument list, we need to determine whether this attribute4598 // was allowed to have an argument list (such as [[deprecated]]), and how4599 // many arguments were parsed (so we can diagnose on [[deprecated()]]).4600 if (Attr.getMaxArgs() && !NumArgs) {4601 // The attribute was allowed to have arguments, but none were provided4602 // even though the attribute parsed successfully. This is an error.4603 Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;4604 Attr.setInvalid(true);4605 } else if (!Attr.getMaxArgs()) {4606 // The attribute parsed successfully, but was not allowed to have any4607 // arguments. It doesn't matter whether any were provided -- the4608 // presence of the argument list (even if empty) is diagnosed.4609 Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)4610 << AttrName4611 << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));4612 Attr.setInvalid(true);4613 }4614 }4615 return true;4616}4617 4618void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,4619 CachedTokens &OpenMPTokens,4620 SourceLocation *EndLoc) {4621 if (Tok.is(tok::kw_alignas)) {4622 // alignas is a valid token in C23 but it is not an attribute, it's a type-4623 // specifier-qualifier, which means it has different parsing behavior. We4624 // handle this in ParseDeclarationSpecifiers() instead of here in C. We4625 // should not get here for C any longer.4626 assert(getLangOpts().CPlusPlus && "'alignas' is not an attribute in C");4627 Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas);4628 ParseAlignmentSpecifier(Attrs, EndLoc);4629 return;4630 }4631 4632 if (Tok.isRegularKeywordAttribute()) {4633 SourceLocation Loc = Tok.getLocation();4634 IdentifierInfo *AttrName = Tok.getIdentifierInfo();4635 ParsedAttr::Form Form = ParsedAttr::Form(Tok.getKind());4636 bool TakesArgs = doesKeywordAttributeTakeArgs(Tok.getKind());4637 ConsumeToken();4638 if (TakesArgs) {4639 if (!Tok.is(tok::l_paren))4640 Diag(Tok.getLocation(), diag::err_expected_lparen_after) << AttrName;4641 else4642 ParseAttributeArgsCommon(AttrName, Loc, Attrs, EndLoc,4643 /*ScopeName*/ nullptr,4644 /*ScopeLoc*/ Loc, Form);4645 } else4646 Attrs.addNew(AttrName, Loc, AttributeScopeInfo(), nullptr, 0, Form);4647 return;4648 }4649 4650 assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) &&4651 "Not a double square bracket attribute list");4652 4653 SourceLocation OpenLoc = Tok.getLocation();4654 if (getLangOpts().CPlusPlus) {4655 Diag(OpenLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_attribute4656 : diag::warn_ext_cxx11_attributes);4657 } else {4658 Diag(OpenLoc, getLangOpts().C23 ? diag::warn_pre_c23_compat_attributes4659 : diag::warn_ext_c23_attributes);4660 }4661 4662 ConsumeBracket();4663 checkCompoundToken(OpenLoc, tok::l_square, CompoundToken::AttrBegin);4664 ConsumeBracket();4665 4666 SourceLocation CommonScopeLoc;4667 IdentifierInfo *CommonScopeName = nullptr;4668 if (Tok.is(tok::kw_using)) {4669 Diag(Tok.getLocation(), getLangOpts().CPlusPlus174670 ? diag::warn_cxx14_compat_using_attribute_ns4671 : diag::ext_using_attribute_ns);4672 ConsumeToken();4673 4674 CommonScopeName = TryParseCXX11AttributeIdentifier(4675 CommonScopeLoc, SemaCodeCompletion::AttributeCompletion::Scope);4676 if (!CommonScopeName) {4677 Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;4678 SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);4679 }4680 if (!TryConsumeToken(tok::colon) && CommonScopeName)4681 Diag(Tok.getLocation(), diag::err_expected) << tok::colon;4682 }4683 4684 bool AttrParsed = false;4685 while (!Tok.isOneOf(tok::r_square, tok::semi, tok::eof)) {4686 if (AttrParsed) {4687 // If we parsed an attribute, a comma is required before parsing any4688 // additional attributes.4689 if (ExpectAndConsume(tok::comma)) {4690 SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);4691 continue;4692 }4693 AttrParsed = false;4694 }4695 4696 // Eat all remaining superfluous commas before parsing the next attribute.4697 while (TryConsumeToken(tok::comma))4698 ;4699 4700 SourceLocation ScopeLoc, AttrLoc;4701 IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr;4702 4703 AttrName = TryParseCXX11AttributeIdentifier(4704 AttrLoc, SemaCodeCompletion::AttributeCompletion::Attribute,4705 CommonScopeName);4706 if (!AttrName)4707 // Break out to the "expected ']'" diagnostic.4708 break;4709 4710 // scoped attribute4711 if (TryConsumeToken(tok::coloncolon)) {4712 ScopeName = AttrName;4713 ScopeLoc = AttrLoc;4714 4715 AttrName = TryParseCXX11AttributeIdentifier(4716 AttrLoc, SemaCodeCompletion::AttributeCompletion::Attribute,4717 ScopeName);4718 if (!AttrName) {4719 Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;4720 SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch);4721 continue;4722 }4723 }4724 4725 if (CommonScopeName) {4726 if (ScopeName) {4727 Diag(ScopeLoc, diag::err_using_attribute_ns_conflict)4728 << SourceRange(CommonScopeLoc);4729 } else {4730 ScopeName = CommonScopeName;4731 ScopeLoc = CommonScopeLoc;4732 }4733 }4734 4735 // Parse attribute arguments4736 if (Tok.is(tok::l_paren))4737 AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, Attrs, EndLoc,4738 ScopeName, ScopeLoc, OpenMPTokens);4739 4740 if (!AttrParsed) {4741 Attrs.addNew(AttrName,4742 SourceRange(ScopeLoc.isValid() && CommonScopeLoc.isInvalid()4743 ? ScopeLoc4744 : AttrLoc,4745 AttrLoc),4746 AttributeScopeInfo(ScopeName, ScopeLoc, CommonScopeLoc),4747 nullptr, 0,4748 getLangOpts().CPlusPlus ? ParsedAttr::Form::CXX11()4749 : ParsedAttr::Form::C23());4750 AttrParsed = true;4751 }4752 4753 if (TryConsumeToken(tok::ellipsis))4754 Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis) << AttrName;4755 }4756 4757 // If we hit an error and recovered by parsing up to a semicolon, eat the4758 // semicolon and don't issue further diagnostics about missing brackets.4759 if (Tok.is(tok::semi)) {4760 ConsumeToken();4761 return;4762 }4763 4764 SourceLocation CloseLoc = Tok.getLocation();4765 if (ExpectAndConsume(tok::r_square))4766 SkipUntil(tok::r_square);4767 else if (Tok.is(tok::r_square))4768 checkCompoundToken(CloseLoc, tok::r_square, CompoundToken::AttrEnd);4769 if (EndLoc)4770 *EndLoc = Tok.getLocation();4771 if (ExpectAndConsume(tok::r_square))4772 SkipUntil(tok::r_square);4773}4774 4775void Parser::ParseCXX11Attributes(ParsedAttributes &Attrs) {4776 SourceLocation StartLoc = Tok.getLocation();4777 SourceLocation EndLoc = StartLoc;4778 4779 do {4780 ParseCXX11AttributeSpecifier(Attrs, &EndLoc);4781 } while (isAllowedCXX11AttributeSpecifier());4782 4783 Attrs.Range = SourceRange(StartLoc, EndLoc);4784}4785 4786void Parser::DiagnoseAndSkipCXX11Attributes() {4787 auto Keyword =4788 Tok.isRegularKeywordAttribute() ? Tok.getIdentifierInfo() : nullptr;4789 // Start and end location of an attribute or an attribute list.4790 SourceLocation StartLoc = Tok.getLocation();4791 SourceLocation EndLoc = SkipCXX11Attributes();4792 4793 if (EndLoc.isValid()) {4794 SourceRange Range(StartLoc, EndLoc);4795 (Keyword ? Diag(StartLoc, diag::err_keyword_not_allowed) << Keyword4796 : Diag(StartLoc, diag::err_attributes_not_allowed))4797 << Range;4798 }4799}4800 4801SourceLocation Parser::SkipCXX11Attributes() {4802 SourceLocation EndLoc;4803 4804 if (isCXX11AttributeSpecifier() == CXX11AttributeKind::NotAttributeSpecifier)4805 return EndLoc;4806 4807 do {4808 if (Tok.is(tok::l_square)) {4809 BalancedDelimiterTracker T(*this, tok::l_square);4810 T.consumeOpen();4811 T.skipToEnd();4812 EndLoc = T.getCloseLocation();4813 } else if (Tok.isRegularKeywordAttribute() &&4814 !doesKeywordAttributeTakeArgs(Tok.getKind())) {4815 EndLoc = Tok.getLocation();4816 ConsumeToken();4817 } else {4818 assert((Tok.is(tok::kw_alignas) || Tok.isRegularKeywordAttribute()) &&4819 "not an attribute specifier");4820 ConsumeToken();4821 BalancedDelimiterTracker T(*this, tok::l_paren);4822 if (!T.consumeOpen())4823 T.skipToEnd();4824 EndLoc = T.getCloseLocation();4825 }4826 } while (isCXX11AttributeSpecifier() !=4827 CXX11AttributeKind::NotAttributeSpecifier);4828 4829 return EndLoc;4830}4831 4832void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) {4833 assert(Tok.is(tok::identifier) && "Not a Microsoft attribute list");4834 IdentifierInfo *UuidIdent = Tok.getIdentifierInfo();4835 assert(UuidIdent->getName() == "uuid" && "Not a Microsoft attribute list");4836 4837 SourceLocation UuidLoc = Tok.getLocation();4838 ConsumeToken();4839 4840 // Ignore the left paren location for now.4841 BalancedDelimiterTracker T(*this, tok::l_paren);4842 if (T.consumeOpen()) {4843 Diag(Tok, diag::err_expected) << tok::l_paren;4844 return;4845 }4846 4847 ArgsVector ArgExprs;4848 if (isTokenStringLiteral()) {4849 // Easy case: uuid("...") -- quoted string.4850 ExprResult StringResult = ParseUnevaluatedStringLiteralExpression();4851 if (StringResult.isInvalid())4852 return;4853 ArgExprs.push_back(StringResult.get());4854 } else {4855 // something like uuid({000000A0-0000-0000-C000-000000000049}) -- no4856 // quotes in the parens. Just append the spelling of all tokens encountered4857 // until the closing paren.4858 4859 SmallString<42> StrBuffer; // 2 "", 36 bytes UUID, 2 optional {}, 1 nul4860 StrBuffer += "\"";4861 4862 // Since none of C++'s keywords match [a-f]+, accepting just tok::l_brace,4863 // tok::r_brace, tok::minus, tok::identifier (think C000) and4864 // tok::numeric_constant (0000) should be enough. But the spelling of the4865 // uuid argument is checked later anyways, so there's no harm in accepting4866 // almost anything here.4867 // cl is very strict about whitespace in this form and errors out if any4868 // is present, so check the space flags on the tokens.4869 SourceLocation StartLoc = Tok.getLocation();4870 while (Tok.isNot(tok::r_paren)) {4871 if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) {4872 Diag(Tok, diag::err_attribute_uuid_malformed_guid);4873 SkipUntil(tok::r_paren, StopAtSemi);4874 return;4875 }4876 SmallString<16> SpellingBuffer;4877 SpellingBuffer.resize(Tok.getLength() + 1);4878 bool Invalid = false;4879 StringRef TokSpelling = PP.getSpelling(Tok, SpellingBuffer, &Invalid);4880 if (Invalid) {4881 SkipUntil(tok::r_paren, StopAtSemi);4882 return;4883 }4884 StrBuffer += TokSpelling;4885 ConsumeAnyToken();4886 }4887 StrBuffer += "\"";4888 4889 if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) {4890 Diag(Tok, diag::err_attribute_uuid_malformed_guid);4891 ConsumeParen();4892 return;4893 }4894 4895 // Pretend the user wrote the appropriate string literal here.4896 // ActOnStringLiteral() copies the string data into the literal, so it's4897 // ok that the Token points to StrBuffer.4898 Token Toks[1];4899 Toks[0].startToken();4900 Toks[0].setKind(tok::string_literal);4901 Toks[0].setLocation(StartLoc);4902 Toks[0].setLiteralData(StrBuffer.data());4903 Toks[0].setLength(StrBuffer.size());4904 StringLiteral *UuidString =4905 cast<StringLiteral>(Actions.ActOnUnevaluatedStringLiteral(Toks).get());4906 ArgExprs.push_back(UuidString);4907 }4908 4909 if (!T.consumeClose()) {4910 Attrs.addNew(UuidIdent, SourceRange(UuidLoc, T.getCloseLocation()),4911 AttributeScopeInfo(), ArgExprs.data(), ArgExprs.size(),4912 ParsedAttr::Form::Microsoft());4913 }4914}4915 4916void Parser::ParseHLSLRootSignatureAttributeArgs(ParsedAttributes &Attrs) {4917 assert(Tok.is(tok::identifier) &&4918 "Expected an identifier to denote which MS attribute to consider");4919 IdentifierInfo *RootSignatureIdent = Tok.getIdentifierInfo();4920 assert(RootSignatureIdent->getName() == "RootSignature" &&4921 "Expected RootSignature identifier for root signature attribute");4922 4923 SourceLocation RootSignatureLoc = Tok.getLocation();4924 ConsumeToken();4925 4926 // Ignore the left paren location for now.4927 BalancedDelimiterTracker T(*this, tok::l_paren);4928 if (T.consumeOpen()) {4929 Diag(Tok, diag::err_expected) << tok::l_paren;4930 return;4931 }4932 4933 auto ProcessStringLiteral = [this]() -> std::optional<StringLiteral *> {4934 if (!isTokenStringLiteral())4935 return std::nullopt;4936 4937 ExprResult StringResult = ParseUnevaluatedStringLiteralExpression();4938 if (StringResult.isInvalid())4939 return std::nullopt;4940 4941 if (auto Lit = dyn_cast<StringLiteral>(StringResult.get()))4942 return Lit;4943 4944 return std::nullopt;4945 };4946 4947 auto Signature = ProcessStringLiteral();4948 if (!Signature.has_value()) {4949 Diag(Tok, diag::err_expected_string_literal)4950 << /*in attributes...*/ 4 << "RootSignature";4951 return;4952 }4953 4954 // Construct our identifier4955 IdentifierInfo *DeclIdent = hlsl::ParseHLSLRootSignature(4956 Actions, getLangOpts().HLSLRootSigVer, *Signature);4957 if (!DeclIdent) {4958 SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);4959 T.consumeClose();4960 return;4961 }4962 4963 // Create the arg for the ParsedAttr4964 IdentifierLoc *ILoc = ::new (Actions.getASTContext())4965 IdentifierLoc(RootSignatureLoc, DeclIdent);4966 4967 ArgsVector Args = {ILoc};4968 4969 if (!T.consumeClose())4970 Attrs.addNew(RootSignatureIdent,4971 SourceRange(RootSignatureLoc, T.getCloseLocation()),4972 AttributeScopeInfo(), Args.data(), Args.size(),4973 ParsedAttr::Form::Microsoft());4974}4975 4976void Parser::ParseMicrosoftAttributes(ParsedAttributes &Attrs) {4977 assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");4978 4979 SourceLocation StartLoc = Tok.getLocation();4980 SourceLocation EndLoc = StartLoc;4981 do {4982 // FIXME: If this is actually a C++11 attribute, parse it as one.4983 BalancedDelimiterTracker T(*this, tok::l_square);4984 T.consumeOpen();4985 4986 // Skip most ms attributes except for a specific list.4987 while (true) {4988 SkipUntil(tok::r_square, tok::identifier,4989 StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);4990 if (Tok.is(tok::code_completion)) {4991 cutOffParsing();4992 Actions.CodeCompletion().CodeCompleteAttribute(4993 AttributeCommonInfo::AS_Microsoft,4994 SemaCodeCompletion::AttributeCompletion::Attribute,4995 /*Scope=*/nullptr);4996 break;4997 }4998 if (Tok.isNot(tok::identifier)) // ']', but also eof4999 break;5000 if (Tok.getIdentifierInfo()->getName() == "uuid")5001 ParseMicrosoftUuidAttributeArgs(Attrs);5002 else if (Tok.getIdentifierInfo()->getName() == "RootSignature")5003 ParseHLSLRootSignatureAttributeArgs(Attrs);5004 else {5005 IdentifierInfo *II = Tok.getIdentifierInfo();5006 SourceLocation NameLoc = Tok.getLocation();5007 ConsumeToken();5008 ParsedAttr::Kind AttrKind =5009 ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_Microsoft);5010 // For HLSL we want to handle all attributes, but for MSVC compat, we5011 // silently ignore unknown Microsoft attributes.5012 if (getLangOpts().HLSL || AttrKind != ParsedAttr::UnknownAttribute) {5013 bool AttrParsed = false;5014 if (Tok.is(tok::l_paren)) {5015 CachedTokens OpenMPTokens;5016 AttrParsed =5017 ParseCXX11AttributeArgs(II, NameLoc, Attrs, &EndLoc, nullptr,5018 SourceLocation(), OpenMPTokens);5019 ReplayOpenMPAttributeTokens(OpenMPTokens);5020 }5021 if (!AttrParsed) {5022 Attrs.addNew(II, NameLoc, AttributeScopeInfo(), nullptr, 0,5023 ParsedAttr::Form::Microsoft());5024 }5025 }5026 }5027 }5028 5029 T.consumeClose();5030 EndLoc = T.getCloseLocation();5031 } while (Tok.is(tok::l_square));5032 5033 Attrs.Range = SourceRange(StartLoc, EndLoc);5034}5035 5036void Parser::ParseMicrosoftIfExistsClassDeclaration(5037 DeclSpec::TST TagType, ParsedAttributes &AccessAttrs,5038 AccessSpecifier &CurAS) {5039 IfExistsCondition Result;5040 if (ParseMicrosoftIfExistsCondition(Result))5041 return;5042 5043 BalancedDelimiterTracker Braces(*this, tok::l_brace);5044 if (Braces.consumeOpen()) {5045 Diag(Tok, diag::err_expected) << tok::l_brace;5046 return;5047 }5048 5049 switch (Result.Behavior) {5050 case IfExistsBehavior::Parse:5051 // Parse the declarations below.5052 break;5053 5054 case IfExistsBehavior::Dependent:5055 Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists)5056 << Result.IsIfExists;5057 // Fall through to skip.5058 [[fallthrough]];5059 5060 case IfExistsBehavior::Skip:5061 Braces.skipToEnd();5062 return;5063 }5064 5065 while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {5066 // __if_exists, __if_not_exists can nest.5067 if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) {5068 ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, CurAS);5069 continue;5070 }5071 5072 // Check for extraneous top-level semicolon.5073 if (Tok.is(tok::semi)) {5074 ConsumeExtraSemi(ExtraSemiKind::InsideStruct, TagType);5075 continue;5076 }5077 5078 AccessSpecifier AS = getAccessSpecifierIfPresent();5079 if (AS != AS_none) {5080 // Current token is a C++ access specifier.5081 CurAS = AS;5082 SourceLocation ASLoc = Tok.getLocation();5083 ConsumeToken();5084 if (Tok.is(tok::colon))5085 Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation(),5086 ParsedAttributesView{});5087 else5088 Diag(Tok, diag::err_expected) << tok::colon;5089 ConsumeToken();5090 continue;5091 }5092 5093 ParsedTemplateInfo TemplateInfo;5094 // Parse all the comma separated declarators.5095 ParseCXXClassMemberDeclaration(CurAS, AccessAttrs, TemplateInfo);5096 }5097 5098 Braces.consumeClose();5099}5100