Path: blob/main/contrib/llvm-project/clang/lib/Parse/ParseDeclCXX.cpp
35233 views
//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the C++ Declaration portions of the Parser interfaces.9//10//===----------------------------------------------------------------------===//1112#include "clang/AST/ASTContext.h"13#include "clang/AST/DeclTemplate.h"14#include "clang/AST/PrettyDeclStackTrace.h"15#include "clang/Basic/AttributeCommonInfo.h"16#include "clang/Basic/Attributes.h"17#include "clang/Basic/CharInfo.h"18#include "clang/Basic/OperatorKinds.h"19#include "clang/Basic/TargetInfo.h"20#include "clang/Basic/TokenKinds.h"21#include "clang/Lex/LiteralSupport.h"22#include "clang/Parse/ParseDiagnostic.h"23#include "clang/Parse/Parser.h"24#include "clang/Parse/RAIIObjectsForParser.h"25#include "clang/Sema/DeclSpec.h"26#include "clang/Sema/EnterExpressionEvaluationContext.h"27#include "clang/Sema/ParsedTemplate.h"28#include "clang/Sema/Scope.h"29#include "clang/Sema/SemaCodeCompletion.h"30#include "llvm/ADT/SmallString.h"31#include "llvm/Support/TimeProfiler.h"32#include <optional>3334using namespace clang;3536/// ParseNamespace - We know that the current token is a namespace keyword. This37/// may either be a top level namespace or a block-level namespace alias. If38/// there was an inline keyword, it has already been parsed.39///40/// namespace-definition: [C++: namespace.def]41/// named-namespace-definition42/// unnamed-namespace-definition43/// nested-namespace-definition44///45/// named-namespace-definition:46/// 'inline'[opt] 'namespace' attributes[opt] identifier '{'47/// namespace-body '}'48///49/// unnamed-namespace-definition:50/// 'inline'[opt] 'namespace' attributes[opt] '{' namespace-body '}'51///52/// nested-namespace-definition:53/// 'namespace' enclosing-namespace-specifier '::' 'inline'[opt]54/// identifier '{' namespace-body '}'55///56/// enclosing-namespace-specifier:57/// identifier58/// enclosing-namespace-specifier '::' 'inline'[opt] identifier59///60/// namespace-alias-definition: [C++ 7.3.2: namespace.alias]61/// 'namespace' identifier '=' qualified-namespace-specifier ';'62///63Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context,64SourceLocation &DeclEnd,65SourceLocation InlineLoc) {66assert(Tok.is(tok::kw_namespace) && "Not a namespace!");67SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'.68ObjCDeclContextSwitch ObjCDC(*this);6970if (Tok.is(tok::code_completion)) {71cutOffParsing();72Actions.CodeCompletion().CodeCompleteNamespaceDecl(getCurScope());73return nullptr;74}7576SourceLocation IdentLoc;77IdentifierInfo *Ident = nullptr;78InnerNamespaceInfoList ExtraNSs;79SourceLocation FirstNestedInlineLoc;8081ParsedAttributes attrs(AttrFactory);8283auto ReadAttributes = [&] {84bool MoreToParse;85do {86MoreToParse = false;87if (Tok.is(tok::kw___attribute)) {88ParseGNUAttributes(attrs);89MoreToParse = true;90}91if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {92Diag(Tok.getLocation(), getLangOpts().CPlusPlus1793? diag::warn_cxx14_compat_ns_enum_attribute94: diag::ext_ns_enum_attribute)95<< 0 /*namespace*/;96ParseCXX11Attributes(attrs);97MoreToParse = true;98}99} while (MoreToParse);100};101102ReadAttributes();103104if (Tok.is(tok::identifier)) {105Ident = Tok.getIdentifierInfo();106IdentLoc = ConsumeToken(); // eat the identifier.107while (Tok.is(tok::coloncolon) &&108(NextToken().is(tok::identifier) ||109(NextToken().is(tok::kw_inline) &&110GetLookAheadToken(2).is(tok::identifier)))) {111112InnerNamespaceInfo Info;113Info.NamespaceLoc = ConsumeToken();114115if (Tok.is(tok::kw_inline)) {116Info.InlineLoc = ConsumeToken();117if (FirstNestedInlineLoc.isInvalid())118FirstNestedInlineLoc = Info.InlineLoc;119}120121Info.Ident = Tok.getIdentifierInfo();122Info.IdentLoc = ConsumeToken();123124ExtraNSs.push_back(Info);125}126}127128ReadAttributes();129130SourceLocation attrLoc = attrs.Range.getBegin();131132// A nested namespace definition cannot have attributes.133if (!ExtraNSs.empty() && attrLoc.isValid())134Diag(attrLoc, diag::err_unexpected_nested_namespace_attribute);135136if (Tok.is(tok::equal)) {137if (!Ident) {138Diag(Tok, diag::err_expected) << tok::identifier;139// Skip to end of the definition and eat the ';'.140SkipUntil(tok::semi);141return nullptr;142}143if (!ExtraNSs.empty()) {144Diag(ExtraNSs.front().NamespaceLoc,145diag::err_unexpected_qualified_namespace_alias)146<< SourceRange(ExtraNSs.front().NamespaceLoc,147ExtraNSs.back().IdentLoc);148SkipUntil(tok::semi);149return nullptr;150}151if (attrLoc.isValid())152Diag(attrLoc, diag::err_unexpected_namespace_attributes_alias);153if (InlineLoc.isValid())154Diag(InlineLoc, diag::err_inline_namespace_alias)155<< FixItHint::CreateRemoval(InlineLoc);156Decl *NSAlias = ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);157return Actions.ConvertDeclToDeclGroup(NSAlias);158}159160BalancedDelimiterTracker T(*this, tok::l_brace);161if (T.consumeOpen()) {162if (Ident)163Diag(Tok, diag::err_expected) << tok::l_brace;164else165Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;166return nullptr;167}168169if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() ||170getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() ||171getCurScope()->getFnParent()) {172Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope);173SkipUntil(tok::r_brace);174return nullptr;175}176177if (ExtraNSs.empty()) {178// Normal namespace definition, not a nested-namespace-definition.179} else if (InlineLoc.isValid()) {180Diag(InlineLoc, diag::err_inline_nested_namespace_definition);181} else if (getLangOpts().CPlusPlus20) {182Diag(ExtraNSs[0].NamespaceLoc,183diag::warn_cxx14_compat_nested_namespace_definition);184if (FirstNestedInlineLoc.isValid())185Diag(FirstNestedInlineLoc,186diag::warn_cxx17_compat_inline_nested_namespace_definition);187} else if (getLangOpts().CPlusPlus17) {188Diag(ExtraNSs[0].NamespaceLoc,189diag::warn_cxx14_compat_nested_namespace_definition);190if (FirstNestedInlineLoc.isValid())191Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition);192} else {193TentativeParsingAction TPA(*this);194SkipUntil(tok::r_brace, StopBeforeMatch);195Token rBraceToken = Tok;196TPA.Revert();197198if (!rBraceToken.is(tok::r_brace)) {199Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition)200<< SourceRange(ExtraNSs.front().NamespaceLoc,201ExtraNSs.back().IdentLoc);202} else {203std::string NamespaceFix;204for (const auto &ExtraNS : ExtraNSs) {205NamespaceFix += " { ";206if (ExtraNS.InlineLoc.isValid())207NamespaceFix += "inline ";208NamespaceFix += "namespace ";209NamespaceFix += ExtraNS.Ident->getName();210}211212std::string RBraces;213for (unsigned i = 0, e = ExtraNSs.size(); i != e; ++i)214RBraces += "} ";215216Diag(ExtraNSs[0].NamespaceLoc, diag::ext_nested_namespace_definition)217<< FixItHint::CreateReplacement(218SourceRange(ExtraNSs.front().NamespaceLoc,219ExtraNSs.back().IdentLoc),220NamespaceFix)221<< FixItHint::CreateInsertion(rBraceToken.getLocation(), RBraces);222}223224// Warn about nested inline namespaces.225if (FirstNestedInlineLoc.isValid())226Diag(FirstNestedInlineLoc, diag::ext_inline_nested_namespace_definition);227}228229// If we're still good, complain about inline namespaces in non-C++0x now.230if (InlineLoc.isValid())231Diag(InlineLoc, getLangOpts().CPlusPlus11232? diag::warn_cxx98_compat_inline_namespace233: diag::ext_inline_namespace);234235// Enter a scope for the namespace.236ParseScope NamespaceScope(this, Scope::DeclScope);237238UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;239Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(240getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident,241T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl, false);242243PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl,244NamespaceLoc, "parsing namespace");245246// Parse the contents of the namespace. This includes parsing recovery on247// any improperly nested namespaces.248ParseInnerNamespace(ExtraNSs, 0, InlineLoc, attrs, T);249250// Leave the namespace scope.251NamespaceScope.Exit();252253DeclEnd = T.getCloseLocation();254Actions.ActOnFinishNamespaceDef(NamespcDecl, DeclEnd);255256return Actions.ConvertDeclToDeclGroup(NamespcDecl,257ImplicitUsingDirectiveDecl);258}259260/// ParseInnerNamespace - Parse the contents of a namespace.261void Parser::ParseInnerNamespace(const InnerNamespaceInfoList &InnerNSs,262unsigned int index, SourceLocation &InlineLoc,263ParsedAttributes &attrs,264BalancedDelimiterTracker &Tracker) {265if (index == InnerNSs.size()) {266while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&267Tok.isNot(tok::eof)) {268ParsedAttributes DeclAttrs(AttrFactory);269MaybeParseCXX11Attributes(DeclAttrs);270ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);271ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs);272}273274// The caller is what called check -- we are simply calling275// the close for it.276Tracker.consumeClose();277278return;279}280281// Handle a nested namespace definition.282// FIXME: Preserve the source information through to the AST rather than283// desugaring it here.284ParseScope NamespaceScope(this, Scope::DeclScope);285UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;286Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(287getCurScope(), InnerNSs[index].InlineLoc, InnerNSs[index].NamespaceLoc,288InnerNSs[index].IdentLoc, InnerNSs[index].Ident,289Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl, true);290assert(!ImplicitUsingDirectiveDecl &&291"nested namespace definition cannot define anonymous namespace");292293ParseInnerNamespace(InnerNSs, ++index, InlineLoc, attrs, Tracker);294295NamespaceScope.Exit();296Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation());297}298299/// ParseNamespaceAlias - Parse the part after the '=' in a namespace300/// alias definition.301///302Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,303SourceLocation AliasLoc,304IdentifierInfo *Alias,305SourceLocation &DeclEnd) {306assert(Tok.is(tok::equal) && "Not equal token");307308ConsumeToken(); // eat the '='.309310if (Tok.is(tok::code_completion)) {311cutOffParsing();312Actions.CodeCompletion().CodeCompleteNamespaceAliasDecl(getCurScope());313return nullptr;314}315316CXXScopeSpec SS;317// Parse (optional) nested-name-specifier.318ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,319/*ObjectHasErrors=*/false,320/*EnteringContext=*/false,321/*MayBePseudoDestructor=*/nullptr,322/*IsTypename=*/false,323/*LastII=*/nullptr,324/*OnlyNamespace=*/true);325326if (Tok.isNot(tok::identifier)) {327Diag(Tok, diag::err_expected_namespace_name);328// Skip to end of the definition and eat the ';'.329SkipUntil(tok::semi);330return nullptr;331}332333if (SS.isInvalid()) {334// Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.335// Skip to end of the definition and eat the ';'.336SkipUntil(tok::semi);337return nullptr;338}339340// Parse identifier.341IdentifierInfo *Ident = Tok.getIdentifierInfo();342SourceLocation IdentLoc = ConsumeToken();343344// Eat the ';'.345DeclEnd = Tok.getLocation();346if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name))347SkipUntil(tok::semi);348349return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc,350Alias, SS, IdentLoc, Ident);351}352353/// ParseLinkage - We know that the current token is a string_literal354/// and just before that, that extern was seen.355///356/// linkage-specification: [C++ 7.5p2: dcl.link]357/// 'extern' string-literal '{' declaration-seq[opt] '}'358/// 'extern' string-literal declaration359///360Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) {361assert(isTokenStringLiteral() && "Not a string literal!");362ExprResult Lang = ParseUnevaluatedStringLiteralExpression();363364ParseScope LinkageScope(this, Scope::DeclScope);365Decl *LinkageSpec =366Lang.isInvalid()367? nullptr368: Actions.ActOnStartLinkageSpecification(369getCurScope(), DS.getSourceRange().getBegin(), Lang.get(),370Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation());371372ParsedAttributes DeclAttrs(AttrFactory);373ParsedAttributes DeclSpecAttrs(AttrFactory);374375while (MaybeParseCXX11Attributes(DeclAttrs) ||376MaybeParseGNUAttributes(DeclSpecAttrs))377;378379if (Tok.isNot(tok::l_brace)) {380// Reset the source range in DS, as the leading "extern"381// does not really belong to the inner declaration ...382DS.SetRangeStart(SourceLocation());383DS.SetRangeEnd(SourceLocation());384// ... but anyway remember that such an "extern" was seen.385DS.setExternInLinkageSpec(true);386ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs, &DS);387return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(388getCurScope(), LinkageSpec, SourceLocation())389: nullptr;390}391392DS.abort();393394ProhibitAttributes(DeclAttrs);395396BalancedDelimiterTracker T(*this, tok::l_brace);397T.consumeOpen();398399unsigned NestedModules = 0;400while (true) {401switch (Tok.getKind()) {402case tok::annot_module_begin:403++NestedModules;404ParseTopLevelDecl();405continue;406407case tok::annot_module_end:408if (!NestedModules)409break;410--NestedModules;411ParseTopLevelDecl();412continue;413414case tok::annot_module_include:415ParseTopLevelDecl();416continue;417418case tok::eof:419break;420421case tok::r_brace:422if (!NestedModules)423break;424[[fallthrough]];425default:426ParsedAttributes DeclAttrs(AttrFactory);427MaybeParseCXX11Attributes(DeclAttrs);428ParseExternalDeclaration(DeclAttrs, DeclSpecAttrs);429continue;430}431432break;433}434435T.consumeClose();436return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(437getCurScope(), LinkageSpec, T.getCloseLocation())438: nullptr;439}440441/// Parse a standard C++ Modules export-declaration.442///443/// export-declaration:444/// 'export' declaration445/// 'export' '{' declaration-seq[opt] '}'446///447/// HLSL: Parse export function declaration.448///449/// export-function-declaration:450/// 'export' function-declaration451///452/// export-declaration-group:453/// 'export' '{' function-declaration-seq[opt] '}'454///455Decl *Parser::ParseExportDeclaration() {456assert(Tok.is(tok::kw_export));457SourceLocation ExportLoc = ConsumeToken();458459ParseScope ExportScope(this, Scope::DeclScope);460Decl *ExportDecl = Actions.ActOnStartExportDecl(461getCurScope(), ExportLoc,462Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation());463464if (Tok.isNot(tok::l_brace)) {465// FIXME: Factor out a ParseExternalDeclarationWithAttrs.466ParsedAttributes DeclAttrs(AttrFactory);467MaybeParseCXX11Attributes(DeclAttrs);468ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);469ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs);470return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl,471SourceLocation());472}473474BalancedDelimiterTracker T(*this, tok::l_brace);475T.consumeOpen();476477while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&478Tok.isNot(tok::eof)) {479ParsedAttributes DeclAttrs(AttrFactory);480MaybeParseCXX11Attributes(DeclAttrs);481ParsedAttributes EmptyDeclSpecAttrs(AttrFactory);482ParseExternalDeclaration(DeclAttrs, EmptyDeclSpecAttrs);483}484485T.consumeClose();486return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl,487T.getCloseLocation());488}489490/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or491/// using-directive. Assumes that current token is 'using'.492Parser::DeclGroupPtrTy Parser::ParseUsingDirectiveOrDeclaration(493DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,494SourceLocation &DeclEnd, ParsedAttributes &Attrs) {495assert(Tok.is(tok::kw_using) && "Not using token");496ObjCDeclContextSwitch ObjCDC(*this);497498// Eat 'using'.499SourceLocation UsingLoc = ConsumeToken();500501if (Tok.is(tok::code_completion)) {502cutOffParsing();503Actions.CodeCompletion().CodeCompleteUsing(getCurScope());504return nullptr;505}506507// Consume unexpected 'template' keywords.508while (Tok.is(tok::kw_template)) {509SourceLocation TemplateLoc = ConsumeToken();510Diag(TemplateLoc, diag::err_unexpected_template_after_using)511<< FixItHint::CreateRemoval(TemplateLoc);512}513514// 'using namespace' means this is a using-directive.515if (Tok.is(tok::kw_namespace)) {516// Template parameters are always an error here.517if (TemplateInfo.Kind) {518SourceRange R = TemplateInfo.getSourceRange();519Diag(UsingLoc, diag::err_templated_using_directive_declaration)520<< 0 /* directive */ << R << FixItHint::CreateRemoval(R);521}522523Decl *UsingDir = ParseUsingDirective(Context, UsingLoc, DeclEnd, Attrs);524return Actions.ConvertDeclToDeclGroup(UsingDir);525}526527// Otherwise, it must be a using-declaration or an alias-declaration.528return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd, Attrs,529AS_none);530}531532/// ParseUsingDirective - Parse C++ using-directive, assumes533/// that current token is 'namespace' and 'using' was already parsed.534///535/// using-directive: [C++ 7.3.p4: namespace.udir]536/// 'using' 'namespace' ::[opt] nested-name-specifier[opt]537/// namespace-name ;538/// [GNU] using-directive:539/// 'using' 'namespace' ::[opt] nested-name-specifier[opt]540/// namespace-name attributes[opt] ;541///542Decl *Parser::ParseUsingDirective(DeclaratorContext Context,543SourceLocation UsingLoc,544SourceLocation &DeclEnd,545ParsedAttributes &attrs) {546assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");547548// Eat 'namespace'.549SourceLocation NamespcLoc = ConsumeToken();550551if (Tok.is(tok::code_completion)) {552cutOffParsing();553Actions.CodeCompletion().CodeCompleteUsingDirective(getCurScope());554return nullptr;555}556557CXXScopeSpec SS;558// Parse (optional) nested-name-specifier.559ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,560/*ObjectHasErrors=*/false,561/*EnteringContext=*/false,562/*MayBePseudoDestructor=*/nullptr,563/*IsTypename=*/false,564/*LastII=*/nullptr,565/*OnlyNamespace=*/true);566567IdentifierInfo *NamespcName = nullptr;568SourceLocation IdentLoc = SourceLocation();569570// Parse namespace-name.571if (Tok.isNot(tok::identifier)) {572Diag(Tok, diag::err_expected_namespace_name);573// If there was invalid namespace name, skip to end of decl, and eat ';'.574SkipUntil(tok::semi);575// FIXME: Are there cases, when we would like to call ActOnUsingDirective?576return nullptr;577}578579if (SS.isInvalid()) {580// Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.581// Skip to end of the definition and eat the ';'.582SkipUntil(tok::semi);583return nullptr;584}585586// Parse identifier.587NamespcName = Tok.getIdentifierInfo();588IdentLoc = ConsumeToken();589590// Parse (optional) attributes (most likely GNU strong-using extension).591bool GNUAttr = false;592if (Tok.is(tok::kw___attribute)) {593GNUAttr = true;594ParseGNUAttributes(attrs);595}596597// Eat ';'.598DeclEnd = Tok.getLocation();599if (ExpectAndConsume(tok::semi,600GNUAttr ? diag::err_expected_semi_after_attribute_list601: diag::err_expected_semi_after_namespace_name))602SkipUntil(tok::semi);603604return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS,605IdentLoc, NamespcName, attrs);606}607608/// Parse a using-declarator (or the identifier in a C++11 alias-declaration).609///610/// using-declarator:611/// 'typename'[opt] nested-name-specifier unqualified-id612///613bool Parser::ParseUsingDeclarator(DeclaratorContext Context,614UsingDeclarator &D) {615D.clear();616617// Ignore optional 'typename'.618// FIXME: This is wrong; we should parse this as a typename-specifier.619TryConsumeToken(tok::kw_typename, D.TypenameLoc);620621if (Tok.is(tok::kw___super)) {622Diag(Tok.getLocation(), diag::err_super_in_using_declaration);623return true;624}625626// Parse nested-name-specifier.627const IdentifierInfo *LastII = nullptr;628if (ParseOptionalCXXScopeSpecifier(D.SS, /*ObjectType=*/nullptr,629/*ObjectHasErrors=*/false,630/*EnteringContext=*/false,631/*MayBePseudoDtor=*/nullptr,632/*IsTypename=*/false,633/*LastII=*/&LastII,634/*OnlyNamespace=*/false,635/*InUsingDeclaration=*/true))636637return true;638if (D.SS.isInvalid())639return true;640641// Parse the unqualified-id. We allow parsing of both constructor and642// destructor names and allow the action module to diagnose any semantic643// errors.644//645// C++11 [class.qual]p2:646// [...] in a using-declaration that is a member-declaration, if the name647// specified after the nested-name-specifier is the same as the identifier648// or the simple-template-id's template-name in the last component of the649// nested-name-specifier, the name is [...] considered to name the650// constructor.651if (getLangOpts().CPlusPlus11 && Context == DeclaratorContext::Member &&652Tok.is(tok::identifier) &&653(NextToken().is(tok::semi) || NextToken().is(tok::comma) ||654NextToken().is(tok::ellipsis) || NextToken().is(tok::l_square) ||655NextToken().isRegularKeywordAttribute() ||656NextToken().is(tok::kw___attribute)) &&657D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&658!D.SS.getScopeRep()->getAsNamespace() &&659!D.SS.getScopeRep()->getAsNamespaceAlias()) {660SourceLocation IdLoc = ConsumeToken();661ParsedType Type =662Actions.getInheritingConstructorName(D.SS, IdLoc, *LastII);663D.Name.setConstructorName(Type, IdLoc, IdLoc);664} else {665if (ParseUnqualifiedId(666D.SS, /*ObjectType=*/nullptr,667/*ObjectHadErrors=*/false, /*EnteringContext=*/false,668/*AllowDestructorName=*/true,669/*AllowConstructorName=*/670!(Tok.is(tok::identifier) && NextToken().is(tok::equal)),671/*AllowDeductionGuide=*/false, nullptr, D.Name))672return true;673}674675if (TryConsumeToken(tok::ellipsis, D.EllipsisLoc))676Diag(Tok.getLocation(), getLangOpts().CPlusPlus17677? diag::warn_cxx17_compat_using_declaration_pack678: diag::ext_using_declaration_pack);679680return false;681}682683/// ParseUsingDeclaration - Parse C++ using-declaration or alias-declaration.684/// Assumes that 'using' was already seen.685///686/// using-declaration: [C++ 7.3.p3: namespace.udecl]687/// 'using' using-declarator-list[opt] ;688///689/// using-declarator-list: [C++1z]690/// using-declarator '...'[opt]691/// using-declarator-list ',' using-declarator '...'[opt]692///693/// using-declarator-list: [C++98-14]694/// using-declarator695///696/// alias-declaration: C++11 [dcl.dcl]p1697/// 'using' identifier attribute-specifier-seq[opt] = type-id ;698///699/// using-enum-declaration: [C++20, dcl.enum]700/// 'using' elaborated-enum-specifier ;701/// The terminal name of the elaborated-enum-specifier undergoes702/// type-only lookup703///704/// elaborated-enum-specifier:705/// 'enum' nested-name-specifier[opt] identifier706Parser::DeclGroupPtrTy Parser::ParseUsingDeclaration(707DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo,708SourceLocation UsingLoc, SourceLocation &DeclEnd,709ParsedAttributes &PrefixAttrs, AccessSpecifier AS) {710SourceLocation UELoc;711bool InInitStatement = Context == DeclaratorContext::SelectionInit ||712Context == DeclaratorContext::ForInit;713714if (TryConsumeToken(tok::kw_enum, UELoc) && !InInitStatement) {715// C++20 using-enum716Diag(UELoc, getLangOpts().CPlusPlus20717? diag::warn_cxx17_compat_using_enum_declaration718: diag::ext_using_enum_declaration);719720DiagnoseCXX11AttributeExtension(PrefixAttrs);721722if (TemplateInfo.Kind) {723SourceRange R = TemplateInfo.getSourceRange();724Diag(UsingLoc, diag::err_templated_using_directive_declaration)725<< 1 /* declaration */ << R << FixItHint::CreateRemoval(R);726SkipUntil(tok::semi);727return nullptr;728}729CXXScopeSpec SS;730if (ParseOptionalCXXScopeSpecifier(SS, /*ParsedType=*/nullptr,731/*ObectHasErrors=*/false,732/*EnteringConttext=*/false,733/*MayBePseudoDestructor=*/nullptr,734/*IsTypename=*/true,735/*IdentifierInfo=*/nullptr,736/*OnlyNamespace=*/false,737/*InUsingDeclaration=*/true)) {738SkipUntil(tok::semi);739return nullptr;740}741742if (Tok.is(tok::code_completion)) {743cutOffParsing();744Actions.CodeCompletion().CodeCompleteUsing(getCurScope());745return nullptr;746}747748Decl *UED = nullptr;749750// FIXME: identifier and annot_template_id handling is very similar to751// ParseBaseTypeSpecifier. It should be factored out into a function.752if (Tok.is(tok::identifier)) {753IdentifierInfo *IdentInfo = Tok.getIdentifierInfo();754SourceLocation IdentLoc = ConsumeToken();755756ParsedType Type = Actions.getTypeName(757*IdentInfo, IdentLoc, getCurScope(), &SS, /*isClassName=*/true,758/*HasTrailingDot=*/false,759/*ObjectType=*/nullptr, /*IsCtorOrDtorName=*/false,760/*WantNontrivialTypeSourceInfo=*/true);761762UED = Actions.ActOnUsingEnumDeclaration(763getCurScope(), AS, UsingLoc, UELoc, IdentLoc, *IdentInfo, Type, &SS);764} else if (Tok.is(tok::annot_template_id)) {765TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);766767if (TemplateId->mightBeType()) {768AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No,769/*IsClassName=*/true);770771assert(Tok.is(tok::annot_typename) && "template-id -> type failed");772TypeResult Type = getTypeAnnotation(Tok);773SourceRange Loc = Tok.getAnnotationRange();774ConsumeAnnotationToken();775776UED = Actions.ActOnUsingEnumDeclaration(getCurScope(), AS, UsingLoc,777UELoc, Loc, *TemplateId->Name,778Type.get(), &SS);779} else {780Diag(Tok.getLocation(), diag::err_using_enum_not_enum)781<< TemplateId->Name->getName()782<< SourceRange(TemplateId->TemplateNameLoc, TemplateId->RAngleLoc);783}784} else {785Diag(Tok.getLocation(), diag::err_using_enum_expect_identifier)786<< Tok.is(tok::kw_enum);787SkipUntil(tok::semi);788return nullptr;789}790791if (!UED) {792SkipUntil(tok::semi);793return nullptr;794}795796DeclEnd = Tok.getLocation();797if (ExpectAndConsume(tok::semi, diag::err_expected_after,798"using-enum declaration"))799SkipUntil(tok::semi);800801return Actions.ConvertDeclToDeclGroup(UED);802}803804// Check for misplaced attributes before the identifier in an805// alias-declaration.806ParsedAttributes MisplacedAttrs(AttrFactory);807MaybeParseCXX11Attributes(MisplacedAttrs);808809if (InInitStatement && Tok.isNot(tok::identifier))810return nullptr;811812UsingDeclarator D;813bool InvalidDeclarator = ParseUsingDeclarator(Context, D);814815ParsedAttributes Attrs(AttrFactory);816MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);817818// If we had any misplaced attributes from earlier, this is where they819// should have been written.820if (MisplacedAttrs.Range.isValid()) {821auto *FirstAttr =822MisplacedAttrs.empty() ? nullptr : &MisplacedAttrs.front();823auto &Range = MisplacedAttrs.Range;824(FirstAttr && FirstAttr->isRegularKeywordAttribute()825? Diag(Range.getBegin(), diag::err_keyword_not_allowed) << FirstAttr826: Diag(Range.getBegin(), diag::err_attributes_not_allowed))827<< FixItHint::CreateInsertionFromRange(828Tok.getLocation(), CharSourceRange::getTokenRange(Range))829<< FixItHint::CreateRemoval(Range);830Attrs.takeAllFrom(MisplacedAttrs);831}832833// Maybe this is an alias-declaration.834if (Tok.is(tok::equal) || InInitStatement) {835if (InvalidDeclarator) {836SkipUntil(tok::semi);837return nullptr;838}839840ProhibitAttributes(PrefixAttrs);841842Decl *DeclFromDeclSpec = nullptr;843Scope *CurScope = getCurScope();844if (CurScope)845CurScope->setFlags(Scope::ScopeFlags::TypeAliasScope |846CurScope->getFlags());847848Decl *AD = ParseAliasDeclarationAfterDeclarator(849TemplateInfo, UsingLoc, D, DeclEnd, AS, Attrs, &DeclFromDeclSpec);850return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec);851}852853DiagnoseCXX11AttributeExtension(PrefixAttrs);854855// Diagnose an attempt to declare a templated using-declaration.856// In C++11, alias-declarations can be templates:857// template <...> using id = type;858if (TemplateInfo.Kind) {859SourceRange R = TemplateInfo.getSourceRange();860Diag(UsingLoc, diag::err_templated_using_directive_declaration)861<< 1 /* declaration */ << R << FixItHint::CreateRemoval(R);862863// Unfortunately, we have to bail out instead of recovering by864// ignoring the parameters, just in case the nested name specifier865// depends on the parameters.866return nullptr;867}868869SmallVector<Decl *, 8> DeclsInGroup;870while (true) {871// Parse (optional) attributes.872MaybeParseAttributes(PAKM_GNU | PAKM_CXX11, Attrs);873DiagnoseCXX11AttributeExtension(Attrs);874Attrs.addAll(PrefixAttrs.begin(), PrefixAttrs.end());875876if (InvalidDeclarator)877SkipUntil(tok::comma, tok::semi, StopBeforeMatch);878else {879// "typename" keyword is allowed for identifiers only,880// because it may be a type definition.881if (D.TypenameLoc.isValid() &&882D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {883Diag(D.Name.getSourceRange().getBegin(),884diag::err_typename_identifiers_only)885<< FixItHint::CreateRemoval(SourceRange(D.TypenameLoc));886// Proceed parsing, but discard the typename keyword.887D.TypenameLoc = SourceLocation();888}889890Decl *UD = Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc,891D.TypenameLoc, D.SS, D.Name,892D.EllipsisLoc, Attrs);893if (UD)894DeclsInGroup.push_back(UD);895}896897if (!TryConsumeToken(tok::comma))898break;899900// Parse another using-declarator.901Attrs.clear();902InvalidDeclarator = ParseUsingDeclarator(Context, D);903}904905if (DeclsInGroup.size() > 1)906Diag(Tok.getLocation(),907getLangOpts().CPlusPlus17908? diag::warn_cxx17_compat_multi_using_declaration909: diag::ext_multi_using_declaration);910911// Eat ';'.912DeclEnd = Tok.getLocation();913if (ExpectAndConsume(tok::semi, diag::err_expected_after,914!Attrs.empty() ? "attributes list"915: UELoc.isValid() ? "using-enum declaration"916: "using declaration"))917SkipUntil(tok::semi);918919return Actions.BuildDeclaratorGroup(DeclsInGroup);920}921922Decl *Parser::ParseAliasDeclarationAfterDeclarator(923const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,924UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS,925ParsedAttributes &Attrs, Decl **OwnedType) {926if (ExpectAndConsume(tok::equal)) {927SkipUntil(tok::semi);928return nullptr;929}930931Diag(Tok.getLocation(), getLangOpts().CPlusPlus11932? diag::warn_cxx98_compat_alias_declaration933: diag::ext_alias_declaration);934935// Type alias templates cannot be specialized.936int SpecKind = -1;937if (TemplateInfo.Kind == ParsedTemplateInfo::Template &&938D.Name.getKind() == UnqualifiedIdKind::IK_TemplateId)939SpecKind = 0;940if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization)941SpecKind = 1;942if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)943SpecKind = 2;944if (SpecKind != -1) {945SourceRange Range;946if (SpecKind == 0)947Range = SourceRange(D.Name.TemplateId->LAngleLoc,948D.Name.TemplateId->RAngleLoc);949else950Range = TemplateInfo.getSourceRange();951Diag(Range.getBegin(), diag::err_alias_declaration_specialization)952<< SpecKind << Range;953SkipUntil(tok::semi);954return nullptr;955}956957// Name must be an identifier.958if (D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) {959Diag(D.Name.StartLocation, diag::err_alias_declaration_not_identifier);960// No removal fixit: can't recover from this.961SkipUntil(tok::semi);962return nullptr;963} else if (D.TypenameLoc.isValid())964Diag(D.TypenameLoc, diag::err_alias_declaration_not_identifier)965<< FixItHint::CreateRemoval(966SourceRange(D.TypenameLoc, D.SS.isNotEmpty() ? D.SS.getEndLoc()967: D.TypenameLoc));968else if (D.SS.isNotEmpty())969Diag(D.SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)970<< FixItHint::CreateRemoval(D.SS.getRange());971if (D.EllipsisLoc.isValid())972Diag(D.EllipsisLoc, diag::err_alias_declaration_pack_expansion)973<< FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc));974975Decl *DeclFromDeclSpec = nullptr;976TypeResult TypeAlias =977ParseTypeName(nullptr,978TemplateInfo.Kind ? DeclaratorContext::AliasTemplate979: DeclaratorContext::AliasDecl,980AS, &DeclFromDeclSpec, &Attrs);981if (OwnedType)982*OwnedType = DeclFromDeclSpec;983984// Eat ';'.985DeclEnd = Tok.getLocation();986if (ExpectAndConsume(tok::semi, diag::err_expected_after,987!Attrs.empty() ? "attributes list"988: "alias declaration"))989SkipUntil(tok::semi);990991TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;992MultiTemplateParamsArg TemplateParamsArg(993TemplateParams ? TemplateParams->data() : nullptr,994TemplateParams ? TemplateParams->size() : 0);995return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,996UsingLoc, D.Name, Attrs, TypeAlias,997DeclFromDeclSpec);998}9991000static FixItHint getStaticAssertNoMessageFixIt(const Expr *AssertExpr,1001SourceLocation EndExprLoc) {1002if (const auto *BO = dyn_cast_or_null<BinaryOperator>(AssertExpr)) {1003if (BO->getOpcode() == BO_LAnd &&1004isa<StringLiteral>(BO->getRHS()->IgnoreImpCasts()))1005return FixItHint::CreateReplacement(BO->getOperatorLoc(), ",");1006}1007return FixItHint::CreateInsertion(EndExprLoc, ", \"\"");1008}10091010/// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration.1011///1012/// [C++0x] static_assert-declaration:1013/// static_assert ( constant-expression , string-literal ) ;1014///1015/// [C11] static_assert-declaration:1016/// _Static_assert ( constant-expression , string-literal ) ;1017///1018Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd) {1019assert(Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert) &&1020"Not a static_assert declaration");10211022// Save the token name used for static assertion.1023const char *TokName = Tok.getName();10241025if (Tok.is(tok::kw__Static_assert))1026diagnoseUseOfC11Keyword(Tok);1027else if (Tok.is(tok::kw_static_assert)) {1028if (!getLangOpts().CPlusPlus) {1029if (getLangOpts().C23)1030Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();1031else1032Diag(Tok, diag::ext_ms_static_assert) << FixItHint::CreateReplacement(1033Tok.getLocation(), "_Static_assert");1034} else1035Diag(Tok, diag::warn_cxx98_compat_static_assert);1036}10371038SourceLocation StaticAssertLoc = ConsumeToken();10391040BalancedDelimiterTracker T(*this, tok::l_paren);1041if (T.consumeOpen()) {1042Diag(Tok, diag::err_expected) << tok::l_paren;1043SkipMalformedDecl();1044return nullptr;1045}10461047EnterExpressionEvaluationContext ConstantEvaluated(1048Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);1049ExprResult AssertExpr(ParseConstantExpressionInExprEvalContext());1050if (AssertExpr.isInvalid()) {1051SkipMalformedDecl();1052return nullptr;1053}10541055ExprResult AssertMessage;1056if (Tok.is(tok::r_paren)) {1057unsigned DiagVal;1058if (getLangOpts().CPlusPlus17)1059DiagVal = diag::warn_cxx14_compat_static_assert_no_message;1060else if (getLangOpts().CPlusPlus)1061DiagVal = diag::ext_cxx_static_assert_no_message;1062else if (getLangOpts().C23)1063DiagVal = diag::warn_c17_compat_static_assert_no_message;1064else1065DiagVal = diag::ext_c_static_assert_no_message;1066Diag(Tok, DiagVal) << getStaticAssertNoMessageFixIt(AssertExpr.get(),1067Tok.getLocation());1068} else {1069if (ExpectAndConsume(tok::comma)) {1070SkipUntil(tok::semi);1071return nullptr;1072}10731074bool ParseAsExpression = false;1075if (getLangOpts().CPlusPlus26) {1076for (unsigned I = 0;; ++I) {1077const Token &T = GetLookAheadToken(I);1078if (T.is(tok::r_paren))1079break;1080if (!tokenIsLikeStringLiteral(T, getLangOpts()) || T.hasUDSuffix()) {1081ParseAsExpression = true;1082break;1083}1084}1085}10861087if (ParseAsExpression)1088AssertMessage = ParseConstantExpressionInExprEvalContext();1089else if (tokenIsLikeStringLiteral(Tok, getLangOpts()))1090AssertMessage = ParseUnevaluatedStringLiteralExpression();1091else {1092Diag(Tok, diag::err_expected_string_literal)1093<< /*Source='static_assert'*/ 1;1094SkipMalformedDecl();1095return nullptr;1096}10971098if (AssertMessage.isInvalid()) {1099SkipMalformedDecl();1100return nullptr;1101}1102}11031104T.consumeClose();11051106DeclEnd = Tok.getLocation();1107ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert, TokName);11081109return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, AssertExpr.get(),1110AssertMessage.get(),1111T.getCloseLocation());1112}11131114/// ParseDecltypeSpecifier - Parse a C++11 decltype specifier.1115///1116/// 'decltype' ( expression )1117/// 'decltype' ( 'auto' ) [C++1y]1118///1119SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {1120assert(Tok.isOneOf(tok::kw_decltype, tok::annot_decltype) &&1121"Not a decltype specifier");11221123ExprResult Result;1124SourceLocation StartLoc = Tok.getLocation();1125SourceLocation EndLoc;11261127if (Tok.is(tok::annot_decltype)) {1128Result = getExprAnnotation(Tok);1129EndLoc = Tok.getAnnotationEndLoc();1130// Unfortunately, we don't know the LParen source location as the annotated1131// token doesn't have it.1132DS.setTypeArgumentRange(SourceRange(SourceLocation(), EndLoc));1133ConsumeAnnotationToken();1134if (Result.isInvalid()) {1135DS.SetTypeSpecError();1136return EndLoc;1137}1138} else {1139if (Tok.getIdentifierInfo()->isStr("decltype"))1140Diag(Tok, diag::warn_cxx98_compat_decltype);11411142ConsumeToken();11431144BalancedDelimiterTracker T(*this, tok::l_paren);1145if (T.expectAndConsume(diag::err_expected_lparen_after, "decltype",1146tok::r_paren)) {1147DS.SetTypeSpecError();1148return T.getOpenLocation() == Tok.getLocation() ? StartLoc1149: T.getOpenLocation();1150}11511152// Check for C++1y 'decltype(auto)'.1153if (Tok.is(tok::kw_auto) && NextToken().is(tok::r_paren)) {1154// the typename-specifier in a function-style cast expression may1155// be 'auto' since C++23.1156Diag(Tok.getLocation(),1157getLangOpts().CPlusPlus141158? diag::warn_cxx11_compat_decltype_auto_type_specifier1159: diag::ext_decltype_auto_type_specifier);1160ConsumeToken();1161} else {1162// Parse the expression11631164// C++11 [dcl.type.simple]p4:1165// The operand of the decltype specifier is an unevaluated operand.1166EnterExpressionEvaluationContext Unevaluated(1167Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,1168Sema::ExpressionEvaluationContextRecord::EK_Decltype);1169Result = Actions.CorrectDelayedTyposInExpr(1170ParseExpression(), /*InitDecl=*/nullptr,1171/*RecoverUncorrectedTypos=*/false,1172[](Expr *E) { return E->hasPlaceholderType() ? ExprError() : E; });1173if (Result.isInvalid()) {1174DS.SetTypeSpecError();1175if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {1176EndLoc = ConsumeParen();1177} else {1178if (PP.isBacktrackEnabled() && Tok.is(tok::semi)) {1179// Backtrack to get the location of the last token before the semi.1180PP.RevertCachedTokens(2);1181ConsumeToken(); // the semi.1182EndLoc = ConsumeAnyToken();1183assert(Tok.is(tok::semi));1184} else {1185EndLoc = Tok.getLocation();1186}1187}1188return EndLoc;1189}11901191Result = Actions.ActOnDecltypeExpression(Result.get());1192}11931194// Match the ')'1195T.consumeClose();1196DS.setTypeArgumentRange(T.getRange());1197if (T.getCloseLocation().isInvalid()) {1198DS.SetTypeSpecError();1199// FIXME: this should return the location of the last token1200// that was consumed (by "consumeClose()")1201return T.getCloseLocation();1202}12031204if (Result.isInvalid()) {1205DS.SetTypeSpecError();1206return T.getCloseLocation();1207}12081209EndLoc = T.getCloseLocation();1210}1211assert(!Result.isInvalid());12121213const char *PrevSpec = nullptr;1214unsigned DiagID;1215const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();1216// Check for duplicate type specifiers (e.g. "int decltype(a)").1217if (Result.get() ? DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc,1218PrevSpec, DiagID, Result.get(), Policy)1219: DS.SetTypeSpecType(DeclSpec::TST_decltype_auto, StartLoc,1220PrevSpec, DiagID, Policy)) {1221Diag(StartLoc, DiagID) << PrevSpec;1222DS.SetTypeSpecError();1223}1224return EndLoc;1225}12261227void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec &DS,1228SourceLocation StartLoc,1229SourceLocation EndLoc) {1230// make sure we have a token we can turn into an annotation token1231if (PP.isBacktrackEnabled()) {1232PP.RevertCachedTokens(1);1233if (DS.getTypeSpecType() == TST_error) {1234// We encountered an error in parsing 'decltype(...)' so lets annotate all1235// the tokens in the backtracking cache - that we likely had to skip over1236// to get to a token that allows us to resume parsing, such as a1237// semi-colon.1238EndLoc = PP.getLastCachedTokenLocation();1239}1240} else1241PP.EnterToken(Tok, /*IsReinject*/ true);12421243Tok.setKind(tok::annot_decltype);1244setExprAnnotation(Tok,1245DS.getTypeSpecType() == TST_decltype ? DS.getRepAsExpr()1246: DS.getTypeSpecType() == TST_decltype_auto ? ExprResult()1247: ExprError());1248Tok.setAnnotationEndLoc(EndLoc);1249Tok.setLocation(StartLoc);1250PP.AnnotateCachedTokens(Tok);1251}12521253SourceLocation Parser::ParsePackIndexingType(DeclSpec &DS) {1254assert(Tok.isOneOf(tok::annot_pack_indexing_type, tok::identifier) &&1255"Expected an identifier");12561257TypeResult Type;1258SourceLocation StartLoc;1259SourceLocation EllipsisLoc;1260const char *PrevSpec;1261unsigned DiagID;1262const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();12631264if (Tok.is(tok::annot_pack_indexing_type)) {1265StartLoc = Tok.getLocation();1266SourceLocation EndLoc;1267Type = getTypeAnnotation(Tok);1268EndLoc = Tok.getAnnotationEndLoc();1269// Unfortunately, we don't know the LParen source location as the annotated1270// token doesn't have it.1271DS.setTypeArgumentRange(SourceRange(SourceLocation(), EndLoc));1272ConsumeAnnotationToken();1273if (Type.isInvalid()) {1274DS.SetTypeSpecError();1275return EndLoc;1276}1277DS.SetTypeSpecType(DeclSpec::TST_typename_pack_indexing, StartLoc, PrevSpec,1278DiagID, Type, Policy);1279return EndLoc;1280}1281if (!NextToken().is(tok::ellipsis) ||1282!GetLookAheadToken(2).is(tok::l_square)) {1283DS.SetTypeSpecError();1284return Tok.getEndLoc();1285}12861287ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(),1288Tok.getLocation(), getCurScope());1289if (!Ty) {1290DS.SetTypeSpecError();1291return Tok.getEndLoc();1292}1293Type = Ty;12941295StartLoc = ConsumeToken();1296EllipsisLoc = ConsumeToken();1297BalancedDelimiterTracker T(*this, tok::l_square);1298T.consumeOpen();1299ExprResult IndexExpr = ParseConstantExpression();1300T.consumeClose();13011302DS.SetRangeStart(StartLoc);1303DS.SetRangeEnd(T.getCloseLocation());13041305if (!IndexExpr.isUsable()) {1306ASTContext &C = Actions.getASTContext();1307IndexExpr = IntegerLiteral::Create(C, C.MakeIntValue(0, C.getSizeType()),1308C.getSizeType(), SourceLocation());1309}13101311DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, PrevSpec, DiagID, Type,1312Policy);1313DS.SetPackIndexingExpr(EllipsisLoc, IndexExpr.get());1314return T.getCloseLocation();1315}13161317void Parser::AnnotateExistingIndexedTypeNamePack(ParsedType T,1318SourceLocation StartLoc,1319SourceLocation EndLoc) {1320// make sure we have a token we can turn into an annotation token1321if (PP.isBacktrackEnabled()) {1322PP.RevertCachedTokens(1);1323if (!T) {1324// We encountered an error in parsing 'decltype(...)' so lets annotate all1325// the tokens in the backtracking cache - that we likely had to skip over1326// to get to a token that allows us to resume parsing, such as a1327// semi-colon.1328EndLoc = PP.getLastCachedTokenLocation();1329}1330} else1331PP.EnterToken(Tok, /*IsReinject*/ true);13321333Tok.setKind(tok::annot_pack_indexing_type);1334setTypeAnnotation(Tok, T);1335Tok.setAnnotationEndLoc(EndLoc);1336Tok.setLocation(StartLoc);1337PP.AnnotateCachedTokens(Tok);1338}13391340DeclSpec::TST Parser::TypeTransformTokToDeclSpec() {1341switch (Tok.getKind()) {1342#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \1343case tok::kw___##Trait: \1344return DeclSpec::TST_##Trait;1345#include "clang/Basic/TransformTypeTraits.def"1346default:1347llvm_unreachable("passed in an unhandled type transformation built-in");1348}1349}13501351bool Parser::MaybeParseTypeTransformTypeSpecifier(DeclSpec &DS) {1352if (!NextToken().is(tok::l_paren)) {1353Tok.setKind(tok::identifier);1354return false;1355}1356DeclSpec::TST TypeTransformTST = TypeTransformTokToDeclSpec();1357SourceLocation StartLoc = ConsumeToken();13581359BalancedDelimiterTracker T(*this, tok::l_paren);1360if (T.expectAndConsume(diag::err_expected_lparen_after, Tok.getName(),1361tok::r_paren))1362return true;13631364TypeResult Result = ParseTypeName();1365if (Result.isInvalid()) {1366SkipUntil(tok::r_paren, StopAtSemi);1367return true;1368}13691370T.consumeClose();1371if (T.getCloseLocation().isInvalid())1372return true;13731374const char *PrevSpec = nullptr;1375unsigned DiagID;1376if (DS.SetTypeSpecType(TypeTransformTST, StartLoc, PrevSpec, DiagID,1377Result.get(),1378Actions.getASTContext().getPrintingPolicy()))1379Diag(StartLoc, DiagID) << PrevSpec;1380DS.setTypeArgumentRange(T.getRange());1381return true;1382}13831384/// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a1385/// class name or decltype-specifier. Note that we only check that the result1386/// names a type; semantic analysis will need to verify that the type names a1387/// class. The result is either a type or null, depending on whether a type1388/// name was found.1389///1390/// base-type-specifier: [C++11 class.derived]1391/// class-or-decltype1392/// class-or-decltype: [C++11 class.derived]1393/// nested-name-specifier[opt] class-name1394/// decltype-specifier1395/// class-name: [C++ class.name]1396/// identifier1397/// simple-template-id1398///1399/// In C++98, instead of base-type-specifier, we have:1400///1401/// ::[opt] nested-name-specifier[opt] class-name1402TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,1403SourceLocation &EndLocation) {1404// Ignore attempts to use typename1405if (Tok.is(tok::kw_typename)) {1406Diag(Tok, diag::err_expected_class_name_not_template)1407<< FixItHint::CreateRemoval(Tok.getLocation());1408ConsumeToken();1409}14101411// Parse optional nested-name-specifier1412CXXScopeSpec SS;1413if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,1414/*ObjectHasErrors=*/false,1415/*EnteringContext=*/false))1416return true;14171418BaseLoc = Tok.getLocation();14191420// Parse decltype-specifier1421// tok == kw_decltype is just error recovery, it can only happen when SS1422// isn't empty1423if (Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) {1424if (SS.isNotEmpty())1425Diag(SS.getBeginLoc(), diag::err_unexpected_scope_on_base_decltype)1426<< FixItHint::CreateRemoval(SS.getRange());1427// Fake up a Declarator to use with ActOnTypeName.1428DeclSpec DS(AttrFactory);14291430EndLocation = ParseDecltypeSpecifier(DS);14311432Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),1433DeclaratorContext::TypeName);1434return Actions.ActOnTypeName(DeclaratorInfo);1435}14361437if (Tok.is(tok::annot_pack_indexing_type)) {1438DeclSpec DS(AttrFactory);1439ParsePackIndexingType(DS);1440Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),1441DeclaratorContext::TypeName);1442return Actions.ActOnTypeName(DeclaratorInfo);1443}14441445// Check whether we have a template-id that names a type.1446// FIXME: identifier and annot_template_id handling in ParseUsingDeclaration1447// work very similarly. It should be refactored into a separate function.1448if (Tok.is(tok::annot_template_id)) {1449TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);1450if (TemplateId->mightBeType()) {1451AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No,1452/*IsClassName=*/true);14531454assert(Tok.is(tok::annot_typename) && "template-id -> type failed");1455TypeResult Type = getTypeAnnotation(Tok);1456EndLocation = Tok.getAnnotationEndLoc();1457ConsumeAnnotationToken();1458return Type;1459}14601461// Fall through to produce an error below.1462}14631464if (Tok.isNot(tok::identifier)) {1465Diag(Tok, diag::err_expected_class_name);1466return true;1467}14681469IdentifierInfo *Id = Tok.getIdentifierInfo();1470SourceLocation IdLoc = ConsumeToken();14711472if (Tok.is(tok::less)) {1473// It looks the user intended to write a template-id here, but the1474// template-name was wrong. Try to fix that.1475// FIXME: Invoke ParseOptionalCXXScopeSpecifier in a "'template' is neither1476// required nor permitted" mode, and do this there.1477TemplateNameKind TNK = TNK_Non_template;1478TemplateTy Template;1479if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(), &SS,1480Template, TNK)) {1481Diag(IdLoc, diag::err_unknown_template_name) << Id;1482}14831484// Form the template name1485UnqualifiedId TemplateName;1486TemplateName.setIdentifier(Id, IdLoc);14871488// Parse the full template-id, then turn it into a type.1489if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),1490TemplateName))1491return true;1492if (Tok.is(tok::annot_template_id) &&1493takeTemplateIdAnnotation(Tok)->mightBeType())1494AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No,1495/*IsClassName=*/true);14961497// If we didn't end up with a typename token, there's nothing more we1498// can do.1499if (Tok.isNot(tok::annot_typename))1500return true;15011502// Retrieve the type from the annotation token, consume that token, and1503// return.1504EndLocation = Tok.getAnnotationEndLoc();1505TypeResult Type = getTypeAnnotation(Tok);1506ConsumeAnnotationToken();1507return Type;1508}15091510// We have an identifier; check whether it is actually a type.1511IdentifierInfo *CorrectedII = nullptr;1512ParsedType Type = Actions.getTypeName(1513*Id, IdLoc, getCurScope(), &SS, /*isClassName=*/true, false, nullptr,1514/*IsCtorOrDtorName=*/false,1515/*WantNontrivialTypeSourceInfo=*/true,1516/*IsClassTemplateDeductionContext=*/false, ImplicitTypenameContext::No,1517&CorrectedII);1518if (!Type) {1519Diag(IdLoc, diag::err_expected_class_name);1520return true;1521}15221523// Consume the identifier.1524EndLocation = IdLoc;15251526// Fake up a Declarator to use with ActOnTypeName.1527DeclSpec DS(AttrFactory);1528DS.SetRangeStart(IdLoc);1529DS.SetRangeEnd(EndLocation);1530DS.getTypeSpecScope() = SS;15311532const char *PrevSpec = nullptr;1533unsigned DiagID;1534DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type,1535Actions.getASTContext().getPrintingPolicy());15361537Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),1538DeclaratorContext::TypeName);1539return Actions.ActOnTypeName(DeclaratorInfo);1540}15411542void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {1543while (Tok.isOneOf(tok::kw___single_inheritance,1544tok::kw___multiple_inheritance,1545tok::kw___virtual_inheritance)) {1546IdentifierInfo *AttrName = Tok.getIdentifierInfo();1547auto Kind = Tok.getKind();1548SourceLocation AttrNameLoc = ConsumeToken();1549attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind);1550}1551}15521553void Parser::ParseNullabilityClassAttributes(ParsedAttributes &attrs) {1554while (Tok.is(tok::kw__Nullable)) {1555IdentifierInfo *AttrName = Tok.getIdentifierInfo();1556auto Kind = Tok.getKind();1557SourceLocation AttrNameLoc = ConsumeToken();1558attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind);1559}1560}15611562/// Determine whether the following tokens are valid after a type-specifier1563/// which could be a standalone declaration. This will conservatively return1564/// true if there's any doubt, and is appropriate for insert-';' fixits.1565bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) {1566// This switch enumerates the valid "follow" set for type-specifiers.1567switch (Tok.getKind()) {1568default:1569if (Tok.isRegularKeywordAttribute())1570return true;1571break;1572case tok::semi: // struct foo {...} ;1573case tok::star: // struct foo {...} * P;1574case tok::amp: // struct foo {...} & R = ...1575case tok::ampamp: // struct foo {...} && R = ...1576case tok::identifier: // struct foo {...} V ;1577case tok::r_paren: //(struct foo {...} ) {4}1578case tok::coloncolon: // struct foo {...} :: a::b;1579case tok::annot_cxxscope: // struct foo {...} a:: b;1580case tok::annot_typename: // struct foo {...} a ::b;1581case tok::annot_template_id: // struct foo {...} a<int> ::b;1582case tok::kw_decltype: // struct foo {...} decltype (a)::b;1583case tok::l_paren: // struct foo {...} ( x);1584case tok::comma: // __builtin_offsetof(struct foo{...} ,1585case tok::kw_operator: // struct foo operator ++() {...}1586case tok::kw___declspec: // struct foo {...} __declspec(...)1587case tok::l_square: // void f(struct f [ 3])1588case tok::ellipsis: // void f(struct f ... [Ns])1589// FIXME: we should emit semantic diagnostic when declaration1590// attribute is in type attribute position.1591case tok::kw___attribute: // struct foo __attribute__((used)) x;1592case tok::annot_pragma_pack: // struct foo {...} _Pragma(pack(pop));1593// struct foo {...} _Pragma(section(...));1594case tok::annot_pragma_ms_pragma:1595// struct foo {...} _Pragma(vtordisp(pop));1596case tok::annot_pragma_ms_vtordisp:1597// struct foo {...} _Pragma(pointers_to_members(...));1598case tok::annot_pragma_ms_pointers_to_members:1599return true;1600case tok::colon:1601return CouldBeBitfield || // enum E { ... } : 2;1602ColonIsSacred; // _Generic(..., enum E : 2);1603// Microsoft compatibility1604case tok::kw___cdecl: // struct foo {...} __cdecl x;1605case tok::kw___fastcall: // struct foo {...} __fastcall x;1606case tok::kw___stdcall: // struct foo {...} __stdcall x;1607case tok::kw___thiscall: // struct foo {...} __thiscall x;1608case tok::kw___vectorcall: // struct foo {...} __vectorcall x;1609// We will diagnose these calling-convention specifiers on non-function1610// declarations later, so claim they are valid after a type specifier.1611return getLangOpts().MicrosoftExt;1612// Type qualifiers1613case tok::kw_const: // struct foo {...} const x;1614case tok::kw_volatile: // struct foo {...} volatile x;1615case tok::kw_restrict: // struct foo {...} restrict x;1616case tok::kw__Atomic: // struct foo {...} _Atomic x;1617case tok::kw___unaligned: // struct foo {...} __unaligned *x;1618// Function specifiers1619// Note, no 'explicit'. An explicit function must be either a conversion1620// operator or a constructor. Either way, it can't have a return type.1621case tok::kw_inline: // struct foo inline f();1622case tok::kw_virtual: // struct foo virtual f();1623case tok::kw_friend: // struct foo friend f();1624// Storage-class specifiers1625case tok::kw_static: // struct foo {...} static x;1626case tok::kw_extern: // struct foo {...} extern x;1627case tok::kw_typedef: // struct foo {...} typedef x;1628case tok::kw_register: // struct foo {...} register x;1629case tok::kw_auto: // struct foo {...} auto x;1630case tok::kw_mutable: // struct foo {...} mutable x;1631case tok::kw_thread_local: // struct foo {...} thread_local x;1632case tok::kw_constexpr: // struct foo {...} constexpr x;1633case tok::kw_consteval: // struct foo {...} consteval x;1634case tok::kw_constinit: // struct foo {...} constinit x;1635// As shown above, type qualifiers and storage class specifiers absolutely1636// can occur after class specifiers according to the grammar. However,1637// almost no one actually writes code like this. If we see one of these,1638// it is much more likely that someone missed a semi colon and the1639// type/storage class specifier we're seeing is part of the *next*1640// intended declaration, as in:1641//1642// struct foo { ... }1643// typedef int X;1644//1645// We'd really like to emit a missing semicolon error instead of emitting1646// an error on the 'int' saying that you can't have two type specifiers in1647// the same declaration of X. Because of this, we look ahead past this1648// token to see if it's a type specifier. If so, we know the code is1649// otherwise invalid, so we can produce the expected semi error.1650if (!isKnownToBeTypeSpecifier(NextToken()))1651return true;1652break;1653case tok::r_brace: // struct bar { struct foo {...} }1654// Missing ';' at end of struct is accepted as an extension in C mode.1655if (!getLangOpts().CPlusPlus)1656return true;1657break;1658case tok::greater:1659// template<class T = class X>1660return getLangOpts().CPlusPlus;1661}1662return false;1663}16641665/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or1666/// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which1667/// until we reach the start of a definition or see a token that1668/// cannot start a definition.1669///1670/// class-specifier: [C++ class]1671/// class-head '{' member-specification[opt] '}'1672/// class-head '{' member-specification[opt] '}' attributes[opt]1673/// class-head:1674/// class-key identifier[opt] base-clause[opt]1675/// class-key nested-name-specifier identifier base-clause[opt]1676/// class-key nested-name-specifier[opt] simple-template-id1677/// base-clause[opt]1678/// [GNU] class-key attributes[opt] identifier[opt] base-clause[opt]1679/// [GNU] class-key attributes[opt] nested-name-specifier1680/// identifier base-clause[opt]1681/// [GNU] class-key attributes[opt] nested-name-specifier[opt]1682/// simple-template-id base-clause[opt]1683/// class-key:1684/// 'class'1685/// 'struct'1686/// 'union'1687///1688/// elaborated-type-specifier: [C++ dcl.type.elab]1689/// class-key ::[opt] nested-name-specifier[opt] identifier1690/// class-key ::[opt] nested-name-specifier[opt] 'template'[opt]1691/// simple-template-id1692///1693/// Note that the C++ class-specifier and elaborated-type-specifier,1694/// together, subsume the C99 struct-or-union-specifier:1695///1696/// struct-or-union-specifier: [C99 6.7.2.1]1697/// struct-or-union identifier[opt] '{' struct-contents '}'1698/// struct-or-union identifier1699/// [GNU] struct-or-union attributes[opt] identifier[opt] '{' struct-contents1700/// '}' attributes[opt]1701/// [GNU] struct-or-union attributes[opt] identifier1702/// struct-or-union:1703/// 'struct'1704/// 'union'1705void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,1706SourceLocation StartLoc, DeclSpec &DS,1707ParsedTemplateInfo &TemplateInfo,1708AccessSpecifier AS, bool EnteringContext,1709DeclSpecContext DSC,1710ParsedAttributes &Attributes) {1711DeclSpec::TST TagType;1712if (TagTokKind == tok::kw_struct)1713TagType = DeclSpec::TST_struct;1714else if (TagTokKind == tok::kw___interface)1715TagType = DeclSpec::TST_interface;1716else if (TagTokKind == tok::kw_class)1717TagType = DeclSpec::TST_class;1718else {1719assert(TagTokKind == tok::kw_union && "Not a class specifier");1720TagType = DeclSpec::TST_union;1721}17221723if (Tok.is(tok::code_completion)) {1724// Code completion for a struct, class, or union name.1725cutOffParsing();1726Actions.CodeCompletion().CodeCompleteTag(getCurScope(), TagType);1727return;1728}17291730// C++20 [temp.class.spec] 13.7.5/101731// The usual access checking rules do not apply to non-dependent names1732// used to specify template arguments of the simple-template-id of the1733// partial specialization.1734// C++20 [temp.spec] 13.9/6:1735// The usual access checking rules do not apply to names in a declaration1736// of an explicit instantiation or explicit specialization...1737const bool shouldDelayDiagsInTag =1738(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate);1739SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);17401741ParsedAttributes attrs(AttrFactory);1742// If attributes exist after tag, parse them.1743for (;;) {1744MaybeParseAttributes(PAKM_CXX11 | PAKM_Declspec | PAKM_GNU, attrs);1745// Parse inheritance specifiers.1746if (Tok.isOneOf(tok::kw___single_inheritance,1747tok::kw___multiple_inheritance,1748tok::kw___virtual_inheritance)) {1749ParseMicrosoftInheritanceClassAttributes(attrs);1750continue;1751}1752if (Tok.is(tok::kw__Nullable)) {1753ParseNullabilityClassAttributes(attrs);1754continue;1755}1756break;1757}17581759// Source location used by FIXIT to insert misplaced1760// C++11 attributes1761SourceLocation AttrFixitLoc = Tok.getLocation();17621763if (TagType == DeclSpec::TST_struct && Tok.isNot(tok::identifier) &&1764!Tok.isAnnotation() && Tok.getIdentifierInfo() &&1765Tok.isOneOf(1766#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) tok::kw___##Trait,1767#include "clang/Basic/TransformTypeTraits.def"1768tok::kw___is_abstract,1769tok::kw___is_aggregate,1770tok::kw___is_arithmetic,1771tok::kw___is_array,1772tok::kw___is_assignable,1773tok::kw___is_base_of,1774tok::kw___is_bounded_array,1775tok::kw___is_class,1776tok::kw___is_complete_type,1777tok::kw___is_compound,1778tok::kw___is_const,1779tok::kw___is_constructible,1780tok::kw___is_convertible,1781tok::kw___is_convertible_to,1782tok::kw___is_destructible,1783tok::kw___is_empty,1784tok::kw___is_enum,1785tok::kw___is_floating_point,1786tok::kw___is_final,1787tok::kw___is_function,1788tok::kw___is_fundamental,1789tok::kw___is_integral,1790tok::kw___is_interface_class,1791tok::kw___is_literal,1792tok::kw___is_lvalue_expr,1793tok::kw___is_lvalue_reference,1794tok::kw___is_member_function_pointer,1795tok::kw___is_member_object_pointer,1796tok::kw___is_member_pointer,1797tok::kw___is_nothrow_assignable,1798tok::kw___is_nothrow_constructible,1799tok::kw___is_nothrow_convertible,1800tok::kw___is_nothrow_destructible,1801tok::kw___is_nullptr,1802tok::kw___is_object,1803tok::kw___is_pod,1804tok::kw___is_pointer,1805tok::kw___is_polymorphic,1806tok::kw___is_reference,1807tok::kw___is_referenceable,1808tok::kw___is_rvalue_expr,1809tok::kw___is_rvalue_reference,1810tok::kw___is_same,1811tok::kw___is_scalar,1812tok::kw___is_scoped_enum,1813tok::kw___is_sealed,1814tok::kw___is_signed,1815tok::kw___is_standard_layout,1816tok::kw___is_trivial,1817tok::kw___is_trivially_equality_comparable,1818tok::kw___is_trivially_assignable,1819tok::kw___is_trivially_constructible,1820tok::kw___is_trivially_copyable,1821tok::kw___is_unbounded_array,1822tok::kw___is_union,1823tok::kw___is_unsigned,1824tok::kw___is_void,1825tok::kw___is_volatile1826))1827// GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the1828// name of struct templates, but some are keywords in GCC >= 4.31829// and Clang. Therefore, when we see the token sequence "struct1830// X", make X into a normal identifier rather than a keyword, to1831// allow libstdc++ 4.2 and libc++ to work properly.1832TryKeywordIdentFallback(true);18331834struct PreserveAtomicIdentifierInfoRAII {1835PreserveAtomicIdentifierInfoRAII(Token &Tok, bool Enabled)1836: AtomicII(nullptr) {1837if (!Enabled)1838return;1839assert(Tok.is(tok::kw__Atomic));1840AtomicII = Tok.getIdentifierInfo();1841AtomicII->revertTokenIDToIdentifier();1842Tok.setKind(tok::identifier);1843}1844~PreserveAtomicIdentifierInfoRAII() {1845if (!AtomicII)1846return;1847AtomicII->revertIdentifierToTokenID(tok::kw__Atomic);1848}1849IdentifierInfo *AtomicII;1850};18511852// HACK: MSVC doesn't consider _Atomic to be a keyword and its STL1853// implementation for VS2013 uses _Atomic as an identifier for one of the1854// classes in <atomic>. When we are parsing 'struct _Atomic', don't consider1855// '_Atomic' to be a keyword. We are careful to undo this so that clang can1856// use '_Atomic' in its own header files.1857bool ShouldChangeAtomicToIdentifier = getLangOpts().MSVCCompat &&1858Tok.is(tok::kw__Atomic) &&1859TagType == DeclSpec::TST_struct;1860PreserveAtomicIdentifierInfoRAII AtomicTokenGuard(1861Tok, ShouldChangeAtomicToIdentifier);18621863// Parse the (optional) nested-name-specifier.1864CXXScopeSpec &SS = DS.getTypeSpecScope();1865if (getLangOpts().CPlusPlus) {1866// "FOO : BAR" is not a potential typo for "FOO::BAR". In this context it1867// is a base-specifier-list.1868ColonProtectionRAIIObject X(*this);18691870CXXScopeSpec Spec;1871if (TemplateInfo.TemplateParams)1872Spec.setTemplateParamLists(*TemplateInfo.TemplateParams);18731874bool HasValidSpec = true;1875if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr,1876/*ObjectHasErrors=*/false,1877EnteringContext)) {1878DS.SetTypeSpecError();1879HasValidSpec = false;1880}1881if (Spec.isSet())1882if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) {1883Diag(Tok, diag::err_expected) << tok::identifier;1884HasValidSpec = false;1885}1886if (HasValidSpec)1887SS = Spec;1888}18891890TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;18911892auto RecoverFromUndeclaredTemplateName = [&](IdentifierInfo *Name,1893SourceLocation NameLoc,1894SourceRange TemplateArgRange,1895bool KnownUndeclared) {1896Diag(NameLoc, diag::err_explicit_spec_non_template)1897<< (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)1898<< TagTokKind << Name << TemplateArgRange << KnownUndeclared;18991900// Strip off the last template parameter list if it was empty, since1901// we've removed its template argument list.1902if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {1903if (TemplateParams->size() > 1) {1904TemplateParams->pop_back();1905} else {1906TemplateParams = nullptr;1907TemplateInfo.Kind = ParsedTemplateInfo::NonTemplate;1908}1909} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {1910// Pretend this is just a forward declaration.1911TemplateParams = nullptr;1912TemplateInfo.Kind = ParsedTemplateInfo::NonTemplate;1913TemplateInfo.TemplateLoc = SourceLocation();1914TemplateInfo.ExternLoc = SourceLocation();1915}1916};19171918// Parse the (optional) class name or simple-template-id.1919IdentifierInfo *Name = nullptr;1920SourceLocation NameLoc;1921TemplateIdAnnotation *TemplateId = nullptr;1922if (Tok.is(tok::identifier)) {1923Name = Tok.getIdentifierInfo();1924NameLoc = ConsumeToken();1925DS.SetRangeEnd(NameLoc);19261927if (Tok.is(tok::less) && getLangOpts().CPlusPlus) {1928// The name was supposed to refer to a template, but didn't.1929// Eat the template argument list and try to continue parsing this as1930// a class (or template thereof).1931TemplateArgList TemplateArgs;1932SourceLocation LAngleLoc, RAngleLoc;1933if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs,1934RAngleLoc)) {1935// We couldn't parse the template argument list at all, so don't1936// try to give any location information for the list.1937LAngleLoc = RAngleLoc = SourceLocation();1938}1939RecoverFromUndeclaredTemplateName(1940Name, NameLoc, SourceRange(LAngleLoc, RAngleLoc), false);1941}1942} else if (Tok.is(tok::annot_template_id)) {1943TemplateId = takeTemplateIdAnnotation(Tok);1944NameLoc = ConsumeAnnotationToken();19451946if (TemplateId->Kind == TNK_Undeclared_template) {1947// Try to resolve the template name to a type template. May update Kind.1948Actions.ActOnUndeclaredTypeTemplateName(1949getCurScope(), TemplateId->Template, TemplateId->Kind, NameLoc, Name);1950if (TemplateId->Kind == TNK_Undeclared_template) {1951RecoverFromUndeclaredTemplateName(1952Name, NameLoc,1953SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc), true);1954TemplateId = nullptr;1955}1956}19571958if (TemplateId && !TemplateId->mightBeType()) {1959// The template-name in the simple-template-id refers to1960// something other than a type template. Give an appropriate1961// error message and skip to the ';'.1962SourceRange Range(NameLoc);1963if (SS.isNotEmpty())1964Range.setBegin(SS.getBeginLoc());19651966// FIXME: Name may be null here.1967Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)1968<< TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range;19691970DS.SetTypeSpecError();1971SkipUntil(tok::semi, StopBeforeMatch);1972return;1973}1974}19751976// There are four options here.1977// - If we are in a trailing return type, this is always just a reference,1978// and we must not try to parse a definition. For instance,1979// [] () -> struct S { };1980// does not define a type.1981// - If we have 'struct foo {...', 'struct foo :...',1982// 'struct foo final :' or 'struct foo final {', then this is a definition.1983// - If we have 'struct foo;', then this is either a forward declaration1984// or a friend declaration, which have to be treated differently.1985// - Otherwise we have something like 'struct foo xyz', a reference.1986//1987// We also detect these erroneous cases to provide better diagnostic for1988// C++11 attributes parsing.1989// - attributes follow class name:1990// struct foo [[]] {};1991// - attributes appear before or after 'final':1992// struct foo [[]] final [[]] {};1993//1994// However, in type-specifier-seq's, things look like declarations but are1995// just references, e.g.1996// new struct s;1997// or1998// &T::operator struct s;1999// For these, DSC is DeclSpecContext::DSC_type_specifier or2000// DeclSpecContext::DSC_alias_declaration.20012002// If there are attributes after class name, parse them.2003MaybeParseCXX11Attributes(Attributes);20042005const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();2006TagUseKind TUK;2007if (isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus) ==2008AllowDefiningTypeSpec::No ||2009(getLangOpts().OpenMP && OpenMPDirectiveParsing))2010TUK = TagUseKind::Reference;2011else if (Tok.is(tok::l_brace) ||2012(DSC != DeclSpecContext::DSC_association &&2013getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||2014(isClassCompatibleKeyword() &&2015(NextToken().is(tok::l_brace) || NextToken().is(tok::colon)))) {2016if (DS.isFriendSpecified()) {2017// C++ [class.friend]p2:2018// A class shall not be defined in a friend declaration.2019Diag(Tok.getLocation(), diag::err_friend_decl_defines_type)2020<< SourceRange(DS.getFriendSpecLoc());20212022// Skip everything up to the semicolon, so that this looks like a proper2023// friend class (or template thereof) declaration.2024SkipUntil(tok::semi, StopBeforeMatch);2025TUK = TagUseKind::Friend;2026} else {2027// Okay, this is a class definition.2028TUK = TagUseKind::Definition;2029}2030} else if (isClassCompatibleKeyword() &&2031(NextToken().is(tok::l_square) ||2032NextToken().is(tok::kw_alignas) ||2033NextToken().isRegularKeywordAttribute() ||2034isCXX11VirtSpecifier(NextToken()) != VirtSpecifiers::VS_None)) {2035// We can't tell if this is a definition or reference2036// until we skipped the 'final' and C++11 attribute specifiers.2037TentativeParsingAction PA(*this);20382039// Skip the 'final', abstract'... keywords.2040while (isClassCompatibleKeyword()) {2041ConsumeToken();2042}20432044// Skip C++11 attribute specifiers.2045while (true) {2046if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {2047ConsumeBracket();2048if (!SkipUntil(tok::r_square, StopAtSemi))2049break;2050} else if (Tok.is(tok::kw_alignas) && NextToken().is(tok::l_paren)) {2051ConsumeToken();2052ConsumeParen();2053if (!SkipUntil(tok::r_paren, StopAtSemi))2054break;2055} else if (Tok.isRegularKeywordAttribute()) {2056bool TakesArgs = doesKeywordAttributeTakeArgs(Tok.getKind());2057ConsumeToken();2058if (TakesArgs) {2059BalancedDelimiterTracker T(*this, tok::l_paren);2060if (!T.consumeOpen())2061T.skipToEnd();2062}2063} else {2064break;2065}2066}20672068if (Tok.isOneOf(tok::l_brace, tok::colon))2069TUK = TagUseKind::Definition;2070else2071TUK = TagUseKind::Reference;20722073PA.Revert();2074} else if (!isTypeSpecifier(DSC) &&2075(Tok.is(tok::semi) ||2076(Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) {2077TUK = DS.isFriendSpecified() ? TagUseKind::Friend : TagUseKind::Declaration;2078if (Tok.isNot(tok::semi)) {2079const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();2080// A semicolon was missing after this declaration. Diagnose and recover.2081ExpectAndConsume(tok::semi, diag::err_expected_after,2082DeclSpec::getSpecifierName(TagType, PPol));2083PP.EnterToken(Tok, /*IsReinject*/ true);2084Tok.setKind(tok::semi);2085}2086} else2087TUK = TagUseKind::Reference;20882089// Forbid misplaced attributes. In cases of a reference, we pass attributes2090// to caller to handle.2091if (TUK != TagUseKind::Reference) {2092// If this is not a reference, then the only possible2093// valid place for C++11 attributes to appear here2094// is between class-key and class-name. If there are2095// any attributes after class-name, we try a fixit to move2096// them to the right place.2097SourceRange AttrRange = Attributes.Range;2098if (AttrRange.isValid()) {2099auto *FirstAttr = Attributes.empty() ? nullptr : &Attributes.front();2100auto Loc = AttrRange.getBegin();2101(FirstAttr && FirstAttr->isRegularKeywordAttribute()2102? Diag(Loc, diag::err_keyword_not_allowed) << FirstAttr2103: Diag(Loc, diag::err_attributes_not_allowed))2104<< AttrRange2105<< FixItHint::CreateInsertionFromRange(2106AttrFixitLoc, CharSourceRange(AttrRange, true))2107<< FixItHint::CreateRemoval(AttrRange);21082109// Recover by adding misplaced attributes to the attribute list2110// of the class so they can be applied on the class later.2111attrs.takeAllFrom(Attributes);2112}2113}21142115if (!Name && !TemplateId &&2116(DS.getTypeSpecType() == DeclSpec::TST_error ||2117TUK != TagUseKind::Definition)) {2118if (DS.getTypeSpecType() != DeclSpec::TST_error) {2119// We have a declaration or reference to an anonymous class.2120Diag(StartLoc, diag::err_anon_type_definition)2121<< DeclSpec::getSpecifierName(TagType, Policy);2122}21232124// If we are parsing a definition and stop at a base-clause, continue on2125// until the semicolon. Continuing from the comma will just trick us into2126// thinking we are seeing a variable declaration.2127if (TUK == TagUseKind::Definition && Tok.is(tok::colon))2128SkipUntil(tok::semi, StopBeforeMatch);2129else2130SkipUntil(tok::comma, StopAtSemi);2131return;2132}21332134// Create the tag portion of the class or class template.2135DeclResult TagOrTempResult = true; // invalid2136TypeResult TypeResult = true; // invalid21372138bool Owned = false;2139SkipBodyInfo SkipBody;2140if (TemplateId) {2141// Explicit specialization, class template partial specialization,2142// or explicit instantiation.2143ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),2144TemplateId->NumArgs);2145if (TemplateId->isInvalid()) {2146// Can't build the declaration.2147} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&2148TUK == TagUseKind::Declaration) {2149// This is an explicit instantiation of a class template.2150ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,2151diag::err_keyword_not_allowed,2152/*DiagnoseEmptyAttrs=*/true);21532154TagOrTempResult = Actions.ActOnExplicitInstantiation(2155getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc,2156TagType, StartLoc, SS, TemplateId->Template,2157TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr,2158TemplateId->RAngleLoc, attrs);21592160// Friend template-ids are treated as references unless2161// they have template headers, in which case they're ill-formed2162// (FIXME: "template <class T> friend class A<T>::B<int>;").2163// We diagnose this error in ActOnClassTemplateSpecialization.2164} else if (TUK == TagUseKind::Reference ||2165(TUK == TagUseKind::Friend &&2166TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) {2167ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,2168diag::err_keyword_not_allowed,2169/*DiagnoseEmptyAttrs=*/true);2170TypeResult = Actions.ActOnTagTemplateIdType(2171TUK, TagType, StartLoc, SS, TemplateId->TemplateKWLoc,2172TemplateId->Template, TemplateId->TemplateNameLoc,2173TemplateId->LAngleLoc, TemplateArgsPtr, TemplateId->RAngleLoc);2174} else {2175// This is an explicit specialization or a class template2176// partial specialization.2177TemplateParameterLists FakedParamLists;2178if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {2179// This looks like an explicit instantiation, because we have2180// something like2181//2182// template class Foo<X>2183//2184// but it actually has a definition. Most likely, this was2185// meant to be an explicit specialization, but the user forgot2186// the '<>' after 'template'.2187// It this is friend declaration however, since it cannot have a2188// template header, it is most likely that the user meant to2189// remove the 'template' keyword.2190assert((TUK == TagUseKind::Definition || TUK == TagUseKind::Friend) &&2191"Expected a definition here");21922193if (TUK == TagUseKind::Friend) {2194Diag(DS.getFriendSpecLoc(), diag::err_friend_explicit_instantiation);2195TemplateParams = nullptr;2196} else {2197SourceLocation LAngleLoc =2198PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);2199Diag(TemplateId->TemplateNameLoc,2200diag::err_explicit_instantiation_with_definition)2201<< SourceRange(TemplateInfo.TemplateLoc)2202<< FixItHint::CreateInsertion(LAngleLoc, "<>");22032204// Create a fake template parameter list that contains only2205// "template<>", so that we treat this construct as a class2206// template specialization.2207FakedParamLists.push_back(Actions.ActOnTemplateParameterList(22080, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc,2209std::nullopt, LAngleLoc, nullptr));2210TemplateParams = &FakedParamLists;2211}2212}22132214// Build the class template specialization.2215TagOrTempResult = Actions.ActOnClassTemplateSpecialization(2216getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(),2217SS, *TemplateId, attrs,2218MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0]2219: nullptr,2220TemplateParams ? TemplateParams->size() : 0),2221&SkipBody);2222}2223} else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&2224TUK == TagUseKind::Declaration) {2225// Explicit instantiation of a member of a class template2226// specialization, e.g.,2227//2228// template struct Outer<int>::Inner;2229//2230ProhibitAttributes(attrs);22312232TagOrTempResult = Actions.ActOnExplicitInstantiation(2233getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc,2234TagType, StartLoc, SS, Name, NameLoc, attrs);2235} else if (TUK == TagUseKind::Friend &&2236TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) {2237ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,2238diag::err_keyword_not_allowed,2239/*DiagnoseEmptyAttrs=*/true);22402241TagOrTempResult = Actions.ActOnTemplatedFriendTag(2242getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name,2243NameLoc, attrs,2244MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr,2245TemplateParams ? TemplateParams->size() : 0));2246} else {2247if (TUK != TagUseKind::Declaration && TUK != TagUseKind::Definition)2248ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,2249diag::err_keyword_not_allowed,2250/* DiagnoseEmptyAttrs=*/true);22512252if (TUK == TagUseKind::Definition &&2253TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {2254// If the declarator-id is not a template-id, issue a diagnostic and2255// recover by ignoring the 'template' keyword.2256Diag(Tok, diag::err_template_defn_explicit_instantiation)2257<< 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);2258TemplateParams = nullptr;2259}22602261bool IsDependent = false;22622263// Don't pass down template parameter lists if this is just a tag2264// reference. For example, we don't need the template parameters here:2265// template <class T> class A *makeA(T t);2266MultiTemplateParamsArg TParams;2267if (TUK != TagUseKind::Reference && TemplateParams)2268TParams =2269MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size());22702271stripTypeAttributesOffDeclSpec(attrs, DS, TUK);22722273// Declaration or definition of a class type2274TagOrTempResult = Actions.ActOnTag(2275getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs, AS,2276DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent,2277SourceLocation(), false, clang::TypeResult(),2278DSC == DeclSpecContext::DSC_type_specifier,2279DSC == DeclSpecContext::DSC_template_param ||2280DSC == DeclSpecContext::DSC_template_type_arg,2281OffsetOfState, &SkipBody);22822283// If ActOnTag said the type was dependent, try again with the2284// less common call.2285if (IsDependent) {2286assert(TUK == TagUseKind::Reference || TUK == TagUseKind::Friend);2287TypeResult = Actions.ActOnDependentTag(getCurScope(), TagType, TUK, SS,2288Name, StartLoc, NameLoc);2289}2290}22912292// If this is an elaborated type specifier in function template,2293// and we delayed diagnostics before,2294// just merge them into the current pool.2295if (shouldDelayDiagsInTag) {2296diagsFromTag.done();2297if (TUK == TagUseKind::Reference &&2298TemplateInfo.Kind == ParsedTemplateInfo::Template)2299diagsFromTag.redelay();2300}23012302// If there is a body, parse it and inform the actions module.2303if (TUK == TagUseKind::Definition) {2304assert(Tok.is(tok::l_brace) ||2305(getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||2306isClassCompatibleKeyword());2307if (SkipBody.ShouldSkip)2308SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType,2309TagOrTempResult.get());2310else if (getLangOpts().CPlusPlus)2311ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType,2312TagOrTempResult.get());2313else {2314Decl *D =2315SkipBody.CheckSameAsPrevious ? SkipBody.New : TagOrTempResult.get();2316// Parse the definition body.2317ParseStructUnionBody(StartLoc, TagType, cast<RecordDecl>(D));2318if (SkipBody.CheckSameAsPrevious &&2319!Actions.ActOnDuplicateDefinition(TagOrTempResult.get(), SkipBody)) {2320DS.SetTypeSpecError();2321return;2322}2323}2324}23252326if (!TagOrTempResult.isInvalid())2327// Delayed processing of attributes.2328Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs);23292330const char *PrevSpec = nullptr;2331unsigned DiagID;2332bool Result;2333if (!TypeResult.isInvalid()) {2334Result = DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc,2335NameLoc.isValid() ? NameLoc : StartLoc,2336PrevSpec, DiagID, TypeResult.get(), Policy);2337} else if (!TagOrTempResult.isInvalid()) {2338Result = DS.SetTypeSpecType(2339TagType, StartLoc, NameLoc.isValid() ? NameLoc : StartLoc, PrevSpec,2340DiagID, TagOrTempResult.get(), Owned, Policy);2341} else {2342DS.SetTypeSpecError();2343return;2344}23452346if (Result)2347Diag(StartLoc, DiagID) << PrevSpec;23482349// At this point, we've successfully parsed a class-specifier in 'definition'2350// form (e.g. "struct foo { int x; }". While we could just return here, we're2351// going to look at what comes after it to improve error recovery. If an2352// impossible token occurs next, we assume that the programmer forgot a ; at2353// the end of the declaration and recover that way.2354//2355// Also enforce C++ [temp]p3:2356// In a template-declaration which defines a class, no declarator2357// is permitted.2358//2359// After a type-specifier, we don't expect a semicolon. This only happens in2360// C, since definitions are not permitted in this context in C++.2361if (TUK == TagUseKind::Definition &&2362(getLangOpts().CPlusPlus || !isTypeSpecifier(DSC)) &&2363(TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {2364if (Tok.isNot(tok::semi)) {2365const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();2366ExpectAndConsume(tok::semi, diag::err_expected_after,2367DeclSpec::getSpecifierName(TagType, PPol));2368// Push this token back into the preprocessor and change our current token2369// to ';' so that the rest of the code recovers as though there were an2370// ';' after the definition.2371PP.EnterToken(Tok, /*IsReinject=*/true);2372Tok.setKind(tok::semi);2373}2374}2375}23762377/// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].2378///2379/// base-clause : [C++ class.derived]2380/// ':' base-specifier-list2381/// base-specifier-list:2382/// base-specifier '...'[opt]2383/// base-specifier-list ',' base-specifier '...'[opt]2384void Parser::ParseBaseClause(Decl *ClassDecl) {2385assert(Tok.is(tok::colon) && "Not a base clause");2386ConsumeToken();23872388// Build up an array of parsed base specifiers.2389SmallVector<CXXBaseSpecifier *, 8> BaseInfo;23902391while (true) {2392// Parse a base-specifier.2393BaseResult Result = ParseBaseSpecifier(ClassDecl);2394if (Result.isInvalid()) {2395// Skip the rest of this base specifier, up until the comma or2396// opening brace.2397SkipUntil(tok::comma, tok::l_brace, StopAtSemi | StopBeforeMatch);2398} else {2399// Add this to our array of base specifiers.2400BaseInfo.push_back(Result.get());2401}24022403// If the next token is a comma, consume it and keep reading2404// base-specifiers.2405if (!TryConsumeToken(tok::comma))2406break;2407}24082409// Attach the base specifiers2410Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo);2411}24122413/// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is2414/// one entry in the base class list of a class specifier, for example:2415/// class foo : public bar, virtual private baz {2416/// 'public bar' and 'virtual private baz' are each base-specifiers.2417///2418/// base-specifier: [C++ class.derived]2419/// attribute-specifier-seq[opt] base-type-specifier2420/// attribute-specifier-seq[opt] 'virtual' access-specifier[opt]2421/// base-type-specifier2422/// attribute-specifier-seq[opt] access-specifier 'virtual'[opt]2423/// base-type-specifier2424BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {2425bool IsVirtual = false;2426SourceLocation StartLoc = Tok.getLocation();24272428ParsedAttributes Attributes(AttrFactory);2429MaybeParseCXX11Attributes(Attributes);24302431// Parse the 'virtual' keyword.2432if (TryConsumeToken(tok::kw_virtual))2433IsVirtual = true;24342435CheckMisplacedCXX11Attribute(Attributes, StartLoc);24362437// Parse an (optional) access specifier.2438AccessSpecifier Access = getAccessSpecifierIfPresent();2439if (Access != AS_none) {2440ConsumeToken();2441if (getLangOpts().HLSL)2442Diag(Tok.getLocation(), diag::ext_hlsl_access_specifiers);2443}24442445CheckMisplacedCXX11Attribute(Attributes, StartLoc);24462447// Parse the 'virtual' keyword (again!), in case it came after the2448// access specifier.2449if (Tok.is(tok::kw_virtual)) {2450SourceLocation VirtualLoc = ConsumeToken();2451if (IsVirtual) {2452// Complain about duplicate 'virtual'2453Diag(VirtualLoc, diag::err_dup_virtual)2454<< FixItHint::CreateRemoval(VirtualLoc);2455}24562457IsVirtual = true;2458}24592460CheckMisplacedCXX11Attribute(Attributes, StartLoc);24612462// Parse the class-name.24632464// HACK: MSVC doesn't consider _Atomic to be a keyword and its STL2465// implementation for VS2013 uses _Atomic as an identifier for one of the2466// classes in <atomic>. Treat '_Atomic' to be an identifier when we are2467// parsing the class-name for a base specifier.2468if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) &&2469NextToken().is(tok::less))2470Tok.setKind(tok::identifier);24712472SourceLocation EndLocation;2473SourceLocation BaseLoc;2474TypeResult BaseType = ParseBaseTypeSpecifier(BaseLoc, EndLocation);2475if (BaseType.isInvalid())2476return true;24772478// Parse the optional ellipsis (for a pack expansion). The ellipsis is2479// actually part of the base-specifier-list grammar productions, but we2480// parse it here for convenience.2481SourceLocation EllipsisLoc;2482TryConsumeToken(tok::ellipsis, EllipsisLoc);24832484// Find the complete source range for the base-specifier.2485SourceRange Range(StartLoc, EndLocation);24862487// Notify semantic analysis that we have parsed a complete2488// base-specifier.2489return Actions.ActOnBaseSpecifier(ClassDecl, Range, Attributes, IsVirtual,2490Access, BaseType.get(), BaseLoc,2491EllipsisLoc);2492}24932494/// getAccessSpecifierIfPresent - Determine whether the next token is2495/// a C++ access-specifier.2496///2497/// access-specifier: [C++ class.derived]2498/// 'private'2499/// 'protected'2500/// 'public'2501AccessSpecifier Parser::getAccessSpecifierIfPresent() const {2502switch (Tok.getKind()) {2503default:2504return AS_none;2505case tok::kw_private:2506return AS_private;2507case tok::kw_protected:2508return AS_protected;2509case tok::kw_public:2510return AS_public;2511}2512}25132514/// If the given declarator has any parts for which parsing has to be2515/// delayed, e.g., default arguments or an exception-specification, create a2516/// late-parsed method declaration record to handle the parsing at the end of2517/// the class definition.2518void Parser::HandleMemberFunctionDeclDelays(Declarator &DeclaratorInfo,2519Decl *ThisDecl) {2520DeclaratorChunk::FunctionTypeInfo &FTI = DeclaratorInfo.getFunctionTypeInfo();2521// If there was a late-parsed exception-specification, we'll need a2522// late parse2523bool NeedLateParse = FTI.getExceptionSpecType() == EST_Unparsed;25242525if (!NeedLateParse) {2526// Look ahead to see if there are any default args2527for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) {2528const auto *Param = cast<ParmVarDecl>(FTI.Params[ParamIdx].Param);2529if (Param->hasUnparsedDefaultArg()) {2530NeedLateParse = true;2531break;2532}2533}2534}25352536if (NeedLateParse) {2537// Push this method onto the stack of late-parsed method2538// declarations.2539auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);2540getCurrentClass().LateParsedDeclarations.push_back(LateMethod);25412542// Push tokens for each parameter. Those that do not have defaults will be2543// NULL. We need to track all the parameters so that we can push them into2544// scope for later parameters and perhaps for the exception specification.2545LateMethod->DefaultArgs.reserve(FTI.NumParams);2546for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx)2547LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument(2548FTI.Params[ParamIdx].Param,2549std::move(FTI.Params[ParamIdx].DefaultArgTokens)));25502551// Stash the exception-specification tokens in the late-pased method.2552if (FTI.getExceptionSpecType() == EST_Unparsed) {2553LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;2554FTI.ExceptionSpecTokens = nullptr;2555}2556}2557}25582559/// isCXX11VirtSpecifier - Determine whether the given token is a C++112560/// virt-specifier.2561///2562/// virt-specifier:2563/// override2564/// final2565/// __final2566VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const {2567if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier))2568return VirtSpecifiers::VS_None;25692570const IdentifierInfo *II = Tok.getIdentifierInfo();25712572// Initialize the contextual keywords.2573if (!Ident_final) {2574Ident_final = &PP.getIdentifierTable().get("final");2575if (getLangOpts().GNUKeywords)2576Ident_GNU_final = &PP.getIdentifierTable().get("__final");2577if (getLangOpts().MicrosoftExt) {2578Ident_sealed = &PP.getIdentifierTable().get("sealed");2579Ident_abstract = &PP.getIdentifierTable().get("abstract");2580}2581Ident_override = &PP.getIdentifierTable().get("override");2582}25832584if (II == Ident_override)2585return VirtSpecifiers::VS_Override;25862587if (II == Ident_sealed)2588return VirtSpecifiers::VS_Sealed;25892590if (II == Ident_abstract)2591return VirtSpecifiers::VS_Abstract;25922593if (II == Ident_final)2594return VirtSpecifiers::VS_Final;25952596if (II == Ident_GNU_final)2597return VirtSpecifiers::VS_GNU_Final;25982599return VirtSpecifiers::VS_None;2600}26012602/// ParseOptionalCXX11VirtSpecifierSeq - Parse a virt-specifier-seq.2603///2604/// virt-specifier-seq:2605/// virt-specifier2606/// virt-specifier-seq virt-specifier2607void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS,2608bool IsInterface,2609SourceLocation FriendLoc) {2610while (true) {2611VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();2612if (Specifier == VirtSpecifiers::VS_None)2613return;26142615if (FriendLoc.isValid()) {2616Diag(Tok.getLocation(), diag::err_friend_decl_spec)2617<< VirtSpecifiers::getSpecifierName(Specifier)2618<< FixItHint::CreateRemoval(Tok.getLocation())2619<< SourceRange(FriendLoc, FriendLoc);2620ConsumeToken();2621continue;2622}26232624// C++ [class.mem]p8:2625// A virt-specifier-seq shall contain at most one of each virt-specifier.2626const char *PrevSpec = nullptr;2627if (VS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec))2628Diag(Tok.getLocation(), diag::err_duplicate_virt_specifier)2629<< PrevSpec << FixItHint::CreateRemoval(Tok.getLocation());26302631if (IsInterface && (Specifier == VirtSpecifiers::VS_Final ||2632Specifier == VirtSpecifiers::VS_Sealed)) {2633Diag(Tok.getLocation(), diag::err_override_control_interface)2634<< VirtSpecifiers::getSpecifierName(Specifier);2635} else if (Specifier == VirtSpecifiers::VS_Sealed) {2636Diag(Tok.getLocation(), diag::ext_ms_sealed_keyword);2637} else if (Specifier == VirtSpecifiers::VS_Abstract) {2638Diag(Tok.getLocation(), diag::ext_ms_abstract_keyword);2639} else if (Specifier == VirtSpecifiers::VS_GNU_Final) {2640Diag(Tok.getLocation(), diag::ext_warn_gnu_final);2641} else {2642Diag(Tok.getLocation(),2643getLangOpts().CPlusPlus112644? diag::warn_cxx98_compat_override_control_keyword2645: diag::ext_override_control_keyword)2646<< VirtSpecifiers::getSpecifierName(Specifier);2647}2648ConsumeToken();2649}2650}26512652/// isCXX11FinalKeyword - Determine whether the next token is a C++112653/// 'final' or Microsoft 'sealed' contextual keyword.2654bool Parser::isCXX11FinalKeyword() const {2655VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();2656return Specifier == VirtSpecifiers::VS_Final ||2657Specifier == VirtSpecifiers::VS_GNU_Final ||2658Specifier == VirtSpecifiers::VS_Sealed;2659}26602661/// isClassCompatibleKeyword - Determine whether the next token is a C++112662/// 'final' or Microsoft 'sealed' or 'abstract' contextual keywords.2663bool Parser::isClassCompatibleKeyword() const {2664VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();2665return Specifier == VirtSpecifiers::VS_Final ||2666Specifier == VirtSpecifiers::VS_GNU_Final ||2667Specifier == VirtSpecifiers::VS_Sealed ||2668Specifier == VirtSpecifiers::VS_Abstract;2669}26702671/// Parse a C++ member-declarator up to, but not including, the optional2672/// brace-or-equal-initializer or pure-specifier.2673bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(2674Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize,2675LateParsedAttrList &LateParsedAttrs) {2676// member-declarator:2677// declarator virt-specifier-seq[opt] pure-specifier[opt]2678// declarator requires-clause2679// declarator brace-or-equal-initializer[opt]2680// identifier attribute-specifier-seq[opt] ':' constant-expression2681// brace-or-equal-initializer[opt]2682// ':' constant-expression2683//2684// NOTE: the latter two productions are a proposed bugfix rather than the2685// current grammar rules as of C++20.2686if (Tok.isNot(tok::colon))2687ParseDeclarator(DeclaratorInfo);2688else2689DeclaratorInfo.SetIdentifier(nullptr, Tok.getLocation());26902691if (getLangOpts().HLSL)2692MaybeParseHLSLAnnotations(DeclaratorInfo, nullptr,2693/*CouldBeBitField*/ true);26942695if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) {2696assert(DeclaratorInfo.isPastIdentifier() &&2697"don't know where identifier would go yet?");2698BitfieldSize = ParseConstantExpression();2699if (BitfieldSize.isInvalid())2700SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);2701} else if (Tok.is(tok::kw_requires)) {2702ParseTrailingRequiresClause(DeclaratorInfo);2703} else {2704ParseOptionalCXX11VirtSpecifierSeq(2705VS, getCurrentClass().IsInterface,2706DeclaratorInfo.getDeclSpec().getFriendSpecLoc());2707if (!VS.isUnset())2708MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo,2709VS);2710}27112712// If a simple-asm-expr is present, parse it.2713if (Tok.is(tok::kw_asm)) {2714SourceLocation Loc;2715ExprResult AsmLabel(ParseSimpleAsm(/*ForAsmLabel*/ true, &Loc));2716if (AsmLabel.isInvalid())2717SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);27182719DeclaratorInfo.setAsmLabel(AsmLabel.get());2720DeclaratorInfo.SetRangeEnd(Loc);2721}27222723// If attributes exist after the declarator, but before an '{', parse them.2724// However, this does not apply for [[]] attributes (which could show up2725// before or after the __attribute__ attributes).2726DiagnoseAndSkipCXX11Attributes();2727MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);2728DiagnoseAndSkipCXX11Attributes();27292730// For compatibility with code written to older Clang, also accept a2731// virt-specifier *after* the GNU attributes.2732if (BitfieldSize.isUnset() && VS.isUnset()) {2733ParseOptionalCXX11VirtSpecifierSeq(2734VS, getCurrentClass().IsInterface,2735DeclaratorInfo.getDeclSpec().getFriendSpecLoc());2736if (!VS.isUnset()) {2737// If we saw any GNU-style attributes that are known to GCC followed by a2738// virt-specifier, issue a GCC-compat warning.2739for (const ParsedAttr &AL : DeclaratorInfo.getAttributes())2740if (AL.isKnownToGCC() && !AL.isCXX11Attribute())2741Diag(AL.getLoc(), diag::warn_gcc_attribute_location);27422743MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo,2744VS);2745}2746}27472748// If this has neither a name nor a bit width, something has gone seriously2749// wrong. Skip until the semi-colon or }.2750if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) {2751// If so, skip until the semi-colon or a }.2752SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);2753return true;2754}2755return false;2756}27572758/// Look for declaration specifiers possibly occurring after C++112759/// virt-specifier-seq and diagnose them.2760void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(2761Declarator &D, VirtSpecifiers &VS) {2762DeclSpec DS(AttrFactory);27632764// GNU-style and C++11 attributes are not allowed here, but they will be2765// handled by the caller. Diagnose everything else.2766ParseTypeQualifierListOpt(2767DS, AR_NoAttributesParsed, false,2768/*IdentifierRequired=*/false, llvm::function_ref<void()>([&]() {2769Actions.CodeCompletion().CodeCompleteFunctionQualifiers(DS, D, &VS);2770}));2771D.ExtendWithDeclSpec(DS);27722773if (D.isFunctionDeclarator()) {2774auto &Function = D.getFunctionTypeInfo();2775if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {2776auto DeclSpecCheck = [&](DeclSpec::TQ TypeQual, StringRef FixItName,2777SourceLocation SpecLoc) {2778FixItHint Insertion;2779auto &MQ = Function.getOrCreateMethodQualifiers();2780if (!(MQ.getTypeQualifiers() & TypeQual)) {2781std::string Name(FixItName.data());2782Name += " ";2783Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);2784MQ.SetTypeQual(TypeQual, SpecLoc);2785}2786Diag(SpecLoc, diag::err_declspec_after_virtspec)2787<< FixItName2788<< VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())2789<< FixItHint::CreateRemoval(SpecLoc) << Insertion;2790};2791DS.forEachQualifier(DeclSpecCheck);2792}27932794// Parse ref-qualifiers.2795bool RefQualifierIsLValueRef = true;2796SourceLocation RefQualifierLoc;2797if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) {2798const char *Name = (RefQualifierIsLValueRef ? "& " : "&& ");2799FixItHint Insertion =2800FixItHint::CreateInsertion(VS.getFirstLocation(), Name);2801Function.RefQualifierIsLValueRef = RefQualifierIsLValueRef;2802Function.RefQualifierLoc = RefQualifierLoc;28032804Diag(RefQualifierLoc, diag::err_declspec_after_virtspec)2805<< (RefQualifierIsLValueRef ? "&" : "&&")2806<< VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())2807<< FixItHint::CreateRemoval(RefQualifierLoc) << Insertion;2808D.SetRangeEnd(RefQualifierLoc);2809}2810}2811}28122813/// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.2814///2815/// member-declaration:2816/// decl-specifier-seq[opt] member-declarator-list[opt] ';'2817/// function-definition ';'[opt]2818/// ::[opt] nested-name-specifier template[opt] unqualified-id ';'[TODO]2819/// using-declaration [TODO]2820/// [C++0x] static_assert-declaration2821/// template-declaration2822/// [GNU] '__extension__' member-declaration2823///2824/// member-declarator-list:2825/// member-declarator2826/// member-declarator-list ',' member-declarator2827///2828/// member-declarator:2829/// declarator virt-specifier-seq[opt] pure-specifier[opt]2830/// [C++2a] declarator requires-clause2831/// declarator constant-initializer[opt]2832/// [C++11] declarator brace-or-equal-initializer[opt]2833/// identifier[opt] ':' constant-expression2834///2835/// virt-specifier-seq:2836/// virt-specifier2837/// virt-specifier-seq virt-specifier2838///2839/// virt-specifier:2840/// override2841/// final2842/// [MS] sealed2843///2844/// pure-specifier:2845/// '= 0'2846///2847/// constant-initializer:2848/// '=' constant-expression2849///2850Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration(2851AccessSpecifier AS, ParsedAttributes &AccessAttrs,2852ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) {2853assert(getLangOpts().CPlusPlus &&2854"ParseCXXClassMemberDeclaration should only be called in C++ mode");2855if (Tok.is(tok::at)) {2856if (getLangOpts().ObjC && NextToken().isObjCAtKeyword(tok::objc_defs))2857Diag(Tok, diag::err_at_defs_cxx);2858else2859Diag(Tok, diag::err_at_in_class);28602861ConsumeToken();2862SkipUntil(tok::r_brace, StopAtSemi);2863return nullptr;2864}28652866// Turn on colon protection early, while parsing declspec, although there is2867// nothing to protect there. It prevents from false errors if error recovery2868// incorrectly determines where the declspec ends, as in the example:2869// struct A { enum class B { C }; };2870// const int C = 4;2871// struct D { A::B : C; };2872ColonProtectionRAIIObject X(*this);28732874// Access declarations.2875bool MalformedTypeSpec = false;2876if (!TemplateInfo.Kind &&2877Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw___super)) {2878if (TryAnnotateCXXScopeToken())2879MalformedTypeSpec = true;28802881bool isAccessDecl;2882if (Tok.isNot(tok::annot_cxxscope))2883isAccessDecl = false;2884else if (NextToken().is(tok::identifier))2885isAccessDecl = GetLookAheadToken(2).is(tok::semi);2886else2887isAccessDecl = NextToken().is(tok::kw_operator);28882889if (isAccessDecl) {2890// Collect the scope specifier token we annotated earlier.2891CXXScopeSpec SS;2892ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,2893/*ObjectHasErrors=*/false,2894/*EnteringContext=*/false);28952896if (SS.isInvalid()) {2897SkipUntil(tok::semi);2898return nullptr;2899}29002901// Try to parse an unqualified-id.2902SourceLocation TemplateKWLoc;2903UnqualifiedId Name;2904if (ParseUnqualifiedId(SS, /*ObjectType=*/nullptr,2905/*ObjectHadErrors=*/false, false, true, true,2906false, &TemplateKWLoc, Name)) {2907SkipUntil(tok::semi);2908return nullptr;2909}29102911// TODO: recover from mistakenly-qualified operator declarations.2912if (ExpectAndConsume(tok::semi, diag::err_expected_after,2913"access declaration")) {2914SkipUntil(tok::semi);2915return nullptr;2916}29172918// FIXME: We should do something with the 'template' keyword here.2919return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration(2920getCurScope(), AS, /*UsingLoc*/ SourceLocation(),2921/*TypenameLoc*/ SourceLocation(), SS, Name,2922/*EllipsisLoc*/ SourceLocation(),2923/*AttrList*/ ParsedAttributesView())));2924}2925}29262927// static_assert-declaration. A templated static_assert declaration is2928// diagnosed in Parser::ParseDeclarationAfterTemplate.2929if (!TemplateInfo.Kind &&2930Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {2931SourceLocation DeclEnd;2932return DeclGroupPtrTy::make(2933DeclGroupRef(ParseStaticAssertDeclaration(DeclEnd)));2934}29352936if (Tok.is(tok::kw_template)) {2937assert(!TemplateInfo.TemplateParams &&2938"Nested template improperly parsed?");2939ObjCDeclContextSwitch ObjCDC(*this);2940SourceLocation DeclEnd;2941return ParseTemplateDeclarationOrSpecialization(DeclaratorContext::Member,2942DeclEnd, AccessAttrs, AS);2943}29442945// Handle: member-declaration ::= '__extension__' member-declaration2946if (Tok.is(tok::kw___extension__)) {2947// __extension__ silences extension warnings in the subexpression.2948ExtensionRAIIObject O(Diags); // Use RAII to do this.2949ConsumeToken();2950return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo,2951TemplateDiags);2952}29532954ParsedAttributes DeclAttrs(AttrFactory);2955// Optional C++11 attribute-specifier2956MaybeParseCXX11Attributes(DeclAttrs);29572958// The next token may be an OpenMP pragma annotation token. That would2959// normally be handled from ParseCXXClassMemberDeclarationWithPragmas, but in2960// this case, it came from an *attribute* rather than a pragma. Handle it now.2961if (Tok.is(tok::annot_attr_openmp))2962return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, DeclAttrs);29632964if (Tok.is(tok::kw_using)) {2965// Eat 'using'.2966SourceLocation UsingLoc = ConsumeToken();29672968// Consume unexpected 'template' keywords.2969while (Tok.is(tok::kw_template)) {2970SourceLocation TemplateLoc = ConsumeToken();2971Diag(TemplateLoc, diag::err_unexpected_template_after_using)2972<< FixItHint::CreateRemoval(TemplateLoc);2973}29742975if (Tok.is(tok::kw_namespace)) {2976Diag(UsingLoc, diag::err_using_namespace_in_class);2977SkipUntil(tok::semi, StopBeforeMatch);2978return nullptr;2979}2980SourceLocation DeclEnd;2981// Otherwise, it must be a using-declaration or an alias-declaration.2982return ParseUsingDeclaration(DeclaratorContext::Member, TemplateInfo,2983UsingLoc, DeclEnd, DeclAttrs, AS);2984}29852986ParsedAttributes DeclSpecAttrs(AttrFactory);2987MaybeParseMicrosoftAttributes(DeclSpecAttrs);29882989// Hold late-parsed attributes so we can attach a Decl to them later.2990LateParsedAttrList CommonLateParsedAttrs;29912992// decl-specifier-seq:2993// Parse the common declaration-specifiers piece.2994ParsingDeclSpec DS(*this, TemplateDiags);2995DS.takeAttributesFrom(DeclSpecAttrs);29962997if (MalformedTypeSpec)2998DS.SetTypeSpecError();29993000// Turn off usual access checking for templates explicit specialization3001// and instantiation.3002// C++20 [temp.spec] 13.9/6.3003// This disables the access checking rules for member function template3004// explicit instantiation and explicit specialization.3005bool IsTemplateSpecOrInst =3006(TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||3007TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);3008SuppressAccessChecks diagsFromTag(*this, IsTemplateSpecOrInst);30093010ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DeclSpecContext::DSC_class,3011&CommonLateParsedAttrs);30123013if (IsTemplateSpecOrInst)3014diagsFromTag.done();30153016// Turn off colon protection that was set for declspec.3017X.restore();30183019// If we had a free-standing type definition with a missing semicolon, we3020// may get this far before the problem becomes obvious.3021if (DS.hasTagDefinition() &&3022TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate &&3023DiagnoseMissingSemiAfterTagDefinition(DS, AS, DeclSpecContext::DSC_class,3024&CommonLateParsedAttrs))3025return nullptr;30263027MultiTemplateParamsArg TemplateParams(3028TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->data()3029: nullptr,3030TemplateInfo.TemplateParams ? TemplateInfo.TemplateParams->size() : 0);30313032if (TryConsumeToken(tok::semi)) {3033if (DS.isFriendSpecified())3034ProhibitAttributes(DeclAttrs);30353036RecordDecl *AnonRecord = nullptr;3037Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(3038getCurScope(), AS, DS, DeclAttrs, TemplateParams, false, AnonRecord);3039Actions.ActOnDefinedDeclarationSpecifier(TheDecl);3040DS.complete(TheDecl);3041if (AnonRecord) {3042Decl *decls[] = {AnonRecord, TheDecl};3043return Actions.BuildDeclaratorGroup(decls);3044}3045return Actions.ConvertDeclToDeclGroup(TheDecl);3046}30473048if (DS.hasTagDefinition())3049Actions.ActOnDefinedDeclarationSpecifier(DS.getRepAsDecl());30503051ParsingDeclarator DeclaratorInfo(*this, DS, DeclAttrs,3052DeclaratorContext::Member);3053if (TemplateInfo.TemplateParams)3054DeclaratorInfo.setTemplateParameterLists(TemplateParams);3055VirtSpecifiers VS;30563057// Hold late-parsed attributes so we can attach a Decl to them later.3058LateParsedAttrList LateParsedAttrs;30593060SourceLocation EqualLoc;3061SourceLocation PureSpecLoc;30623063auto TryConsumePureSpecifier = [&](bool AllowDefinition) {3064if (Tok.isNot(tok::equal))3065return false;30663067auto &Zero = NextToken();3068SmallString<8> Buffer;3069if (Zero.isNot(tok::numeric_constant) ||3070PP.getSpelling(Zero, Buffer) != "0")3071return false;30723073auto &After = GetLookAheadToken(2);3074if (!After.isOneOf(tok::semi, tok::comma) &&3075!(AllowDefinition &&3076After.isOneOf(tok::l_brace, tok::colon, tok::kw_try)))3077return false;30783079EqualLoc = ConsumeToken();3080PureSpecLoc = ConsumeToken();3081return true;3082};30833084SmallVector<Decl *, 8> DeclsInGroup;3085ExprResult BitfieldSize;3086ExprResult TrailingRequiresClause;3087bool ExpectSemi = true;30883089// C++20 [temp.spec] 13.9/6.3090// This disables the access checking rules for member function template3091// explicit instantiation and explicit specialization.3092SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);30933094// Parse the first declarator.3095if (ParseCXXMemberDeclaratorBeforeInitializer(3096DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) {3097TryConsumeToken(tok::semi);3098return nullptr;3099}31003101if (IsTemplateSpecOrInst)3102SAC.done();31033104// Check for a member function definition.3105if (BitfieldSize.isUnset()) {3106// MSVC permits pure specifier on inline functions defined at class scope.3107// Hence check for =0 before checking for function definition.3108if (getLangOpts().MicrosoftExt && DeclaratorInfo.isDeclarationOfFunction())3109TryConsumePureSpecifier(/*AllowDefinition*/ true);31103111FunctionDefinitionKind DefinitionKind = FunctionDefinitionKind::Declaration;3112// function-definition:3113//3114// In C++11, a non-function declarator followed by an open brace is a3115// braced-init-list for an in-class member initialization, not an3116// erroneous function definition.3117if (Tok.is(tok::l_brace) && !getLangOpts().CPlusPlus11) {3118DefinitionKind = FunctionDefinitionKind::Definition;3119} else if (DeclaratorInfo.isFunctionDeclarator()) {3120if (Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try)) {3121DefinitionKind = FunctionDefinitionKind::Definition;3122} else if (Tok.is(tok::equal)) {3123const Token &KW = NextToken();3124if (KW.is(tok::kw_default))3125DefinitionKind = FunctionDefinitionKind::Defaulted;3126else if (KW.is(tok::kw_delete))3127DefinitionKind = FunctionDefinitionKind::Deleted;3128else if (KW.is(tok::code_completion)) {3129cutOffParsing();3130Actions.CodeCompletion().CodeCompleteAfterFunctionEquals(3131DeclaratorInfo);3132return nullptr;3133}3134}3135}3136DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind);31373138// C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains3139// to a friend declaration, that declaration shall be a definition.3140if (DeclaratorInfo.isFunctionDeclarator() &&3141DefinitionKind == FunctionDefinitionKind::Declaration &&3142DS.isFriendSpecified()) {3143// Diagnose attributes that appear before decl specifier:3144// [[]] friend int foo();3145ProhibitAttributes(DeclAttrs);3146}31473148if (DefinitionKind != FunctionDefinitionKind::Declaration) {3149if (!DeclaratorInfo.isFunctionDeclarator()) {3150Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params);3151ConsumeBrace();3152SkipUntil(tok::r_brace);31533154// Consume the optional ';'3155TryConsumeToken(tok::semi);31563157return nullptr;3158}31593160if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {3161Diag(DeclaratorInfo.getIdentifierLoc(),3162diag::err_function_declared_typedef);31633164// Recover by treating the 'typedef' as spurious.3165DS.ClearStorageClassSpecs();3166}31673168Decl *FunDecl = ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo,3169TemplateInfo, VS, PureSpecLoc);31703171if (FunDecl) {3172for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) {3173CommonLateParsedAttrs[i]->addDecl(FunDecl);3174}3175for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {3176LateParsedAttrs[i]->addDecl(FunDecl);3177}3178}3179LateParsedAttrs.clear();31803181// Consume the ';' - it's optional unless we have a delete or default3182if (Tok.is(tok::semi))3183ConsumeExtraSemi(AfterMemberFunctionDefinition);31843185return DeclGroupPtrTy::make(DeclGroupRef(FunDecl));3186}3187}31883189// member-declarator-list:3190// member-declarator3191// member-declarator-list ',' member-declarator31923193while (true) {3194InClassInitStyle HasInClassInit = ICIS_NoInit;3195bool HasStaticInitializer = false;3196if (Tok.isOneOf(tok::equal, tok::l_brace) && PureSpecLoc.isInvalid()) {3197// DRXXXX: Anonymous bit-fields cannot have a brace-or-equal-initializer.3198if (BitfieldSize.isUsable() && !DeclaratorInfo.hasName()) {3199// Diagnose the error and pretend there is no in-class initializer.3200Diag(Tok, diag::err_anon_bitfield_member_init);3201SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);3202} else if (DeclaratorInfo.isDeclarationOfFunction()) {3203// It's a pure-specifier.3204if (!TryConsumePureSpecifier(/*AllowFunctionDefinition*/ false))3205// Parse it as an expression so that Sema can diagnose it.3206HasStaticInitializer = true;3207} else if (DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=3208DeclSpec::SCS_static &&3209DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=3210DeclSpec::SCS_typedef &&3211!DS.isFriendSpecified() &&3212TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate) {3213// It's a default member initializer.3214if (BitfieldSize.get())3215Diag(Tok, getLangOpts().CPlusPlus203216? diag::warn_cxx17_compat_bitfield_member_init3217: diag::ext_bitfield_member_init);3218HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit;3219} else {3220HasStaticInitializer = true;3221}3222}32233224// NOTE: If Sema is the Action module and declarator is an instance field,3225// this call will *not* return the created decl; It will return null.3226// See Sema::ActOnCXXMemberDeclarator for details.32273228NamedDecl *ThisDecl = nullptr;3229if (DS.isFriendSpecified()) {3230// C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains3231// to a friend declaration, that declaration shall be a definition.3232//3233// Diagnose attributes that appear in a friend member function declarator:3234// friend int foo [[]] ();3235for (const ParsedAttr &AL : DeclaratorInfo.getAttributes())3236if (AL.isCXX11Attribute() || AL.isRegularKeywordAttribute()) {3237auto Loc = AL.getRange().getBegin();3238(AL.isRegularKeywordAttribute()3239? Diag(Loc, diag::err_keyword_not_allowed) << AL3240: Diag(Loc, diag::err_attributes_not_allowed))3241<< AL.getRange();3242}32433244ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,3245TemplateParams);3246} else {3247ThisDecl = Actions.ActOnCXXMemberDeclarator(3248getCurScope(), AS, DeclaratorInfo, TemplateParams, BitfieldSize.get(),3249VS, HasInClassInit);32503251if (VarTemplateDecl *VT =3252ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : nullptr)3253// Re-direct this decl to refer to the templated decl so that we can3254// initialize it.3255ThisDecl = VT->getTemplatedDecl();32563257if (ThisDecl)3258Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs);3259}32603261// Error recovery might have converted a non-static member into a static3262// member.3263if (HasInClassInit != ICIS_NoInit &&3264DeclaratorInfo.getDeclSpec().getStorageClassSpec() ==3265DeclSpec::SCS_static) {3266HasInClassInit = ICIS_NoInit;3267HasStaticInitializer = true;3268}32693270if (PureSpecLoc.isValid() && VS.getAbstractLoc().isValid()) {3271Diag(PureSpecLoc, diag::err_duplicate_virt_specifier) << "abstract";3272}3273if (ThisDecl && PureSpecLoc.isValid())3274Actions.ActOnPureSpecifier(ThisDecl, PureSpecLoc);3275else if (ThisDecl && VS.getAbstractLoc().isValid())3276Actions.ActOnPureSpecifier(ThisDecl, VS.getAbstractLoc());32773278// Handle the initializer.3279if (HasInClassInit != ICIS_NoInit) {3280// The initializer was deferred; parse it and cache the tokens.3281Diag(Tok, getLangOpts().CPlusPlus113282? diag::warn_cxx98_compat_nonstatic_member_init3283: diag::ext_nonstatic_member_init);32843285if (DeclaratorInfo.isArrayOfUnknownBound()) {3286// C++11 [dcl.array]p3: An array bound may also be omitted when the3287// declarator is followed by an initializer.3288//3289// A brace-or-equal-initializer for a member-declarator is not an3290// initializer in the grammar, so this is ill-formed.3291Diag(Tok, diag::err_incomplete_array_member_init);3292SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);32933294// Avoid later warnings about a class member of incomplete type.3295if (ThisDecl)3296ThisDecl->setInvalidDecl();3297} else3298ParseCXXNonStaticMemberInitializer(ThisDecl);3299} else if (HasStaticInitializer) {3300// Normal initializer.3301ExprResult Init = ParseCXXMemberInitializer(3302ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);33033304if (Init.isInvalid()) {3305if (ThisDecl)3306Actions.ActOnUninitializedDecl(ThisDecl);3307SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);3308} else if (ThisDecl)3309Actions.AddInitializerToDecl(ThisDecl, Init.get(),3310EqualLoc.isInvalid());3311} else if (ThisDecl && DeclaratorInfo.isStaticMember())3312// No initializer.3313Actions.ActOnUninitializedDecl(ThisDecl);33143315if (ThisDecl) {3316if (!ThisDecl->isInvalidDecl()) {3317// Set the Decl for any late parsed attributes3318for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i)3319CommonLateParsedAttrs[i]->addDecl(ThisDecl);33203321for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i)3322LateParsedAttrs[i]->addDecl(ThisDecl);3323}3324Actions.FinalizeDeclaration(ThisDecl);3325DeclsInGroup.push_back(ThisDecl);33263327if (DeclaratorInfo.isFunctionDeclarator() &&3328DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=3329DeclSpec::SCS_typedef)3330HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl);3331}3332LateParsedAttrs.clear();33333334DeclaratorInfo.complete(ThisDecl);33353336// If we don't have a comma, it is either the end of the list (a ';')3337// or an error, bail out.3338SourceLocation CommaLoc;3339if (!TryConsumeToken(tok::comma, CommaLoc))3340break;33413342if (Tok.isAtStartOfLine() &&3343!MightBeDeclarator(DeclaratorContext::Member)) {3344// This comma was followed by a line-break and something which can't be3345// the start of a declarator. The comma was probably a typo for a3346// semicolon.3347Diag(CommaLoc, diag::err_expected_semi_declaration)3348<< FixItHint::CreateReplacement(CommaLoc, ";");3349ExpectSemi = false;3350break;3351}33523353// C++23 [temp.pre]p5:3354// In a template-declaration, explicit specialization, or explicit3355// instantiation the init-declarator-list in the declaration shall3356// contain at most one declarator.3357if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&3358DeclaratorInfo.isFirstDeclarator()) {3359Diag(CommaLoc, diag::err_multiple_template_declarators)3360<< TemplateInfo.Kind;3361}33623363// Parse the next declarator.3364DeclaratorInfo.clear();3365VS.clear();3366BitfieldSize = ExprResult(/*Invalid=*/false);3367EqualLoc = PureSpecLoc = SourceLocation();3368DeclaratorInfo.setCommaLoc(CommaLoc);33693370// GNU attributes are allowed before the second and subsequent declarator.3371// However, this does not apply for [[]] attributes (which could show up3372// before or after the __attribute__ attributes).3373DiagnoseAndSkipCXX11Attributes();3374MaybeParseGNUAttributes(DeclaratorInfo);3375DiagnoseAndSkipCXX11Attributes();33763377if (ParseCXXMemberDeclaratorBeforeInitializer(3378DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs))3379break;3380}33813382if (ExpectSemi &&3383ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) {3384// Skip to end of block or statement.3385SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);3386// If we stopped at a ';', eat it.3387TryConsumeToken(tok::semi);3388return nullptr;3389}33903391return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);3392}33933394/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer.3395/// Also detect and reject any attempted defaulted/deleted function definition.3396/// The location of the '=', if any, will be placed in EqualLoc.3397///3398/// This does not check for a pure-specifier; that's handled elsewhere.3399///3400/// brace-or-equal-initializer:3401/// '=' initializer-expression3402/// braced-init-list3403///3404/// initializer-clause:3405/// assignment-expression3406/// braced-init-list3407///3408/// defaulted/deleted function-definition:3409/// '=' 'default'3410/// '=' 'delete'3411///3412/// Prior to C++0x, the assignment-expression in an initializer-clause must3413/// be a constant-expression.3414ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction,3415SourceLocation &EqualLoc) {3416assert(Tok.isOneOf(tok::equal, tok::l_brace) &&3417"Data member initializer not starting with '=' or '{'");34183419bool IsFieldInitialization = isa_and_present<FieldDecl>(D);34203421EnterExpressionEvaluationContext Context(3422Actions,3423IsFieldInitialization3424? Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed3425: Sema::ExpressionEvaluationContext::PotentiallyEvaluated,3426D);34273428// CWG27603429// Default member initializers used to initialize a base or member subobject3430// [...] are considered to be part of the function body3431Actions.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =3432IsFieldInitialization;34333434if (TryConsumeToken(tok::equal, EqualLoc)) {3435if (Tok.is(tok::kw_delete)) {3436// In principle, an initializer of '= delete p;' is legal, but it will3437// never type-check. It's better to diagnose it as an ill-formed3438// expression than as an ill-formed deleted non-function member. An3439// initializer of '= delete p, foo' will never be parsed, because a3440// top-level comma always ends the initializer expression.3441const Token &Next = NextToken();3442if (IsFunction || Next.isOneOf(tok::semi, tok::comma, tok::eof)) {3443if (IsFunction)3444Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)3445<< 1 /* delete */;3446else3447Diag(ConsumeToken(), diag::err_deleted_non_function);3448SkipDeletedFunctionBody();3449return ExprError();3450}3451} else if (Tok.is(tok::kw_default)) {3452if (IsFunction)3453Diag(Tok, diag::err_default_delete_in_multiple_declaration)3454<< 0 /* default */;3455else3456Diag(ConsumeToken(), diag::err_default_special_members)3457<< getLangOpts().CPlusPlus20;3458return ExprError();3459}3460}3461if (const auto *PD = dyn_cast_or_null<MSPropertyDecl>(D)) {3462Diag(Tok, diag::err_ms_property_initializer) << PD;3463return ExprError();3464}3465return ParseInitializer();3466}34673468void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,3469SourceLocation AttrFixitLoc,3470unsigned TagType, Decl *TagDecl) {3471// Skip the optional 'final' keyword.3472if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {3473assert(isCXX11FinalKeyword() && "not a class definition");3474ConsumeToken();34753476// Diagnose any C++11 attributes after 'final' keyword.3477// We deliberately discard these attributes.3478ParsedAttributes Attrs(AttrFactory);3479CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);34803481// This can only happen if we had malformed misplaced attributes;3482// we only get called if there is a colon or left-brace after the3483// attributes.3484if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_brace))3485return;3486}34873488// Skip the base clauses. This requires actually parsing them, because3489// otherwise we can't be sure where they end (a left brace may appear3490// within a template argument).3491if (Tok.is(tok::colon)) {3492// Enter the scope of the class so that we can correctly parse its bases.3493ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope);3494ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true,3495TagType == DeclSpec::TST_interface);3496auto OldContext =3497Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl);34983499// Parse the bases but don't attach them to the class.3500ParseBaseClause(nullptr);35013502Actions.ActOnTagFinishSkippedDefinition(OldContext);35033504if (!Tok.is(tok::l_brace)) {3505Diag(PP.getLocForEndOfToken(PrevTokLocation),3506diag::err_expected_lbrace_after_base_specifiers);3507return;3508}3509}35103511// Skip the body.3512assert(Tok.is(tok::l_brace));3513BalancedDelimiterTracker T(*this, tok::l_brace);3514T.consumeOpen();3515T.skipToEnd();35163517// Parse and discard any trailing attributes.3518if (Tok.is(tok::kw___attribute)) {3519ParsedAttributes Attrs(AttrFactory);3520MaybeParseGNUAttributes(Attrs);3521}3522}35233524Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(3525AccessSpecifier &AS, ParsedAttributes &AccessAttrs, DeclSpec::TST TagType,3526Decl *TagDecl) {3527ParenBraceBracketBalancer BalancerRAIIObj(*this);35283529switch (Tok.getKind()) {3530case tok::kw___if_exists:3531case tok::kw___if_not_exists:3532ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, AS);3533return nullptr;35343535case tok::semi:3536// Check for extraneous top-level semicolon.3537ConsumeExtraSemi(InsideStruct, TagType);3538return nullptr;35393540// Handle pragmas that can appear as member declarations.3541case tok::annot_pragma_vis:3542HandlePragmaVisibility();3543return nullptr;3544case tok::annot_pragma_pack:3545HandlePragmaPack();3546return nullptr;3547case tok::annot_pragma_align:3548HandlePragmaAlign();3549return nullptr;3550case tok::annot_pragma_ms_pointers_to_members:3551HandlePragmaMSPointersToMembers();3552return nullptr;3553case tok::annot_pragma_ms_pragma:3554HandlePragmaMSPragma();3555return nullptr;3556case tok::annot_pragma_ms_vtordisp:3557HandlePragmaMSVtorDisp();3558return nullptr;3559case tok::annot_pragma_dump:3560HandlePragmaDump();3561return nullptr;35623563case tok::kw_namespace:3564// If we see a namespace here, a close brace was missing somewhere.3565DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));3566return nullptr;35673568case tok::kw_private:3569// FIXME: We don't accept GNU attributes on access specifiers in OpenCL mode3570// yet.3571if (getLangOpts().OpenCL && !NextToken().is(tok::colon)) {3572ParsedTemplateInfo TemplateInfo;3573return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo);3574}3575[[fallthrough]];3576case tok::kw_public:3577case tok::kw_protected: {3578if (getLangOpts().HLSL)3579Diag(Tok.getLocation(), diag::ext_hlsl_access_specifiers);3580AccessSpecifier NewAS = getAccessSpecifierIfPresent();3581assert(NewAS != AS_none);3582// Current token is a C++ access specifier.3583AS = NewAS;3584SourceLocation ASLoc = Tok.getLocation();3585unsigned TokLength = Tok.getLength();3586ConsumeToken();3587AccessAttrs.clear();3588MaybeParseGNUAttributes(AccessAttrs);35893590SourceLocation EndLoc;3591if (TryConsumeToken(tok::colon, EndLoc)) {3592} else if (TryConsumeToken(tok::semi, EndLoc)) {3593Diag(EndLoc, diag::err_expected)3594<< tok::colon << FixItHint::CreateReplacement(EndLoc, ":");3595} else {3596EndLoc = ASLoc.getLocWithOffset(TokLength);3597Diag(EndLoc, diag::err_expected)3598<< tok::colon << FixItHint::CreateInsertion(EndLoc, ":");3599}36003601// The Microsoft extension __interface does not permit non-public3602// access specifiers.3603if (TagType == DeclSpec::TST_interface && AS != AS_public) {3604Diag(ASLoc, diag::err_access_specifier_interface) << (AS == AS_protected);3605}36063607if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, AccessAttrs)) {3608// found another attribute than only annotations3609AccessAttrs.clear();3610}36113612return nullptr;3613}36143615case tok::annot_attr_openmp:3616case tok::annot_pragma_openmp:3617return ParseOpenMPDeclarativeDirectiveWithExtDecl(3618AS, AccessAttrs, /*Delayed=*/true, TagType, TagDecl);3619case tok::annot_pragma_openacc:3620return ParseOpenACCDirectiveDecl();36213622default:3623if (tok::isPragmaAnnotation(Tok.getKind())) {3624Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl)3625<< DeclSpec::getSpecifierName(3626TagType, Actions.getASTContext().getPrintingPolicy());3627ConsumeAnnotationToken();3628return nullptr;3629}3630ParsedTemplateInfo TemplateInfo;3631return ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo);3632}3633}36343635/// ParseCXXMemberSpecification - Parse the class definition.3636///3637/// member-specification:3638/// member-declaration member-specification[opt]3639/// access-specifier ':' member-specification[opt]3640///3641void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,3642SourceLocation AttrFixitLoc,3643ParsedAttributes &Attrs,3644unsigned TagType, Decl *TagDecl) {3645assert((TagType == DeclSpec::TST_struct ||3646TagType == DeclSpec::TST_interface ||3647TagType == DeclSpec::TST_union || TagType == DeclSpec::TST_class) &&3648"Invalid TagType!");36493650llvm::TimeTraceScope TimeScope("ParseClass", [&]() {3651if (auto *TD = dyn_cast_or_null<NamedDecl>(TagDecl))3652return TD->getQualifiedNameAsString();3653return std::string("<anonymous>");3654});36553656PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,3657"parsing struct/union/class body");36583659// Determine whether this is a non-nested class. Note that local3660// classes are *not* considered to be nested classes.3661bool NonNestedClass = true;3662if (!ClassStack.empty()) {3663for (const Scope *S = getCurScope(); S; S = S->getParent()) {3664if (S->isClassScope()) {3665// We're inside a class scope, so this is a nested class.3666NonNestedClass = false;36673668// The Microsoft extension __interface does not permit nested classes.3669if (getCurrentClass().IsInterface) {3670Diag(RecordLoc, diag::err_invalid_member_in_interface)3671<< /*ErrorType=*/63672<< (isa<NamedDecl>(TagDecl)3673? cast<NamedDecl>(TagDecl)->getQualifiedNameAsString()3674: "(anonymous)");3675}3676break;3677}36783679if (S->isFunctionScope())3680// If we're in a function or function template then this is a local3681// class rather than a nested class.3682break;3683}3684}36853686// Enter a scope for the class.3687ParseScope ClassScope(this, Scope::ClassScope | Scope::DeclScope);36883689// Note that we are parsing a new (potentially-nested) class definition.3690ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass,3691TagType == DeclSpec::TST_interface);36923693if (TagDecl)3694Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);36953696SourceLocation FinalLoc;3697SourceLocation AbstractLoc;3698bool IsFinalSpelledSealed = false;3699bool IsAbstract = false;37003701// Parse the optional 'final' keyword.3702if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {3703while (true) {3704VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);3705if (Specifier == VirtSpecifiers::VS_None)3706break;3707if (isCXX11FinalKeyword()) {3708if (FinalLoc.isValid()) {3709auto Skipped = ConsumeToken();3710Diag(Skipped, diag::err_duplicate_class_virt_specifier)3711<< VirtSpecifiers::getSpecifierName(Specifier);3712} else {3713FinalLoc = ConsumeToken();3714if (Specifier == VirtSpecifiers::VS_Sealed)3715IsFinalSpelledSealed = true;3716}3717} else {3718if (AbstractLoc.isValid()) {3719auto Skipped = ConsumeToken();3720Diag(Skipped, diag::err_duplicate_class_virt_specifier)3721<< VirtSpecifiers::getSpecifierName(Specifier);3722} else {3723AbstractLoc = ConsumeToken();3724IsAbstract = true;3725}3726}3727if (TagType == DeclSpec::TST_interface)3728Diag(FinalLoc, diag::err_override_control_interface)3729<< VirtSpecifiers::getSpecifierName(Specifier);3730else if (Specifier == VirtSpecifiers::VS_Final)3731Diag(FinalLoc, getLangOpts().CPlusPlus113732? diag::warn_cxx98_compat_override_control_keyword3733: diag::ext_override_control_keyword)3734<< VirtSpecifiers::getSpecifierName(Specifier);3735else if (Specifier == VirtSpecifiers::VS_Sealed)3736Diag(FinalLoc, diag::ext_ms_sealed_keyword);3737else if (Specifier == VirtSpecifiers::VS_Abstract)3738Diag(AbstractLoc, diag::ext_ms_abstract_keyword);3739else if (Specifier == VirtSpecifiers::VS_GNU_Final)3740Diag(FinalLoc, diag::ext_warn_gnu_final);3741}3742assert((FinalLoc.isValid() || AbstractLoc.isValid()) &&3743"not a class definition");37443745// Parse any C++11 attributes after 'final' keyword.3746// These attributes are not allowed to appear here,3747// and the only possible place for them to appertain3748// to the class would be between class-key and class-name.3749CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);37503751// ParseClassSpecifier() does only a superficial check for attributes before3752// deciding to call this method. For example, for3753// `class C final alignas ([l) {` it will decide that this looks like a3754// misplaced attribute since it sees `alignas '(' ')'`. But the actual3755// attribute parsing code will try to parse the '[' as a constexpr lambda3756// and consume enough tokens that the alignas parsing code will eat the3757// opening '{'. So bail out if the next token isn't one we expect.3758if (!Tok.is(tok::colon) && !Tok.is(tok::l_brace)) {3759if (TagDecl)3760Actions.ActOnTagDefinitionError(getCurScope(), TagDecl);3761return;3762}3763}37643765if (Tok.is(tok::colon)) {3766ParseScope InheritanceScope(this, getCurScope()->getFlags() |3767Scope::ClassInheritanceScope);37683769ParseBaseClause(TagDecl);3770if (!Tok.is(tok::l_brace)) {3771bool SuggestFixIt = false;3772SourceLocation BraceLoc = PP.getLocForEndOfToken(PrevTokLocation);3773if (Tok.isAtStartOfLine()) {3774switch (Tok.getKind()) {3775case tok::kw_private:3776case tok::kw_protected:3777case tok::kw_public:3778SuggestFixIt = NextToken().getKind() == tok::colon;3779break;3780case tok::kw_static_assert:3781case tok::r_brace:3782case tok::kw_using:3783// base-clause can have simple-template-id; 'template' can't be there3784case tok::kw_template:3785SuggestFixIt = true;3786break;3787case tok::identifier:3788SuggestFixIt = isConstructorDeclarator(true);3789break;3790default:3791SuggestFixIt = isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);3792break;3793}3794}3795DiagnosticBuilder LBraceDiag =3796Diag(BraceLoc, diag::err_expected_lbrace_after_base_specifiers);3797if (SuggestFixIt) {3798LBraceDiag << FixItHint::CreateInsertion(BraceLoc, " {");3799// Try recovering from missing { after base-clause.3800PP.EnterToken(Tok, /*IsReinject*/ true);3801Tok.setKind(tok::l_brace);3802} else {3803if (TagDecl)3804Actions.ActOnTagDefinitionError(getCurScope(), TagDecl);3805return;3806}3807}3808}38093810assert(Tok.is(tok::l_brace));3811BalancedDelimiterTracker T(*this, tok::l_brace);3812T.consumeOpen();38133814if (TagDecl)3815Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, FinalLoc,3816IsFinalSpelledSealed, IsAbstract,3817T.getOpenLocation());38183819// C++ 11p3: Members of a class defined with the keyword class are private3820// by default. Members of a class defined with the keywords struct or union3821// are public by default.3822// HLSL: In HLSL members of a class are public by default.3823AccessSpecifier CurAS;3824if (TagType == DeclSpec::TST_class && !getLangOpts().HLSL)3825CurAS = AS_private;3826else3827CurAS = AS_public;3828ParsedAttributes AccessAttrs(AttrFactory);38293830if (TagDecl) {3831// While we still have something to read, read the member-declarations.3832while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&3833Tok.isNot(tok::eof)) {3834// Each iteration of this loop reads one member-declaration.3835ParseCXXClassMemberDeclarationWithPragmas(3836CurAS, AccessAttrs, static_cast<DeclSpec::TST>(TagType), TagDecl);3837MaybeDestroyTemplateIds();3838}3839T.consumeClose();3840} else {3841SkipUntil(tok::r_brace);3842}38433844// If attributes exist after class contents, parse them.3845ParsedAttributes attrs(AttrFactory);3846MaybeParseGNUAttributes(attrs);38473848if (TagDecl)3849Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl,3850T.getOpenLocation(),3851T.getCloseLocation(), attrs);38523853// C++11 [class.mem]p2:3854// Within the class member-specification, the class is regarded as complete3855// within function bodies, default arguments, exception-specifications, and3856// brace-or-equal-initializers for non-static data members (including such3857// things in nested classes).3858if (TagDecl && NonNestedClass) {3859// We are not inside a nested class. This class and its nested classes3860// are complete and we can parse the delayed portions of method3861// declarations and the lexed inline method definitions, along with any3862// delayed attributes.38633864SourceLocation SavedPrevTokLocation = PrevTokLocation;3865ParseLexedPragmas(getCurrentClass());3866ParseLexedAttributes(getCurrentClass());3867ParseLexedMethodDeclarations(getCurrentClass());38683869// We've finished with all pending member declarations.3870Actions.ActOnFinishCXXMemberDecls();38713872ParseLexedMemberInitializers(getCurrentClass());3873ParseLexedMethodDefs(getCurrentClass());3874PrevTokLocation = SavedPrevTokLocation;38753876// We've finished parsing everything, including default argument3877// initializers.3878Actions.ActOnFinishCXXNonNestedClass();3879}38803881if (TagDecl)3882Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange());38833884// Leave the class scope.3885ParsingDef.Pop();3886ClassScope.Exit();3887}38883889void Parser::DiagnoseUnexpectedNamespace(NamedDecl *D) {3890assert(Tok.is(tok::kw_namespace));38913892// FIXME: Suggest where the close brace should have gone by looking3893// at indentation changes within the definition body.3894Diag(D->getLocation(), diag::err_missing_end_of_definition) << D;3895Diag(Tok.getLocation(), diag::note_missing_end_of_definition_before) << D;38963897// Push '};' onto the token stream to recover.3898PP.EnterToken(Tok, /*IsReinject*/ true);38993900Tok.startToken();3901Tok.setLocation(PP.getLocForEndOfToken(PrevTokLocation));3902Tok.setKind(tok::semi);3903PP.EnterToken(Tok, /*IsReinject*/ true);39043905Tok.setKind(tok::r_brace);3906}39073908/// ParseConstructorInitializer - Parse a C++ constructor initializer,3909/// which explicitly initializes the members or base classes of a3910/// class (C++ [class.base.init]). For example, the three initializers3911/// after the ':' in the Derived constructor below:3912///3913/// @code3914/// class Base { };3915/// class Derived : Base {3916/// int x;3917/// float f;3918/// public:3919/// Derived(float f) : Base(), x(17), f(f) { }3920/// };3921/// @endcode3922///3923/// [C++] ctor-initializer:3924/// ':' mem-initializer-list3925///3926/// [C++] mem-initializer-list:3927/// mem-initializer ...[opt]3928/// mem-initializer ...[opt] , mem-initializer-list3929void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {3930assert(Tok.is(tok::colon) &&3931"Constructor initializer always starts with ':'");39323933// Poison the SEH identifiers so they are flagged as illegal in constructor3934// initializers.3935PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true);3936SourceLocation ColonLoc = ConsumeToken();39373938SmallVector<CXXCtorInitializer *, 4> MemInitializers;3939bool AnyErrors = false;39403941do {3942if (Tok.is(tok::code_completion)) {3943cutOffParsing();3944Actions.CodeCompletion().CodeCompleteConstructorInitializer(3945ConstructorDecl, MemInitializers);3946return;3947}39483949MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);3950if (!MemInit.isInvalid())3951MemInitializers.push_back(MemInit.get());3952else3953AnyErrors = true;39543955if (Tok.is(tok::comma))3956ConsumeToken();3957else if (Tok.is(tok::l_brace))3958break;3959// If the previous initializer was valid and the next token looks like a3960// base or member initializer, assume that we're just missing a comma.3961else if (!MemInit.isInvalid() &&3962Tok.isOneOf(tok::identifier, tok::coloncolon)) {3963SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation);3964Diag(Loc, diag::err_ctor_init_missing_comma)3965<< FixItHint::CreateInsertion(Loc, ", ");3966} else {3967// Skip over garbage, until we get to '{'. Don't eat the '{'.3968if (!MemInit.isInvalid())3969Diag(Tok.getLocation(), diag::err_expected_either)3970<< tok::l_brace << tok::comma;3971SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);3972break;3973}3974} while (true);39753976Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc, MemInitializers,3977AnyErrors);3978}39793980/// ParseMemInitializer - Parse a C++ member initializer, which is3981/// part of a constructor initializer that explicitly initializes one3982/// member or base class (C++ [class.base.init]). See3983/// ParseConstructorInitializer for an example.3984///3985/// [C++] mem-initializer:3986/// mem-initializer-id '(' expression-list[opt] ')'3987/// [C++0x] mem-initializer-id braced-init-list3988///3989/// [C++] mem-initializer-id:3990/// '::'[opt] nested-name-specifier[opt] class-name3991/// identifier3992MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {3993// parse '::'[opt] nested-name-specifier[opt]3994CXXScopeSpec SS;3995if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,3996/*ObjectHasErrors=*/false,3997/*EnteringContext=*/false))3998return true;39994000// : identifier4001IdentifierInfo *II = nullptr;4002SourceLocation IdLoc = Tok.getLocation();4003// : declype(...)4004DeclSpec DS(AttrFactory);4005// : template_name<...>4006TypeResult TemplateTypeTy;40074008if (Tok.is(tok::identifier)) {4009// Get the identifier. This may be a member name or a class name,4010// but we'll let the semantic analysis determine which it is.4011II = Tok.getIdentifierInfo();4012ConsumeToken();4013} else if (Tok.is(tok::annot_decltype)) {4014// Get the decltype expression, if there is one.4015// Uses of decltype will already have been converted to annot_decltype by4016// ParseOptionalCXXScopeSpecifier at this point.4017// FIXME: Can we get here with a scope specifier?4018ParseDecltypeSpecifier(DS);4019} else if (Tok.is(tok::annot_pack_indexing_type)) {4020// Uses of T...[N] will already have been converted to4021// annot_pack_indexing_type by ParseOptionalCXXScopeSpecifier at this point.4022ParsePackIndexingType(DS);4023} else {4024TemplateIdAnnotation *TemplateId = Tok.is(tok::annot_template_id)4025? takeTemplateIdAnnotation(Tok)4026: nullptr;4027if (TemplateId && TemplateId->mightBeType()) {4028AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::No,4029/*IsClassName=*/true);4030assert(Tok.is(tok::annot_typename) && "template-id -> type failed");4031TemplateTypeTy = getTypeAnnotation(Tok);4032ConsumeAnnotationToken();4033} else {4034Diag(Tok, diag::err_expected_member_or_base_name);4035return true;4036}4037}40384039// Parse the '('.4040if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {4041Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);40424043// FIXME: Add support for signature help inside initializer lists.4044ExprResult InitList = ParseBraceInitializer();4045if (InitList.isInvalid())4046return true;40474048SourceLocation EllipsisLoc;4049TryConsumeToken(tok::ellipsis, EllipsisLoc);40504051if (TemplateTypeTy.isInvalid())4052return true;4053return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,4054TemplateTypeTy.get(), DS, IdLoc,4055InitList.get(), EllipsisLoc);4056} else if (Tok.is(tok::l_paren)) {4057BalancedDelimiterTracker T(*this, tok::l_paren);4058T.consumeOpen();40594060// Parse the optional expression-list.4061ExprVector ArgExprs;4062auto RunSignatureHelp = [&] {4063if (TemplateTypeTy.isInvalid())4064return QualType();4065QualType PreferredType =4066Actions.CodeCompletion().ProduceCtorInitMemberSignatureHelp(4067ConstructorDecl, SS, TemplateTypeTy.get(), ArgExprs, II,4068T.getOpenLocation(), /*Braced=*/false);4069CalledSignatureHelp = true;4070return PreferredType;4071};4072if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, [&] {4073PreferredType.enterFunctionArgument(Tok.getLocation(),4074RunSignatureHelp);4075})) {4076if (PP.isCodeCompletionReached() && !CalledSignatureHelp)4077RunSignatureHelp();4078SkipUntil(tok::r_paren, StopAtSemi);4079return true;4080}40814082T.consumeClose();40834084SourceLocation EllipsisLoc;4085TryConsumeToken(tok::ellipsis, EllipsisLoc);40864087if (TemplateTypeTy.isInvalid())4088return true;4089return Actions.ActOnMemInitializer(4090ConstructorDecl, getCurScope(), SS, II, TemplateTypeTy.get(), DS, IdLoc,4091T.getOpenLocation(), ArgExprs, T.getCloseLocation(), EllipsisLoc);4092}40934094if (TemplateTypeTy.isInvalid())4095return true;40964097if (getLangOpts().CPlusPlus11)4098return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace;4099else4100return Diag(Tok, diag::err_expected) << tok::l_paren;4101}41024103/// Parse a C++ exception-specification if present (C++0x [except.spec]).4104///4105/// exception-specification:4106/// dynamic-exception-specification4107/// noexcept-specification4108///4109/// noexcept-specification:4110/// 'noexcept'4111/// 'noexcept' '(' constant-expression ')'4112ExceptionSpecificationType Parser::tryParseExceptionSpecification(4113bool Delayed, SourceRange &SpecificationRange,4114SmallVectorImpl<ParsedType> &DynamicExceptions,4115SmallVectorImpl<SourceRange> &DynamicExceptionRanges,4116ExprResult &NoexceptExpr, CachedTokens *&ExceptionSpecTokens) {4117ExceptionSpecificationType Result = EST_None;4118ExceptionSpecTokens = nullptr;41194120// Handle delayed parsing of exception-specifications.4121if (Delayed) {4122if (Tok.isNot(tok::kw_throw) && Tok.isNot(tok::kw_noexcept))4123return EST_None;41244125// Consume and cache the starting token.4126bool IsNoexcept = Tok.is(tok::kw_noexcept);4127Token StartTok = Tok;4128SpecificationRange = SourceRange(ConsumeToken());41294130// Check for a '('.4131if (!Tok.is(tok::l_paren)) {4132// If this is a bare 'noexcept', we're done.4133if (IsNoexcept) {4134Diag(Tok, diag::warn_cxx98_compat_noexcept_decl);4135NoexceptExpr = nullptr;4136return EST_BasicNoexcept;4137}41384139Diag(Tok, diag::err_expected_lparen_after) << "throw";4140return EST_DynamicNone;4141}41424143// Cache the tokens for the exception-specification.4144ExceptionSpecTokens = new CachedTokens;4145ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept'4146ExceptionSpecTokens->push_back(Tok); // '('4147SpecificationRange.setEnd(ConsumeParen()); // '('41484149ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens,4150/*StopAtSemi=*/true,4151/*ConsumeFinalToken=*/true);4152SpecificationRange.setEnd(ExceptionSpecTokens->back().getLocation());41534154return EST_Unparsed;4155}41564157// See if there's a dynamic specification.4158if (Tok.is(tok::kw_throw)) {4159Result = ParseDynamicExceptionSpecification(4160SpecificationRange, DynamicExceptions, DynamicExceptionRanges);4161assert(DynamicExceptions.size() == DynamicExceptionRanges.size() &&4162"Produced different number of exception types and ranges.");4163}41644165// If there's no noexcept specification, we're done.4166if (Tok.isNot(tok::kw_noexcept))4167return Result;41684169Diag(Tok, diag::warn_cxx98_compat_noexcept_decl);41704171// If we already had a dynamic specification, parse the noexcept for,4172// recovery, but emit a diagnostic and don't store the results.4173SourceRange NoexceptRange;4174ExceptionSpecificationType NoexceptType = EST_None;41754176SourceLocation KeywordLoc = ConsumeToken();4177if (Tok.is(tok::l_paren)) {4178// There is an argument.4179BalancedDelimiterTracker T(*this, tok::l_paren);4180T.consumeOpen();41814182EnterExpressionEvaluationContext ConstantEvaluated(4183Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);4184NoexceptExpr = ParseConstantExpressionInExprEvalContext();41854186T.consumeClose();4187if (!NoexceptExpr.isInvalid()) {4188NoexceptExpr =4189Actions.ActOnNoexceptSpec(NoexceptExpr.get(), NoexceptType);4190NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());4191} else {4192NoexceptType = EST_BasicNoexcept;4193}4194} else {4195// There is no argument.4196NoexceptType = EST_BasicNoexcept;4197NoexceptRange = SourceRange(KeywordLoc, KeywordLoc);4198}41994200if (Result == EST_None) {4201SpecificationRange = NoexceptRange;4202Result = NoexceptType;42034204// If there's a dynamic specification after a noexcept specification,4205// parse that and ignore the results.4206if (Tok.is(tok::kw_throw)) {4207Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification);4208ParseDynamicExceptionSpecification(NoexceptRange, DynamicExceptions,4209DynamicExceptionRanges);4210}4211} else {4212Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification);4213}42144215return Result;4216}42174218static void diagnoseDynamicExceptionSpecification(Parser &P, SourceRange Range,4219bool IsNoexcept) {4220if (P.getLangOpts().CPlusPlus11) {4221const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)";4222P.Diag(Range.getBegin(), P.getLangOpts().CPlusPlus17 && !IsNoexcept4223? diag::ext_dynamic_exception_spec4224: diag::warn_exception_spec_deprecated)4225<< Range;4226P.Diag(Range.getBegin(), diag::note_exception_spec_deprecated)4227<< Replacement << FixItHint::CreateReplacement(Range, Replacement);4228}4229}42304231/// ParseDynamicExceptionSpecification - Parse a C++4232/// dynamic-exception-specification (C++ [except.spec]).4233///4234/// dynamic-exception-specification:4235/// 'throw' '(' type-id-list [opt] ')'4236/// [MS] 'throw' '(' '...' ')'4237///4238/// type-id-list:4239/// type-id ... [opt]4240/// type-id-list ',' type-id ... [opt]4241///4242ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(4243SourceRange &SpecificationRange, SmallVectorImpl<ParsedType> &Exceptions,4244SmallVectorImpl<SourceRange> &Ranges) {4245assert(Tok.is(tok::kw_throw) && "expected throw");42464247SpecificationRange.setBegin(ConsumeToken());4248BalancedDelimiterTracker T(*this, tok::l_paren);4249if (T.consumeOpen()) {4250Diag(Tok, diag::err_expected_lparen_after) << "throw";4251SpecificationRange.setEnd(SpecificationRange.getBegin());4252return EST_DynamicNone;4253}42544255// Parse throw(...), a Microsoft extension that means "this function4256// can throw anything".4257if (Tok.is(tok::ellipsis)) {4258SourceLocation EllipsisLoc = ConsumeToken();4259if (!getLangOpts().MicrosoftExt)4260Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec);4261T.consumeClose();4262SpecificationRange.setEnd(T.getCloseLocation());4263diagnoseDynamicExceptionSpecification(*this, SpecificationRange, false);4264return EST_MSAny;4265}42664267// Parse the sequence of type-ids.4268SourceRange Range;4269while (Tok.isNot(tok::r_paren)) {4270TypeResult Res(ParseTypeName(&Range));42714272if (Tok.is(tok::ellipsis)) {4273// C++0x [temp.variadic]p5:4274// - In a dynamic-exception-specification (15.4); the pattern is a4275// type-id.4276SourceLocation Ellipsis = ConsumeToken();4277Range.setEnd(Ellipsis);4278if (!Res.isInvalid())4279Res = Actions.ActOnPackExpansion(Res.get(), Ellipsis);4280}42814282if (!Res.isInvalid()) {4283Exceptions.push_back(Res.get());4284Ranges.push_back(Range);4285}42864287if (!TryConsumeToken(tok::comma))4288break;4289}42904291T.consumeClose();4292SpecificationRange.setEnd(T.getCloseLocation());4293diagnoseDynamicExceptionSpecification(*this, SpecificationRange,4294Exceptions.empty());4295return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic;4296}42974298/// ParseTrailingReturnType - Parse a trailing return type on a new-style4299/// function declaration.4300TypeResult Parser::ParseTrailingReturnType(SourceRange &Range,4301bool MayBeFollowedByDirectInit) {4302assert(Tok.is(tok::arrow) && "expected arrow");43034304ConsumeToken();43054306return ParseTypeName(&Range, MayBeFollowedByDirectInit4307? DeclaratorContext::TrailingReturnVar4308: DeclaratorContext::TrailingReturn);4309}43104311/// Parse a requires-clause as part of a function declaration.4312void Parser::ParseTrailingRequiresClause(Declarator &D) {4313assert(Tok.is(tok::kw_requires) && "expected requires");43144315SourceLocation RequiresKWLoc = ConsumeToken();43164317// C++23 [basic.scope.namespace]p1:4318// For each non-friend redeclaration or specialization whose target scope4319// is or is contained by the scope, the portion after the declarator-id,4320// class-head-name, or enum-head-name is also included in the scope.4321// C++23 [basic.scope.class]p1:4322// For each non-friend redeclaration or specialization whose target scope4323// is or is contained by the scope, the portion after the declarator-id,4324// class-head-name, or enum-head-name is also included in the scope.4325//4326// FIXME: We should really be calling ParseTrailingRequiresClause in4327// ParseDirectDeclarator, when we are already in the declarator scope.4328// This would also correctly suppress access checks for specializations4329// and explicit instantiations, which we currently do not do.4330CXXScopeSpec &SS = D.getCXXScopeSpec();4331DeclaratorScopeObj DeclScopeObj(*this, SS);4332if (SS.isValid() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))4333DeclScopeObj.EnterDeclaratorScope();43344335ExprResult TrailingRequiresClause;4336ParseScope ParamScope(this, Scope::DeclScope |4337Scope::FunctionDeclarationScope |4338Scope::FunctionPrototypeScope);43394340Actions.ActOnStartTrailingRequiresClause(getCurScope(), D);43414342std::optional<Sema::CXXThisScopeRAII> ThisScope;4343InitCXXThisScopeForDeclaratorIfRelevant(D, D.getDeclSpec(), ThisScope);43444345TrailingRequiresClause =4346ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true);43474348TrailingRequiresClause =4349Actions.ActOnFinishTrailingRequiresClause(TrailingRequiresClause);43504351if (!D.isDeclarationOfFunction()) {4352Diag(RequiresKWLoc,4353diag::err_requires_clause_on_declarator_not_declaring_a_function);4354return;4355}43564357if (TrailingRequiresClause.isInvalid())4358SkipUntil({tok::l_brace, tok::arrow, tok::kw_try, tok::comma, tok::colon},4359StopAtSemi | StopBeforeMatch);4360else4361D.setTrailingRequiresClause(TrailingRequiresClause.get());43624363// Did the user swap the trailing return type and requires clause?4364if (D.isFunctionDeclarator() && Tok.is(tok::arrow) &&4365D.getDeclSpec().getTypeSpecType() == TST_auto) {4366SourceLocation ArrowLoc = Tok.getLocation();4367SourceRange Range;4368TypeResult TrailingReturnType =4369ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit=*/false);43704371if (!TrailingReturnType.isInvalid()) {4372Diag(ArrowLoc,4373diag::err_requires_clause_must_appear_after_trailing_return)4374<< Range;4375auto &FunctionChunk = D.getFunctionTypeInfo();4376FunctionChunk.HasTrailingReturnType = TrailingReturnType.isUsable();4377FunctionChunk.TrailingReturnType = TrailingReturnType.get();4378FunctionChunk.TrailingReturnTypeLoc = Range.getBegin();4379} else4380SkipUntil({tok::equal, tok::l_brace, tok::arrow, tok::kw_try, tok::comma},4381StopAtSemi | StopBeforeMatch);4382}4383}43844385/// We have just started parsing the definition of a new class,4386/// so push that class onto our stack of classes that is currently4387/// being parsed.4388Sema::ParsingClassState Parser::PushParsingClass(Decl *ClassDecl,4389bool NonNestedClass,4390bool IsInterface) {4391assert((NonNestedClass || !ClassStack.empty()) &&4392"Nested class without outer class");4393ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass, IsInterface));4394return Actions.PushParsingClass();4395}43964397/// Deallocate the given parsed class and all of its nested4398/// classes.4399void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {4400for (unsigned I = 0, N = Class->LateParsedDeclarations.size(); I != N; ++I)4401delete Class->LateParsedDeclarations[I];4402delete Class;4403}44044405/// Pop the top class of the stack of classes that are4406/// currently being parsed.4407///4408/// This routine should be called when we have finished parsing the4409/// definition of a class, but have not yet popped the Scope4410/// associated with the class's definition.4411void Parser::PopParsingClass(Sema::ParsingClassState state) {4412assert(!ClassStack.empty() && "Mismatched push/pop for class parsing");44134414Actions.PopParsingClass(state);44154416ParsingClass *Victim = ClassStack.top();4417ClassStack.pop();4418if (Victim->TopLevelClass) {4419// Deallocate all of the nested classes of this class,4420// recursively: we don't need to keep any of this information.4421DeallocateParsedClasses(Victim);4422return;4423}4424assert(!ClassStack.empty() && "Missing top-level class?");44254426if (Victim->LateParsedDeclarations.empty()) {4427// The victim is a nested class, but we will not need to perform4428// any processing after the definition of this class since it has4429// no members whose handling was delayed. Therefore, we can just4430// remove this nested class.4431DeallocateParsedClasses(Victim);4432return;4433}44344435// This nested class has some members that will need to be processed4436// after the top-level class is completely defined. Therefore, add4437// it to the list of nested classes within its parent.4438assert(getCurScope()->isClassScope() &&4439"Nested class outside of class scope?");4440ClassStack.top()->LateParsedDeclarations.push_back(4441new LateParsedClass(this, Victim));4442}44434444/// Try to parse an 'identifier' which appears within an attribute-token.4445///4446/// \return the parsed identifier on success, and 0 if the next token is not an4447/// attribute-token.4448///4449/// C++11 [dcl.attr.grammar]p3:4450/// If a keyword or an alternative token that satisfies the syntactic4451/// requirements of an identifier is contained in an attribute-token,4452/// it is considered an identifier.4453IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(4454SourceLocation &Loc, SemaCodeCompletion::AttributeCompletion Completion,4455const IdentifierInfo *Scope) {4456switch (Tok.getKind()) {4457default:4458// Identifiers and keywords have identifier info attached.4459if (!Tok.isAnnotation()) {4460if (IdentifierInfo *II = Tok.getIdentifierInfo()) {4461Loc = ConsumeToken();4462return II;4463}4464}4465return nullptr;44664467case tok::code_completion:4468cutOffParsing();4469Actions.CodeCompletion().CodeCompleteAttribute(4470getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C23,4471Completion, Scope);4472return nullptr;44734474case tok::numeric_constant: {4475// If we got a numeric constant, check to see if it comes from a macro that4476// corresponds to the predefined __clang__ macro. If it does, warn the user4477// and recover by pretending they said _Clang instead.4478if (Tok.getLocation().isMacroID()) {4479SmallString<8> ExpansionBuf;4480SourceLocation ExpansionLoc =4481PP.getSourceManager().getExpansionLoc(Tok.getLocation());4482StringRef Spelling = PP.getSpelling(ExpansionLoc, ExpansionBuf);4483if (Spelling == "__clang__") {4484SourceRange TokRange(4485ExpansionLoc,4486PP.getSourceManager().getExpansionLoc(Tok.getEndLoc()));4487Diag(Tok, diag::warn_wrong_clang_attr_namespace)4488<< FixItHint::CreateReplacement(TokRange, "_Clang");4489Loc = ConsumeToken();4490return &PP.getIdentifierTable().get("_Clang");4491}4492}4493return nullptr;4494}44954496case tok::ampamp: // 'and'4497case tok::pipe: // 'bitor'4498case tok::pipepipe: // 'or'4499case tok::caret: // 'xor'4500case tok::tilde: // 'compl'4501case tok::amp: // 'bitand'4502case tok::ampequal: // 'and_eq'4503case tok::pipeequal: // 'or_eq'4504case tok::caretequal: // 'xor_eq'4505case tok::exclaim: // 'not'4506case tok::exclaimequal: // 'not_eq'4507// Alternative tokens do not have identifier info, but their spelling4508// starts with an alphabetical character.4509SmallString<8> SpellingBuf;4510SourceLocation SpellingLoc =4511PP.getSourceManager().getSpellingLoc(Tok.getLocation());4512StringRef Spelling = PP.getSpelling(SpellingLoc, SpellingBuf);4513if (isLetter(Spelling[0])) {4514Loc = ConsumeToken();4515return &PP.getIdentifierTable().get(Spelling);4516}4517return nullptr;4518}4519}45204521void Parser::ParseOpenMPAttributeArgs(const IdentifierInfo *AttrName,4522CachedTokens &OpenMPTokens) {4523// Both 'sequence' and 'directive' attributes require arguments, so parse the4524// open paren for the argument list.4525BalancedDelimiterTracker T(*this, tok::l_paren);4526if (T.consumeOpen()) {4527Diag(Tok, diag::err_expected) << tok::l_paren;4528return;4529}45304531if (AttrName->isStr("directive")) {4532// If the attribute is named `directive`, we can consume its argument list4533// and push the tokens from it into the cached token stream for a new OpenMP4534// pragma directive.4535Token OMPBeginTok;4536OMPBeginTok.startToken();4537OMPBeginTok.setKind(tok::annot_attr_openmp);4538OMPBeginTok.setLocation(Tok.getLocation());4539OpenMPTokens.push_back(OMPBeginTok);45404541ConsumeAndStoreUntil(tok::r_paren, OpenMPTokens, /*StopAtSemi=*/false,4542/*ConsumeFinalToken*/ false);4543Token OMPEndTok;4544OMPEndTok.startToken();4545OMPEndTok.setKind(tok::annot_pragma_openmp_end);4546OMPEndTok.setLocation(Tok.getLocation());4547OpenMPTokens.push_back(OMPEndTok);4548} else {4549assert(AttrName->isStr("sequence") &&4550"Expected either 'directive' or 'sequence'");4551// If the attribute is named 'sequence', its argument is a list of one or4552// more OpenMP attributes (either 'omp::directive' or 'omp::sequence',4553// where the 'omp::' is optional).4554do {4555// We expect to see one of the following:4556// * An identifier (omp) for the attribute namespace followed by ::4557// * An identifier (directive) or an identifier (sequence).4558SourceLocation IdentLoc;4559const IdentifierInfo *Ident = TryParseCXX11AttributeIdentifier(IdentLoc);45604561// If there is an identifier and it is 'omp', a double colon is required4562// followed by the actual identifier we're after.4563if (Ident && Ident->isStr("omp") && !ExpectAndConsume(tok::coloncolon))4564Ident = TryParseCXX11AttributeIdentifier(IdentLoc);45654566// If we failed to find an identifier (scoped or otherwise), or we found4567// an unexpected identifier, diagnose.4568if (!Ident || (!Ident->isStr("directive") && !Ident->isStr("sequence"))) {4569Diag(Tok.getLocation(), diag::err_expected_sequence_or_directive);4570SkipUntil(tok::r_paren, StopBeforeMatch);4571continue;4572}4573// We read an identifier. If the identifier is one of the ones we4574// expected, we can recurse to parse the args.4575ParseOpenMPAttributeArgs(Ident, OpenMPTokens);45764577// There may be a comma to signal that we expect another directive in the4578// sequence.4579} while (TryConsumeToken(tok::comma));4580}4581// Parse the closing paren for the argument list.4582T.consumeClose();4583}45844585static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,4586IdentifierInfo *ScopeName) {4587switch (4588ParsedAttr::getParsedKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) {4589case ParsedAttr::AT_CarriesDependency:4590case ParsedAttr::AT_Deprecated:4591case ParsedAttr::AT_FallThrough:4592case ParsedAttr::AT_CXX11NoReturn:4593case ParsedAttr::AT_NoUniqueAddress:4594case ParsedAttr::AT_Likely:4595case ParsedAttr::AT_Unlikely:4596return true;4597case ParsedAttr::AT_WarnUnusedResult:4598return !ScopeName && AttrName->getName() == "nodiscard";4599case ParsedAttr::AT_Unused:4600return !ScopeName && AttrName->getName() == "maybe_unused";4601default:4602return false;4603}4604}46054606/// Parse the argument to C++23's [[assume()]] attribute.4607bool Parser::ParseCXXAssumeAttributeArg(ParsedAttributes &Attrs,4608IdentifierInfo *AttrName,4609SourceLocation AttrNameLoc,4610SourceLocation *EndLoc,4611ParsedAttr::Form Form) {4612assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");4613BalancedDelimiterTracker T(*this, tok::l_paren);4614T.consumeOpen();46154616// [dcl.attr.assume]: The expression is potentially evaluated.4617EnterExpressionEvaluationContext Unevaluated(4618Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);46194620TentativeParsingAction TPA(*this);4621ExprResult Res(4622Actions.CorrectDelayedTyposInExpr(ParseConditionalExpression()));4623if (Res.isInvalid()) {4624TPA.Commit();4625SkipUntil(tok::r_paren, tok::r_square, StopAtSemi | StopBeforeMatch);4626if (Tok.is(tok::r_paren))4627T.consumeClose();4628return true;4629}46304631if (!Tok.isOneOf(tok::r_paren, tok::r_square)) {4632// Emit a better diagnostic if this is an otherwise valid expression that4633// is not allowed here.4634TPA.Revert();4635Res = ParseExpression();4636if (!Res.isInvalid()) {4637auto *E = Res.get();4638Diag(E->getExprLoc(), diag::err_assume_attr_expects_cond_expr)4639<< AttrName << FixItHint::CreateInsertion(E->getBeginLoc(), "(")4640<< FixItHint::CreateInsertion(PP.getLocForEndOfToken(E->getEndLoc()),4641")")4642<< E->getSourceRange();4643}46444645T.consumeClose();4646return true;4647}46484649TPA.Commit();4650ArgsUnion Assumption = Res.get();4651auto RParen = Tok.getLocation();4652T.consumeClose();4653Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), nullptr,4654SourceLocation(), &Assumption, 1, Form);46554656if (EndLoc)4657*EndLoc = RParen;46584659return false;4660}46614662/// ParseCXX11AttributeArgs -- Parse a C++11 attribute-argument-clause.4663///4664/// [C++11] attribute-argument-clause:4665/// '(' balanced-token-seq ')'4666///4667/// [C++11] balanced-token-seq:4668/// balanced-token4669/// balanced-token-seq balanced-token4670///4671/// [C++11] balanced-token:4672/// '(' balanced-token-seq ')'4673/// '[' balanced-token-seq ']'4674/// '{' balanced-token-seq '}'4675/// any token but '(', ')', '[', ']', '{', or '}'4676bool Parser::ParseCXX11AttributeArgs(4677IdentifierInfo *AttrName, SourceLocation AttrNameLoc,4678ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,4679SourceLocation ScopeLoc, CachedTokens &OpenMPTokens) {4680assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");4681SourceLocation LParenLoc = Tok.getLocation();4682const LangOptions &LO = getLangOpts();4683ParsedAttr::Form Form =4684LO.CPlusPlus ? ParsedAttr::Form::CXX11() : ParsedAttr::Form::C23();46854686// Try parsing microsoft attributes4687if (getLangOpts().MicrosoftExt || getLangOpts().HLSL) {4688if (hasAttribute(AttributeCommonInfo::Syntax::AS_Microsoft, ScopeName,4689AttrName, getTargetInfo(), getLangOpts()))4690Form = ParsedAttr::Form::Microsoft();4691}46924693// If the attribute isn't known, we will not attempt to parse any4694// arguments.4695if (Form.getSyntax() != ParsedAttr::AS_Microsoft &&4696!hasAttribute(LO.CPlusPlus ? AttributeCommonInfo::Syntax::AS_CXX114697: AttributeCommonInfo::Syntax::AS_C23,4698ScopeName, AttrName, getTargetInfo(), getLangOpts())) {4699// Eat the left paren, then skip to the ending right paren.4700ConsumeParen();4701SkipUntil(tok::r_paren);4702return false;4703}47044705if (ScopeName && (ScopeName->isStr("gnu") || ScopeName->isStr("__gnu__"))) {4706// GNU-scoped attributes have some special cases to handle GNU-specific4707// behaviors.4708ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,4709ScopeLoc, Form, nullptr);4710return true;4711}47124713// [[omp::directive]] and [[omp::sequence]] need special handling.4714if (ScopeName && ScopeName->isStr("omp") &&4715(AttrName->isStr("directive") || AttrName->isStr("sequence"))) {4716Diag(AttrNameLoc, getLangOpts().OpenMP >= 514717? diag::warn_omp51_compat_attributes4718: diag::ext_omp_attributes);47194720ParseOpenMPAttributeArgs(AttrName, OpenMPTokens);47214722// We claim that an attribute was parsed and added so that one is not4723// created for us by the caller.4724return true;4725}47264727unsigned NumArgs;4728// Some Clang-scoped attributes have some special parsing behavior.4729if (ScopeName && (ScopeName->isStr("clang") || ScopeName->isStr("_Clang")))4730NumArgs = ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc,4731ScopeName, ScopeLoc, Form);4732// So does C++23's assume() attribute.4733else if (!ScopeName && AttrName->isStr("assume")) {4734if (ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form))4735return true;4736NumArgs = 1;4737} else4738NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,4739ScopeName, ScopeLoc, Form);47404741if (!Attrs.empty() &&4742IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {4743ParsedAttr &Attr = Attrs.back();47444745// Ignore attributes that don't exist for the target.4746if (!Attr.existsInTarget(getTargetInfo())) {4747Diag(LParenLoc, diag::warn_unknown_attribute_ignored) << AttrName;4748Attr.setInvalid(true);4749return true;4750}47514752// If the attribute is a standard or built-in attribute and we are4753// parsing an argument list, we need to determine whether this attribute4754// was allowed to have an argument list (such as [[deprecated]]), and how4755// many arguments were parsed (so we can diagnose on [[deprecated()]]).4756if (Attr.getMaxArgs() && !NumArgs) {4757// The attribute was allowed to have arguments, but none were provided4758// even though the attribute parsed successfully. This is an error.4759Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;4760Attr.setInvalid(true);4761} else if (!Attr.getMaxArgs()) {4762// The attribute parsed successfully, but was not allowed to have any4763// arguments. It doesn't matter whether any were provided -- the4764// presence of the argument list (even if empty) is diagnosed.4765Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)4766<< AttrName4767<< FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));4768Attr.setInvalid(true);4769}4770}4771return true;4772}47734774/// Parse a C++11 or C23 attribute-specifier.4775///4776/// [C++11] attribute-specifier:4777/// '[' '[' attribute-list ']' ']'4778/// alignment-specifier4779///4780/// [C++11] attribute-list:4781/// attribute[opt]4782/// attribute-list ',' attribute[opt]4783/// attribute '...'4784/// attribute-list ',' attribute '...'4785///4786/// [C++11] attribute:4787/// attribute-token attribute-argument-clause[opt]4788///4789/// [C++11] attribute-token:4790/// identifier4791/// attribute-scoped-token4792///4793/// [C++11] attribute-scoped-token:4794/// attribute-namespace '::' identifier4795///4796/// [C++11] attribute-namespace:4797/// identifier4798void Parser::ParseCXX11AttributeSpecifierInternal(ParsedAttributes &Attrs,4799CachedTokens &OpenMPTokens,4800SourceLocation *EndLoc) {4801if (Tok.is(tok::kw_alignas)) {4802// alignas is a valid token in C23 but it is not an attribute, it's a type-4803// specifier-qualifier, which means it has different parsing behavior. We4804// handle this in ParseDeclarationSpecifiers() instead of here in C. We4805// should not get here for C any longer.4806assert(getLangOpts().CPlusPlus && "'alignas' is not an attribute in C");4807Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas);4808ParseAlignmentSpecifier(Attrs, EndLoc);4809return;4810}48114812if (Tok.isRegularKeywordAttribute()) {4813SourceLocation Loc = Tok.getLocation();4814IdentifierInfo *AttrName = Tok.getIdentifierInfo();4815ParsedAttr::Form Form = ParsedAttr::Form(Tok.getKind());4816bool TakesArgs = doesKeywordAttributeTakeArgs(Tok.getKind());4817ConsumeToken();4818if (TakesArgs) {4819if (!Tok.is(tok::l_paren))4820Diag(Tok.getLocation(), diag::err_expected_lparen_after) << AttrName;4821else4822ParseAttributeArgsCommon(AttrName, Loc, Attrs, EndLoc,4823/*ScopeName*/ nullptr,4824/*ScopeLoc*/ Loc, Form);4825} else4826Attrs.addNew(AttrName, Loc, nullptr, Loc, nullptr, 0, Form);4827return;4828}48294830assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) &&4831"Not a double square bracket attribute list");48324833SourceLocation OpenLoc = Tok.getLocation();4834if (getLangOpts().CPlusPlus) {4835Diag(OpenLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_attribute4836: diag::warn_ext_cxx11_attributes);4837} else {4838Diag(OpenLoc, getLangOpts().C23 ? diag::warn_pre_c23_compat_attributes4839: diag::warn_ext_c23_attributes);4840}48414842ConsumeBracket();4843checkCompoundToken(OpenLoc, tok::l_square, CompoundToken::AttrBegin);4844ConsumeBracket();48454846SourceLocation CommonScopeLoc;4847IdentifierInfo *CommonScopeName = nullptr;4848if (Tok.is(tok::kw_using)) {4849Diag(Tok.getLocation(), getLangOpts().CPlusPlus174850? diag::warn_cxx14_compat_using_attribute_ns4851: diag::ext_using_attribute_ns);4852ConsumeToken();48534854CommonScopeName = TryParseCXX11AttributeIdentifier(4855CommonScopeLoc, SemaCodeCompletion::AttributeCompletion::Scope);4856if (!CommonScopeName) {4857Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;4858SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);4859}4860if (!TryConsumeToken(tok::colon) && CommonScopeName)4861Diag(Tok.getLocation(), diag::err_expected) << tok::colon;4862}48634864bool AttrParsed = false;4865while (!Tok.isOneOf(tok::r_square, tok::semi, tok::eof)) {4866if (AttrParsed) {4867// If we parsed an attribute, a comma is required before parsing any4868// additional attributes.4869if (ExpectAndConsume(tok::comma)) {4870SkipUntil(tok::r_square, StopAtSemi | StopBeforeMatch);4871continue;4872}4873AttrParsed = false;4874}48754876// Eat all remaining superfluous commas before parsing the next attribute.4877while (TryConsumeToken(tok::comma))4878;48794880SourceLocation ScopeLoc, AttrLoc;4881IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr;48824883AttrName = TryParseCXX11AttributeIdentifier(4884AttrLoc, SemaCodeCompletion::AttributeCompletion::Attribute,4885CommonScopeName);4886if (!AttrName)4887// Break out to the "expected ']'" diagnostic.4888break;48894890// scoped attribute4891if (TryConsumeToken(tok::coloncolon)) {4892ScopeName = AttrName;4893ScopeLoc = AttrLoc;48944895AttrName = TryParseCXX11AttributeIdentifier(4896AttrLoc, SemaCodeCompletion::AttributeCompletion::Attribute,4897ScopeName);4898if (!AttrName) {4899Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;4900SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch);4901continue;4902}4903}49044905if (CommonScopeName) {4906if (ScopeName) {4907Diag(ScopeLoc, diag::err_using_attribute_ns_conflict)4908<< SourceRange(CommonScopeLoc);4909} else {4910ScopeName = CommonScopeName;4911ScopeLoc = CommonScopeLoc;4912}4913}49144915// Parse attribute arguments4916if (Tok.is(tok::l_paren))4917AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, Attrs, EndLoc,4918ScopeName, ScopeLoc, OpenMPTokens);49194920if (!AttrParsed) {4921Attrs.addNew(4922AttrName,4923SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc),4924ScopeName, ScopeLoc, nullptr, 0,4925getLangOpts().CPlusPlus ? ParsedAttr::Form::CXX11()4926: ParsedAttr::Form::C23());4927AttrParsed = true;4928}49294930if (TryConsumeToken(tok::ellipsis))4931Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis) << AttrName;4932}49334934// If we hit an error and recovered by parsing up to a semicolon, eat the4935// semicolon and don't issue further diagnostics about missing brackets.4936if (Tok.is(tok::semi)) {4937ConsumeToken();4938return;4939}49404941SourceLocation CloseLoc = Tok.getLocation();4942if (ExpectAndConsume(tok::r_square))4943SkipUntil(tok::r_square);4944else if (Tok.is(tok::r_square))4945checkCompoundToken(CloseLoc, tok::r_square, CompoundToken::AttrEnd);4946if (EndLoc)4947*EndLoc = Tok.getLocation();4948if (ExpectAndConsume(tok::r_square))4949SkipUntil(tok::r_square);4950}49514952/// ParseCXX11Attributes - Parse a C++11 or C23 attribute-specifier-seq.4953///4954/// attribute-specifier-seq:4955/// attribute-specifier-seq[opt] attribute-specifier4956void Parser::ParseCXX11Attributes(ParsedAttributes &Attrs) {4957SourceLocation StartLoc = Tok.getLocation();4958SourceLocation EndLoc = StartLoc;49594960do {4961ParseCXX11AttributeSpecifier(Attrs, &EndLoc);4962} while (isAllowedCXX11AttributeSpecifier());49634964Attrs.Range = SourceRange(StartLoc, EndLoc);4965}49664967void Parser::DiagnoseAndSkipCXX11Attributes() {4968auto Keyword =4969Tok.isRegularKeywordAttribute() ? Tok.getIdentifierInfo() : nullptr;4970// Start and end location of an attribute or an attribute list.4971SourceLocation StartLoc = Tok.getLocation();4972SourceLocation EndLoc = SkipCXX11Attributes();49734974if (EndLoc.isValid()) {4975SourceRange Range(StartLoc, EndLoc);4976(Keyword ? Diag(StartLoc, diag::err_keyword_not_allowed) << Keyword4977: Diag(StartLoc, diag::err_attributes_not_allowed))4978<< Range;4979}4980}49814982SourceLocation Parser::SkipCXX11Attributes() {4983SourceLocation EndLoc;49844985if (!isCXX11AttributeSpecifier())4986return EndLoc;49874988do {4989if (Tok.is(tok::l_square)) {4990BalancedDelimiterTracker T(*this, tok::l_square);4991T.consumeOpen();4992T.skipToEnd();4993EndLoc = T.getCloseLocation();4994} else if (Tok.isRegularKeywordAttribute() &&4995!doesKeywordAttributeTakeArgs(Tok.getKind())) {4996EndLoc = Tok.getLocation();4997ConsumeToken();4998} else {4999assert((Tok.is(tok::kw_alignas) || Tok.isRegularKeywordAttribute()) &&5000"not an attribute specifier");5001ConsumeToken();5002BalancedDelimiterTracker T(*this, tok::l_paren);5003if (!T.consumeOpen())5004T.skipToEnd();5005EndLoc = T.getCloseLocation();5006}5007} while (isCXX11AttributeSpecifier());50085009return EndLoc;5010}50115012/// Parse uuid() attribute when it appears in a [] Microsoft attribute.5013void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) {5014assert(Tok.is(tok::identifier) && "Not a Microsoft attribute list");5015IdentifierInfo *UuidIdent = Tok.getIdentifierInfo();5016assert(UuidIdent->getName() == "uuid" && "Not a Microsoft attribute list");50175018SourceLocation UuidLoc = Tok.getLocation();5019ConsumeToken();50205021// Ignore the left paren location for now.5022BalancedDelimiterTracker T(*this, tok::l_paren);5023if (T.consumeOpen()) {5024Diag(Tok, diag::err_expected) << tok::l_paren;5025return;5026}50275028ArgsVector ArgExprs;5029if (isTokenStringLiteral()) {5030// Easy case: uuid("...") -- quoted string.5031ExprResult StringResult = ParseUnevaluatedStringLiteralExpression();5032if (StringResult.isInvalid())5033return;5034ArgExprs.push_back(StringResult.get());5035} else {5036// something like uuid({000000A0-0000-0000-C000-000000000049}) -- no5037// quotes in the parens. Just append the spelling of all tokens encountered5038// until the closing paren.50395040SmallString<42> StrBuffer; // 2 "", 36 bytes UUID, 2 optional {}, 1 nul5041StrBuffer += "\"";50425043// Since none of C++'s keywords match [a-f]+, accepting just tok::l_brace,5044// tok::r_brace, tok::minus, tok::identifier (think C000) and5045// tok::numeric_constant (0000) should be enough. But the spelling of the5046// uuid argument is checked later anyways, so there's no harm in accepting5047// almost anything here.5048// cl is very strict about whitespace in this form and errors out if any5049// is present, so check the space flags on the tokens.5050SourceLocation StartLoc = Tok.getLocation();5051while (Tok.isNot(tok::r_paren)) {5052if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) {5053Diag(Tok, diag::err_attribute_uuid_malformed_guid);5054SkipUntil(tok::r_paren, StopAtSemi);5055return;5056}5057SmallString<16> SpellingBuffer;5058SpellingBuffer.resize(Tok.getLength() + 1);5059bool Invalid = false;5060StringRef TokSpelling = PP.getSpelling(Tok, SpellingBuffer, &Invalid);5061if (Invalid) {5062SkipUntil(tok::r_paren, StopAtSemi);5063return;5064}5065StrBuffer += TokSpelling;5066ConsumeAnyToken();5067}5068StrBuffer += "\"";50695070if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) {5071Diag(Tok, diag::err_attribute_uuid_malformed_guid);5072ConsumeParen();5073return;5074}50755076// Pretend the user wrote the appropriate string literal here.5077// ActOnStringLiteral() copies the string data into the literal, so it's5078// ok that the Token points to StrBuffer.5079Token Toks[1];5080Toks[0].startToken();5081Toks[0].setKind(tok::string_literal);5082Toks[0].setLocation(StartLoc);5083Toks[0].setLiteralData(StrBuffer.data());5084Toks[0].setLength(StrBuffer.size());5085StringLiteral *UuidString =5086cast<StringLiteral>(Actions.ActOnUnevaluatedStringLiteral(Toks).get());5087ArgExprs.push_back(UuidString);5088}50895090if (!T.consumeClose()) {5091Attrs.addNew(UuidIdent, SourceRange(UuidLoc, T.getCloseLocation()), nullptr,5092SourceLocation(), ArgExprs.data(), ArgExprs.size(),5093ParsedAttr::Form::Microsoft());5094}5095}50965097/// ParseMicrosoftAttributes - Parse Microsoft attributes [Attr]5098///5099/// [MS] ms-attribute:5100/// '[' token-seq ']'5101///5102/// [MS] ms-attribute-seq:5103/// ms-attribute[opt]5104/// ms-attribute ms-attribute-seq5105void Parser::ParseMicrosoftAttributes(ParsedAttributes &Attrs) {5106assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");51075108SourceLocation StartLoc = Tok.getLocation();5109SourceLocation EndLoc = StartLoc;5110do {5111// FIXME: If this is actually a C++11 attribute, parse it as one.5112BalancedDelimiterTracker T(*this, tok::l_square);5113T.consumeOpen();51145115// Skip most ms attributes except for a specific list.5116while (true) {5117SkipUntil(tok::r_square, tok::identifier,5118StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);5119if (Tok.is(tok::code_completion)) {5120cutOffParsing();5121Actions.CodeCompletion().CodeCompleteAttribute(5122AttributeCommonInfo::AS_Microsoft,5123SemaCodeCompletion::AttributeCompletion::Attribute,5124/*Scope=*/nullptr);5125break;5126}5127if (Tok.isNot(tok::identifier)) // ']', but also eof5128break;5129if (Tok.getIdentifierInfo()->getName() == "uuid")5130ParseMicrosoftUuidAttributeArgs(Attrs);5131else {5132IdentifierInfo *II = Tok.getIdentifierInfo();5133SourceLocation NameLoc = Tok.getLocation();5134ConsumeToken();5135ParsedAttr::Kind AttrKind =5136ParsedAttr::getParsedKind(II, nullptr, ParsedAttr::AS_Microsoft);5137// For HLSL we want to handle all attributes, but for MSVC compat, we5138// silently ignore unknown Microsoft attributes.5139if (getLangOpts().HLSL || AttrKind != ParsedAttr::UnknownAttribute) {5140bool AttrParsed = false;5141if (Tok.is(tok::l_paren)) {5142CachedTokens OpenMPTokens;5143AttrParsed =5144ParseCXX11AttributeArgs(II, NameLoc, Attrs, &EndLoc, nullptr,5145SourceLocation(), OpenMPTokens);5146ReplayOpenMPAttributeTokens(OpenMPTokens);5147}5148if (!AttrParsed) {5149Attrs.addNew(II, NameLoc, nullptr, SourceLocation(), nullptr, 0,5150ParsedAttr::Form::Microsoft());5151}5152}5153}5154}51555156T.consumeClose();5157EndLoc = T.getCloseLocation();5158} while (Tok.is(tok::l_square));51595160Attrs.Range = SourceRange(StartLoc, EndLoc);5161}51625163void Parser::ParseMicrosoftIfExistsClassDeclaration(5164DeclSpec::TST TagType, ParsedAttributes &AccessAttrs,5165AccessSpecifier &CurAS) {5166IfExistsCondition Result;5167if (ParseMicrosoftIfExistsCondition(Result))5168return;51695170BalancedDelimiterTracker Braces(*this, tok::l_brace);5171if (Braces.consumeOpen()) {5172Diag(Tok, diag::err_expected) << tok::l_brace;5173return;5174}51755176switch (Result.Behavior) {5177case IEB_Parse:5178// Parse the declarations below.5179break;51805181case IEB_Dependent:5182Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists)5183<< Result.IsIfExists;5184// Fall through to skip.5185[[fallthrough]];51865187case IEB_Skip:5188Braces.skipToEnd();5189return;5190}51915192while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {5193// __if_exists, __if_not_exists can nest.5194if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) {5195ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, CurAS);5196continue;5197}51985199// Check for extraneous top-level semicolon.5200if (Tok.is(tok::semi)) {5201ConsumeExtraSemi(InsideStruct, TagType);5202continue;5203}52045205AccessSpecifier AS = getAccessSpecifierIfPresent();5206if (AS != AS_none) {5207// Current token is a C++ access specifier.5208CurAS = AS;5209SourceLocation ASLoc = Tok.getLocation();5210ConsumeToken();5211if (Tok.is(tok::colon))5212Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation(),5213ParsedAttributesView{});5214else5215Diag(Tok, diag::err_expected) << tok::colon;5216ConsumeToken();5217continue;5218}52195220ParsedTemplateInfo TemplateInfo;5221// Parse all the comma separated declarators.5222ParseCXXClassMemberDeclaration(CurAS, AccessAttrs, TemplateInfo);5223}52245225Braces.consumeClose();5226}522752285229