Path: blob/main/contrib/llvm-project/clang/lib/Parse/ParseDecl.cpp
35234 views
//===--- ParseDecl.cpp - 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 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/AddressSpaces.h"16#include "clang/Basic/AttributeCommonInfo.h"17#include "clang/Basic/Attributes.h"18#include "clang/Basic/CharInfo.h"19#include "clang/Basic/TargetInfo.h"20#include "clang/Basic/TokenKinds.h"21#include "clang/Parse/ParseDiagnostic.h"22#include "clang/Parse/Parser.h"23#include "clang/Parse/RAIIObjectsForParser.h"24#include "clang/Sema/EnterExpressionEvaluationContext.h"25#include "clang/Sema/Lookup.h"26#include "clang/Sema/ParsedTemplate.h"27#include "clang/Sema/Scope.h"28#include "clang/Sema/SemaCUDA.h"29#include "clang/Sema/SemaCodeCompletion.h"30#include "clang/Sema/SemaDiagnostic.h"31#include "clang/Sema/SemaObjC.h"32#include "clang/Sema/SemaOpenMP.h"33#include "llvm/ADT/SmallSet.h"34#include "llvm/ADT/SmallString.h"35#include "llvm/ADT/StringSwitch.h"36#include <optional>3738using namespace clang;3940//===----------------------------------------------------------------------===//41// C99 6.7: Declarations.42//===----------------------------------------------------------------------===//4344/// ParseTypeName45/// type-name: [C99 6.7.6]46/// specifier-qualifier-list abstract-declarator[opt]47///48/// Called type-id in C++.49TypeResult Parser::ParseTypeName(SourceRange *Range, DeclaratorContext Context,50AccessSpecifier AS, Decl **OwnedType,51ParsedAttributes *Attrs) {52DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context);53if (DSC == DeclSpecContext::DSC_normal)54DSC = DeclSpecContext::DSC_type_specifier;5556// Parse the common declaration-specifiers piece.57DeclSpec DS(AttrFactory);58if (Attrs)59DS.addAttributes(*Attrs);60ParseSpecifierQualifierList(DS, AS, DSC);61if (OwnedType)62*OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr;6364// Move declspec attributes to ParsedAttributes65if (Attrs) {66llvm::SmallVector<ParsedAttr *, 1> ToBeMoved;67for (ParsedAttr &AL : DS.getAttributes()) {68if (AL.isDeclspecAttribute())69ToBeMoved.push_back(&AL);70}7172for (ParsedAttr *AL : ToBeMoved)73Attrs->takeOneFrom(DS.getAttributes(), AL);74}7576// Parse the abstract-declarator, if present.77Declarator DeclaratorInfo(DS, ParsedAttributesView::none(), Context);78ParseDeclarator(DeclaratorInfo);79if (Range)80*Range = DeclaratorInfo.getSourceRange();8182if (DeclaratorInfo.isInvalidType())83return true;8485return Actions.ActOnTypeName(DeclaratorInfo);86}8788/// Normalizes an attribute name by dropping prefixed and suffixed __.89static StringRef normalizeAttrName(StringRef Name) {90if (Name.size() >= 4 && Name.starts_with("__") && Name.ends_with("__"))91return Name.drop_front(2).drop_back(2);92return Name;93}9495/// returns true iff attribute is annotated with `LateAttrParseExperimentalExt`96/// in `Attr.td`.97static bool IsAttributeLateParsedExperimentalExt(const IdentifierInfo &II) {98#define CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST99return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))100#include "clang/Parse/AttrParserStringSwitches.inc"101.Default(false);102#undef CLANG_ATTR_LATE_PARSED_EXPERIMENTAL_EXT_LIST103}104105/// returns true iff attribute is annotated with `LateAttrParseStandard` in106/// `Attr.td`.107static bool IsAttributeLateParsedStandard(const IdentifierInfo &II) {108#define CLANG_ATTR_LATE_PARSED_LIST109return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))110#include "clang/Parse/AttrParserStringSwitches.inc"111.Default(false);112#undef CLANG_ATTR_LATE_PARSED_LIST113}114115/// Check if the a start and end source location expand to the same macro.116static bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc,117SourceLocation EndLoc) {118if (!StartLoc.isMacroID() || !EndLoc.isMacroID())119return false;120121SourceManager &SM = PP.getSourceManager();122if (SM.getFileID(StartLoc) != SM.getFileID(EndLoc))123return false;124125bool AttrStartIsInMacro =126Lexer::isAtStartOfMacroExpansion(StartLoc, SM, PP.getLangOpts());127bool AttrEndIsInMacro =128Lexer::isAtEndOfMacroExpansion(EndLoc, SM, PP.getLangOpts());129return AttrStartIsInMacro && AttrEndIsInMacro;130}131132void Parser::ParseAttributes(unsigned WhichAttrKinds, ParsedAttributes &Attrs,133LateParsedAttrList *LateAttrs) {134bool MoreToParse;135do {136// Assume there's nothing left to parse, but if any attributes are in fact137// parsed, loop to ensure all specified attribute combinations are parsed.138MoreToParse = false;139if (WhichAttrKinds & PAKM_CXX11)140MoreToParse |= MaybeParseCXX11Attributes(Attrs);141if (WhichAttrKinds & PAKM_GNU)142MoreToParse |= MaybeParseGNUAttributes(Attrs, LateAttrs);143if (WhichAttrKinds & PAKM_Declspec)144MoreToParse |= MaybeParseMicrosoftDeclSpecs(Attrs);145} while (MoreToParse);146}147148/// ParseGNUAttributes - Parse a non-empty attributes list.149///150/// [GNU] attributes:151/// attribute152/// attributes attribute153///154/// [GNU] attribute:155/// '__attribute__' '(' '(' attribute-list ')' ')'156///157/// [GNU] attribute-list:158/// attrib159/// attribute_list ',' attrib160///161/// [GNU] attrib:162/// empty163/// attrib-name164/// attrib-name '(' identifier ')'165/// attrib-name '(' identifier ',' nonempty-expr-list ')'166/// attrib-name '(' argument-expression-list [C99 6.5.2] ')'167///168/// [GNU] attrib-name:169/// identifier170/// typespec171/// typequal172/// storageclass173///174/// Whether an attribute takes an 'identifier' is determined by the175/// attrib-name. GCC's behavior here is not worth imitating:176///177/// * In C mode, if the attribute argument list starts with an identifier178/// followed by a ',' or an ')', and the identifier doesn't resolve to179/// a type, it is parsed as an identifier. If the attribute actually180/// wanted an expression, it's out of luck (but it turns out that no181/// attributes work that way, because C constant expressions are very182/// limited).183/// * In C++ mode, if the attribute argument list starts with an identifier,184/// and the attribute *wants* an identifier, it is parsed as an identifier.185/// At block scope, any additional tokens between the identifier and the186/// ',' or ')' are ignored, otherwise they produce a parse error.187///188/// We follow the C++ model, but don't allow junk after the identifier.189void Parser::ParseGNUAttributes(ParsedAttributes &Attrs,190LateParsedAttrList *LateAttrs, Declarator *D) {191assert(Tok.is(tok::kw___attribute) && "Not a GNU attribute list!");192193SourceLocation StartLoc = Tok.getLocation();194SourceLocation EndLoc = StartLoc;195196while (Tok.is(tok::kw___attribute)) {197SourceLocation AttrTokLoc = ConsumeToken();198unsigned OldNumAttrs = Attrs.size();199unsigned OldNumLateAttrs = LateAttrs ? LateAttrs->size() : 0;200201if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,202"attribute")) {203SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ;204return;205}206if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "(")) {207SkipUntil(tok::r_paren, StopAtSemi); // skip until ) or ;208return;209}210// Parse the attribute-list. e.g. __attribute__(( weak, alias("__f") ))211do {212// Eat preceeding commas to allow __attribute__((,,,foo))213while (TryConsumeToken(tok::comma))214;215216// Expect an identifier or declaration specifier (const, int, etc.)217if (Tok.isAnnotation())218break;219if (Tok.is(tok::code_completion)) {220cutOffParsing();221Actions.CodeCompletion().CodeCompleteAttribute(222AttributeCommonInfo::Syntax::AS_GNU);223break;224}225IdentifierInfo *AttrName = Tok.getIdentifierInfo();226if (!AttrName)227break;228229SourceLocation AttrNameLoc = ConsumeToken();230231if (Tok.isNot(tok::l_paren)) {232Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,233ParsedAttr::Form::GNU());234continue;235}236237bool LateParse = false;238if (!LateAttrs)239LateParse = false;240else if (LateAttrs->lateAttrParseExperimentalExtOnly()) {241// The caller requested that this attribute **only** be late242// parsed for `LateAttrParseExperimentalExt` attributes. This will243// only be late parsed if the experimental language option is enabled.244LateParse = getLangOpts().ExperimentalLateParseAttributes &&245IsAttributeLateParsedExperimentalExt(*AttrName);246} else {247// The caller did not restrict late parsing to only248// `LateAttrParseExperimentalExt` attributes so late parse249// both `LateAttrParseStandard` and `LateAttrParseExperimentalExt`250// attributes.251LateParse = IsAttributeLateParsedExperimentalExt(*AttrName) ||252IsAttributeLateParsedStandard(*AttrName);253}254255// Handle "parameterized" attributes256if (!LateParse) {257ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, &EndLoc, nullptr,258SourceLocation(), ParsedAttr::Form::GNU(), D);259continue;260}261262// Handle attributes with arguments that require late parsing.263LateParsedAttribute *LA =264new LateParsedAttribute(this, *AttrName, AttrNameLoc);265LateAttrs->push_back(LA);266267// Attributes in a class are parsed at the end of the class, along268// with other late-parsed declarations.269if (!ClassStack.empty() && !LateAttrs->parseSoon())270getCurrentClass().LateParsedDeclarations.push_back(LA);271272// Be sure ConsumeAndStoreUntil doesn't see the start l_paren, since it273// recursively consumes balanced parens.274LA->Toks.push_back(Tok);275ConsumeParen();276// Consume everything up to and including the matching right parens.277ConsumeAndStoreUntil(tok::r_paren, LA->Toks, /*StopAtSemi=*/true);278279Token Eof;280Eof.startToken();281Eof.setLocation(Tok.getLocation());282LA->Toks.push_back(Eof);283} while (Tok.is(tok::comma));284285if (ExpectAndConsume(tok::r_paren))286SkipUntil(tok::r_paren, StopAtSemi);287SourceLocation Loc = Tok.getLocation();288if (ExpectAndConsume(tok::r_paren))289SkipUntil(tok::r_paren, StopAtSemi);290EndLoc = Loc;291292// If this was declared in a macro, attach the macro IdentifierInfo to the293// parsed attribute.294auto &SM = PP.getSourceManager();295if (!SM.isWrittenInBuiltinFile(SM.getSpellingLoc(AttrTokLoc)) &&296FindLocsWithCommonFileID(PP, AttrTokLoc, Loc)) {297CharSourceRange ExpansionRange = SM.getExpansionRange(AttrTokLoc);298StringRef FoundName =299Lexer::getSourceText(ExpansionRange, SM, PP.getLangOpts());300IdentifierInfo *MacroII = PP.getIdentifierInfo(FoundName);301302for (unsigned i = OldNumAttrs; i < Attrs.size(); ++i)303Attrs[i].setMacroIdentifier(MacroII, ExpansionRange.getBegin());304305if (LateAttrs) {306for (unsigned i = OldNumLateAttrs; i < LateAttrs->size(); ++i)307(*LateAttrs)[i]->MacroII = MacroII;308}309}310}311312Attrs.Range = SourceRange(StartLoc, EndLoc);313}314315/// Determine whether the given attribute has an identifier argument.316static bool attributeHasIdentifierArg(const IdentifierInfo &II) {317#define CLANG_ATTR_IDENTIFIER_ARG_LIST318return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))319#include "clang/Parse/AttrParserStringSwitches.inc"320.Default(false);321#undef CLANG_ATTR_IDENTIFIER_ARG_LIST322}323324/// Determine whether the given attribute has an identifier argument.325static ParsedAttributeArgumentsProperties326attributeStringLiteralListArg(const llvm::Triple &T, const IdentifierInfo &II) {327#define CLANG_ATTR_STRING_LITERAL_ARG_LIST328return llvm::StringSwitch<uint32_t>(normalizeAttrName(II.getName()))329#include "clang/Parse/AttrParserStringSwitches.inc"330.Default(0);331#undef CLANG_ATTR_STRING_LITERAL_ARG_LIST332}333334/// Determine whether the given attribute has a variadic identifier argument.335static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II) {336#define CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST337return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))338#include "clang/Parse/AttrParserStringSwitches.inc"339.Default(false);340#undef CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST341}342343/// Determine whether the given attribute treats kw_this as an identifier.344static bool attributeTreatsKeywordThisAsIdentifier(const IdentifierInfo &II) {345#define CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST346return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))347#include "clang/Parse/AttrParserStringSwitches.inc"348.Default(false);349#undef CLANG_ATTR_THIS_ISA_IDENTIFIER_ARG_LIST350}351352/// Determine if an attribute accepts parameter packs.353static bool attributeAcceptsExprPack(const IdentifierInfo &II) {354#define CLANG_ATTR_ACCEPTS_EXPR_PACK355return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))356#include "clang/Parse/AttrParserStringSwitches.inc"357.Default(false);358#undef CLANG_ATTR_ACCEPTS_EXPR_PACK359}360361/// Determine whether the given attribute parses a type argument.362static bool attributeIsTypeArgAttr(const IdentifierInfo &II) {363#define CLANG_ATTR_TYPE_ARG_LIST364return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))365#include "clang/Parse/AttrParserStringSwitches.inc"366.Default(false);367#undef CLANG_ATTR_TYPE_ARG_LIST368}369370/// Determine whether the given attribute takes identifier arguments.371static bool attributeHasStrictIdentifierArgs(const IdentifierInfo &II) {372#define CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST373return (llvm::StringSwitch<uint64_t>(normalizeAttrName(II.getName()))374#include "clang/Parse/AttrParserStringSwitches.inc"375.Default(0)) != 0;376#undef CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST377}378379/// Determine whether the given attribute takes an identifier argument at a380/// specific index381static bool attributeHasStrictIdentifierArgAtIndex(const IdentifierInfo &II,382size_t argIndex) {383#define CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST384return (llvm::StringSwitch<uint64_t>(normalizeAttrName(II.getName()))385#include "clang/Parse/AttrParserStringSwitches.inc"386.Default(0)) &387(1ull << argIndex);388#undef CLANG_ATTR_STRICT_IDENTIFIER_ARG_AT_INDEX_LIST389}390391/// Determine whether the given attribute requires parsing its arguments392/// in an unevaluated context or not.393static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) {394#define CLANG_ATTR_ARG_CONTEXT_LIST395return llvm::StringSwitch<bool>(normalizeAttrName(II.getName()))396#include "clang/Parse/AttrParserStringSwitches.inc"397.Default(false);398#undef CLANG_ATTR_ARG_CONTEXT_LIST399}400401IdentifierLoc *Parser::ParseIdentifierLoc() {402assert(Tok.is(tok::identifier) && "expected an identifier");403IdentifierLoc *IL = IdentifierLoc::create(Actions.Context,404Tok.getLocation(),405Tok.getIdentifierInfo());406ConsumeToken();407return IL;408}409410void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName,411SourceLocation AttrNameLoc,412ParsedAttributes &Attrs,413IdentifierInfo *ScopeName,414SourceLocation ScopeLoc,415ParsedAttr::Form Form) {416BalancedDelimiterTracker Parens(*this, tok::l_paren);417Parens.consumeOpen();418419TypeResult T;420if (Tok.isNot(tok::r_paren))421T = ParseTypeName();422423if (Parens.consumeClose())424return;425426if (T.isInvalid())427return;428429if (T.isUsable())430Attrs.addNewTypeAttr(&AttrName,431SourceRange(AttrNameLoc, Parens.getCloseLocation()),432ScopeName, ScopeLoc, T.get(), Form);433else434Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()),435ScopeName, ScopeLoc, nullptr, 0, Form);436}437438ExprResult439Parser::ParseUnevaluatedStringInAttribute(const IdentifierInfo &AttrName) {440if (Tok.is(tok::l_paren)) {441BalancedDelimiterTracker Paren(*this, tok::l_paren);442Paren.consumeOpen();443ExprResult Res = ParseUnevaluatedStringInAttribute(AttrName);444Paren.consumeClose();445return Res;446}447if (!isTokenStringLiteral()) {448Diag(Tok.getLocation(), diag::err_expected_string_literal)449<< /*in attribute...*/ 4 << AttrName.getName();450return ExprError();451}452return ParseUnevaluatedStringLiteralExpression();453}454455bool Parser::ParseAttributeArgumentList(456const IdentifierInfo &AttrName, SmallVectorImpl<Expr *> &Exprs,457ParsedAttributeArgumentsProperties ArgsProperties) {458bool SawError = false;459unsigned Arg = 0;460while (true) {461ExprResult Expr;462if (ArgsProperties.isStringLiteralArg(Arg)) {463Expr = ParseUnevaluatedStringInAttribute(AttrName);464} else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {465Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);466Expr = ParseBraceInitializer();467} else {468Expr = ParseAssignmentExpression();469}470Expr = Actions.CorrectDelayedTyposInExpr(Expr);471472if (Tok.is(tok::ellipsis))473Expr = Actions.ActOnPackExpansion(Expr.get(), ConsumeToken());474else if (Tok.is(tok::code_completion)) {475// There's nothing to suggest in here as we parsed a full expression.476// Instead fail and propagate the error since caller might have something477// the suggest, e.g. signature help in function call. Note that this is478// performed before pushing the \p Expr, so that signature help can report479// current argument correctly.480SawError = true;481cutOffParsing();482break;483}484485if (Expr.isInvalid()) {486SawError = true;487break;488}489490if (Actions.DiagnoseUnexpandedParameterPack(Expr.get())) {491SawError = true;492break;493}494495Exprs.push_back(Expr.get());496497if (Tok.isNot(tok::comma))498break;499// Move to the next argument, remember where the comma was.500Token Comma = Tok;501ConsumeToken();502checkPotentialAngleBracketDelimiter(Comma);503Arg++;504}505506if (SawError) {507// Ensure typos get diagnosed when errors were encountered while parsing the508// expression list.509for (auto &E : Exprs) {510ExprResult Expr = Actions.CorrectDelayedTyposInExpr(E);511if (Expr.isUsable())512E = Expr.get();513}514}515return SawError;516}517518unsigned Parser::ParseAttributeArgsCommon(519IdentifierInfo *AttrName, SourceLocation AttrNameLoc,520ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,521SourceLocation ScopeLoc, ParsedAttr::Form Form) {522// Ignore the left paren location for now.523ConsumeParen();524525bool ChangeKWThisToIdent = attributeTreatsKeywordThisAsIdentifier(*AttrName);526bool AttributeIsTypeArgAttr = attributeIsTypeArgAttr(*AttrName);527bool AttributeHasVariadicIdentifierArg =528attributeHasVariadicIdentifierArg(*AttrName);529530// Interpret "kw_this" as an identifier if the attributed requests it.531if (ChangeKWThisToIdent && Tok.is(tok::kw_this))532Tok.setKind(tok::identifier);533534ArgsVector ArgExprs;535if (Tok.is(tok::identifier)) {536// If this attribute wants an 'identifier' argument, make it so.537bool IsIdentifierArg = AttributeHasVariadicIdentifierArg ||538attributeHasIdentifierArg(*AttrName);539ParsedAttr::Kind AttrKind =540ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax());541542// If we don't know how to parse this attribute, but this is the only543// token in this argument, assume it's meant to be an identifier.544if (AttrKind == ParsedAttr::UnknownAttribute ||545AttrKind == ParsedAttr::IgnoredAttribute) {546const Token &Next = NextToken();547IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma);548}549550if (IsIdentifierArg)551ArgExprs.push_back(ParseIdentifierLoc());552}553554ParsedType TheParsedType;555if (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren)) {556// Eat the comma.557if (!ArgExprs.empty())558ConsumeToken();559560if (AttributeIsTypeArgAttr) {561// FIXME: Multiple type arguments are not implemented.562TypeResult T = ParseTypeName();563if (T.isInvalid()) {564SkipUntil(tok::r_paren, StopAtSemi);565return 0;566}567if (T.isUsable())568TheParsedType = T.get();569} else if (AttributeHasVariadicIdentifierArg ||570attributeHasStrictIdentifierArgs(*AttrName)) {571// Parse variadic identifier arg. This can either consume identifiers or572// expressions. Variadic identifier args do not support parameter packs573// because those are typically used for attributes with enumeration574// arguments, and those enumerations are not something the user could575// express via a pack.576do {577// Interpret "kw_this" as an identifier if the attributed requests it.578if (ChangeKWThisToIdent && Tok.is(tok::kw_this))579Tok.setKind(tok::identifier);580581if (Tok.is(tok::identifier) && attributeHasStrictIdentifierArgAtIndex(582*AttrName, ArgExprs.size())) {583ArgExprs.push_back(ParseIdentifierLoc());584continue;585}586587ExprResult ArgExpr;588if (Tok.is(tok::identifier)) {589ArgExprs.push_back(ParseIdentifierLoc());590} else {591bool Uneval = attributeParsedArgsUnevaluated(*AttrName);592EnterExpressionEvaluationContext Unevaluated(593Actions,594Uneval ? Sema::ExpressionEvaluationContext::Unevaluated595: Sema::ExpressionEvaluationContext::ConstantEvaluated,596nullptr,597Sema::ExpressionEvaluationContextRecord::EK_AttrArgument);598599ExprResult ArgExpr(600Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));601602if (ArgExpr.isInvalid()) {603SkipUntil(tok::r_paren, StopAtSemi);604return 0;605}606ArgExprs.push_back(ArgExpr.get());607}608// Eat the comma, move to the next argument609} while (TryConsumeToken(tok::comma));610} else {611// General case. Parse all available expressions.612bool Uneval = attributeParsedArgsUnevaluated(*AttrName);613EnterExpressionEvaluationContext Unevaluated(614Actions,615Uneval ? Sema::ExpressionEvaluationContext::Unevaluated616: Sema::ExpressionEvaluationContext::ConstantEvaluated,617nullptr,618Sema::ExpressionEvaluationContextRecord::ExpressionKind::619EK_AttrArgument);620621ExprVector ParsedExprs;622ParsedAttributeArgumentsProperties ArgProperties =623attributeStringLiteralListArg(getTargetInfo().getTriple(), *AttrName);624if (ParseAttributeArgumentList(*AttrName, ParsedExprs, ArgProperties)) {625SkipUntil(tok::r_paren, StopAtSemi);626return 0;627}628629// Pack expansion must currently be explicitly supported by an attribute.630for (size_t I = 0; I < ParsedExprs.size(); ++I) {631if (!isa<PackExpansionExpr>(ParsedExprs[I]))632continue;633634if (!attributeAcceptsExprPack(*AttrName)) {635Diag(Tok.getLocation(),636diag::err_attribute_argument_parm_pack_not_supported)637<< AttrName;638SkipUntil(tok::r_paren, StopAtSemi);639return 0;640}641}642643ArgExprs.insert(ArgExprs.end(), ParsedExprs.begin(), ParsedExprs.end());644}645}646647SourceLocation RParen = Tok.getLocation();648if (!ExpectAndConsume(tok::r_paren)) {649SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc;650651if (AttributeIsTypeArgAttr && !TheParsedType.get().isNull()) {652Attrs.addNewTypeAttr(AttrName, SourceRange(AttrNameLoc, RParen),653ScopeName, ScopeLoc, TheParsedType, Form);654} else {655Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,656ArgExprs.data(), ArgExprs.size(), Form);657}658}659660if (EndLoc)661*EndLoc = RParen;662663return static_cast<unsigned>(ArgExprs.size() + !TheParsedType.get().isNull());664}665666/// Parse the arguments to a parameterized GNU attribute or667/// a C++11 attribute in "gnu" namespace.668void Parser::ParseGNUAttributeArgs(669IdentifierInfo *AttrName, SourceLocation AttrNameLoc,670ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,671SourceLocation ScopeLoc, ParsedAttr::Form Form, Declarator *D) {672673assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");674675ParsedAttr::Kind AttrKind =676ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax());677678if (AttrKind == ParsedAttr::AT_Availability) {679ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,680ScopeLoc, Form);681return;682} else if (AttrKind == ParsedAttr::AT_ExternalSourceSymbol) {683ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,684ScopeName, ScopeLoc, Form);685return;686} else if (AttrKind == ParsedAttr::AT_ObjCBridgeRelated) {687ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,688ScopeName, ScopeLoc, Form);689return;690} else if (AttrKind == ParsedAttr::AT_SwiftNewType) {691ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,692ScopeLoc, Form);693return;694} else if (AttrKind == ParsedAttr::AT_TypeTagForDatatype) {695ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,696ScopeName, ScopeLoc, Form);697return;698} else if (attributeIsTypeArgAttr(*AttrName)) {699ParseAttributeWithTypeArg(*AttrName, AttrNameLoc, Attrs, ScopeName,700ScopeLoc, Form);701return;702} else if (AttrKind == ParsedAttr::AT_CountedBy ||703AttrKind == ParsedAttr::AT_CountedByOrNull ||704AttrKind == ParsedAttr::AT_SizedBy ||705AttrKind == ParsedAttr::AT_SizedByOrNull) {706ParseBoundsAttribute(*AttrName, AttrNameLoc, Attrs, ScopeName, ScopeLoc,707Form);708return;709} else if (AttrKind == ParsedAttr::AT_CXXAssume) {710ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form);711return;712}713714// These may refer to the function arguments, but need to be parsed early to715// participate in determining whether it's a redeclaration.716std::optional<ParseScope> PrototypeScope;717if (normalizeAttrName(AttrName->getName()) == "enable_if" &&718D && D->isFunctionDeclarator()) {719DeclaratorChunk::FunctionTypeInfo FTI = D->getFunctionTypeInfo();720PrototypeScope.emplace(this, Scope::FunctionPrototypeScope |721Scope::FunctionDeclarationScope |722Scope::DeclScope);723for (unsigned i = 0; i != FTI.NumParams; ++i) {724ParmVarDecl *Param = cast<ParmVarDecl>(FTI.Params[i].Param);725Actions.ActOnReenterCXXMethodParameter(getCurScope(), Param);726}727}728729ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,730ScopeLoc, Form);731}732733unsigned Parser::ParseClangAttributeArgs(734IdentifierInfo *AttrName, SourceLocation AttrNameLoc,735ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,736SourceLocation ScopeLoc, ParsedAttr::Form Form) {737assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");738739ParsedAttr::Kind AttrKind =740ParsedAttr::getParsedKind(AttrName, ScopeName, Form.getSyntax());741742switch (AttrKind) {743default:744return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,745ScopeName, ScopeLoc, Form);746case ParsedAttr::AT_ExternalSourceSymbol:747ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,748ScopeName, ScopeLoc, Form);749break;750case ParsedAttr::AT_Availability:751ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,752ScopeLoc, Form);753break;754case ParsedAttr::AT_ObjCBridgeRelated:755ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,756ScopeName, ScopeLoc, Form);757break;758case ParsedAttr::AT_SwiftNewType:759ParseSwiftNewTypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,760ScopeLoc, Form);761break;762case ParsedAttr::AT_TypeTagForDatatype:763ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc,764ScopeName, ScopeLoc, Form);765break;766767case ParsedAttr::AT_CXXAssume:768ParseCXXAssumeAttributeArg(Attrs, AttrName, AttrNameLoc, EndLoc, Form);769break;770}771return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0;772}773774bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName,775SourceLocation AttrNameLoc,776ParsedAttributes &Attrs) {777unsigned ExistingAttrs = Attrs.size();778779// If the attribute isn't known, we will not attempt to parse any780// arguments.781if (!hasAttribute(AttributeCommonInfo::Syntax::AS_Declspec, nullptr, AttrName,782getTargetInfo(), getLangOpts())) {783// Eat the left paren, then skip to the ending right paren.784ConsumeParen();785SkipUntil(tok::r_paren);786return false;787}788789SourceLocation OpenParenLoc = Tok.getLocation();790791if (AttrName->getName() == "property") {792// The property declspec is more complex in that it can take one or two793// assignment expressions as a parameter, but the lhs of the assignment794// must be named get or put.795796BalancedDelimiterTracker T(*this, tok::l_paren);797T.expectAndConsume(diag::err_expected_lparen_after,798AttrName->getNameStart(), tok::r_paren);799800enum AccessorKind {801AK_Invalid = -1,802AK_Put = 0,803AK_Get = 1 // indices into AccessorNames804};805IdentifierInfo *AccessorNames[] = {nullptr, nullptr};806bool HasInvalidAccessor = false;807808// Parse the accessor specifications.809while (true) {810// Stop if this doesn't look like an accessor spec.811if (!Tok.is(tok::identifier)) {812// If the user wrote a completely empty list, use a special diagnostic.813if (Tok.is(tok::r_paren) && !HasInvalidAccessor &&814AccessorNames[AK_Put] == nullptr &&815AccessorNames[AK_Get] == nullptr) {816Diag(AttrNameLoc, diag::err_ms_property_no_getter_or_putter);817break;818}819820Diag(Tok.getLocation(), diag::err_ms_property_unknown_accessor);821break;822}823824AccessorKind Kind;825SourceLocation KindLoc = Tok.getLocation();826StringRef KindStr = Tok.getIdentifierInfo()->getName();827if (KindStr == "get") {828Kind = AK_Get;829} else if (KindStr == "put") {830Kind = AK_Put;831832// Recover from the common mistake of using 'set' instead of 'put'.833} else if (KindStr == "set") {834Diag(KindLoc, diag::err_ms_property_has_set_accessor)835<< FixItHint::CreateReplacement(KindLoc, "put");836Kind = AK_Put;837838// Handle the mistake of forgetting the accessor kind by skipping839// this accessor.840} else if (NextToken().is(tok::comma) || NextToken().is(tok::r_paren)) {841Diag(KindLoc, diag::err_ms_property_missing_accessor_kind);842ConsumeToken();843HasInvalidAccessor = true;844goto next_property_accessor;845846// Otherwise, complain about the unknown accessor kind.847} else {848Diag(KindLoc, diag::err_ms_property_unknown_accessor);849HasInvalidAccessor = true;850Kind = AK_Invalid;851852// Try to keep parsing unless it doesn't look like an accessor spec.853if (!NextToken().is(tok::equal))854break;855}856857// Consume the identifier.858ConsumeToken();859860// Consume the '='.861if (!TryConsumeToken(tok::equal)) {862Diag(Tok.getLocation(), diag::err_ms_property_expected_equal)863<< KindStr;864break;865}866867// Expect the method name.868if (!Tok.is(tok::identifier)) {869Diag(Tok.getLocation(), diag::err_ms_property_expected_accessor_name);870break;871}872873if (Kind == AK_Invalid) {874// Just drop invalid accessors.875} else if (AccessorNames[Kind] != nullptr) {876// Complain about the repeated accessor, ignore it, and keep parsing.877Diag(KindLoc, diag::err_ms_property_duplicate_accessor) << KindStr;878} else {879AccessorNames[Kind] = Tok.getIdentifierInfo();880}881ConsumeToken();882883next_property_accessor:884// Keep processing accessors until we run out.885if (TryConsumeToken(tok::comma))886continue;887888// If we run into the ')', stop without consuming it.889if (Tok.is(tok::r_paren))890break;891892Diag(Tok.getLocation(), diag::err_ms_property_expected_comma_or_rparen);893break;894}895896// Only add the property attribute if it was well-formed.897if (!HasInvalidAccessor)898Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(),899AccessorNames[AK_Get], AccessorNames[AK_Put],900ParsedAttr::Form::Declspec());901T.skipToEnd();902return !HasInvalidAccessor;903}904905unsigned NumArgs =906ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,907SourceLocation(), ParsedAttr::Form::Declspec());908909// If this attribute's args were parsed, and it was expected to have910// arguments but none were provided, emit a diagnostic.911if (ExistingAttrs < Attrs.size() && Attrs.back().getMaxArgs() && !NumArgs) {912Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName;913return false;914}915return true;916}917918/// [MS] decl-specifier:919/// __declspec ( extended-decl-modifier-seq )920///921/// [MS] extended-decl-modifier-seq:922/// extended-decl-modifier[opt]923/// extended-decl-modifier extended-decl-modifier-seq924void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs) {925assert(getLangOpts().DeclSpecKeyword && "__declspec keyword is not enabled");926assert(Tok.is(tok::kw___declspec) && "Not a declspec!");927928SourceLocation StartLoc = Tok.getLocation();929SourceLocation EndLoc = StartLoc;930931while (Tok.is(tok::kw___declspec)) {932ConsumeToken();933BalancedDelimiterTracker T(*this, tok::l_paren);934if (T.expectAndConsume(diag::err_expected_lparen_after, "__declspec",935tok::r_paren))936return;937938// An empty declspec is perfectly legal and should not warn. Additionally,939// you can specify multiple attributes per declspec.940while (Tok.isNot(tok::r_paren)) {941// Attribute not present.942if (TryConsumeToken(tok::comma))943continue;944945if (Tok.is(tok::code_completion)) {946cutOffParsing();947Actions.CodeCompletion().CodeCompleteAttribute(948AttributeCommonInfo::AS_Declspec);949return;950}951952// We expect either a well-known identifier or a generic string. Anything953// else is a malformed declspec.954bool IsString = Tok.getKind() == tok::string_literal;955if (!IsString && Tok.getKind() != tok::identifier &&956Tok.getKind() != tok::kw_restrict) {957Diag(Tok, diag::err_ms_declspec_type);958T.skipToEnd();959return;960}961962IdentifierInfo *AttrName;963SourceLocation AttrNameLoc;964if (IsString) {965SmallString<8> StrBuffer;966bool Invalid = false;967StringRef Str = PP.getSpelling(Tok, StrBuffer, &Invalid);968if (Invalid) {969T.skipToEnd();970return;971}972AttrName = PP.getIdentifierInfo(Str);973AttrNameLoc = ConsumeStringToken();974} else {975AttrName = Tok.getIdentifierInfo();976AttrNameLoc = ConsumeToken();977}978979bool AttrHandled = false;980981// Parse attribute arguments.982if (Tok.is(tok::l_paren))983AttrHandled = ParseMicrosoftDeclSpecArgs(AttrName, AttrNameLoc, Attrs);984else if (AttrName->getName() == "property")985// The property attribute must have an argument list.986Diag(Tok.getLocation(), diag::err_expected_lparen_after)987<< AttrName->getName();988989if (!AttrHandled)990Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,991ParsedAttr::Form::Declspec());992}993T.consumeClose();994EndLoc = T.getCloseLocation();995}996997Attrs.Range = SourceRange(StartLoc, EndLoc);998}9991000void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) {1001// Treat these like attributes1002while (true) {1003auto Kind = Tok.getKind();1004switch (Kind) {1005case tok::kw___fastcall:1006case tok::kw___stdcall:1007case tok::kw___thiscall:1008case tok::kw___regcall:1009case tok::kw___cdecl:1010case tok::kw___vectorcall:1011case tok::kw___ptr64:1012case tok::kw___w64:1013case tok::kw___ptr32:1014case tok::kw___sptr:1015case tok::kw___uptr: {1016IdentifierInfo *AttrName = Tok.getIdentifierInfo();1017SourceLocation AttrNameLoc = ConsumeToken();1018attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,1019Kind);1020break;1021}1022default:1023return;1024}1025}1026}10271028void Parser::ParseWebAssemblyFuncrefTypeAttribute(ParsedAttributes &attrs) {1029assert(Tok.is(tok::kw___funcref));1030SourceLocation StartLoc = Tok.getLocation();1031if (!getTargetInfo().getTriple().isWasm()) {1032ConsumeToken();1033Diag(StartLoc, diag::err_wasm_funcref_not_wasm);1034return;1035}10361037IdentifierInfo *AttrName = Tok.getIdentifierInfo();1038SourceLocation AttrNameLoc = ConsumeToken();1039attrs.addNew(AttrName, AttrNameLoc, /*ScopeName=*/nullptr,1040/*ScopeLoc=*/SourceLocation{}, /*Args=*/nullptr, /*numArgs=*/0,1041tok::kw___funcref);1042}10431044void Parser::DiagnoseAndSkipExtendedMicrosoftTypeAttributes() {1045SourceLocation StartLoc = Tok.getLocation();1046SourceLocation EndLoc = SkipExtendedMicrosoftTypeAttributes();10471048if (EndLoc.isValid()) {1049SourceRange Range(StartLoc, EndLoc);1050Diag(StartLoc, diag::warn_microsoft_qualifiers_ignored) << Range;1051}1052}10531054SourceLocation Parser::SkipExtendedMicrosoftTypeAttributes() {1055SourceLocation EndLoc;10561057while (true) {1058switch (Tok.getKind()) {1059case tok::kw_const:1060case tok::kw_volatile:1061case tok::kw___fastcall:1062case tok::kw___stdcall:1063case tok::kw___thiscall:1064case tok::kw___cdecl:1065case tok::kw___vectorcall:1066case tok::kw___ptr32:1067case tok::kw___ptr64:1068case tok::kw___w64:1069case tok::kw___unaligned:1070case tok::kw___sptr:1071case tok::kw___uptr:1072EndLoc = ConsumeToken();1073break;1074default:1075return EndLoc;1076}1077}1078}10791080void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) {1081// Treat these like attributes1082while (Tok.is(tok::kw___pascal)) {1083IdentifierInfo *AttrName = Tok.getIdentifierInfo();1084SourceLocation AttrNameLoc = ConsumeToken();1085attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,1086tok::kw___pascal);1087}1088}10891090void Parser::ParseOpenCLKernelAttributes(ParsedAttributes &attrs) {1091// Treat these like attributes1092while (Tok.is(tok::kw___kernel)) {1093IdentifierInfo *AttrName = Tok.getIdentifierInfo();1094SourceLocation AttrNameLoc = ConsumeToken();1095attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,1096tok::kw___kernel);1097}1098}10991100void Parser::ParseCUDAFunctionAttributes(ParsedAttributes &attrs) {1101while (Tok.is(tok::kw___noinline__)) {1102IdentifierInfo *AttrName = Tok.getIdentifierInfo();1103SourceLocation AttrNameLoc = ConsumeToken();1104attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,1105tok::kw___noinline__);1106}1107}11081109void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) {1110IdentifierInfo *AttrName = Tok.getIdentifierInfo();1111SourceLocation AttrNameLoc = Tok.getLocation();1112Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,1113Tok.getKind());1114}11151116bool Parser::isHLSLQualifier(const Token &Tok) const {1117return Tok.is(tok::kw_groupshared);1118}11191120void Parser::ParseHLSLQualifiers(ParsedAttributes &Attrs) {1121IdentifierInfo *AttrName = Tok.getIdentifierInfo();1122auto Kind = Tok.getKind();1123SourceLocation AttrNameLoc = ConsumeToken();1124Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, Kind);1125}11261127void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) {1128// Treat these like attributes, even though they're type specifiers.1129while (true) {1130auto Kind = Tok.getKind();1131switch (Kind) {1132case tok::kw__Nonnull:1133case tok::kw__Nullable:1134case tok::kw__Nullable_result:1135case tok::kw__Null_unspecified: {1136IdentifierInfo *AttrName = Tok.getIdentifierInfo();1137SourceLocation AttrNameLoc = ConsumeToken();1138if (!getLangOpts().ObjC)1139Diag(AttrNameLoc, diag::ext_nullability)1140<< AttrName;1141attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,1142Kind);1143break;1144}1145default:1146return;1147}1148}1149}11501151static bool VersionNumberSeparator(const char Separator) {1152return (Separator == '.' || Separator == '_');1153}11541155/// Parse a version number.1156///1157/// version:1158/// simple-integer1159/// simple-integer '.' simple-integer1160/// simple-integer '_' simple-integer1161/// simple-integer '.' simple-integer '.' simple-integer1162/// simple-integer '_' simple-integer '_' simple-integer1163VersionTuple Parser::ParseVersionTuple(SourceRange &Range) {1164Range = SourceRange(Tok.getLocation(), Tok.getEndLoc());11651166if (!Tok.is(tok::numeric_constant)) {1167Diag(Tok, diag::err_expected_version);1168SkipUntil(tok::comma, tok::r_paren,1169StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);1170return VersionTuple();1171}11721173// Parse the major (and possibly minor and subminor) versions, which1174// are stored in the numeric constant. We utilize a quirk of the1175// lexer, which is that it handles something like 1.2.3 as a single1176// numeric constant, rather than two separate tokens.1177SmallString<512> Buffer;1178Buffer.resize(Tok.getLength()+1);1179const char *ThisTokBegin = &Buffer[0];11801181// Get the spelling of the token, which eliminates trigraphs, etc.1182bool Invalid = false;1183unsigned ActualLength = PP.getSpelling(Tok, ThisTokBegin, &Invalid);1184if (Invalid)1185return VersionTuple();11861187// Parse the major version.1188unsigned AfterMajor = 0;1189unsigned Major = 0;1190while (AfterMajor < ActualLength && isDigit(ThisTokBegin[AfterMajor])) {1191Major = Major * 10 + ThisTokBegin[AfterMajor] - '0';1192++AfterMajor;1193}11941195if (AfterMajor == 0) {1196Diag(Tok, diag::err_expected_version);1197SkipUntil(tok::comma, tok::r_paren,1198StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);1199return VersionTuple();1200}12011202if (AfterMajor == ActualLength) {1203ConsumeToken();12041205// We only had a single version component.1206if (Major == 0) {1207Diag(Tok, diag::err_zero_version);1208return VersionTuple();1209}12101211return VersionTuple(Major);1212}12131214const char AfterMajorSeparator = ThisTokBegin[AfterMajor];1215if (!VersionNumberSeparator(AfterMajorSeparator)1216|| (AfterMajor + 1 == ActualLength)) {1217Diag(Tok, diag::err_expected_version);1218SkipUntil(tok::comma, tok::r_paren,1219StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);1220return VersionTuple();1221}12221223// Parse the minor version.1224unsigned AfterMinor = AfterMajor + 1;1225unsigned Minor = 0;1226while (AfterMinor < ActualLength && isDigit(ThisTokBegin[AfterMinor])) {1227Minor = Minor * 10 + ThisTokBegin[AfterMinor] - '0';1228++AfterMinor;1229}12301231if (AfterMinor == ActualLength) {1232ConsumeToken();12331234// We had major.minor.1235if (Major == 0 && Minor == 0) {1236Diag(Tok, diag::err_zero_version);1237return VersionTuple();1238}12391240return VersionTuple(Major, Minor);1241}12421243const char AfterMinorSeparator = ThisTokBegin[AfterMinor];1244// If what follows is not a '.' or '_', we have a problem.1245if (!VersionNumberSeparator(AfterMinorSeparator)) {1246Diag(Tok, diag::err_expected_version);1247SkipUntil(tok::comma, tok::r_paren,1248StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);1249return VersionTuple();1250}12511252// Warn if separators, be it '.' or '_', do not match.1253if (AfterMajorSeparator != AfterMinorSeparator)1254Diag(Tok, diag::warn_expected_consistent_version_separator);12551256// Parse the subminor version.1257unsigned AfterSubminor = AfterMinor + 1;1258unsigned Subminor = 0;1259while (AfterSubminor < ActualLength && isDigit(ThisTokBegin[AfterSubminor])) {1260Subminor = Subminor * 10 + ThisTokBegin[AfterSubminor] - '0';1261++AfterSubminor;1262}12631264if (AfterSubminor != ActualLength) {1265Diag(Tok, diag::err_expected_version);1266SkipUntil(tok::comma, tok::r_paren,1267StopAtSemi | StopBeforeMatch | StopAtCodeCompletion);1268return VersionTuple();1269}1270ConsumeToken();1271return VersionTuple(Major, Minor, Subminor);1272}12731274/// Parse the contents of the "availability" attribute.1275///1276/// availability-attribute:1277/// 'availability' '(' platform ',' opt-strict version-arg-list,1278/// opt-replacement, opt-message')'1279///1280/// platform:1281/// identifier1282///1283/// opt-strict:1284/// 'strict' ','1285///1286/// version-arg-list:1287/// version-arg1288/// version-arg ',' version-arg-list1289///1290/// version-arg:1291/// 'introduced' '=' version1292/// 'deprecated' '=' version1293/// 'obsoleted' = version1294/// 'unavailable'1295/// opt-replacement:1296/// 'replacement' '=' <string>1297/// opt-message:1298/// 'message' '=' <string>1299void Parser::ParseAvailabilityAttribute(1300IdentifierInfo &Availability, SourceLocation AvailabilityLoc,1301ParsedAttributes &attrs, SourceLocation *endLoc, IdentifierInfo *ScopeName,1302SourceLocation ScopeLoc, ParsedAttr::Form Form) {1303enum { Introduced, Deprecated, Obsoleted, Unknown };1304AvailabilityChange Changes[Unknown];1305ExprResult MessageExpr, ReplacementExpr;1306IdentifierLoc *EnvironmentLoc = nullptr;13071308// Opening '('.1309BalancedDelimiterTracker T(*this, tok::l_paren);1310if (T.consumeOpen()) {1311Diag(Tok, diag::err_expected) << tok::l_paren;1312return;1313}13141315// Parse the platform name.1316if (Tok.isNot(tok::identifier)) {1317Diag(Tok, diag::err_availability_expected_platform);1318SkipUntil(tok::r_paren, StopAtSemi);1319return;1320}1321IdentifierLoc *Platform = ParseIdentifierLoc();1322if (const IdentifierInfo *const Ident = Platform->Ident) {1323// Disallow xrOS for availability attributes.1324if (Ident->getName().contains("xrOS") || Ident->getName().contains("xros"))1325Diag(Platform->Loc, diag::warn_availability_unknown_platform) << Ident;1326// Canonicalize platform name from "macosx" to "macos".1327else if (Ident->getName() == "macosx")1328Platform->Ident = PP.getIdentifierInfo("macos");1329// Canonicalize platform name from "macosx_app_extension" to1330// "macos_app_extension".1331else if (Ident->getName() == "macosx_app_extension")1332Platform->Ident = PP.getIdentifierInfo("macos_app_extension");1333else1334Platform->Ident = PP.getIdentifierInfo(1335AvailabilityAttr::canonicalizePlatformName(Ident->getName()));1336}13371338// Parse the ',' following the platform name.1339if (ExpectAndConsume(tok::comma)) {1340SkipUntil(tok::r_paren, StopAtSemi);1341return;1342}13431344// If we haven't grabbed the pointers for the identifiers1345// "introduced", "deprecated", and "obsoleted", do so now.1346if (!Ident_introduced) {1347Ident_introduced = PP.getIdentifierInfo("introduced");1348Ident_deprecated = PP.getIdentifierInfo("deprecated");1349Ident_obsoleted = PP.getIdentifierInfo("obsoleted");1350Ident_unavailable = PP.getIdentifierInfo("unavailable");1351Ident_message = PP.getIdentifierInfo("message");1352Ident_strict = PP.getIdentifierInfo("strict");1353Ident_replacement = PP.getIdentifierInfo("replacement");1354Ident_environment = PP.getIdentifierInfo("environment");1355}13561357// Parse the optional "strict", the optional "replacement" and the set of1358// introductions/deprecations/removals.1359SourceLocation UnavailableLoc, StrictLoc;1360do {1361if (Tok.isNot(tok::identifier)) {1362Diag(Tok, diag::err_availability_expected_change);1363SkipUntil(tok::r_paren, StopAtSemi);1364return;1365}1366IdentifierInfo *Keyword = Tok.getIdentifierInfo();1367SourceLocation KeywordLoc = ConsumeToken();13681369if (Keyword == Ident_strict) {1370if (StrictLoc.isValid()) {1371Diag(KeywordLoc, diag::err_availability_redundant)1372<< Keyword << SourceRange(StrictLoc);1373}1374StrictLoc = KeywordLoc;1375continue;1376}13771378if (Keyword == Ident_unavailable) {1379if (UnavailableLoc.isValid()) {1380Diag(KeywordLoc, diag::err_availability_redundant)1381<< Keyword << SourceRange(UnavailableLoc);1382}1383UnavailableLoc = KeywordLoc;1384continue;1385}13861387if (Keyword == Ident_deprecated && Platform->Ident &&1388Platform->Ident->isStr("swift")) {1389// For swift, we deprecate for all versions.1390if (Changes[Deprecated].KeywordLoc.isValid()) {1391Diag(KeywordLoc, diag::err_availability_redundant)1392<< Keyword1393<< SourceRange(Changes[Deprecated].KeywordLoc);1394}13951396Changes[Deprecated].KeywordLoc = KeywordLoc;1397// Use a fake version here.1398Changes[Deprecated].Version = VersionTuple(1);1399continue;1400}14011402if (Keyword == Ident_environment) {1403if (EnvironmentLoc != nullptr) {1404Diag(KeywordLoc, diag::err_availability_redundant)1405<< Keyword << SourceRange(EnvironmentLoc->Loc);1406}1407}14081409if (Tok.isNot(tok::equal)) {1410Diag(Tok, diag::err_expected_after) << Keyword << tok::equal;1411SkipUntil(tok::r_paren, StopAtSemi);1412return;1413}1414ConsumeToken();1415if (Keyword == Ident_message || Keyword == Ident_replacement) {1416if (!isTokenStringLiteral()) {1417Diag(Tok, diag::err_expected_string_literal)1418<< /*Source='availability attribute'*/2;1419SkipUntil(tok::r_paren, StopAtSemi);1420return;1421}1422if (Keyword == Ident_message) {1423MessageExpr = ParseUnevaluatedStringLiteralExpression();1424break;1425} else {1426ReplacementExpr = ParseUnevaluatedStringLiteralExpression();1427continue;1428}1429}1430if (Keyword == Ident_environment) {1431if (Tok.isNot(tok::identifier)) {1432Diag(Tok, diag::err_availability_expected_environment);1433SkipUntil(tok::r_paren, StopAtSemi);1434return;1435}1436EnvironmentLoc = ParseIdentifierLoc();1437continue;1438}14391440// Special handling of 'NA' only when applied to introduced or1441// deprecated.1442if ((Keyword == Ident_introduced || Keyword == Ident_deprecated) &&1443Tok.is(tok::identifier)) {1444IdentifierInfo *NA = Tok.getIdentifierInfo();1445if (NA->getName() == "NA") {1446ConsumeToken();1447if (Keyword == Ident_introduced)1448UnavailableLoc = KeywordLoc;1449continue;1450}1451}14521453SourceRange VersionRange;1454VersionTuple Version = ParseVersionTuple(VersionRange);14551456if (Version.empty()) {1457SkipUntil(tok::r_paren, StopAtSemi);1458return;1459}14601461unsigned Index;1462if (Keyword == Ident_introduced)1463Index = Introduced;1464else if (Keyword == Ident_deprecated)1465Index = Deprecated;1466else if (Keyword == Ident_obsoleted)1467Index = Obsoleted;1468else1469Index = Unknown;14701471if (Index < Unknown) {1472if (!Changes[Index].KeywordLoc.isInvalid()) {1473Diag(KeywordLoc, diag::err_availability_redundant)1474<< Keyword1475<< SourceRange(Changes[Index].KeywordLoc,1476Changes[Index].VersionRange.getEnd());1477}14781479Changes[Index].KeywordLoc = KeywordLoc;1480Changes[Index].Version = Version;1481Changes[Index].VersionRange = VersionRange;1482} else {1483Diag(KeywordLoc, diag::err_availability_unknown_change)1484<< Keyword << VersionRange;1485}14861487} while (TryConsumeToken(tok::comma));14881489// Closing ')'.1490if (T.consumeClose())1491return;14921493if (endLoc)1494*endLoc = T.getCloseLocation();14951496// The 'unavailable' availability cannot be combined with any other1497// availability changes. Make sure that hasn't happened.1498if (UnavailableLoc.isValid()) {1499bool Complained = false;1500for (unsigned Index = Introduced; Index != Unknown; ++Index) {1501if (Changes[Index].KeywordLoc.isValid()) {1502if (!Complained) {1503Diag(UnavailableLoc, diag::warn_availability_and_unavailable)1504<< SourceRange(Changes[Index].KeywordLoc,1505Changes[Index].VersionRange.getEnd());1506Complained = true;1507}15081509// Clear out the availability.1510Changes[Index] = AvailabilityChange();1511}1512}1513}15141515// Record this attribute1516attrs.addNew(&Availability,1517SourceRange(AvailabilityLoc, T.getCloseLocation()), ScopeName,1518ScopeLoc, Platform, Changes[Introduced], Changes[Deprecated],1519Changes[Obsoleted], UnavailableLoc, MessageExpr.get(), Form,1520StrictLoc, ReplacementExpr.get(), EnvironmentLoc);1521}15221523/// Parse the contents of the "external_source_symbol" attribute.1524///1525/// external-source-symbol-attribute:1526/// 'external_source_symbol' '(' keyword-arg-list ')'1527///1528/// keyword-arg-list:1529/// keyword-arg1530/// keyword-arg ',' keyword-arg-list1531///1532/// keyword-arg:1533/// 'language' '=' <string>1534/// 'defined_in' '=' <string>1535/// 'USR' '=' <string>1536/// 'generated_declaration'1537void Parser::ParseExternalSourceSymbolAttribute(1538IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc,1539ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,1540SourceLocation ScopeLoc, ParsedAttr::Form Form) {1541// Opening '('.1542BalancedDelimiterTracker T(*this, tok::l_paren);1543if (T.expectAndConsume())1544return;15451546// Initialize the pointers for the keyword identifiers when required.1547if (!Ident_language) {1548Ident_language = PP.getIdentifierInfo("language");1549Ident_defined_in = PP.getIdentifierInfo("defined_in");1550Ident_generated_declaration = PP.getIdentifierInfo("generated_declaration");1551Ident_USR = PP.getIdentifierInfo("USR");1552}15531554ExprResult Language;1555bool HasLanguage = false;1556ExprResult DefinedInExpr;1557bool HasDefinedIn = false;1558IdentifierLoc *GeneratedDeclaration = nullptr;1559ExprResult USR;1560bool HasUSR = false;15611562// Parse the language/defined_in/generated_declaration keywords1563do {1564if (Tok.isNot(tok::identifier)) {1565Diag(Tok, diag::err_external_source_symbol_expected_keyword);1566SkipUntil(tok::r_paren, StopAtSemi);1567return;1568}15691570SourceLocation KeywordLoc = Tok.getLocation();1571IdentifierInfo *Keyword = Tok.getIdentifierInfo();1572if (Keyword == Ident_generated_declaration) {1573if (GeneratedDeclaration) {1574Diag(Tok, diag::err_external_source_symbol_duplicate_clause) << Keyword;1575SkipUntil(tok::r_paren, StopAtSemi);1576return;1577}1578GeneratedDeclaration = ParseIdentifierLoc();1579continue;1580}15811582if (Keyword != Ident_language && Keyword != Ident_defined_in &&1583Keyword != Ident_USR) {1584Diag(Tok, diag::err_external_source_symbol_expected_keyword);1585SkipUntil(tok::r_paren, StopAtSemi);1586return;1587}15881589ConsumeToken();1590if (ExpectAndConsume(tok::equal, diag::err_expected_after,1591Keyword->getName())) {1592SkipUntil(tok::r_paren, StopAtSemi);1593return;1594}15951596bool HadLanguage = HasLanguage, HadDefinedIn = HasDefinedIn,1597HadUSR = HasUSR;1598if (Keyword == Ident_language)1599HasLanguage = true;1600else if (Keyword == Ident_USR)1601HasUSR = true;1602else1603HasDefinedIn = true;16041605if (!isTokenStringLiteral()) {1606Diag(Tok, diag::err_expected_string_literal)1607<< /*Source='external_source_symbol attribute'*/ 31608<< /*language | source container | USR*/ (1609Keyword == Ident_language1610? 01611: (Keyword == Ident_defined_in ? 1 : 2));1612SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);1613continue;1614}1615if (Keyword == Ident_language) {1616if (HadLanguage) {1617Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)1618<< Keyword;1619ParseUnevaluatedStringLiteralExpression();1620continue;1621}1622Language = ParseUnevaluatedStringLiteralExpression();1623} else if (Keyword == Ident_USR) {1624if (HadUSR) {1625Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)1626<< Keyword;1627ParseUnevaluatedStringLiteralExpression();1628continue;1629}1630USR = ParseUnevaluatedStringLiteralExpression();1631} else {1632assert(Keyword == Ident_defined_in && "Invalid clause keyword!");1633if (HadDefinedIn) {1634Diag(KeywordLoc, diag::err_external_source_symbol_duplicate_clause)1635<< Keyword;1636ParseUnevaluatedStringLiteralExpression();1637continue;1638}1639DefinedInExpr = ParseUnevaluatedStringLiteralExpression();1640}1641} while (TryConsumeToken(tok::comma));16421643// Closing ')'.1644if (T.consumeClose())1645return;1646if (EndLoc)1647*EndLoc = T.getCloseLocation();16481649ArgsUnion Args[] = {Language.get(), DefinedInExpr.get(), GeneratedDeclaration,1650USR.get()};1651Attrs.addNew(&ExternalSourceSymbol, SourceRange(Loc, T.getCloseLocation()),1652ScopeName, ScopeLoc, Args, std::size(Args), Form);1653}16541655/// Parse the contents of the "objc_bridge_related" attribute.1656/// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')'1657/// related_class:1658/// Identifier1659///1660/// opt-class_method:1661/// Identifier: | <empty>1662///1663/// opt-instance_method:1664/// Identifier | <empty>1665///1666void Parser::ParseObjCBridgeRelatedAttribute(1667IdentifierInfo &ObjCBridgeRelated, SourceLocation ObjCBridgeRelatedLoc,1668ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,1669SourceLocation ScopeLoc, ParsedAttr::Form Form) {1670// Opening '('.1671BalancedDelimiterTracker T(*this, tok::l_paren);1672if (T.consumeOpen()) {1673Diag(Tok, diag::err_expected) << tok::l_paren;1674return;1675}16761677// Parse the related class name.1678if (Tok.isNot(tok::identifier)) {1679Diag(Tok, diag::err_objcbridge_related_expected_related_class);1680SkipUntil(tok::r_paren, StopAtSemi);1681return;1682}1683IdentifierLoc *RelatedClass = ParseIdentifierLoc();1684if (ExpectAndConsume(tok::comma)) {1685SkipUntil(tok::r_paren, StopAtSemi);1686return;1687}16881689// Parse class method name. It's non-optional in the sense that a trailing1690// comma is required, but it can be the empty string, and then we record a1691// nullptr.1692IdentifierLoc *ClassMethod = nullptr;1693if (Tok.is(tok::identifier)) {1694ClassMethod = ParseIdentifierLoc();1695if (!TryConsumeToken(tok::colon)) {1696Diag(Tok, diag::err_objcbridge_related_selector_name);1697SkipUntil(tok::r_paren, StopAtSemi);1698return;1699}1700}1701if (!TryConsumeToken(tok::comma)) {1702if (Tok.is(tok::colon))1703Diag(Tok, diag::err_objcbridge_related_selector_name);1704else1705Diag(Tok, diag::err_expected) << tok::comma;1706SkipUntil(tok::r_paren, StopAtSemi);1707return;1708}17091710// Parse instance method name. Also non-optional but empty string is1711// permitted.1712IdentifierLoc *InstanceMethod = nullptr;1713if (Tok.is(tok::identifier))1714InstanceMethod = ParseIdentifierLoc();1715else if (Tok.isNot(tok::r_paren)) {1716Diag(Tok, diag::err_expected) << tok::r_paren;1717SkipUntil(tok::r_paren, StopAtSemi);1718return;1719}17201721// Closing ')'.1722if (T.consumeClose())1723return;17241725if (EndLoc)1726*EndLoc = T.getCloseLocation();17271728// Record this attribute1729Attrs.addNew(&ObjCBridgeRelated,1730SourceRange(ObjCBridgeRelatedLoc, T.getCloseLocation()),1731ScopeName, ScopeLoc, RelatedClass, ClassMethod, InstanceMethod,1732Form);1733}17341735void Parser::ParseSwiftNewTypeAttribute(1736IdentifierInfo &AttrName, SourceLocation AttrNameLoc,1737ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,1738SourceLocation ScopeLoc, ParsedAttr::Form Form) {1739BalancedDelimiterTracker T(*this, tok::l_paren);17401741// Opening '('1742if (T.consumeOpen()) {1743Diag(Tok, diag::err_expected) << tok::l_paren;1744return;1745}17461747if (Tok.is(tok::r_paren)) {1748Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);1749T.consumeClose();1750return;1751}1752if (Tok.isNot(tok::kw_struct) && Tok.isNot(tok::kw_enum)) {1753Diag(Tok, diag::warn_attribute_type_not_supported)1754<< &AttrName << Tok.getIdentifierInfo();1755if (!isTokenSpecial())1756ConsumeToken();1757T.consumeClose();1758return;1759}17601761auto *SwiftType = IdentifierLoc::create(Actions.Context, Tok.getLocation(),1762Tok.getIdentifierInfo());1763ConsumeToken();17641765// Closing ')'1766if (T.consumeClose())1767return;1768if (EndLoc)1769*EndLoc = T.getCloseLocation();17701771ArgsUnion Args[] = {SwiftType};1772Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, T.getCloseLocation()),1773ScopeName, ScopeLoc, Args, std::size(Args), Form);1774}17751776void Parser::ParseTypeTagForDatatypeAttribute(1777IdentifierInfo &AttrName, SourceLocation AttrNameLoc,1778ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName,1779SourceLocation ScopeLoc, ParsedAttr::Form Form) {1780assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");17811782BalancedDelimiterTracker T(*this, tok::l_paren);1783T.consumeOpen();17841785if (Tok.isNot(tok::identifier)) {1786Diag(Tok, diag::err_expected) << tok::identifier;1787T.skipToEnd();1788return;1789}1790IdentifierLoc *ArgumentKind = ParseIdentifierLoc();17911792if (ExpectAndConsume(tok::comma)) {1793T.skipToEnd();1794return;1795}17961797SourceRange MatchingCTypeRange;1798TypeResult MatchingCType = ParseTypeName(&MatchingCTypeRange);1799if (MatchingCType.isInvalid()) {1800T.skipToEnd();1801return;1802}18031804bool LayoutCompatible = false;1805bool MustBeNull = false;1806while (TryConsumeToken(tok::comma)) {1807if (Tok.isNot(tok::identifier)) {1808Diag(Tok, diag::err_expected) << tok::identifier;1809T.skipToEnd();1810return;1811}1812IdentifierInfo *Flag = Tok.getIdentifierInfo();1813if (Flag->isStr("layout_compatible"))1814LayoutCompatible = true;1815else if (Flag->isStr("must_be_null"))1816MustBeNull = true;1817else {1818Diag(Tok, diag::err_type_safety_unknown_flag) << Flag;1819T.skipToEnd();1820return;1821}1822ConsumeToken(); // consume flag1823}18241825if (!T.consumeClose()) {1826Attrs.addNewTypeTagForDatatype(&AttrName, AttrNameLoc, ScopeName, ScopeLoc,1827ArgumentKind, MatchingCType.get(),1828LayoutCompatible, MustBeNull, Form);1829}18301831if (EndLoc)1832*EndLoc = T.getCloseLocation();1833}18341835/// DiagnoseProhibitedCXX11Attribute - We have found the opening square brackets1836/// of a C++11 attribute-specifier in a location where an attribute is not1837/// permitted. By C++11 [dcl.attr.grammar]p6, this is ill-formed. Diagnose this1838/// situation.1839///1840/// \return \c true if we skipped an attribute-like chunk of tokens, \c false if1841/// this doesn't appear to actually be an attribute-specifier, and the caller1842/// should try to parse it.1843bool Parser::DiagnoseProhibitedCXX11Attribute() {1844assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square));18451846switch (isCXX11AttributeSpecifier(/*Disambiguate*/true)) {1847case CAK_NotAttributeSpecifier:1848// No diagnostic: we're in Obj-C++11 and this is not actually an attribute.1849return false;18501851case CAK_InvalidAttributeSpecifier:1852Diag(Tok.getLocation(), diag::err_l_square_l_square_not_attribute);1853return false;18541855case CAK_AttributeSpecifier:1856// Parse and discard the attributes.1857SourceLocation BeginLoc = ConsumeBracket();1858ConsumeBracket();1859SkipUntil(tok::r_square);1860assert(Tok.is(tok::r_square) && "isCXX11AttributeSpecifier lied");1861SourceLocation EndLoc = ConsumeBracket();1862Diag(BeginLoc, diag::err_attributes_not_allowed)1863<< SourceRange(BeginLoc, EndLoc);1864return true;1865}1866llvm_unreachable("All cases handled above.");1867}18681869/// We have found the opening square brackets of a C++111870/// attribute-specifier in a location where an attribute is not permitted, but1871/// we know where the attributes ought to be written. Parse them anyway, and1872/// provide a fixit moving them to the right place.1873void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributes &Attrs,1874SourceLocation CorrectLocation) {1875assert((Tok.is(tok::l_square) && NextToken().is(tok::l_square)) ||1876Tok.is(tok::kw_alignas) || Tok.isRegularKeywordAttribute());18771878// Consume the attributes.1879auto Keyword =1880Tok.isRegularKeywordAttribute() ? Tok.getIdentifierInfo() : nullptr;1881SourceLocation Loc = Tok.getLocation();1882ParseCXX11Attributes(Attrs);1883CharSourceRange AttrRange(SourceRange(Loc, Attrs.Range.getEnd()), true);1884// FIXME: use err_attributes_misplaced1885(Keyword ? Diag(Loc, diag::err_keyword_not_allowed) << Keyword1886: Diag(Loc, diag::err_attributes_not_allowed))1887<< FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)1888<< FixItHint::CreateRemoval(AttrRange);1889}18901891void Parser::DiagnoseProhibitedAttributes(1892const ParsedAttributesView &Attrs, const SourceLocation CorrectLocation) {1893auto *FirstAttr = Attrs.empty() ? nullptr : &Attrs.front();1894if (CorrectLocation.isValid()) {1895CharSourceRange AttrRange(Attrs.Range, true);1896(FirstAttr && FirstAttr->isRegularKeywordAttribute()1897? Diag(CorrectLocation, diag::err_keyword_misplaced) << FirstAttr1898: Diag(CorrectLocation, diag::err_attributes_misplaced))1899<< FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange)1900<< FixItHint::CreateRemoval(AttrRange);1901} else {1902const SourceRange &Range = Attrs.Range;1903(FirstAttr && FirstAttr->isRegularKeywordAttribute()1904? Diag(Range.getBegin(), diag::err_keyword_not_allowed) << FirstAttr1905: Diag(Range.getBegin(), diag::err_attributes_not_allowed))1906<< Range;1907}1908}19091910void Parser::ProhibitCXX11Attributes(ParsedAttributes &Attrs,1911unsigned AttrDiagID,1912unsigned KeywordDiagID,1913bool DiagnoseEmptyAttrs,1914bool WarnOnUnknownAttrs) {19151916if (DiagnoseEmptyAttrs && Attrs.empty() && Attrs.Range.isValid()) {1917// An attribute list has been parsed, but it was empty.1918// This is the case for [[]].1919const auto &LangOpts = getLangOpts();1920auto &SM = PP.getSourceManager();1921Token FirstLSquare;1922Lexer::getRawToken(Attrs.Range.getBegin(), FirstLSquare, SM, LangOpts);19231924if (FirstLSquare.is(tok::l_square)) {1925std::optional<Token> SecondLSquare =1926Lexer::findNextToken(FirstLSquare.getLocation(), SM, LangOpts);19271928if (SecondLSquare && SecondLSquare->is(tok::l_square)) {1929// The attribute range starts with [[, but is empty. So this must1930// be [[]], which we are supposed to diagnose because1931// DiagnoseEmptyAttrs is true.1932Diag(Attrs.Range.getBegin(), AttrDiagID) << Attrs.Range;1933return;1934}1935}1936}19371938for (const ParsedAttr &AL : Attrs) {1939if (AL.isRegularKeywordAttribute()) {1940Diag(AL.getLoc(), KeywordDiagID) << AL;1941AL.setInvalid();1942continue;1943}1944if (!AL.isStandardAttributeSyntax())1945continue;1946if (AL.getKind() == ParsedAttr::UnknownAttribute) {1947if (WarnOnUnknownAttrs)1948Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored)1949<< AL << AL.getRange();1950} else {1951Diag(AL.getLoc(), AttrDiagID) << AL;1952AL.setInvalid();1953}1954}1955}19561957void Parser::DiagnoseCXX11AttributeExtension(ParsedAttributes &Attrs) {1958for (const ParsedAttr &PA : Attrs) {1959if (PA.isStandardAttributeSyntax() || PA.isRegularKeywordAttribute())1960Diag(PA.getLoc(), diag::ext_cxx11_attr_placement)1961<< PA << PA.isRegularKeywordAttribute() << PA.getRange();1962}1963}19641965// Usually, `__attribute__((attrib)) class Foo {} var` means that attribute1966// applies to var, not the type Foo.1967// As an exception to the rule, __declspec(align(...)) before the1968// class-key affects the type instead of the variable.1969// Also, Microsoft-style [attributes] seem to affect the type instead of the1970// variable.1971// This function moves attributes that should apply to the type off DS to Attrs.1972void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributes &Attrs,1973DeclSpec &DS, TagUseKind TUK) {1974if (TUK == TagUseKind::Reference)1975return;19761977llvm::SmallVector<ParsedAttr *, 1> ToBeMoved;19781979for (ParsedAttr &AL : DS.getAttributes()) {1980if ((AL.getKind() == ParsedAttr::AT_Aligned &&1981AL.isDeclspecAttribute()) ||1982AL.isMicrosoftAttribute())1983ToBeMoved.push_back(&AL);1984}19851986for (ParsedAttr *AL : ToBeMoved) {1987DS.getAttributes().remove(AL);1988Attrs.addAtEnd(AL);1989}1990}19911992/// ParseDeclaration - Parse a full 'declaration', which consists of1993/// declaration-specifiers, some number of declarators, and a semicolon.1994/// 'Context' should be a DeclaratorContext value. This returns the1995/// location of the semicolon in DeclEnd.1996///1997/// declaration: [C99 6.7]1998/// block-declaration ->1999/// simple-declaration2000/// others [FIXME]2001/// [C++] template-declaration2002/// [C++] namespace-definition2003/// [C++] using-directive2004/// [C++] using-declaration2005/// [C++11/C11] static_assert-declaration2006/// others... [FIXME]2007///2008Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,2009SourceLocation &DeclEnd,2010ParsedAttributes &DeclAttrs,2011ParsedAttributes &DeclSpecAttrs,2012SourceLocation *DeclSpecStart) {2013ParenBraceBracketBalancer BalancerRAIIObj(*this);2014// Must temporarily exit the objective-c container scope for2015// parsing c none objective-c decls.2016ObjCDeclContextSwitch ObjCDC(*this);20172018Decl *SingleDecl = nullptr;2019switch (Tok.getKind()) {2020case tok::kw_template:2021case tok::kw_export:2022ProhibitAttributes(DeclAttrs);2023ProhibitAttributes(DeclSpecAttrs);2024return ParseDeclarationStartingWithTemplate(Context, DeclEnd, DeclAttrs);2025case tok::kw_inline:2026// Could be the start of an inline namespace. Allowed as an ext in C++03.2027if (getLangOpts().CPlusPlus && NextToken().is(tok::kw_namespace)) {2028ProhibitAttributes(DeclAttrs);2029ProhibitAttributes(DeclSpecAttrs);2030SourceLocation InlineLoc = ConsumeToken();2031return ParseNamespace(Context, DeclEnd, InlineLoc);2032}2033return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs,2034true, nullptr, DeclSpecStart);20352036case tok::kw_cbuffer:2037case tok::kw_tbuffer:2038SingleDecl = ParseHLSLBuffer(DeclEnd);2039break;2040case tok::kw_namespace:2041ProhibitAttributes(DeclAttrs);2042ProhibitAttributes(DeclSpecAttrs);2043return ParseNamespace(Context, DeclEnd);2044case tok::kw_using: {2045ParsedAttributes Attrs(AttrFactory);2046takeAndConcatenateAttrs(DeclAttrs, DeclSpecAttrs, Attrs);2047return ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(),2048DeclEnd, Attrs);2049}2050case tok::kw_static_assert:2051case tok::kw__Static_assert:2052ProhibitAttributes(DeclAttrs);2053ProhibitAttributes(DeclSpecAttrs);2054SingleDecl = ParseStaticAssertDeclaration(DeclEnd);2055break;2056default:2057return ParseSimpleDeclaration(Context, DeclEnd, DeclAttrs, DeclSpecAttrs,2058true, nullptr, DeclSpecStart);2059}20602061// This routine returns a DeclGroup, if the thing we parsed only contains a2062// single decl, convert it now.2063return Actions.ConvertDeclToDeclGroup(SingleDecl);2064}20652066/// simple-declaration: [C99 6.7: declaration] [C++ 7p1: dcl.dcl]2067/// declaration-specifiers init-declarator-list[opt] ';'2068/// [C++11] attribute-specifier-seq decl-specifier-seq[opt]2069/// init-declarator-list ';'2070///[C90/C++]init-declarator-list ';' [TODO]2071/// [OMP] threadprivate-directive2072/// [OMP] allocate-directive [TODO]2073///2074/// for-range-declaration: [C++11 6.5p1: stmt.ranged]2075/// attribute-specifier-seq[opt] type-specifier-seq declarator2076///2077/// If RequireSemi is false, this does not check for a ';' at the end of the2078/// declaration. If it is true, it checks for and eats it.2079///2080/// If FRI is non-null, we might be parsing a for-range-declaration instead2081/// of a simple-declaration. If we find that we are, we also parse the2082/// for-range-initializer, and place it here.2083///2084/// DeclSpecStart is used when decl-specifiers are parsed before parsing2085/// the Declaration. The SourceLocation for this Decl is set to2086/// DeclSpecStart if DeclSpecStart is non-null.2087Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(2088DeclaratorContext Context, SourceLocation &DeclEnd,2089ParsedAttributes &DeclAttrs, ParsedAttributes &DeclSpecAttrs,2090bool RequireSemi, ForRangeInit *FRI, SourceLocation *DeclSpecStart) {2091// Need to retain these for diagnostics before we add them to the DeclSepc.2092ParsedAttributesView OriginalDeclSpecAttrs;2093OriginalDeclSpecAttrs.addAll(DeclSpecAttrs.begin(), DeclSpecAttrs.end());2094OriginalDeclSpecAttrs.Range = DeclSpecAttrs.Range;20952096// Parse the common declaration-specifiers piece.2097ParsingDeclSpec DS(*this);2098DS.takeAttributesFrom(DeclSpecAttrs);20992100ParsedTemplateInfo TemplateInfo;2101DeclSpecContext DSContext = getDeclSpecContextFromDeclaratorContext(Context);2102ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none, DSContext);21032104// If we had a free-standing type definition with a missing semicolon, we2105// may get this far before the problem becomes obvious.2106if (DS.hasTagDefinition() &&2107DiagnoseMissingSemiAfterTagDefinition(DS, AS_none, DSContext))2108return nullptr;21092110// C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };"2111// declaration-specifiers init-declarator-list[opt] ';'2112if (Tok.is(tok::semi)) {2113ProhibitAttributes(DeclAttrs);2114DeclEnd = Tok.getLocation();2115if (RequireSemi) ConsumeToken();2116RecordDecl *AnonRecord = nullptr;2117Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(2118getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);2119Actions.ActOnDefinedDeclarationSpecifier(TheDecl);2120DS.complete(TheDecl);2121if (AnonRecord) {2122Decl* decls[] = {AnonRecord, TheDecl};2123return Actions.BuildDeclaratorGroup(decls);2124}2125return Actions.ConvertDeclToDeclGroup(TheDecl);2126}21272128if (DS.hasTagDefinition())2129Actions.ActOnDefinedDeclarationSpecifier(DS.getRepAsDecl());21302131if (DeclSpecStart)2132DS.SetRangeStart(*DeclSpecStart);21332134return ParseDeclGroup(DS, Context, DeclAttrs, TemplateInfo, &DeclEnd, FRI);2135}21362137/// Returns true if this might be the start of a declarator, or a common typo2138/// for a declarator.2139bool Parser::MightBeDeclarator(DeclaratorContext Context) {2140switch (Tok.getKind()) {2141case tok::annot_cxxscope:2142case tok::annot_template_id:2143case tok::caret:2144case tok::code_completion:2145case tok::coloncolon:2146case tok::ellipsis:2147case tok::kw___attribute:2148case tok::kw_operator:2149case tok::l_paren:2150case tok::star:2151return true;21522153case tok::amp:2154case tok::ampamp:2155return getLangOpts().CPlusPlus;21562157case tok::l_square: // Might be an attribute on an unnamed bit-field.2158return Context == DeclaratorContext::Member && getLangOpts().CPlusPlus11 &&2159NextToken().is(tok::l_square);21602161case tok::colon: // Might be a typo for '::' or an unnamed bit-field.2162return Context == DeclaratorContext::Member || getLangOpts().CPlusPlus;21632164case tok::identifier:2165switch (NextToken().getKind()) {2166case tok::code_completion:2167case tok::coloncolon:2168case tok::comma:2169case tok::equal:2170case tok::equalequal: // Might be a typo for '='.2171case tok::kw_alignas:2172case tok::kw_asm:2173case tok::kw___attribute:2174case tok::l_brace:2175case tok::l_paren:2176case tok::l_square:2177case tok::less:2178case tok::r_brace:2179case tok::r_paren:2180case tok::r_square:2181case tok::semi:2182return true;21832184case tok::colon:2185// At namespace scope, 'identifier:' is probably a typo for 'identifier::'2186// and in block scope it's probably a label. Inside a class definition,2187// this is a bit-field.2188return Context == DeclaratorContext::Member ||2189(getLangOpts().CPlusPlus && Context == DeclaratorContext::File);21902191case tok::identifier: // Possible virt-specifier.2192return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken());21932194default:2195return Tok.isRegularKeywordAttribute();2196}21972198default:2199return Tok.isRegularKeywordAttribute();2200}2201}22022203/// Skip until we reach something which seems like a sensible place to pick2204/// up parsing after a malformed declaration. This will sometimes stop sooner2205/// than SkipUntil(tok::r_brace) would, but will never stop later.2206void Parser::SkipMalformedDecl() {2207while (true) {2208switch (Tok.getKind()) {2209case tok::l_brace:2210// Skip until matching }, then stop. We've probably skipped over2211// a malformed class or function definition or similar.2212ConsumeBrace();2213SkipUntil(tok::r_brace);2214if (Tok.isOneOf(tok::comma, tok::l_brace, tok::kw_try)) {2215// This declaration isn't over yet. Keep skipping.2216continue;2217}2218TryConsumeToken(tok::semi);2219return;22202221case tok::l_square:2222ConsumeBracket();2223SkipUntil(tok::r_square);2224continue;22252226case tok::l_paren:2227ConsumeParen();2228SkipUntil(tok::r_paren);2229continue;22302231case tok::r_brace:2232return;22332234case tok::semi:2235ConsumeToken();2236return;22372238case tok::kw_inline:2239// 'inline namespace' at the start of a line is almost certainly2240// a good place to pick back up parsing, except in an Objective-C2241// @interface context.2242if (Tok.isAtStartOfLine() && NextToken().is(tok::kw_namespace) &&2243(!ParsingInObjCContainer || CurParsedObjCImpl))2244return;2245break;22462247case tok::kw_namespace:2248// 'namespace' at the start of a line is almost certainly a good2249// place to pick back up parsing, except in an Objective-C2250// @interface context.2251if (Tok.isAtStartOfLine() &&2252(!ParsingInObjCContainer || CurParsedObjCImpl))2253return;2254break;22552256case tok::at:2257// @end is very much like } in Objective-C contexts.2258if (NextToken().isObjCAtKeyword(tok::objc_end) &&2259ParsingInObjCContainer)2260return;2261break;22622263case tok::minus:2264case tok::plus:2265// - and + probably start new method declarations in Objective-C contexts.2266if (Tok.isAtStartOfLine() && ParsingInObjCContainer)2267return;2268break;22692270case tok::eof:2271case tok::annot_module_begin:2272case tok::annot_module_end:2273case tok::annot_module_include:2274case tok::annot_repl_input_end:2275return;22762277default:2278break;2279}22802281ConsumeAnyToken();2282}2283}22842285/// ParseDeclGroup - Having concluded that this is either a function2286/// definition or a group of object declarations, actually parse the2287/// result.2288Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,2289DeclaratorContext Context,2290ParsedAttributes &Attrs,2291ParsedTemplateInfo &TemplateInfo,2292SourceLocation *DeclEnd,2293ForRangeInit *FRI) {2294// Parse the first declarator.2295// Consume all of the attributes from `Attrs` by moving them to our own local2296// list. This ensures that we will not attempt to interpret them as statement2297// attributes higher up the callchain.2298ParsedAttributes LocalAttrs(AttrFactory);2299LocalAttrs.takeAllFrom(Attrs);2300ParsingDeclarator D(*this, DS, LocalAttrs, Context);2301if (TemplateInfo.TemplateParams)2302D.setTemplateParameterLists(*TemplateInfo.TemplateParams);23032304bool IsTemplateSpecOrInst =2305(TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||2306TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);2307SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);23082309ParseDeclarator(D);23102311if (IsTemplateSpecOrInst)2312SAC.done();23132314// Bail out if the first declarator didn't seem well-formed.2315if (!D.hasName() && !D.mayOmitIdentifier()) {2316SkipMalformedDecl();2317return nullptr;2318}23192320if (getLangOpts().HLSL)2321MaybeParseHLSLAnnotations(D);23222323if (Tok.is(tok::kw_requires))2324ParseTrailingRequiresClause(D);23252326// Save late-parsed attributes for now; they need to be parsed in the2327// appropriate function scope after the function Decl has been constructed.2328// These will be parsed in ParseFunctionDefinition or ParseLexedAttrList.2329LateParsedAttrList LateParsedAttrs(true);2330if (D.isFunctionDeclarator()) {2331MaybeParseGNUAttributes(D, &LateParsedAttrs);23322333// The _Noreturn keyword can't appear here, unlike the GNU noreturn2334// attribute. If we find the keyword here, tell the user to put it2335// at the start instead.2336if (Tok.is(tok::kw__Noreturn)) {2337SourceLocation Loc = ConsumeToken();2338const char *PrevSpec;2339unsigned DiagID;23402341// We can offer a fixit if it's valid to mark this function as _Noreturn2342// and we don't have any other declarators in this declaration.2343bool Fixit = !DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);2344MaybeParseGNUAttributes(D, &LateParsedAttrs);2345Fixit &= Tok.isOneOf(tok::semi, tok::l_brace, tok::kw_try);23462347Diag(Loc, diag::err_c11_noreturn_misplaced)2348<< (Fixit ? FixItHint::CreateRemoval(Loc) : FixItHint())2349<< (Fixit ? FixItHint::CreateInsertion(D.getBeginLoc(), "_Noreturn ")2350: FixItHint());2351}23522353// Check to see if we have a function *definition* which must have a body.2354if (Tok.is(tok::equal) && NextToken().is(tok::code_completion)) {2355cutOffParsing();2356Actions.CodeCompletion().CodeCompleteAfterFunctionEquals(D);2357return nullptr;2358}2359// We're at the point where the parsing of function declarator is finished.2360//2361// A common error is that users accidently add a virtual specifier2362// (e.g. override) in an out-line method definition.2363// We attempt to recover by stripping all these specifiers coming after2364// the declarator.2365while (auto Specifier = isCXX11VirtSpecifier()) {2366Diag(Tok, diag::err_virt_specifier_outside_class)2367<< VirtSpecifiers::getSpecifierName(Specifier)2368<< FixItHint::CreateRemoval(Tok.getLocation());2369ConsumeToken();2370}2371// Look at the next token to make sure that this isn't a function2372// declaration. We have to check this because __attribute__ might be the2373// start of a function definition in GCC-extended K&R C.2374if (!isDeclarationAfterDeclarator()) {23752376// Function definitions are only allowed at file scope and in C++ classes.2377// The C++ inline method definition case is handled elsewhere, so we only2378// need to handle the file scope definition case.2379if (Context == DeclaratorContext::File) {2380if (isStartOfFunctionDefinition(D)) {2381// C++23 [dcl.typedef] p1:2382// The typedef specifier shall not be [...], and it shall not be2383// used in the decl-specifier-seq of a parameter-declaration nor in2384// the decl-specifier-seq of a function-definition.2385if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {2386// If the user intended to write 'typename', we should have already2387// suggested adding it elsewhere. In any case, recover by ignoring2388// 'typedef' and suggest removing it.2389Diag(DS.getStorageClassSpecLoc(),2390diag::err_function_declared_typedef)2391<< FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());2392DS.ClearStorageClassSpecs();2393}2394Decl *TheDecl = nullptr;23952396if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {2397if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {2398// If the declarator-id is not a template-id, issue a diagnostic2399// and recover by ignoring the 'template' keyword.2400Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;2401TheDecl = ParseFunctionDefinition(D, ParsedTemplateInfo(),2402&LateParsedAttrs);2403} else {2404SourceLocation LAngleLoc =2405PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);2406Diag(D.getIdentifierLoc(),2407diag::err_explicit_instantiation_with_definition)2408<< SourceRange(TemplateInfo.TemplateLoc)2409<< FixItHint::CreateInsertion(LAngleLoc, "<>");24102411// Recover as if it were an explicit specialization.2412TemplateParameterLists FakedParamLists;2413FakedParamLists.push_back(Actions.ActOnTemplateParameterList(24140, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc,2415std::nullopt, LAngleLoc, nullptr));24162417TheDecl = ParseFunctionDefinition(2418D,2419ParsedTemplateInfo(&FakedParamLists,2420/*isSpecialization=*/true,2421/*lastParameterListWasEmpty=*/true),2422&LateParsedAttrs);2423}2424} else {2425TheDecl =2426ParseFunctionDefinition(D, TemplateInfo, &LateParsedAttrs);2427}24282429return Actions.ConvertDeclToDeclGroup(TheDecl);2430}24312432if (isDeclarationSpecifier(ImplicitTypenameContext::No) ||2433Tok.is(tok::kw_namespace)) {2434// If there is an invalid declaration specifier or a namespace2435// definition right after the function prototype, then we must be in a2436// missing semicolon case where this isn't actually a body. Just fall2437// through into the code that handles it as a prototype, and let the2438// top-level code handle the erroneous declspec where it would2439// otherwise expect a comma or semicolon. Note that2440// isDeclarationSpecifier already covers 'inline namespace', since2441// 'inline' can be a declaration specifier.2442} else {2443Diag(Tok, diag::err_expected_fn_body);2444SkipUntil(tok::semi);2445return nullptr;2446}2447} else {2448if (Tok.is(tok::l_brace)) {2449Diag(Tok, diag::err_function_definition_not_allowed);2450SkipMalformedDecl();2451return nullptr;2452}2453}2454}2455}24562457if (ParseAsmAttributesAfterDeclarator(D))2458return nullptr;24592460// C++0x [stmt.iter]p1: Check if we have a for-range-declarator. If so, we2461// must parse and analyze the for-range-initializer before the declaration is2462// analyzed.2463//2464// Handle the Objective-C for-in loop variable similarly, although we2465// don't need to parse the container in advance.2466if (FRI && (Tok.is(tok::colon) || isTokIdentifier_in())) {2467bool IsForRangeLoop = false;2468if (TryConsumeToken(tok::colon, FRI->ColonLoc)) {2469IsForRangeLoop = true;2470EnterExpressionEvaluationContext ForRangeInitContext(2471Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated,2472/*LambdaContextDecl=*/nullptr,2473Sema::ExpressionEvaluationContextRecord::EK_Other,2474getLangOpts().CPlusPlus23);24752476// P2718R0 - Lifetime extension in range-based for loops.2477if (getLangOpts().CPlusPlus23) {2478auto &LastRecord = Actions.ExprEvalContexts.back();2479LastRecord.InLifetimeExtendingContext = true;2480}24812482if (getLangOpts().OpenMP)2483Actions.OpenMP().startOpenMPCXXRangeFor();2484if (Tok.is(tok::l_brace))2485FRI->RangeExpr = ParseBraceInitializer();2486else2487FRI->RangeExpr = ParseExpression();24882489// Before c++23, ForRangeLifetimeExtendTemps should be empty.2490assert(2491getLangOpts().CPlusPlus23 ||2492Actions.ExprEvalContexts.back().ForRangeLifetimeExtendTemps.empty());24932494// Move the collected materialized temporaries into ForRangeInit before2495// ForRangeInitContext exit.2496FRI->LifetimeExtendTemps = std::move(2497Actions.ExprEvalContexts.back().ForRangeLifetimeExtendTemps);2498}24992500Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);2501if (IsForRangeLoop) {2502Actions.ActOnCXXForRangeDecl(ThisDecl);2503} else {2504// Obj-C for loop2505if (auto *VD = dyn_cast_or_null<VarDecl>(ThisDecl))2506VD->setObjCForDecl(true);2507}2508Actions.FinalizeDeclaration(ThisDecl);2509D.complete(ThisDecl);2510return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, ThisDecl);2511}25122513SmallVector<Decl *, 8> DeclsInGroup;2514Decl *FirstDecl =2515ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo, FRI);2516if (LateParsedAttrs.size() > 0)2517ParseLexedAttributeList(LateParsedAttrs, FirstDecl, true, false);2518D.complete(FirstDecl);2519if (FirstDecl)2520DeclsInGroup.push_back(FirstDecl);25212522bool ExpectSemi = Context != DeclaratorContext::ForInit;25232524// If we don't have a comma, it is either the end of the list (a ';') or an2525// error, bail out.2526SourceLocation CommaLoc;2527while (TryConsumeToken(tok::comma, CommaLoc)) {2528if (Tok.isAtStartOfLine() && ExpectSemi && !MightBeDeclarator(Context)) {2529// This comma was followed by a line-break and something which can't be2530// the start of a declarator. The comma was probably a typo for a2531// semicolon.2532Diag(CommaLoc, diag::err_expected_semi_declaration)2533<< FixItHint::CreateReplacement(CommaLoc, ";");2534ExpectSemi = false;2535break;2536}25372538// C++23 [temp.pre]p5:2539// In a template-declaration, explicit specialization, or explicit2540// instantiation the init-declarator-list in the declaration shall2541// contain at most one declarator.2542if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&2543D.isFirstDeclarator()) {2544Diag(CommaLoc, diag::err_multiple_template_declarators)2545<< TemplateInfo.Kind;2546}25472548// Parse the next declarator.2549D.clear();2550D.setCommaLoc(CommaLoc);25512552// Accept attributes in an init-declarator. In the first declarator in a2553// declaration, these would be part of the declspec. In subsequent2554// declarators, they become part of the declarator itself, so that they2555// don't apply to declarators after *this* one. Examples:2556// short __attribute__((common)) var; -> declspec2557// short var __attribute__((common)); -> declarator2558// short x, __attribute__((common)) var; -> declarator2559MaybeParseGNUAttributes(D);25602561// MSVC parses but ignores qualifiers after the comma as an extension.2562if (getLangOpts().MicrosoftExt)2563DiagnoseAndSkipExtendedMicrosoftTypeAttributes();25642565ParseDeclarator(D);25662567if (getLangOpts().HLSL)2568MaybeParseHLSLAnnotations(D);25692570if (!D.isInvalidType()) {2571// C++2a [dcl.decl]p12572// init-declarator:2573// declarator initializer[opt]2574// declarator requires-clause2575if (Tok.is(tok::kw_requires))2576ParseTrailingRequiresClause(D);2577Decl *ThisDecl = ParseDeclarationAfterDeclarator(D, TemplateInfo);2578D.complete(ThisDecl);2579if (ThisDecl)2580DeclsInGroup.push_back(ThisDecl);2581}2582}25832584if (DeclEnd)2585*DeclEnd = Tok.getLocation();25862587if (ExpectSemi && ExpectAndConsumeSemi(2588Context == DeclaratorContext::File2589? diag::err_invalid_token_after_toplevel_declarator2590: diag::err_expected_semi_declaration)) {2591// Okay, there was no semicolon and one was expected. If we see a2592// declaration specifier, just assume it was missing and continue parsing.2593// Otherwise things are very confused and we skip to recover.2594if (!isDeclarationSpecifier(ImplicitTypenameContext::No))2595SkipMalformedDecl();2596}25972598return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);2599}26002601/// Parse an optional simple-asm-expr and attributes, and attach them to a2602/// declarator. Returns true on an error.2603bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) {2604// If a simple-asm-expr is present, parse it.2605if (Tok.is(tok::kw_asm)) {2606SourceLocation Loc;2607ExprResult AsmLabel(ParseSimpleAsm(/*ForAsmLabel*/ true, &Loc));2608if (AsmLabel.isInvalid()) {2609SkipUntil(tok::semi, StopBeforeMatch);2610return true;2611}26122613D.setAsmLabel(AsmLabel.get());2614D.SetRangeEnd(Loc);2615}26162617MaybeParseGNUAttributes(D);2618return false;2619}26202621/// Parse 'declaration' after parsing 'declaration-specifiers2622/// declarator'. This method parses the remainder of the declaration2623/// (including any attributes or initializer, among other things) and2624/// finalizes the declaration.2625///2626/// init-declarator: [C99 6.7]2627/// declarator2628/// declarator '=' initializer2629/// [GNU] declarator simple-asm-expr[opt] attributes[opt]2630/// [GNU] declarator simple-asm-expr[opt] attributes[opt] '=' initializer2631/// [C++] declarator initializer[opt]2632///2633/// [C++] initializer:2634/// [C++] '=' initializer-clause2635/// [C++] '(' expression-list ')'2636/// [C++0x] '=' 'default' [TODO]2637/// [C++0x] '=' 'delete'2638/// [C++0x] braced-init-list2639///2640/// According to the standard grammar, =default and =delete are function2641/// definitions, but that definitely doesn't fit with the parser here.2642///2643Decl *Parser::ParseDeclarationAfterDeclarator(2644Declarator &D, const ParsedTemplateInfo &TemplateInfo) {2645if (ParseAsmAttributesAfterDeclarator(D))2646return nullptr;26472648return ParseDeclarationAfterDeclaratorAndAttributes(D, TemplateInfo);2649}26502651Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes(2652Declarator &D, const ParsedTemplateInfo &TemplateInfo, ForRangeInit *FRI) {2653// RAII type used to track whether we're inside an initializer.2654struct InitializerScopeRAII {2655Parser &P;2656Declarator &D;2657Decl *ThisDecl;2658bool Entered;26592660InitializerScopeRAII(Parser &P, Declarator &D, Decl *ThisDecl)2661: P(P), D(D), ThisDecl(ThisDecl), Entered(false) {2662if (ThisDecl && P.getLangOpts().CPlusPlus) {2663Scope *S = nullptr;2664if (D.getCXXScopeSpec().isSet()) {2665P.EnterScope(0);2666S = P.getCurScope();2667}2668if (ThisDecl && !ThisDecl->isInvalidDecl()) {2669P.Actions.ActOnCXXEnterDeclInitializer(S, ThisDecl);2670Entered = true;2671}2672}2673}2674~InitializerScopeRAII() {2675if (ThisDecl && P.getLangOpts().CPlusPlus) {2676Scope *S = nullptr;2677if (D.getCXXScopeSpec().isSet())2678S = P.getCurScope();26792680if (Entered)2681P.Actions.ActOnCXXExitDeclInitializer(S, ThisDecl);2682if (S)2683P.ExitScope();2684}2685ThisDecl = nullptr;2686}2687};26882689enum class InitKind { Uninitialized, Equal, CXXDirect, CXXBraced };2690InitKind TheInitKind;2691// If a '==' or '+=' is found, suggest a fixit to '='.2692if (isTokenEqualOrEqualTypo())2693TheInitKind = InitKind::Equal;2694else if (Tok.is(tok::l_paren))2695TheInitKind = InitKind::CXXDirect;2696else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace) &&2697(!CurParsedObjCImpl || !D.isFunctionDeclarator()))2698TheInitKind = InitKind::CXXBraced;2699else2700TheInitKind = InitKind::Uninitialized;2701if (TheInitKind != InitKind::Uninitialized)2702D.setHasInitializer();27032704// Inform Sema that we just parsed this declarator.2705Decl *ThisDecl = nullptr;2706Decl *OuterDecl = nullptr;2707switch (TemplateInfo.Kind) {2708case ParsedTemplateInfo::NonTemplate:2709ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);2710break;27112712case ParsedTemplateInfo::Template:2713case ParsedTemplateInfo::ExplicitSpecialization: {2714ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(),2715*TemplateInfo.TemplateParams,2716D);2717if (VarTemplateDecl *VT = dyn_cast_or_null<VarTemplateDecl>(ThisDecl)) {2718// Re-direct this decl to refer to the templated decl so that we can2719// initialize it.2720ThisDecl = VT->getTemplatedDecl();2721OuterDecl = VT;2722}2723break;2724}2725case ParsedTemplateInfo::ExplicitInstantiation: {2726if (Tok.is(tok::semi)) {2727DeclResult ThisRes = Actions.ActOnExplicitInstantiation(2728getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, D);2729if (ThisRes.isInvalid()) {2730SkipUntil(tok::semi, StopBeforeMatch);2731return nullptr;2732}2733ThisDecl = ThisRes.get();2734} else {2735// FIXME: This check should be for a variable template instantiation only.27362737// Check that this is a valid instantiation2738if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) {2739// If the declarator-id is not a template-id, issue a diagnostic and2740// recover by ignoring the 'template' keyword.2741Diag(Tok, diag::err_template_defn_explicit_instantiation)2742<< 2 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);2743ThisDecl = Actions.ActOnDeclarator(getCurScope(), D);2744} else {2745SourceLocation LAngleLoc =2746PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);2747Diag(D.getIdentifierLoc(),2748diag::err_explicit_instantiation_with_definition)2749<< SourceRange(TemplateInfo.TemplateLoc)2750<< FixItHint::CreateInsertion(LAngleLoc, "<>");27512752// Recover as if it were an explicit specialization.2753TemplateParameterLists FakedParamLists;2754FakedParamLists.push_back(Actions.ActOnTemplateParameterList(27550, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc,2756std::nullopt, LAngleLoc, nullptr));27572758ThisDecl =2759Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D);2760}2761}2762break;2763}2764}27652766SemaCUDA::CUDATargetContextRAII X(Actions.CUDA(),2767SemaCUDA::CTCK_InitGlobalVar, ThisDecl);2768switch (TheInitKind) {2769// Parse declarator '=' initializer.2770case InitKind::Equal: {2771SourceLocation EqualLoc = ConsumeToken();27722773if (Tok.is(tok::kw_delete)) {2774if (D.isFunctionDeclarator())2775Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)2776<< 1 /* delete */;2777else2778Diag(ConsumeToken(), diag::err_deleted_non_function);2779SkipDeletedFunctionBody();2780} else if (Tok.is(tok::kw_default)) {2781if (D.isFunctionDeclarator())2782Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)2783<< 0 /* default */;2784else2785Diag(ConsumeToken(), diag::err_default_special_members)2786<< getLangOpts().CPlusPlus20;2787} else {2788InitializerScopeRAII InitScope(*this, D, ThisDecl);27892790if (Tok.is(tok::code_completion)) {2791cutOffParsing();2792Actions.CodeCompletion().CodeCompleteInitializer(getCurScope(),2793ThisDecl);2794Actions.FinalizeDeclaration(ThisDecl);2795return nullptr;2796}27972798PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);2799ExprResult Init = ParseInitializer();28002801// If this is the only decl in (possibly) range based for statement,2802// our best guess is that the user meant ':' instead of '='.2803if (Tok.is(tok::r_paren) && FRI && D.isFirstDeclarator()) {2804Diag(EqualLoc, diag::err_single_decl_assign_in_for_range)2805<< FixItHint::CreateReplacement(EqualLoc, ":");2806// We are trying to stop parser from looking for ';' in this for2807// statement, therefore preventing spurious errors to be issued.2808FRI->ColonLoc = EqualLoc;2809Init = ExprError();2810FRI->RangeExpr = Init;2811}28122813if (Init.isInvalid()) {2814SmallVector<tok::TokenKind, 2> StopTokens;2815StopTokens.push_back(tok::comma);2816if (D.getContext() == DeclaratorContext::ForInit ||2817D.getContext() == DeclaratorContext::SelectionInit)2818StopTokens.push_back(tok::r_paren);2819SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch);2820Actions.ActOnInitializerError(ThisDecl);2821} else2822Actions.AddInitializerToDecl(ThisDecl, Init.get(),2823/*DirectInit=*/false);2824}2825break;2826}2827case InitKind::CXXDirect: {2828// Parse C++ direct initializer: '(' expression-list ')'2829BalancedDelimiterTracker T(*this, tok::l_paren);2830T.consumeOpen();28312832ExprVector Exprs;28332834InitializerScopeRAII InitScope(*this, D, ThisDecl);28352836auto ThisVarDecl = dyn_cast_or_null<VarDecl>(ThisDecl);2837auto RunSignatureHelp = [&]() {2838QualType PreferredType =2839Actions.CodeCompletion().ProduceConstructorSignatureHelp(2840ThisVarDecl->getType()->getCanonicalTypeInternal(),2841ThisDecl->getLocation(), Exprs, T.getOpenLocation(),2842/*Braced=*/false);2843CalledSignatureHelp = true;2844return PreferredType;2845};2846auto SetPreferredType = [&] {2847PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp);2848};28492850llvm::function_ref<void()> ExpressionStarts;2851if (ThisVarDecl) {2852// ParseExpressionList can sometimes succeed even when ThisDecl is not2853// VarDecl. This is an error and it is reported in a call to2854// Actions.ActOnInitializerError(). However, we call2855// ProduceConstructorSignatureHelp only on VarDecls.2856ExpressionStarts = SetPreferredType;2857}28582859bool SawError = ParseExpressionList(Exprs, ExpressionStarts);28602861if (SawError) {2862if (ThisVarDecl && PP.isCodeCompletionReached() && !CalledSignatureHelp) {2863Actions.CodeCompletion().ProduceConstructorSignatureHelp(2864ThisVarDecl->getType()->getCanonicalTypeInternal(),2865ThisDecl->getLocation(), Exprs, T.getOpenLocation(),2866/*Braced=*/false);2867CalledSignatureHelp = true;2868}2869Actions.ActOnInitializerError(ThisDecl);2870SkipUntil(tok::r_paren, StopAtSemi);2871} else {2872// Match the ')'.2873T.consumeClose();28742875ExprResult Initializer = Actions.ActOnParenListExpr(T.getOpenLocation(),2876T.getCloseLocation(),2877Exprs);2878Actions.AddInitializerToDecl(ThisDecl, Initializer.get(),2879/*DirectInit=*/true);2880}2881break;2882}2883case InitKind::CXXBraced: {2884// Parse C++0x braced-init-list.2885Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);28862887InitializerScopeRAII InitScope(*this, D, ThisDecl);28882889PreferredType.enterVariableInit(Tok.getLocation(), ThisDecl);2890ExprResult Init(ParseBraceInitializer());28912892if (Init.isInvalid()) {2893Actions.ActOnInitializerError(ThisDecl);2894} else2895Actions.AddInitializerToDecl(ThisDecl, Init.get(), /*DirectInit=*/true);2896break;2897}2898case InitKind::Uninitialized: {2899Actions.ActOnUninitializedDecl(ThisDecl);2900break;2901}2902}29032904Actions.FinalizeDeclaration(ThisDecl);2905return OuterDecl ? OuterDecl : ThisDecl;2906}29072908/// ParseSpecifierQualifierList2909/// specifier-qualifier-list:2910/// type-specifier specifier-qualifier-list[opt]2911/// type-qualifier specifier-qualifier-list[opt]2912/// [GNU] attributes specifier-qualifier-list[opt]2913///2914void Parser::ParseSpecifierQualifierList(2915DeclSpec &DS, ImplicitTypenameContext AllowImplicitTypename,2916AccessSpecifier AS, DeclSpecContext DSC) {2917ParsedTemplateInfo TemplateInfo;2918/// specifier-qualifier-list is a subset of declaration-specifiers. Just2919/// parse declaration-specifiers and complain about extra stuff.2920/// TODO: diagnose attribute-specifiers and alignment-specifiers.2921ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC, nullptr,2922AllowImplicitTypename);29232924// Validate declspec for type-name.2925unsigned Specs = DS.getParsedSpecifiers();2926if (isTypeSpecifier(DSC) && !DS.hasTypeSpecifier()) {2927Diag(Tok, diag::err_expected_type);2928DS.SetTypeSpecError();2929} else if (Specs == DeclSpec::PQ_None && !DS.hasAttributes()) {2930Diag(Tok, diag::err_typename_requires_specqual);2931if (!DS.hasTypeSpecifier())2932DS.SetTypeSpecError();2933}29342935// Issue diagnostic and remove storage class if present.2936if (Specs & DeclSpec::PQ_StorageClassSpecifier) {2937if (DS.getStorageClassSpecLoc().isValid())2938Diag(DS.getStorageClassSpecLoc(),diag::err_typename_invalid_storageclass);2939else2940Diag(DS.getThreadStorageClassSpecLoc(),2941diag::err_typename_invalid_storageclass);2942DS.ClearStorageClassSpecs();2943}29442945// Issue diagnostic and remove function specifier if present.2946if (Specs & DeclSpec::PQ_FunctionSpecifier) {2947if (DS.isInlineSpecified())2948Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec);2949if (DS.isVirtualSpecified())2950Diag(DS.getVirtualSpecLoc(), diag::err_typename_invalid_functionspec);2951if (DS.hasExplicitSpecifier())2952Diag(DS.getExplicitSpecLoc(), diag::err_typename_invalid_functionspec);2953if (DS.isNoreturnSpecified())2954Diag(DS.getNoreturnSpecLoc(), diag::err_typename_invalid_functionspec);2955DS.ClearFunctionSpecs();2956}29572958// Issue diagnostic and remove constexpr specifier if present.2959if (DS.hasConstexprSpecifier() && DSC != DeclSpecContext::DSC_condition) {2960Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr)2961<< static_cast<int>(DS.getConstexprSpecifier());2962DS.ClearConstexprSpec();2963}2964}29652966/// isValidAfterIdentifierInDeclaratorAfterDeclSpec - Return true if the2967/// specified token is valid after the identifier in a declarator which2968/// immediately follows the declspec. For example, these things are valid:2969///2970/// int x [ 4]; // direct-declarator2971/// int x ( int y); // direct-declarator2972/// int(int x ) // direct-declarator2973/// int x ; // simple-declaration2974/// int x = 17; // init-declarator-list2975/// int x , y; // init-declarator-list2976/// int x __asm__ ("foo"); // init-declarator-list2977/// int x : 4; // struct-declarator2978/// int x { 5}; // C++'0x unified initializers2979///2980/// This is not, because 'x' does not immediately follow the declspec (though2981/// ')' happens to be valid anyway).2982/// int (x)2983///2984static bool isValidAfterIdentifierInDeclarator(const Token &T) {2985return T.isOneOf(tok::l_square, tok::l_paren, tok::r_paren, tok::semi,2986tok::comma, tok::equal, tok::kw_asm, tok::l_brace,2987tok::colon);2988}29892990/// ParseImplicitInt - This method is called when we have an non-typename2991/// identifier in a declspec (which normally terminates the decl spec) when2992/// the declspec has no type specifier. In this case, the declspec is either2993/// malformed or is "implicit int" (in K&R and C89).2994///2995/// This method handles diagnosing this prettily and returns false if the2996/// declspec is done being processed. If it recovers and thinks there may be2997/// other pieces of declspec after it, it returns true.2998///2999bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,3000ParsedTemplateInfo &TemplateInfo,3001AccessSpecifier AS, DeclSpecContext DSC,3002ParsedAttributes &Attrs) {3003assert(Tok.is(tok::identifier) && "should have identifier");30043005SourceLocation Loc = Tok.getLocation();3006// If we see an identifier that is not a type name, we normally would3007// parse it as the identifier being declared. However, when a typename3008// is typo'd or the definition is not included, this will incorrectly3009// parse the typename as the identifier name and fall over misparsing3010// later parts of the diagnostic.3011//3012// As such, we try to do some look-ahead in cases where this would3013// otherwise be an "implicit-int" case to see if this is invalid. For3014// example: "static foo_t x = 4;" In this case, if we parsed foo_t as3015// an identifier with implicit int, we'd get a parse error because the3016// next token is obviously invalid for a type. Parse these as a case3017// with an invalid type specifier.3018assert(!DS.hasTypeSpecifier() && "Type specifier checked above");30193020// Since we know that this either implicit int (which is rare) or an3021// error, do lookahead to try to do better recovery. This never applies3022// within a type specifier. Outside of C++, we allow this even if the3023// language doesn't "officially" support implicit int -- we support3024// implicit int as an extension in some language modes.3025if (!isTypeSpecifier(DSC) && getLangOpts().isImplicitIntAllowed() &&3026isValidAfterIdentifierInDeclarator(NextToken())) {3027// If this token is valid for implicit int, e.g. "static x = 4", then3028// we just avoid eating the identifier, so it will be parsed as the3029// identifier in the declarator.3030return false;3031}30323033// Early exit as Sema has a dedicated missing_actual_pipe_type diagnostic3034// for incomplete declarations such as `pipe p`.3035if (getLangOpts().OpenCLCPlusPlus && DS.isTypeSpecPipe())3036return false;30373038if (getLangOpts().CPlusPlus &&3039DS.getStorageClassSpec() == DeclSpec::SCS_auto) {3040// Don't require a type specifier if we have the 'auto' storage class3041// specifier in C++98 -- we'll promote it to a type specifier.3042if (SS)3043AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);3044return false;3045}30463047if (getLangOpts().CPlusPlus && (!SS || SS->isEmpty()) &&3048getLangOpts().MSVCCompat) {3049// Lookup of an unqualified type name has failed in MSVC compatibility mode.3050// Give Sema a chance to recover if we are in a template with dependent base3051// classes.3052if (ParsedType T = Actions.ActOnMSVCUnknownTypeName(3053*Tok.getIdentifierInfo(), Tok.getLocation(),3054DSC == DeclSpecContext::DSC_template_type_arg)) {3055const char *PrevSpec;3056unsigned DiagID;3057DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,3058Actions.getASTContext().getPrintingPolicy());3059DS.SetRangeEnd(Tok.getLocation());3060ConsumeToken();3061return false;3062}3063}30643065// Otherwise, if we don't consume this token, we are going to emit an3066// error anyway. Try to recover from various common problems. Check3067// to see if this was a reference to a tag name without a tag specified.3068// This is a common problem in C (saying 'foo' instead of 'struct foo').3069//3070// C++ doesn't need this, and isTagName doesn't take SS.3071if (SS == nullptr) {3072const char *TagName = nullptr, *FixitTagName = nullptr;3073tok::TokenKind TagKind = tok::unknown;30743075switch (Actions.isTagName(*Tok.getIdentifierInfo(), getCurScope())) {3076default: break;3077case DeclSpec::TST_enum:3078TagName="enum" ; FixitTagName = "enum " ; TagKind=tok::kw_enum ;break;3079case DeclSpec::TST_union:3080TagName="union" ; FixitTagName = "union " ;TagKind=tok::kw_union ;break;3081case DeclSpec::TST_struct:3082TagName="struct"; FixitTagName = "struct ";TagKind=tok::kw_struct;break;3083case DeclSpec::TST_interface:3084TagName="__interface"; FixitTagName = "__interface ";3085TagKind=tok::kw___interface;break;3086case DeclSpec::TST_class:3087TagName="class" ; FixitTagName = "class " ;TagKind=tok::kw_class ;break;3088}30893090if (TagName) {3091IdentifierInfo *TokenName = Tok.getIdentifierInfo();3092LookupResult R(Actions, TokenName, SourceLocation(),3093Sema::LookupOrdinaryName);30943095Diag(Loc, diag::err_use_of_tag_name_without_tag)3096<< TokenName << TagName << getLangOpts().CPlusPlus3097<< FixItHint::CreateInsertion(Tok.getLocation(), FixitTagName);30983099if (Actions.LookupName(R, getCurScope())) {3100for (LookupResult::iterator I = R.begin(), IEnd = R.end();3101I != IEnd; ++I)3102Diag((*I)->getLocation(), diag::note_decl_hiding_tag_type)3103<< TokenName << TagName;3104}31053106// Parse this as a tag as if the missing tag were present.3107if (TagKind == tok::kw_enum)3108ParseEnumSpecifier(Loc, DS, TemplateInfo, AS,3109DeclSpecContext::DSC_normal);3110else3111ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS,3112/*EnteringContext*/ false,3113DeclSpecContext::DSC_normal, Attrs);3114return true;3115}3116}31173118// Determine whether this identifier could plausibly be the name of something3119// being declared (with a missing type).3120if (!isTypeSpecifier(DSC) && (!SS || DSC == DeclSpecContext::DSC_top_level ||3121DSC == DeclSpecContext::DSC_class)) {3122// Look ahead to the next token to try to figure out what this declaration3123// was supposed to be.3124switch (NextToken().getKind()) {3125case tok::l_paren: {3126// static x(4); // 'x' is not a type3127// x(int n); // 'x' is not a type3128// x (*p)[]; // 'x' is a type3129//3130// Since we're in an error case, we can afford to perform a tentative3131// parse to determine which case we're in.3132TentativeParsingAction PA(*this);3133ConsumeToken();3134TPResult TPR = TryParseDeclarator(/*mayBeAbstract*/false);3135PA.Revert();31363137if (TPR != TPResult::False) {3138// The identifier is followed by a parenthesized declarator.3139// It's supposed to be a type.3140break;3141}31423143// If we're in a context where we could be declaring a constructor,3144// check whether this is a constructor declaration with a bogus name.3145if (DSC == DeclSpecContext::DSC_class ||3146(DSC == DeclSpecContext::DSC_top_level && SS)) {3147IdentifierInfo *II = Tok.getIdentifierInfo();3148if (Actions.isCurrentClassNameTypo(II, SS)) {3149Diag(Loc, diag::err_constructor_bad_name)3150<< Tok.getIdentifierInfo() << II3151<< FixItHint::CreateReplacement(Tok.getLocation(), II->getName());3152Tok.setIdentifierInfo(II);3153}3154}3155// Fall through.3156[[fallthrough]];3157}3158case tok::comma:3159case tok::equal:3160case tok::kw_asm:3161case tok::l_brace:3162case tok::l_square:3163case tok::semi:3164// This looks like a variable or function declaration. The type is3165// probably missing. We're done parsing decl-specifiers.3166// But only if we are not in a function prototype scope.3167if (getCurScope()->isFunctionPrototypeScope())3168break;3169if (SS)3170AnnotateScopeToken(*SS, /*IsNewAnnotation*/false);3171return false;31723173default:3174// This is probably supposed to be a type. This includes cases like:3175// int f(itn);3176// struct S { unsigned : 4; };3177break;3178}3179}31803181// This is almost certainly an invalid type name. Let Sema emit a diagnostic3182// and attempt to recover.3183ParsedType T;3184IdentifierInfo *II = Tok.getIdentifierInfo();3185bool IsTemplateName = getLangOpts().CPlusPlus && NextToken().is(tok::less);3186Actions.DiagnoseUnknownTypeName(II, Loc, getCurScope(), SS, T,3187IsTemplateName);3188if (T) {3189// The action has suggested that the type T could be used. Set that as3190// the type in the declaration specifiers, consume the would-be type3191// name token, and we're done.3192const char *PrevSpec;3193unsigned DiagID;3194DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T,3195Actions.getASTContext().getPrintingPolicy());3196DS.SetRangeEnd(Tok.getLocation());3197ConsumeToken();3198// There may be other declaration specifiers after this.3199return true;3200} else if (II != Tok.getIdentifierInfo()) {3201// If no type was suggested, the correction is to a keyword3202Tok.setKind(II->getTokenID());3203// There may be other declaration specifiers after this.3204return true;3205}32063207// Otherwise, the action had no suggestion for us. Mark this as an error.3208DS.SetTypeSpecError();3209DS.SetRangeEnd(Tok.getLocation());3210ConsumeToken();32113212// Eat any following template arguments.3213if (IsTemplateName) {3214SourceLocation LAngle, RAngle;3215TemplateArgList Args;3216ParseTemplateIdAfterTemplateName(true, LAngle, Args, RAngle);3217}32183219// TODO: Could inject an invalid typedef decl in an enclosing scope to3220// avoid rippling error messages on subsequent uses of the same type,3221// could be useful if #include was forgotten.3222return true;3223}32243225/// Determine the declaration specifier context from the declarator3226/// context.3227///3228/// \param Context the declarator context, which is one of the3229/// DeclaratorContext enumerator values.3230Parser::DeclSpecContext3231Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) {3232switch (Context) {3233case DeclaratorContext::Member:3234return DeclSpecContext::DSC_class;3235case DeclaratorContext::File:3236return DeclSpecContext::DSC_top_level;3237case DeclaratorContext::TemplateParam:3238return DeclSpecContext::DSC_template_param;3239case DeclaratorContext::TemplateArg:3240return DeclSpecContext::DSC_template_arg;3241case DeclaratorContext::TemplateTypeArg:3242return DeclSpecContext::DSC_template_type_arg;3243case DeclaratorContext::TrailingReturn:3244case DeclaratorContext::TrailingReturnVar:3245return DeclSpecContext::DSC_trailing;3246case DeclaratorContext::AliasDecl:3247case DeclaratorContext::AliasTemplate:3248return DeclSpecContext::DSC_alias_declaration;3249case DeclaratorContext::Association:3250return DeclSpecContext::DSC_association;3251case DeclaratorContext::TypeName:3252return DeclSpecContext::DSC_type_specifier;3253case DeclaratorContext::Condition:3254return DeclSpecContext::DSC_condition;3255case DeclaratorContext::ConversionId:3256return DeclSpecContext::DSC_conv_operator;3257case DeclaratorContext::CXXNew:3258return DeclSpecContext::DSC_new;3259case DeclaratorContext::Prototype:3260case DeclaratorContext::ObjCResult:3261case DeclaratorContext::ObjCParameter:3262case DeclaratorContext::KNRTypeList:3263case DeclaratorContext::FunctionalCast:3264case DeclaratorContext::Block:3265case DeclaratorContext::ForInit:3266case DeclaratorContext::SelectionInit:3267case DeclaratorContext::CXXCatch:3268case DeclaratorContext::ObjCCatch:3269case DeclaratorContext::BlockLiteral:3270case DeclaratorContext::LambdaExpr:3271case DeclaratorContext::LambdaExprParameter:3272case DeclaratorContext::RequiresExpr:3273return DeclSpecContext::DSC_normal;3274}32753276llvm_unreachable("Missing DeclaratorContext case");3277}32783279/// ParseAlignArgument - Parse the argument to an alignment-specifier.3280///3281/// [C11] type-id3282/// [C11] constant-expression3283/// [C++0x] type-id ...[opt]3284/// [C++0x] assignment-expression ...[opt]3285ExprResult Parser::ParseAlignArgument(StringRef KWName, SourceLocation Start,3286SourceLocation &EllipsisLoc, bool &IsType,3287ParsedType &TypeResult) {3288ExprResult ER;3289if (isTypeIdInParens()) {3290SourceLocation TypeLoc = Tok.getLocation();3291ParsedType Ty = ParseTypeName().get();3292SourceRange TypeRange(Start, Tok.getLocation());3293if (Actions.ActOnAlignasTypeArgument(KWName, Ty, TypeLoc, TypeRange))3294return ExprError();3295TypeResult = Ty;3296IsType = true;3297} else {3298ER = ParseConstantExpression();3299IsType = false;3300}33013302if (getLangOpts().CPlusPlus11)3303TryConsumeToken(tok::ellipsis, EllipsisLoc);33043305return ER;3306}33073308/// ParseAlignmentSpecifier - Parse an alignment-specifier, and add the3309/// attribute to Attrs.3310///3311/// alignment-specifier:3312/// [C11] '_Alignas' '(' type-id ')'3313/// [C11] '_Alignas' '(' constant-expression ')'3314/// [C++11] 'alignas' '(' type-id ...[opt] ')'3315/// [C++11] 'alignas' '(' assignment-expression ...[opt] ')'3316void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs,3317SourceLocation *EndLoc) {3318assert(Tok.isOneOf(tok::kw_alignas, tok::kw__Alignas) &&3319"Not an alignment-specifier!");3320Token KWTok = Tok;3321IdentifierInfo *KWName = KWTok.getIdentifierInfo();3322auto Kind = KWTok.getKind();3323SourceLocation KWLoc = ConsumeToken();33243325BalancedDelimiterTracker T(*this, tok::l_paren);3326if (T.expectAndConsume())3327return;33283329bool IsType;3330ParsedType TypeResult;3331SourceLocation EllipsisLoc;3332ExprResult ArgExpr =3333ParseAlignArgument(PP.getSpelling(KWTok), T.getOpenLocation(),3334EllipsisLoc, IsType, TypeResult);3335if (ArgExpr.isInvalid()) {3336T.skipToEnd();3337return;3338}33393340T.consumeClose();3341if (EndLoc)3342*EndLoc = T.getCloseLocation();33433344if (IsType) {3345Attrs.addNewTypeAttr(KWName, KWLoc, nullptr, KWLoc, TypeResult, Kind,3346EllipsisLoc);3347} else {3348ArgsVector ArgExprs;3349ArgExprs.push_back(ArgExpr.get());3350Attrs.addNew(KWName, KWLoc, nullptr, KWLoc, ArgExprs.data(), 1, Kind,3351EllipsisLoc);3352}3353}33543355void Parser::DistributeCLateParsedAttrs(Decl *Dcl,3356LateParsedAttrList *LateAttrs) {3357if (!LateAttrs)3358return;33593360if (Dcl) {3361for (auto *LateAttr : *LateAttrs) {3362if (LateAttr->Decls.empty())3363LateAttr->addDecl(Dcl);3364}3365}3366}33673368/// Bounds attributes (e.g., counted_by):3369/// AttrName '(' expression ')'3370void Parser::ParseBoundsAttribute(IdentifierInfo &AttrName,3371SourceLocation AttrNameLoc,3372ParsedAttributes &Attrs,3373IdentifierInfo *ScopeName,3374SourceLocation ScopeLoc,3375ParsedAttr::Form Form) {3376assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");33773378BalancedDelimiterTracker Parens(*this, tok::l_paren);3379Parens.consumeOpen();33803381if (Tok.is(tok::r_paren)) {3382Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);3383Parens.consumeClose();3384return;3385}33863387ArgsVector ArgExprs;3388// Don't evaluate argument when the attribute is ignored.3389using ExpressionKind =3390Sema::ExpressionEvaluationContextRecord::ExpressionKind;3391EnterExpressionEvaluationContext EC(3392Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, nullptr,3393ExpressionKind::EK_AttrArgument);33943395ExprResult ArgExpr(3396Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()));33973398if (ArgExpr.isInvalid()) {3399Parens.skipToEnd();3400return;3401}34023403ArgExprs.push_back(ArgExpr.get());3404Parens.consumeClose();34053406ASTContext &Ctx = Actions.getASTContext();34073408ArgExprs.push_back(IntegerLiteral::Create(3409Ctx, llvm::APInt(Ctx.getTypeSize(Ctx.getSizeType()), 0),3410Ctx.getSizeType(), SourceLocation()));34113412Attrs.addNew(&AttrName, SourceRange(AttrNameLoc, Parens.getCloseLocation()),3413ScopeName, ScopeLoc, ArgExprs.data(), ArgExprs.size(), Form);3414}34153416ExprResult Parser::ParseExtIntegerArgument() {3417assert(Tok.isOneOf(tok::kw__ExtInt, tok::kw__BitInt) &&3418"Not an extended int type");3419ConsumeToken();34203421BalancedDelimiterTracker T(*this, tok::l_paren);3422if (T.expectAndConsume())3423return ExprError();34243425ExprResult ER = ParseConstantExpression();3426if (ER.isInvalid()) {3427T.skipToEnd();3428return ExprError();3429}34303431if(T.consumeClose())3432return ExprError();3433return ER;3434}34353436/// Determine whether we're looking at something that might be a declarator3437/// in a simple-declaration. If it can't possibly be a declarator, maybe3438/// diagnose a missing semicolon after a prior tag definition in the decl3439/// specifier.3440///3441/// \return \c true if an error occurred and this can't be any kind of3442/// declaration.3443bool3444Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,3445DeclSpecContext DSContext,3446LateParsedAttrList *LateAttrs) {3447assert(DS.hasTagDefinition() && "shouldn't call this");34483449bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||3450DSContext == DeclSpecContext::DSC_top_level);34513452if (getLangOpts().CPlusPlus &&3453Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype,3454tok::annot_template_id) &&3455TryAnnotateCXXScopeToken(EnteringContext)) {3456SkipMalformedDecl();3457return true;3458}34593460bool HasScope = Tok.is(tok::annot_cxxscope);3461// Make a copy in case GetLookAheadToken invalidates the result of NextToken.3462Token AfterScope = HasScope ? NextToken() : Tok;34633464// Determine whether the following tokens could possibly be a3465// declarator.3466bool MightBeDeclarator = true;3467if (Tok.isOneOf(tok::kw_typename, tok::annot_typename)) {3468// A declarator-id can't start with 'typename'.3469MightBeDeclarator = false;3470} else if (AfterScope.is(tok::annot_template_id)) {3471// If we have a type expressed as a template-id, this cannot be a3472// declarator-id (such a type cannot be redeclared in a simple-declaration).3473TemplateIdAnnotation *Annot =3474static_cast<TemplateIdAnnotation *>(AfterScope.getAnnotationValue());3475if (Annot->Kind == TNK_Type_template)3476MightBeDeclarator = false;3477} else if (AfterScope.is(tok::identifier)) {3478const Token &Next = HasScope ? GetLookAheadToken(2) : NextToken();34793480// These tokens cannot come after the declarator-id in a3481// simple-declaration, and are likely to come after a type-specifier.3482if (Next.isOneOf(tok::star, tok::amp, tok::ampamp, tok::identifier,3483tok::annot_cxxscope, tok::coloncolon)) {3484// Missing a semicolon.3485MightBeDeclarator = false;3486} else if (HasScope) {3487// If the declarator-id has a scope specifier, it must redeclare a3488// previously-declared entity. If that's a type (and this is not a3489// typedef), that's an error.3490CXXScopeSpec SS;3491Actions.RestoreNestedNameSpecifierAnnotation(3492Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS);3493IdentifierInfo *Name = AfterScope.getIdentifierInfo();3494Sema::NameClassification Classification = Actions.ClassifyName(3495getCurScope(), SS, Name, AfterScope.getLocation(), Next,3496/*CCC=*/nullptr);3497switch (Classification.getKind()) {3498case Sema::NC_Error:3499SkipMalformedDecl();3500return true;35013502case Sema::NC_Keyword:3503llvm_unreachable("typo correction is not possible here");35043505case Sema::NC_Type:3506case Sema::NC_TypeTemplate:3507case Sema::NC_UndeclaredNonType:3508case Sema::NC_UndeclaredTemplate:3509// Not a previously-declared non-type entity.3510MightBeDeclarator = false;3511break;35123513case Sema::NC_Unknown:3514case Sema::NC_NonType:3515case Sema::NC_DependentNonType:3516case Sema::NC_OverloadSet:3517case Sema::NC_VarTemplate:3518case Sema::NC_FunctionTemplate:3519case Sema::NC_Concept:3520// Might be a redeclaration of a prior entity.3521break;3522}3523}3524}35253526if (MightBeDeclarator)3527return false;35283529const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();3530Diag(PP.getLocForEndOfToken(DS.getRepAsDecl()->getEndLoc()),3531diag::err_expected_after)3532<< DeclSpec::getSpecifierName(DS.getTypeSpecType(), PPol) << tok::semi;35333534// Try to recover from the typo, by dropping the tag definition and parsing3535// the problematic tokens as a type.3536//3537// FIXME: Split the DeclSpec into pieces for the standalone3538// declaration and pieces for the following declaration, instead3539// of assuming that all the other pieces attach to new declaration,3540// and call ParsedFreeStandingDeclSpec as appropriate.3541DS.ClearTypeSpecType();3542ParsedTemplateInfo NotATemplate;3543ParseDeclarationSpecifiers(DS, NotATemplate, AS, DSContext, LateAttrs);3544return false;3545}35463547/// ParseDeclarationSpecifiers3548/// declaration-specifiers: [C99 6.7]3549/// storage-class-specifier declaration-specifiers[opt]3550/// type-specifier declaration-specifiers[opt]3551/// [C99] function-specifier declaration-specifiers[opt]3552/// [C11] alignment-specifier declaration-specifiers[opt]3553/// [GNU] attributes declaration-specifiers[opt]3554/// [Clang] '__module_private__' declaration-specifiers[opt]3555/// [ObjC1] '__kindof' declaration-specifiers[opt]3556///3557/// storage-class-specifier: [C99 6.7.1]3558/// 'typedef'3559/// 'extern'3560/// 'static'3561/// 'auto'3562/// 'register'3563/// [C++] 'mutable'3564/// [C++11] 'thread_local'3565/// [C11] '_Thread_local'3566/// [GNU] '__thread'3567/// function-specifier: [C99 6.7.4]3568/// [C99] 'inline'3569/// [C++] 'virtual'3570/// [C++] 'explicit'3571/// [OpenCL] '__kernel'3572/// 'friend': [C++ dcl.friend]3573/// 'constexpr': [C++0x dcl.constexpr]3574void Parser::ParseDeclarationSpecifiers(3575DeclSpec &DS, ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS,3576DeclSpecContext DSContext, LateParsedAttrList *LateAttrs,3577ImplicitTypenameContext AllowImplicitTypename) {3578if (DS.getSourceRange().isInvalid()) {3579// Start the range at the current token but make the end of the range3580// invalid. This will make the entire range invalid unless we successfully3581// consume a token.3582DS.SetRangeStart(Tok.getLocation());3583DS.SetRangeEnd(SourceLocation());3584}35853586// If we are in a operator context, convert it back into a type specifier3587// context for better error handling later on.3588if (DSContext == DeclSpecContext::DSC_conv_operator) {3589// No implicit typename here.3590AllowImplicitTypename = ImplicitTypenameContext::No;3591DSContext = DeclSpecContext::DSC_type_specifier;3592}35933594bool EnteringContext = (DSContext == DeclSpecContext::DSC_class ||3595DSContext == DeclSpecContext::DSC_top_level);3596bool AttrsLastTime = false;3597ParsedAttributes attrs(AttrFactory);3598// We use Sema's policy to get bool macros right.3599PrintingPolicy Policy = Actions.getPrintingPolicy();3600while (true) {3601bool isInvalid = false;3602bool isStorageClass = false;3603const char *PrevSpec = nullptr;3604unsigned DiagID = 0;36053606// This value needs to be set to the location of the last token if the last3607// token of the specifier is already consumed.3608SourceLocation ConsumedEnd;36093610// HACK: MSVC doesn't consider _Atomic to be a keyword and its STL3611// implementation for VS2013 uses _Atomic as an identifier for one of the3612// classes in <atomic>.3613//3614// A typedef declaration containing _Atomic<...> is among the places where3615// the class is used. If we are currently parsing such a declaration, treat3616// the token as an identifier.3617if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) &&3618DS.getStorageClassSpec() == clang::DeclSpec::SCS_typedef &&3619!DS.hasTypeSpecifier() && GetLookAheadToken(1).is(tok::less))3620Tok.setKind(tok::identifier);36213622SourceLocation Loc = Tok.getLocation();36233624// Helper for image types in OpenCL.3625auto handleOpenCLImageKW = [&] (StringRef Ext, TypeSpecifierType ImageTypeSpec) {3626// Check if the image type is supported and otherwise turn the keyword into an identifier3627// because image types from extensions are not reserved identifiers.3628if (!StringRef(Ext).empty() && !getActions().getOpenCLOptions().isSupported(Ext, getLangOpts())) {3629Tok.getIdentifierInfo()->revertTokenIDToIdentifier();3630Tok.setKind(tok::identifier);3631return false;3632}3633isInvalid = DS.SetTypeSpecType(ImageTypeSpec, Loc, PrevSpec, DiagID, Policy);3634return true;3635};36363637// Turn off usual access checking for template specializations and3638// instantiations.3639bool IsTemplateSpecOrInst =3640(TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||3641TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);36423643switch (Tok.getKind()) {3644default:3645if (Tok.isRegularKeywordAttribute())3646goto Attribute;36473648DoneWithDeclSpec:3649if (!AttrsLastTime)3650ProhibitAttributes(attrs);3651else {3652// Reject C++11 / C23 attributes that aren't type attributes.3653for (const ParsedAttr &PA : attrs) {3654if (!PA.isCXX11Attribute() && !PA.isC23Attribute() &&3655!PA.isRegularKeywordAttribute())3656continue;3657if (PA.getKind() == ParsedAttr::UnknownAttribute)3658// We will warn about the unknown attribute elsewhere (in3659// SemaDeclAttr.cpp)3660continue;3661// GCC ignores this attribute when placed on the DeclSpec in [[]]3662// syntax, so we do the same.3663if (PA.getKind() == ParsedAttr::AT_VectorSize) {3664Diag(PA.getLoc(), diag::warn_attribute_ignored) << PA;3665PA.setInvalid();3666continue;3667}3668// We reject AT_LifetimeBound and AT_AnyX86NoCfCheck, even though they3669// are type attributes, because we historically haven't allowed these3670// to be used as type attributes in C++11 / C23 syntax.3671if (PA.isTypeAttr() && PA.getKind() != ParsedAttr::AT_LifetimeBound &&3672PA.getKind() != ParsedAttr::AT_AnyX86NoCfCheck)3673continue;3674Diag(PA.getLoc(), diag::err_attribute_not_type_attr)3675<< PA << PA.isRegularKeywordAttribute();3676PA.setInvalid();3677}36783679DS.takeAttributesFrom(attrs);3680}36813682// If this is not a declaration specifier token, we're done reading decl3683// specifiers. First verify that DeclSpec's are consistent.3684DS.Finish(Actions, Policy);3685return;36863687// alignment-specifier3688case tok::kw__Alignas:3689diagnoseUseOfC11Keyword(Tok);3690[[fallthrough]];3691case tok::kw_alignas:3692// _Alignas and alignas (C23, not C++) should parse the same way. The C++3693// parsing for alignas happens through the usual attribute parsing. This3694// ensures that an alignas specifier can appear in a type position in C3695// despite that not being valid in C++.3696if (getLangOpts().C23 || Tok.getKind() == tok::kw__Alignas) {3697if (Tok.getKind() == tok::kw_alignas)3698Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();3699ParseAlignmentSpecifier(DS.getAttributes());3700continue;3701}3702[[fallthrough]];3703case tok::l_square:3704if (!isAllowedCXX11AttributeSpecifier())3705goto DoneWithDeclSpec;37063707Attribute:3708ProhibitAttributes(attrs);3709// FIXME: It would be good to recover by accepting the attributes,3710// but attempting to do that now would cause serious3711// madness in terms of diagnostics.3712attrs.clear();3713attrs.Range = SourceRange();37143715ParseCXX11Attributes(attrs);3716AttrsLastTime = true;3717continue;37183719case tok::code_completion: {3720SemaCodeCompletion::ParserCompletionContext CCC =3721SemaCodeCompletion::PCC_Namespace;3722if (DS.hasTypeSpecifier()) {3723bool AllowNonIdentifiers3724= (getCurScope()->getFlags() & (Scope::ControlScope |3725Scope::BlockScope |3726Scope::TemplateParamScope |3727Scope::FunctionPrototypeScope |3728Scope::AtCatchScope)) == 0;3729bool AllowNestedNameSpecifiers3730= DSContext == DeclSpecContext::DSC_top_level ||3731(DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified());37323733cutOffParsing();3734Actions.CodeCompletion().CodeCompleteDeclSpec(3735getCurScope(), DS, AllowNonIdentifiers, AllowNestedNameSpecifiers);3736return;3737}37383739// Class context can appear inside a function/block, so prioritise that.3740if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate)3741CCC = DSContext == DeclSpecContext::DSC_class3742? SemaCodeCompletion::PCC_MemberTemplate3743: SemaCodeCompletion::PCC_Template;3744else if (DSContext == DeclSpecContext::DSC_class)3745CCC = SemaCodeCompletion::PCC_Class;3746else if (getCurScope()->getFnParent() || getCurScope()->getBlockParent())3747CCC = SemaCodeCompletion::PCC_LocalDeclarationSpecifiers;3748else if (CurParsedObjCImpl)3749CCC = SemaCodeCompletion::PCC_ObjCImplementation;37503751cutOffParsing();3752Actions.CodeCompletion().CodeCompleteOrdinaryName(getCurScope(), CCC);3753return;3754}37553756case tok::coloncolon: // ::foo::bar3757// C++ scope specifier. Annotate and loop, or bail out on error.3758if (getLangOpts().CPlusPlus &&3759TryAnnotateCXXScopeToken(EnteringContext)) {3760if (!DS.hasTypeSpecifier())3761DS.SetTypeSpecError();3762goto DoneWithDeclSpec;3763}3764if (Tok.is(tok::coloncolon)) // ::new or ::delete3765goto DoneWithDeclSpec;3766continue;37673768case tok::annot_cxxscope: {3769if (DS.hasTypeSpecifier() || DS.isTypeAltiVecVector())3770goto DoneWithDeclSpec;37713772CXXScopeSpec SS;3773if (TemplateInfo.TemplateParams)3774SS.setTemplateParamLists(*TemplateInfo.TemplateParams);3775Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),3776Tok.getAnnotationRange(),3777SS);37783779// We are looking for a qualified typename.3780Token Next = NextToken();37813782TemplateIdAnnotation *TemplateId = Next.is(tok::annot_template_id)3783? takeTemplateIdAnnotation(Next)3784: nullptr;3785if (TemplateId && TemplateId->hasInvalidName()) {3786// We found something like 'T::U<Args> x', but U is not a template.3787// Assume it was supposed to be a type.3788DS.SetTypeSpecError();3789ConsumeAnnotationToken();3790break;3791}37923793if (TemplateId && TemplateId->Kind == TNK_Type_template) {3794// We have a qualified template-id, e.g., N::A<int>37953796// If this would be a valid constructor declaration with template3797// arguments, we will reject the attempt to form an invalid type-id3798// referring to the injected-class-name when we annotate the token,3799// per C++ [class.qual]p2.3800//3801// To improve diagnostics for this case, parse the declaration as a3802// constructor (and reject the extra template arguments later).3803if ((DSContext == DeclSpecContext::DSC_top_level ||3804DSContext == DeclSpecContext::DSC_class) &&3805TemplateId->Name &&3806Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) &&3807isConstructorDeclarator(/*Unqualified=*/false,3808/*DeductionGuide=*/false,3809DS.isFriendSpecified())) {3810// The user meant this to be an out-of-line constructor3811// definition, but template arguments are not allowed3812// there. Just allow this as a constructor; we'll3813// complain about it later.3814goto DoneWithDeclSpec;3815}38163817DS.getTypeSpecScope() = SS;3818ConsumeAnnotationToken(); // The C++ scope.3819assert(Tok.is(tok::annot_template_id) &&3820"ParseOptionalCXXScopeSpecifier not working");3821AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename);3822continue;3823}38243825if (TemplateId && TemplateId->Kind == TNK_Concept_template) {3826DS.getTypeSpecScope() = SS;3827// This is probably a qualified placeholder-specifier, e.g., ::C<int>3828// auto ... Consume the scope annotation and continue to consume the3829// template-id as a placeholder-specifier. Let the next iteration3830// diagnose a missing auto.3831ConsumeAnnotationToken();3832continue;3833}38343835if (Next.is(tok::annot_typename)) {3836DS.getTypeSpecScope() = SS;3837ConsumeAnnotationToken(); // The C++ scope.3838TypeResult T = getTypeAnnotation(Tok);3839isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename,3840Tok.getAnnotationEndLoc(),3841PrevSpec, DiagID, T, Policy);3842if (isInvalid)3843break;3844DS.SetRangeEnd(Tok.getAnnotationEndLoc());3845ConsumeAnnotationToken(); // The typename3846}38473848if (AllowImplicitTypename == ImplicitTypenameContext::Yes &&3849Next.is(tok::annot_template_id) &&3850static_cast<TemplateIdAnnotation *>(Next.getAnnotationValue())3851->Kind == TNK_Dependent_template_name) {3852DS.getTypeSpecScope() = SS;3853ConsumeAnnotationToken(); // The C++ scope.3854AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename);3855continue;3856}38573858if (Next.isNot(tok::identifier))3859goto DoneWithDeclSpec;38603861// Check whether this is a constructor declaration. If we're in a3862// context where the identifier could be a class name, and it has the3863// shape of a constructor declaration, process it as one.3864if ((DSContext == DeclSpecContext::DSC_top_level ||3865DSContext == DeclSpecContext::DSC_class) &&3866Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(),3867&SS) &&3868isConstructorDeclarator(/*Unqualified=*/false,3869/*DeductionGuide=*/false,3870DS.isFriendSpecified(),3871&TemplateInfo))3872goto DoneWithDeclSpec;38733874// C++20 [temp.spec] 13.9/6.3875// This disables the access checking rules for function template explicit3876// instantiation and explicit specialization:3877// - `return type`.3878SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);38793880ParsedType TypeRep = Actions.getTypeName(3881*Next.getIdentifierInfo(), Next.getLocation(), getCurScope(), &SS,3882false, false, nullptr,3883/*IsCtorOrDtorName=*/false,3884/*WantNontrivialTypeSourceInfo=*/true,3885isClassTemplateDeductionContext(DSContext), AllowImplicitTypename);38863887if (IsTemplateSpecOrInst)3888SAC.done();38893890// If the referenced identifier is not a type, then this declspec is3891// erroneous: We already checked about that it has no type specifier, and3892// C++ doesn't have implicit int. Diagnose it as a typo w.r.t. to the3893// typename.3894if (!TypeRep) {3895if (TryAnnotateTypeConstraint())3896goto DoneWithDeclSpec;3897if (Tok.isNot(tok::annot_cxxscope) ||3898NextToken().isNot(tok::identifier))3899continue;3900// Eat the scope spec so the identifier is current.3901ConsumeAnnotationToken();3902ParsedAttributes Attrs(AttrFactory);3903if (ParseImplicitInt(DS, &SS, TemplateInfo, AS, DSContext, Attrs)) {3904if (!Attrs.empty()) {3905AttrsLastTime = true;3906attrs.takeAllFrom(Attrs);3907}3908continue;3909}3910goto DoneWithDeclSpec;3911}39123913DS.getTypeSpecScope() = SS;3914ConsumeAnnotationToken(); // The C++ scope.39153916isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,3917DiagID, TypeRep, Policy);3918if (isInvalid)3919break;39203921DS.SetRangeEnd(Tok.getLocation());3922ConsumeToken(); // The typename.39233924continue;3925}39263927case tok::annot_typename: {3928// If we've previously seen a tag definition, we were almost surely3929// missing a semicolon after it.3930if (DS.hasTypeSpecifier() && DS.hasTagDefinition())3931goto DoneWithDeclSpec;39323933TypeResult T = getTypeAnnotation(Tok);3934isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,3935DiagID, T, Policy);3936if (isInvalid)3937break;39383939DS.SetRangeEnd(Tok.getAnnotationEndLoc());3940ConsumeAnnotationToken(); // The typename39413942continue;3943}39443945case tok::kw___is_signed:3946// GNU libstdc++ 4.4 uses __is_signed as an identifier, but Clang3947// typically treats it as a trait. If we see __is_signed as it appears3948// in libstdc++, e.g.,3949//3950// static const bool __is_signed;3951//3952// then treat __is_signed as an identifier rather than as a keyword.3953if (DS.getTypeSpecType() == TST_bool &&3954DS.getTypeQualifiers() == DeclSpec::TQ_const &&3955DS.getStorageClassSpec() == DeclSpec::SCS_static)3956TryKeywordIdentFallback(true);39573958// We're done with the declaration-specifiers.3959goto DoneWithDeclSpec;39603961// typedef-name3962case tok::kw___super:3963case tok::kw_decltype:3964case tok::identifier:3965ParseIdentifier: {3966// This identifier can only be a typedef name if we haven't already seen3967// a type-specifier. Without this check we misparse:3968// typedef int X; struct Y { short X; }; as 'short int'.3969if (DS.hasTypeSpecifier())3970goto DoneWithDeclSpec;39713972// If the token is an identifier named "__declspec" and Microsoft3973// extensions are not enabled, it is likely that there will be cascading3974// parse errors if this really is a __declspec attribute. Attempt to3975// recognize that scenario and recover gracefully.3976if (!getLangOpts().DeclSpecKeyword && Tok.is(tok::identifier) &&3977Tok.getIdentifierInfo()->getName() == "__declspec") {3978Diag(Loc, diag::err_ms_attributes_not_enabled);39793980// The next token should be an open paren. If it is, eat the entire3981// attribute declaration and continue.3982if (NextToken().is(tok::l_paren)) {3983// Consume the __declspec identifier.3984ConsumeToken();39853986// Eat the parens and everything between them.3987BalancedDelimiterTracker T(*this, tok::l_paren);3988if (T.consumeOpen()) {3989assert(false && "Not a left paren?");3990return;3991}3992T.skipToEnd();3993continue;3994}3995}39963997// In C++, check to see if this is a scope specifier like foo::bar::, if3998// so handle it as such. This is important for ctor parsing.3999if (getLangOpts().CPlusPlus) {4000// C++20 [temp.spec] 13.9/6.4001// This disables the access checking rules for function template4002// explicit instantiation and explicit specialization:4003// - `return type`.4004SuppressAccessChecks SAC(*this, IsTemplateSpecOrInst);40054006const bool Success = TryAnnotateCXXScopeToken(EnteringContext);40074008if (IsTemplateSpecOrInst)4009SAC.done();40104011if (Success) {4012if (IsTemplateSpecOrInst)4013SAC.redelay();4014DS.SetTypeSpecError();4015goto DoneWithDeclSpec;4016}40174018if (!Tok.is(tok::identifier))4019continue;4020}40214022// Check for need to substitute AltiVec keyword tokens.4023if (TryAltiVecToken(DS, Loc, PrevSpec, DiagID, isInvalid))4024break;40254026// [AltiVec] 2.2: [If the 'vector' specifier is used] The syntax does not4027// allow the use of a typedef name as a type specifier.4028if (DS.isTypeAltiVecVector())4029goto DoneWithDeclSpec;40304031if (DSContext == DeclSpecContext::DSC_objc_method_result &&4032isObjCInstancetype()) {4033ParsedType TypeRep = Actions.ObjC().ActOnObjCInstanceType(Loc);4034assert(TypeRep);4035isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,4036DiagID, TypeRep, Policy);4037if (isInvalid)4038break;40394040DS.SetRangeEnd(Loc);4041ConsumeToken();4042continue;4043}40444045// If we're in a context where the identifier could be a class name,4046// check whether this is a constructor declaration.4047if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&4048Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) &&4049isConstructorDeclarator(/*Unqualified=*/true,4050/*DeductionGuide=*/false,4051DS.isFriendSpecified()))4052goto DoneWithDeclSpec;40534054ParsedType TypeRep = Actions.getTypeName(4055*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr,4056false, false, nullptr, false, false,4057isClassTemplateDeductionContext(DSContext));40584059// If this is not a typedef name, don't parse it as part of the declspec,4060// it must be an implicit int or an error.4061if (!TypeRep) {4062if (TryAnnotateTypeConstraint())4063goto DoneWithDeclSpec;4064if (Tok.isNot(tok::identifier))4065continue;4066ParsedAttributes Attrs(AttrFactory);4067if (ParseImplicitInt(DS, nullptr, TemplateInfo, AS, DSContext, Attrs)) {4068if (!Attrs.empty()) {4069AttrsLastTime = true;4070attrs.takeAllFrom(Attrs);4071}4072continue;4073}4074goto DoneWithDeclSpec;4075}40764077// Likewise, if this is a context where the identifier could be a template4078// name, check whether this is a deduction guide declaration.4079CXXScopeSpec SS;4080if (getLangOpts().CPlusPlus17 &&4081(DSContext == DeclSpecContext::DSC_class ||4082DSContext == DeclSpecContext::DSC_top_level) &&4083Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(),4084Tok.getLocation(), SS) &&4085isConstructorDeclarator(/*Unqualified*/ true,4086/*DeductionGuide*/ true))4087goto DoneWithDeclSpec;40884089isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec,4090DiagID, TypeRep, Policy);4091if (isInvalid)4092break;40934094DS.SetRangeEnd(Tok.getLocation());4095ConsumeToken(); // The identifier40964097// Objective-C supports type arguments and protocol references4098// following an Objective-C object or object pointer4099// type. Handle either one of them.4100if (Tok.is(tok::less) && getLangOpts().ObjC) {4101SourceLocation NewEndLoc;4102TypeResult NewTypeRep = parseObjCTypeArgsAndProtocolQualifiers(4103Loc, TypeRep, /*consumeLastToken=*/true,4104NewEndLoc);4105if (NewTypeRep.isUsable()) {4106DS.UpdateTypeRep(NewTypeRep.get());4107DS.SetRangeEnd(NewEndLoc);4108}4109}41104111// Need to support trailing type qualifiers (e.g. "id<p> const").4112// If a type specifier follows, it will be diagnosed elsewhere.4113continue;4114}41154116// type-name or placeholder-specifier4117case tok::annot_template_id: {4118TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);41194120if (TemplateId->hasInvalidName()) {4121DS.SetTypeSpecError();4122break;4123}41244125if (TemplateId->Kind == TNK_Concept_template) {4126// If we've already diagnosed that this type-constraint has invalid4127// arguments, drop it and just form 'auto' or 'decltype(auto)'.4128if (TemplateId->hasInvalidArgs())4129TemplateId = nullptr;41304131// Any of the following tokens are likely the start of the user4132// forgetting 'auto' or 'decltype(auto)', so diagnose.4133// Note: if updating this list, please make sure we update4134// isCXXDeclarationSpecifier's check for IsPlaceholderSpecifier to have4135// a matching list.4136if (NextToken().isOneOf(tok::identifier, tok::kw_const,4137tok::kw_volatile, tok::kw_restrict, tok::amp,4138tok::ampamp)) {4139Diag(Loc, diag::err_placeholder_expected_auto_or_decltype_auto)4140<< FixItHint::CreateInsertion(NextToken().getLocation(), "auto");4141// Attempt to continue as if 'auto' was placed here.4142isInvalid = DS.SetTypeSpecType(TST_auto, Loc, PrevSpec, DiagID,4143TemplateId, Policy);4144break;4145}4146if (!NextToken().isOneOf(tok::kw_auto, tok::kw_decltype))4147goto DoneWithDeclSpec;41484149if (TemplateId && !isInvalid && Actions.CheckTypeConstraint(TemplateId))4150TemplateId = nullptr;41514152ConsumeAnnotationToken();4153SourceLocation AutoLoc = Tok.getLocation();4154if (TryConsumeToken(tok::kw_decltype)) {4155BalancedDelimiterTracker Tracker(*this, tok::l_paren);4156if (Tracker.consumeOpen()) {4157// Something like `void foo(Iterator decltype i)`4158Diag(Tok, diag::err_expected) << tok::l_paren;4159} else {4160if (!TryConsumeToken(tok::kw_auto)) {4161// Something like `void foo(Iterator decltype(int) i)`4162Tracker.skipToEnd();4163Diag(Tok, diag::err_placeholder_expected_auto_or_decltype_auto)4164<< FixItHint::CreateReplacement(SourceRange(AutoLoc,4165Tok.getLocation()),4166"auto");4167} else {4168Tracker.consumeClose();4169}4170}4171ConsumedEnd = Tok.getLocation();4172DS.setTypeArgumentRange(Tracker.getRange());4173// Even if something went wrong above, continue as if we've seen4174// `decltype(auto)`.4175isInvalid = DS.SetTypeSpecType(TST_decltype_auto, Loc, PrevSpec,4176DiagID, TemplateId, Policy);4177} else {4178isInvalid = DS.SetTypeSpecType(TST_auto, AutoLoc, PrevSpec, DiagID,4179TemplateId, Policy);4180}4181break;4182}41834184if (TemplateId->Kind != TNK_Type_template &&4185TemplateId->Kind != TNK_Undeclared_template) {4186// This template-id does not refer to a type name, so we're4187// done with the type-specifiers.4188goto DoneWithDeclSpec;4189}41904191// If we're in a context where the template-id could be a4192// constructor name or specialization, check whether this is a4193// constructor declaration.4194if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class &&4195Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) &&4196isConstructorDeclarator(/*Unqualified=*/true,4197/*DeductionGuide=*/false,4198DS.isFriendSpecified()))4199goto DoneWithDeclSpec;42004201// Turn the template-id annotation token into a type annotation4202// token, then try again to parse it as a type-specifier.4203CXXScopeSpec SS;4204AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename);4205continue;4206}42074208// Attributes support.4209case tok::kw___attribute:4210case tok::kw___declspec:4211ParseAttributes(PAKM_GNU | PAKM_Declspec, DS.getAttributes(), LateAttrs);4212continue;42134214// Microsoft single token adornments.4215case tok::kw___forceinline: {4216isInvalid = DS.setFunctionSpecForceInline(Loc, PrevSpec, DiagID);4217IdentifierInfo *AttrName = Tok.getIdentifierInfo();4218SourceLocation AttrNameLoc = Tok.getLocation();4219DS.getAttributes().addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc,4220nullptr, 0, tok::kw___forceinline);4221break;4222}42234224case tok::kw___unaligned:4225isInvalid = DS.SetTypeQual(DeclSpec::TQ_unaligned, Loc, PrevSpec, DiagID,4226getLangOpts());4227break;42284229case tok::kw___sptr:4230case tok::kw___uptr:4231case tok::kw___ptr64:4232case tok::kw___ptr32:4233case tok::kw___w64:4234case tok::kw___cdecl:4235case tok::kw___stdcall:4236case tok::kw___fastcall:4237case tok::kw___thiscall:4238case tok::kw___regcall:4239case tok::kw___vectorcall:4240ParseMicrosoftTypeAttributes(DS.getAttributes());4241continue;42424243case tok::kw___funcref:4244ParseWebAssemblyFuncrefTypeAttribute(DS.getAttributes());4245continue;42464247// Borland single token adornments.4248case tok::kw___pascal:4249ParseBorlandTypeAttributes(DS.getAttributes());4250continue;42514252// OpenCL single token adornments.4253case tok::kw___kernel:4254ParseOpenCLKernelAttributes(DS.getAttributes());4255continue;42564257// CUDA/HIP single token adornments.4258case tok::kw___noinline__:4259ParseCUDAFunctionAttributes(DS.getAttributes());4260continue;42614262// Nullability type specifiers.4263case tok::kw__Nonnull:4264case tok::kw__Nullable:4265case tok::kw__Nullable_result:4266case tok::kw__Null_unspecified:4267ParseNullabilityTypeSpecifiers(DS.getAttributes());4268continue;42694270// Objective-C 'kindof' types.4271case tok::kw___kindof:4272DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,4273nullptr, 0, tok::kw___kindof);4274(void)ConsumeToken();4275continue;42764277// storage-class-specifier4278case tok::kw_typedef:4279isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_typedef, Loc,4280PrevSpec, DiagID, Policy);4281isStorageClass = true;4282break;4283case tok::kw_extern:4284if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)4285Diag(Tok, diag::ext_thread_before) << "extern";4286isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_extern, Loc,4287PrevSpec, DiagID, Policy);4288isStorageClass = true;4289break;4290case tok::kw___private_extern__:4291isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_private_extern,4292Loc, PrevSpec, DiagID, Policy);4293isStorageClass = true;4294break;4295case tok::kw_static:4296if (DS.getThreadStorageClassSpec() == DeclSpec::TSCS___thread)4297Diag(Tok, diag::ext_thread_before) << "static";4298isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_static, Loc,4299PrevSpec, DiagID, Policy);4300isStorageClass = true;4301break;4302case tok::kw_auto:4303if (getLangOpts().CPlusPlus11 || getLangOpts().C23) {4304if (isKnownToBeTypeSpecifier(GetLookAheadToken(1))) {4305isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,4306PrevSpec, DiagID, Policy);4307if (!isInvalid && !getLangOpts().C23)4308Diag(Tok, diag::ext_auto_storage_class)4309<< FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());4310} else4311isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto, Loc, PrevSpec,4312DiagID, Policy);4313} else4314isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_auto, Loc,4315PrevSpec, DiagID, Policy);4316isStorageClass = true;4317break;4318case tok::kw___auto_type:4319Diag(Tok, diag::ext_auto_type);4320isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto_type, Loc, PrevSpec,4321DiagID, Policy);4322break;4323case tok::kw_register:4324isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc,4325PrevSpec, DiagID, Policy);4326isStorageClass = true;4327break;4328case tok::kw_mutable:4329isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_mutable, Loc,4330PrevSpec, DiagID, Policy);4331isStorageClass = true;4332break;4333case tok::kw___thread:4334isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc,4335PrevSpec, DiagID);4336isStorageClass = true;4337break;4338case tok::kw_thread_local:4339if (getLangOpts().C23)4340Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();4341// We map thread_local to _Thread_local in C23 mode so it retains the C4342// semantics rather than getting the C++ semantics.4343// FIXME: diagnostics will show _Thread_local when the user wrote4344// thread_local in source in C23 mode; we need some general way to4345// identify which way the user spelled the keyword in source.4346isInvalid = DS.SetStorageClassSpecThread(4347getLangOpts().C23 ? DeclSpec::TSCS__Thread_local4348: DeclSpec::TSCS_thread_local,4349Loc, PrevSpec, DiagID);4350isStorageClass = true;4351break;4352case tok::kw__Thread_local:4353diagnoseUseOfC11Keyword(Tok);4354isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local,4355Loc, PrevSpec, DiagID);4356isStorageClass = true;4357break;43584359// function-specifier4360case tok::kw_inline:4361isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID);4362break;4363case tok::kw_virtual:4364// C++ for OpenCL does not allow virtual function qualifier, to avoid4365// function pointers restricted in OpenCL v2.0 s6.9.a.4366if (getLangOpts().OpenCLCPlusPlus &&4367!getActions().getOpenCLOptions().isAvailableOption(4368"__cl_clang_function_pointers", getLangOpts())) {4369DiagID = diag::err_openclcxx_virtual_function;4370PrevSpec = Tok.getIdentifierInfo()->getNameStart();4371isInvalid = true;4372} else {4373isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID);4374}4375break;4376case tok::kw_explicit: {4377SourceLocation ExplicitLoc = Loc;4378SourceLocation CloseParenLoc;4379ExplicitSpecifier ExplicitSpec(nullptr, ExplicitSpecKind::ResolvedTrue);4380ConsumedEnd = ExplicitLoc;4381ConsumeToken(); // kw_explicit4382if (Tok.is(tok::l_paren)) {4383if (getLangOpts().CPlusPlus20 || isExplicitBool() == TPResult::True) {4384Diag(Tok.getLocation(), getLangOpts().CPlusPlus204385? diag::warn_cxx17_compat_explicit_bool4386: diag::ext_explicit_bool);43874388ExprResult ExplicitExpr(static_cast<Expr *>(nullptr));4389BalancedDelimiterTracker Tracker(*this, tok::l_paren);4390Tracker.consumeOpen();43914392EnterExpressionEvaluationContext ConstantEvaluated(4393Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);43944395ExplicitExpr = ParseConstantExpressionInExprEvalContext();4396ConsumedEnd = Tok.getLocation();4397if (ExplicitExpr.isUsable()) {4398CloseParenLoc = Tok.getLocation();4399Tracker.consumeClose();4400ExplicitSpec =4401Actions.ActOnExplicitBoolSpecifier(ExplicitExpr.get());4402} else4403Tracker.skipToEnd();4404} else {4405Diag(Tok.getLocation(), diag::warn_cxx20_compat_explicit_bool);4406}4407}4408isInvalid = DS.setFunctionSpecExplicit(ExplicitLoc, PrevSpec, DiagID,4409ExplicitSpec, CloseParenLoc);4410break;4411}4412case tok::kw__Noreturn:4413diagnoseUseOfC11Keyword(Tok);4414isInvalid = DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);4415break;44164417// friend4418case tok::kw_friend:4419if (DSContext == DeclSpecContext::DSC_class) {4420isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID);4421Scope *CurS = getCurScope();4422if (!isInvalid && CurS)4423CurS->setFlags(CurS->getFlags() | Scope::FriendScope);4424} else {4425PrevSpec = ""; // not actually used by the diagnostic4426DiagID = diag::err_friend_invalid_in_context;4427isInvalid = true;4428}4429break;44304431// Modules4432case tok::kw___module_private__:4433isInvalid = DS.setModulePrivateSpec(Loc, PrevSpec, DiagID);4434break;44354436// constexpr, consteval, constinit specifiers4437case tok::kw_constexpr:4438if (getLangOpts().C23)4439Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();4440isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constexpr, Loc,4441PrevSpec, DiagID);4442break;4443case tok::kw_consteval:4444isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Consteval, Loc,4445PrevSpec, DiagID);4446break;4447case tok::kw_constinit:4448isInvalid = DS.SetConstexprSpec(ConstexprSpecKind::Constinit, Loc,4449PrevSpec, DiagID);4450break;44514452// type-specifier4453case tok::kw_short:4454isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::Short, Loc, PrevSpec,4455DiagID, Policy);4456break;4457case tok::kw_long:4458if (DS.getTypeSpecWidth() != TypeSpecifierWidth::Long)4459isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::Long, Loc, PrevSpec,4460DiagID, Policy);4461else4462isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::LongLong, Loc,4463PrevSpec, DiagID, Policy);4464break;4465case tok::kw___int64:4466isInvalid = DS.SetTypeSpecWidth(TypeSpecifierWidth::LongLong, Loc,4467PrevSpec, DiagID, Policy);4468break;4469case tok::kw_signed:4470isInvalid =4471DS.SetTypeSpecSign(TypeSpecifierSign::Signed, Loc, PrevSpec, DiagID);4472break;4473case tok::kw_unsigned:4474isInvalid = DS.SetTypeSpecSign(TypeSpecifierSign::Unsigned, Loc, PrevSpec,4475DiagID);4476break;4477case tok::kw__Complex:4478if (!getLangOpts().C99)4479Diag(Tok, diag::ext_c99_feature) << Tok.getName();4480isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,4481DiagID);4482break;4483case tok::kw__Imaginary:4484if (!getLangOpts().C99)4485Diag(Tok, diag::ext_c99_feature) << Tok.getName();4486isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,4487DiagID);4488break;4489case tok::kw_void:4490isInvalid = DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec,4491DiagID, Policy);4492break;4493case tok::kw_char:4494isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec,4495DiagID, Policy);4496break;4497case tok::kw_int:4498isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec,4499DiagID, Policy);4500break;4501case tok::kw__ExtInt:4502case tok::kw__BitInt: {4503DiagnoseBitIntUse(Tok);4504ExprResult ER = ParseExtIntegerArgument();4505if (ER.isInvalid())4506continue;4507isInvalid = DS.SetBitIntType(Loc, ER.get(), PrevSpec, DiagID, Policy);4508ConsumedEnd = PrevTokLocation;4509break;4510}4511case tok::kw___int128:4512isInvalid = DS.SetTypeSpecType(DeclSpec::TST_int128, Loc, PrevSpec,4513DiagID, Policy);4514break;4515case tok::kw_half:4516isInvalid = DS.SetTypeSpecType(DeclSpec::TST_half, Loc, PrevSpec,4517DiagID, Policy);4518break;4519case tok::kw___bf16:4520isInvalid = DS.SetTypeSpecType(DeclSpec::TST_BFloat16, Loc, PrevSpec,4521DiagID, Policy);4522break;4523case tok::kw_float:4524isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec,4525DiagID, Policy);4526break;4527case tok::kw_double:4528isInvalid = DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec,4529DiagID, Policy);4530break;4531case tok::kw__Float16:4532isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec,4533DiagID, Policy);4534break;4535case tok::kw__Accum:4536assert(getLangOpts().FixedPoint &&4537"This keyword is only used when fixed point types are enabled "4538"with `-ffixed-point`");4539isInvalid = DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec, DiagID,4540Policy);4541break;4542case tok::kw__Fract:4543assert(getLangOpts().FixedPoint &&4544"This keyword is only used when fixed point types are enabled "4545"with `-ffixed-point`");4546isInvalid = DS.SetTypeSpecType(DeclSpec::TST_fract, Loc, PrevSpec, DiagID,4547Policy);4548break;4549case tok::kw__Sat:4550assert(getLangOpts().FixedPoint &&4551"This keyword is only used when fixed point types are enabled "4552"with `-ffixed-point`");4553isInvalid = DS.SetTypeSpecSat(Loc, PrevSpec, DiagID);4554break;4555case tok::kw___float128:4556isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec,4557DiagID, Policy);4558break;4559case tok::kw___ibm128:4560isInvalid = DS.SetTypeSpecType(DeclSpec::TST_ibm128, Loc, PrevSpec,4561DiagID, Policy);4562break;4563case tok::kw_wchar_t:4564isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec,4565DiagID, Policy);4566break;4567case tok::kw_char8_t:4568isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char8, Loc, PrevSpec,4569DiagID, Policy);4570break;4571case tok::kw_char16_t:4572isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec,4573DiagID, Policy);4574break;4575case tok::kw_char32_t:4576isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec,4577DiagID, Policy);4578break;4579case tok::kw_bool:4580if (getLangOpts().C23)4581Diag(Tok, diag::warn_c23_compat_keyword) << Tok.getName();4582[[fallthrough]];4583case tok::kw__Bool:4584if (Tok.is(tok::kw__Bool) && !getLangOpts().C99)4585Diag(Tok, diag::ext_c99_feature) << Tok.getName();45864587if (Tok.is(tok::kw_bool) &&4588DS.getTypeSpecType() != DeclSpec::TST_unspecified &&4589DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {4590PrevSpec = ""; // Not used by the diagnostic.4591DiagID = diag::err_bool_redeclaration;4592// For better error recovery.4593Tok.setKind(tok::identifier);4594isInvalid = true;4595} else {4596isInvalid = DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec,4597DiagID, Policy);4598}4599break;4600case tok::kw__Decimal32:4601isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal32, Loc, PrevSpec,4602DiagID, Policy);4603break;4604case tok::kw__Decimal64:4605isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal64, Loc, PrevSpec,4606DiagID, Policy);4607break;4608case tok::kw__Decimal128:4609isInvalid = DS.SetTypeSpecType(DeclSpec::TST_decimal128, Loc, PrevSpec,4610DiagID, Policy);4611break;4612case tok::kw___vector:4613isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);4614break;4615case tok::kw___pixel:4616isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);4617break;4618case tok::kw___bool:4619isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);4620break;4621case tok::kw_pipe:4622if (!getLangOpts().OpenCL ||4623getLangOpts().getOpenCLCompatibleVersion() < 200) {4624// OpenCL 2.0 and later define this keyword. OpenCL 1.2 and earlier4625// should support the "pipe" word as identifier.4626Tok.getIdentifierInfo()->revertTokenIDToIdentifier();4627Tok.setKind(tok::identifier);4628goto DoneWithDeclSpec;4629} else if (!getLangOpts().OpenCLPipes) {4630DiagID = diag::err_opencl_unknown_type_specifier;4631PrevSpec = Tok.getIdentifierInfo()->getNameStart();4632isInvalid = true;4633} else4634isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy);4635break;4636// We only need to enumerate each image type once.4637#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext)4638#define IMAGE_WRITE_TYPE(Type, Id, Ext)4639#define IMAGE_READ_TYPE(ImgType, Id, Ext) \4640case tok::kw_##ImgType##_t: \4641if (!handleOpenCLImageKW(Ext, DeclSpec::TST_##ImgType##_t)) \4642goto DoneWithDeclSpec; \4643break;4644#include "clang/Basic/OpenCLImageTypes.def"4645case tok::kw___unknown_anytype:4646isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc,4647PrevSpec, DiagID, Policy);4648break;46494650// class-specifier:4651case tok::kw_class:4652case tok::kw_struct:4653case tok::kw___interface:4654case tok::kw_union: {4655tok::TokenKind Kind = Tok.getKind();4656ConsumeToken();46574658// These are attributes following class specifiers.4659// To produce better diagnostic, we parse them when4660// parsing class specifier.4661ParsedAttributes Attributes(AttrFactory);4662ParseClassSpecifier(Kind, Loc, DS, TemplateInfo, AS,4663EnteringContext, DSContext, Attributes);46644665// If there are attributes following class specifier,4666// take them over and handle them here.4667if (!Attributes.empty()) {4668AttrsLastTime = true;4669attrs.takeAllFrom(Attributes);4670}4671continue;4672}46734674// enum-specifier:4675case tok::kw_enum:4676ConsumeToken();4677ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSContext);4678continue;46794680// cv-qualifier:4681case tok::kw_const:4682isInvalid = DS.SetTypeQual(DeclSpec::TQ_const, Loc, PrevSpec, DiagID,4683getLangOpts());4684break;4685case tok::kw_volatile:4686isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,4687getLangOpts());4688break;4689case tok::kw_restrict:4690isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,4691getLangOpts());4692break;46934694// C++ typename-specifier:4695case tok::kw_typename:4696if (TryAnnotateTypeOrScopeToken()) {4697DS.SetTypeSpecError();4698goto DoneWithDeclSpec;4699}4700if (!Tok.is(tok::kw_typename))4701continue;4702break;47034704// C23/GNU typeof support.4705case tok::kw_typeof:4706case tok::kw_typeof_unqual:4707ParseTypeofSpecifier(DS);4708continue;47094710case tok::annot_decltype:4711ParseDecltypeSpecifier(DS);4712continue;47134714case tok::annot_pack_indexing_type:4715ParsePackIndexingType(DS);4716continue;47174718case tok::annot_pragma_pack:4719HandlePragmaPack();4720continue;47214722case tok::annot_pragma_ms_pragma:4723HandlePragmaMSPragma();4724continue;47254726case tok::annot_pragma_ms_vtordisp:4727HandlePragmaMSVtorDisp();4728continue;47294730case tok::annot_pragma_ms_pointers_to_members:4731HandlePragmaMSPointersToMembers();4732continue;47334734#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:4735#include "clang/Basic/TransformTypeTraits.def"4736// HACK: libstdc++ already uses '__remove_cv' as an alias template so we4737// work around this by expecting all transform type traits to be suffixed4738// with '('. They're an identifier otherwise.4739if (!MaybeParseTypeTransformTypeSpecifier(DS))4740goto ParseIdentifier;4741continue;47424743case tok::kw__Atomic:4744// C11 6.7.2.4/4:4745// If the _Atomic keyword is immediately followed by a left parenthesis,4746// it is interpreted as a type specifier (with a type name), not as a4747// type qualifier.4748diagnoseUseOfC11Keyword(Tok);4749if (NextToken().is(tok::l_paren)) {4750ParseAtomicSpecifier(DS);4751continue;4752}4753isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,4754getLangOpts());4755break;47564757// OpenCL address space qualifiers:4758case tok::kw___generic:4759// generic address space is introduced only in OpenCL v2.04760// see OpenCL C Spec v2.0 s6.5.54761// OpenCL v3.0 introduces __opencl_c_generic_address_space4762// feature macro to indicate if generic address space is supported4763if (!Actions.getLangOpts().OpenCLGenericAddressSpace) {4764DiagID = diag::err_opencl_unknown_type_specifier;4765PrevSpec = Tok.getIdentifierInfo()->getNameStart();4766isInvalid = true;4767break;4768}4769[[fallthrough]];4770case tok::kw_private:4771// It's fine (but redundant) to check this for __generic on the4772// fallthrough path; we only form the __generic token in OpenCL mode.4773if (!getLangOpts().OpenCL)4774goto DoneWithDeclSpec;4775[[fallthrough]];4776case tok::kw___private:4777case tok::kw___global:4778case tok::kw___local:4779case tok::kw___constant:4780// OpenCL access qualifiers:4781case tok::kw___read_only:4782case tok::kw___write_only:4783case tok::kw___read_write:4784ParseOpenCLQualifiers(DS.getAttributes());4785break;47864787case tok::kw_groupshared:4788case tok::kw_in:4789case tok::kw_inout:4790case tok::kw_out:4791// NOTE: ParseHLSLQualifiers will consume the qualifier token.4792ParseHLSLQualifiers(DS.getAttributes());4793continue;47944795case tok::less:4796// GCC ObjC supports types like "<SomeProtocol>" as a synonym for4797// "id<SomeProtocol>". This is hopelessly old fashioned and dangerous,4798// but we support it.4799if (DS.hasTypeSpecifier() || !getLangOpts().ObjC)4800goto DoneWithDeclSpec;48014802SourceLocation StartLoc = Tok.getLocation();4803SourceLocation EndLoc;4804TypeResult Type = parseObjCProtocolQualifierType(EndLoc);4805if (Type.isUsable()) {4806if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc, StartLoc,4807PrevSpec, DiagID, Type.get(),4808Actions.getASTContext().getPrintingPolicy()))4809Diag(StartLoc, DiagID) << PrevSpec;48104811DS.SetRangeEnd(EndLoc);4812} else {4813DS.SetTypeSpecError();4814}48154816// Need to support trailing type qualifiers (e.g. "id<p> const").4817// If a type specifier follows, it will be diagnosed elsewhere.4818continue;4819}48204821DS.SetRangeEnd(ConsumedEnd.isValid() ? ConsumedEnd : Tok.getLocation());48224823// If the specifier wasn't legal, issue a diagnostic.4824if (isInvalid) {4825assert(PrevSpec && "Method did not return previous specifier!");4826assert(DiagID);48274828if (DiagID == diag::ext_duplicate_declspec ||4829DiagID == diag::ext_warn_duplicate_declspec ||4830DiagID == diag::err_duplicate_declspec)4831Diag(Loc, DiagID) << PrevSpec4832<< FixItHint::CreateRemoval(4833SourceRange(Loc, DS.getEndLoc()));4834else if (DiagID == diag::err_opencl_unknown_type_specifier) {4835Diag(Loc, DiagID) << getLangOpts().getOpenCLVersionString() << PrevSpec4836<< isStorageClass;4837} else4838Diag(Loc, DiagID) << PrevSpec;4839}48404841if (DiagID != diag::err_bool_redeclaration && ConsumedEnd.isInvalid())4842// After an error the next token can be an annotation token.4843ConsumeAnyToken();48444845AttrsLastTime = false;4846}4847}48484849static void DiagnoseCountAttributedTypeInUnnamedAnon(ParsingDeclSpec &DS,4850Parser &P) {48514852if (DS.getTypeSpecType() != DeclSpec::TST_struct)4853return;48544855auto *RD = dyn_cast<RecordDecl>(DS.getRepAsDecl());4856// We're only interested in unnamed, non-anonymous struct4857if (!RD || !RD->getName().empty() || RD->isAnonymousStructOrUnion())4858return;48594860for (auto *I : RD->decls()) {4861auto *VD = dyn_cast<ValueDecl>(I);4862if (!VD)4863continue;48644865auto *CAT = VD->getType()->getAs<CountAttributedType>();4866if (!CAT)4867continue;48684869for (const auto &DD : CAT->dependent_decls()) {4870if (!RD->containsDecl(DD.getDecl())) {4871P.Diag(VD->getBeginLoc(), diag::err_count_attr_param_not_in_same_struct)4872<< DD.getDecl() << CAT->getKind() << CAT->isArrayType();4873P.Diag(DD.getDecl()->getBeginLoc(),4874diag::note_flexible_array_counted_by_attr_field)4875<< DD.getDecl();4876}4877}4878}4879}48804881/// ParseStructDeclaration - Parse a struct declaration without the terminating4882/// semicolon.4883///4884/// Note that a struct declaration refers to a declaration in a struct,4885/// not to the declaration of a struct.4886///4887/// struct-declaration:4888/// [C23] attributes-specifier-seq[opt]4889/// specifier-qualifier-list struct-declarator-list4890/// [GNU] __extension__ struct-declaration4891/// [GNU] specifier-qualifier-list4892/// struct-declarator-list:4893/// struct-declarator4894/// struct-declarator-list ',' struct-declarator4895/// [GNU] struct-declarator-list ',' attributes[opt] struct-declarator4896/// struct-declarator:4897/// declarator4898/// [GNU] declarator attributes[opt]4899/// declarator[opt] ':' constant-expression4900/// [GNU] declarator[opt] ':' constant-expression attributes[opt]4901///4902void Parser::ParseStructDeclaration(4903ParsingDeclSpec &DS,4904llvm::function_ref<Decl *(ParsingFieldDeclarator &)> FieldsCallback,4905LateParsedAttrList *LateFieldAttrs) {49064907if (Tok.is(tok::kw___extension__)) {4908// __extension__ silences extension warnings in the subexpression.4909ExtensionRAIIObject O(Diags); // Use RAII to do this.4910ConsumeToken();4911return ParseStructDeclaration(DS, FieldsCallback, LateFieldAttrs);4912}49134914// Parse leading attributes.4915ParsedAttributes Attrs(AttrFactory);4916MaybeParseCXX11Attributes(Attrs);49174918// Parse the common specifier-qualifiers-list piece.4919ParseSpecifierQualifierList(DS);49204921// If there are no declarators, this is a free-standing declaration4922// specifier. Let the actions module cope with it.4923if (Tok.is(tok::semi)) {4924// C23 6.7.2.1p9 : "The optional attribute specifier sequence in a4925// member declaration appertains to each of the members declared by the4926// member declarator list; it shall not appear if the optional member4927// declarator list is omitted."4928ProhibitAttributes(Attrs);4929RecordDecl *AnonRecord = nullptr;4930Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(4931getCurScope(), AS_none, DS, ParsedAttributesView::none(), AnonRecord);4932assert(!AnonRecord && "Did not expect anonymous struct or union here");4933DS.complete(TheDecl);4934return;4935}49364937// Read struct-declarators until we find the semicolon.4938bool FirstDeclarator = true;4939SourceLocation CommaLoc;4940while (true) {4941ParsingFieldDeclarator DeclaratorInfo(*this, DS, Attrs);4942DeclaratorInfo.D.setCommaLoc(CommaLoc);49434944// Attributes are only allowed here on successive declarators.4945if (!FirstDeclarator) {4946// However, this does not apply for [[]] attributes (which could show up4947// before or after the __attribute__ attributes).4948DiagnoseAndSkipCXX11Attributes();4949MaybeParseGNUAttributes(DeclaratorInfo.D);4950DiagnoseAndSkipCXX11Attributes();4951}49524953/// struct-declarator: declarator4954/// struct-declarator: declarator[opt] ':' constant-expression4955if (Tok.isNot(tok::colon)) {4956// Don't parse FOO:BAR as if it were a typo for FOO::BAR.4957ColonProtectionRAIIObject X(*this);4958ParseDeclarator(DeclaratorInfo.D);4959} else4960DeclaratorInfo.D.SetIdentifier(nullptr, Tok.getLocation());49614962// Here, we now know that the unnamed struct is not an anonymous struct.4963// Report an error if a counted_by attribute refers to a field in a4964// different named struct.4965DiagnoseCountAttributedTypeInUnnamedAnon(DS, *this);49664967if (TryConsumeToken(tok::colon)) {4968ExprResult Res(ParseConstantExpression());4969if (Res.isInvalid())4970SkipUntil(tok::semi, StopBeforeMatch);4971else4972DeclaratorInfo.BitfieldSize = Res.get();4973}49744975// If attributes exist after the declarator, parse them.4976MaybeParseGNUAttributes(DeclaratorInfo.D, LateFieldAttrs);49774978// We're done with this declarator; invoke the callback.4979Decl *Field = FieldsCallback(DeclaratorInfo);4980if (Field)4981DistributeCLateParsedAttrs(Field, LateFieldAttrs);49824983// If we don't have a comma, it is either the end of the list (a ';')4984// or an error, bail out.4985if (!TryConsumeToken(tok::comma, CommaLoc))4986return;49874988FirstDeclarator = false;4989}4990}49914992// TODO: All callers of this function should be moved to4993// `Parser::ParseLexedAttributeList`.4994void Parser::ParseLexedCAttributeList(LateParsedAttrList &LAs, bool EnterScope,4995ParsedAttributes *OutAttrs) {4996assert(LAs.parseSoon() &&4997"Attribute list should be marked for immediate parsing.");4998for (auto *LA : LAs) {4999ParseLexedCAttribute(*LA, EnterScope, OutAttrs);5000delete LA;5001}5002LAs.clear();5003}50045005/// Finish parsing an attribute for which parsing was delayed.5006/// This will be called at the end of parsing a class declaration5007/// for each LateParsedAttribute. We consume the saved tokens and5008/// create an attribute with the arguments filled in. We add this5009/// to the Attribute list for the decl.5010void Parser::ParseLexedCAttribute(LateParsedAttribute &LA, bool EnterScope,5011ParsedAttributes *OutAttrs) {5012// Create a fake EOF so that attribute parsing won't go off the end of the5013// attribute.5014Token AttrEnd;5015AttrEnd.startToken();5016AttrEnd.setKind(tok::eof);5017AttrEnd.setLocation(Tok.getLocation());5018AttrEnd.setEofData(LA.Toks.data());5019LA.Toks.push_back(AttrEnd);50205021// Append the current token at the end of the new token stream so that it5022// doesn't get lost.5023LA.Toks.push_back(Tok);5024PP.EnterTokenStream(LA.Toks, /*DisableMacroExpansion=*/true,5025/*IsReinject=*/true);5026// Drop the current token and bring the first cached one. It's the same token5027// as when we entered this function.5028ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);50295030// TODO: Use `EnterScope`5031(void)EnterScope;50325033ParsedAttributes Attrs(AttrFactory);50345035assert(LA.Decls.size() <= 1 &&5036"late field attribute expects to have at most one declaration.");50375038// Dispatch based on the attribute and parse it5039ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, nullptr, nullptr,5040SourceLocation(), ParsedAttr::Form::GNU(), nullptr);50415042for (auto *D : LA.Decls)5043Actions.ActOnFinishDelayedAttribute(getCurScope(), D, Attrs);50445045// Due to a parsing error, we either went over the cached tokens or5046// there are still cached tokens left, so we skip the leftover tokens.5047while (Tok.isNot(tok::eof))5048ConsumeAnyToken();50495050// Consume the fake EOF token if it's there5051if (Tok.is(tok::eof) && Tok.getEofData() == AttrEnd.getEofData())5052ConsumeAnyToken();50535054if (OutAttrs) {5055OutAttrs->takeAllFrom(Attrs);5056}5057}50585059/// ParseStructUnionBody5060/// struct-contents:5061/// struct-declaration-list5062/// [EXT] empty5063/// [GNU] "struct-declaration-list" without terminating ';'5064/// struct-declaration-list:5065/// struct-declaration5066/// struct-declaration-list struct-declaration5067/// [OBC] '@' 'defs' '(' class-name ')'5068///5069void Parser::ParseStructUnionBody(SourceLocation RecordLoc,5070DeclSpec::TST TagType, RecordDecl *TagDecl) {5071PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,5072"parsing struct/union body");5073assert(!getLangOpts().CPlusPlus && "C++ declarations not supported");50745075BalancedDelimiterTracker T(*this, tok::l_brace);5076if (T.consumeOpen())5077return;50785079ParseScope StructScope(this, Scope::ClassScope|Scope::DeclScope);5080Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);50815082// `LateAttrParseExperimentalExtOnly=true` requests that only attributes5083// marked with `LateAttrParseExperimentalExt` are late parsed.5084LateParsedAttrList LateFieldAttrs(/*PSoon=*/true,5085/*LateAttrParseExperimentalExtOnly=*/true);50865087// While we still have something to read, read the declarations in the struct.5088while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&5089Tok.isNot(tok::eof)) {5090// Each iteration of this loop reads one struct-declaration.50915092// Check for extraneous top-level semicolon.5093if (Tok.is(tok::semi)) {5094ConsumeExtraSemi(InsideStruct, TagType);5095continue;5096}50975098// Parse _Static_assert declaration.5099if (Tok.isOneOf(tok::kw__Static_assert, tok::kw_static_assert)) {5100SourceLocation DeclEnd;5101ParseStaticAssertDeclaration(DeclEnd);5102continue;5103}51045105if (Tok.is(tok::annot_pragma_pack)) {5106HandlePragmaPack();5107continue;5108}51095110if (Tok.is(tok::annot_pragma_align)) {5111HandlePragmaAlign();5112continue;5113}51145115if (Tok.isOneOf(tok::annot_pragma_openmp, tok::annot_attr_openmp)) {5116// Result can be ignored, because it must be always empty.5117AccessSpecifier AS = AS_none;5118ParsedAttributes Attrs(AttrFactory);5119(void)ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs);5120continue;5121}51225123if (Tok.is(tok::annot_pragma_openacc)) {5124ParseOpenACCDirectiveDecl();5125continue;5126}51275128if (tok::isPragmaAnnotation(Tok.getKind())) {5129Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl)5130<< DeclSpec::getSpecifierName(5131TagType, Actions.getASTContext().getPrintingPolicy());5132ConsumeAnnotationToken();5133continue;5134}51355136if (!Tok.is(tok::at)) {5137auto CFieldCallback = [&](ParsingFieldDeclarator &FD) -> Decl * {5138// Install the declarator into the current TagDecl.5139Decl *Field =5140Actions.ActOnField(getCurScope(), TagDecl,5141FD.D.getDeclSpec().getSourceRange().getBegin(),5142FD.D, FD.BitfieldSize);5143FD.complete(Field);5144return Field;5145};51465147// Parse all the comma separated declarators.5148ParsingDeclSpec DS(*this);5149ParseStructDeclaration(DS, CFieldCallback, &LateFieldAttrs);5150} else { // Handle @defs5151ConsumeToken();5152if (!Tok.isObjCAtKeyword(tok::objc_defs)) {5153Diag(Tok, diag::err_unexpected_at);5154SkipUntil(tok::semi);5155continue;5156}5157ConsumeToken();5158ExpectAndConsume(tok::l_paren);5159if (!Tok.is(tok::identifier)) {5160Diag(Tok, diag::err_expected) << tok::identifier;5161SkipUntil(tok::semi);5162continue;5163}5164SmallVector<Decl *, 16> Fields;5165Actions.ObjC().ActOnDefs(getCurScope(), TagDecl, Tok.getLocation(),5166Tok.getIdentifierInfo(), Fields);5167ConsumeToken();5168ExpectAndConsume(tok::r_paren);5169}51705171if (TryConsumeToken(tok::semi))5172continue;51735174if (Tok.is(tok::r_brace)) {5175ExpectAndConsume(tok::semi, diag::ext_expected_semi_decl_list);5176break;5177}51785179ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);5180// Skip to end of block or statement to avoid ext-warning on extra ';'.5181SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);5182// If we stopped at a ';', eat it.5183TryConsumeToken(tok::semi);5184}51855186T.consumeClose();51875188ParsedAttributes attrs(AttrFactory);5189// If attributes exist after struct contents, parse them.5190MaybeParseGNUAttributes(attrs, &LateFieldAttrs);51915192// Late parse field attributes if necessary.5193ParseLexedCAttributeList(LateFieldAttrs, /*EnterScope=*/false);51945195SmallVector<Decl *, 32> FieldDecls(TagDecl->fields());51965197Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls,5198T.getOpenLocation(), T.getCloseLocation(), attrs);5199StructScope.Exit();5200Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange());5201}52025203/// ParseEnumSpecifier5204/// enum-specifier: [C99 6.7.2.2]5205/// 'enum' identifier[opt] '{' enumerator-list '}'5206///[C99/C++]'enum' identifier[opt] '{' enumerator-list ',' '}'5207/// [GNU] 'enum' attributes[opt] identifier[opt] '{' enumerator-list ',' [opt]5208/// '}' attributes[opt]5209/// [MS] 'enum' __declspec[opt] identifier[opt] '{' enumerator-list ',' [opt]5210/// '}'5211/// 'enum' identifier5212/// [GNU] 'enum' attributes[opt] identifier5213///5214/// [C++11] enum-head '{' enumerator-list[opt] '}'5215/// [C++11] enum-head '{' enumerator-list ',' '}'5216///5217/// enum-head: [C++11]5218/// enum-key attribute-specifier-seq[opt] identifier[opt] enum-base[opt]5219/// enum-key attribute-specifier-seq[opt] nested-name-specifier5220/// identifier enum-base[opt]5221///5222/// enum-key: [C++11]5223/// 'enum'5224/// 'enum' 'class'5225/// 'enum' 'struct'5226///5227/// enum-base: [C++11]5228/// ':' type-specifier-seq5229///5230/// [C++] elaborated-type-specifier:5231/// [C++] 'enum' nested-name-specifier[opt] identifier5232///5233void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,5234const ParsedTemplateInfo &TemplateInfo,5235AccessSpecifier AS, DeclSpecContext DSC) {5236// Parse the tag portion of this.5237if (Tok.is(tok::code_completion)) {5238// Code completion for an enum name.5239cutOffParsing();5240Actions.CodeCompletion().CodeCompleteTag(getCurScope(), DeclSpec::TST_enum);5241DS.SetTypeSpecError(); // Needed by ActOnUsingDeclaration.5242return;5243}52445245// If attributes exist after tag, parse them.5246ParsedAttributes attrs(AttrFactory);5247MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);52485249SourceLocation ScopedEnumKWLoc;5250bool IsScopedUsingClassTag = false;52515252// In C++11, recognize 'enum class' and 'enum struct'.5253if (Tok.isOneOf(tok::kw_class, tok::kw_struct) && getLangOpts().CPlusPlus) {5254Diag(Tok, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_scoped_enum5255: diag::ext_scoped_enum);5256IsScopedUsingClassTag = Tok.is(tok::kw_class);5257ScopedEnumKWLoc = ConsumeToken();52585259// Attributes are not allowed between these keywords. Diagnose,5260// but then just treat them like they appeared in the right place.5261ProhibitAttributes(attrs);52625263// They are allowed afterwards, though.5264MaybeParseAttributes(PAKM_GNU | PAKM_Declspec | PAKM_CXX11, attrs);5265}52665267// C++11 [temp.explicit]p12:5268// The usual access controls do not apply to names used to specify5269// explicit instantiations.5270// We extend this to also cover explicit specializations. Note that5271// we don't suppress if this turns out to be an elaborated type5272// specifier.5273bool shouldDelayDiagsInTag =5274(TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||5275TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);5276SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);52775278// Determine whether this declaration is permitted to have an enum-base.5279AllowDefiningTypeSpec AllowEnumSpecifier =5280isDefiningTypeSpecifierContext(DSC, getLangOpts().CPlusPlus);5281bool CanBeOpaqueEnumDeclaration =5282DS.isEmpty() && isOpaqueEnumDeclarationContext(DSC);5283bool CanHaveEnumBase = (getLangOpts().CPlusPlus11 || getLangOpts().ObjC ||5284getLangOpts().MicrosoftExt) &&5285(AllowEnumSpecifier == AllowDefiningTypeSpec::Yes ||5286CanBeOpaqueEnumDeclaration);52875288CXXScopeSpec &SS = DS.getTypeSpecScope();5289if (getLangOpts().CPlusPlus) {5290// "enum foo : bar;" is not a potential typo for "enum foo::bar;".5291ColonProtectionRAIIObject X(*this);52925293CXXScopeSpec Spec;5294if (ParseOptionalCXXScopeSpecifier(Spec, /*ObjectType=*/nullptr,5295/*ObjectHasErrors=*/false,5296/*EnteringContext=*/true))5297return;52985299if (Spec.isSet() && Tok.isNot(tok::identifier)) {5300Diag(Tok, diag::err_expected) << tok::identifier;5301DS.SetTypeSpecError();5302if (Tok.isNot(tok::l_brace)) {5303// Has no name and is not a definition.5304// Skip the rest of this declarator, up until the comma or semicolon.5305SkipUntil(tok::comma, StopAtSemi);5306return;5307}5308}53095310SS = Spec;5311}53125313// Must have either 'enum name' or 'enum {...}' or (rarely) 'enum : T { ... }'.5314if (Tok.isNot(tok::identifier) && Tok.isNot(tok::l_brace) &&5315Tok.isNot(tok::colon)) {5316Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;53175318DS.SetTypeSpecError();5319// Skip the rest of this declarator, up until the comma or semicolon.5320SkipUntil(tok::comma, StopAtSemi);5321return;5322}53235324// If an identifier is present, consume and remember it.5325IdentifierInfo *Name = nullptr;5326SourceLocation NameLoc;5327if (Tok.is(tok::identifier)) {5328Name = Tok.getIdentifierInfo();5329NameLoc = ConsumeToken();5330}53315332if (!Name && ScopedEnumKWLoc.isValid()) {5333// C++0x 7.2p2: The optional identifier shall not be omitted in the5334// declaration of a scoped enumeration.5335Diag(Tok, diag::err_scoped_enum_missing_identifier);5336ScopedEnumKWLoc = SourceLocation();5337IsScopedUsingClassTag = false;5338}53395340// Okay, end the suppression area. We'll decide whether to emit the5341// diagnostics in a second.5342if (shouldDelayDiagsInTag)5343diagsFromTag.done();53445345TypeResult BaseType;5346SourceRange BaseRange;53475348bool CanBeBitfield =5349getCurScope()->isClassScope() && ScopedEnumKWLoc.isInvalid() && Name;53505351// Parse the fixed underlying type.5352if (Tok.is(tok::colon)) {5353// This might be an enum-base or part of some unrelated enclosing context.5354//5355// 'enum E : base' is permitted in two circumstances:5356//5357// 1) As a defining-type-specifier, when followed by '{'.5358// 2) As the sole constituent of a complete declaration -- when DS is empty5359// and the next token is ';'.5360//5361// The restriction to defining-type-specifiers is important to allow parsing5362// a ? new enum E : int{}5363// _Generic(a, enum E : int{})5364// properly.5365//5366// One additional consideration applies:5367//5368// C++ [dcl.enum]p1:5369// A ':' following "enum nested-name-specifier[opt] identifier" within5370// the decl-specifier-seq of a member-declaration is parsed as part of5371// an enum-base.5372//5373// Other language modes supporting enumerations with fixed underlying types5374// do not have clear rules on this, so we disambiguate to determine whether5375// the tokens form a bit-field width or an enum-base.53765377if (CanBeBitfield && !isEnumBase(CanBeOpaqueEnumDeclaration)) {5378// Outside C++11, do not interpret the tokens as an enum-base if they do5379// not make sense as one. In C++11, it's an error if this happens.5380if (getLangOpts().CPlusPlus11)5381Diag(Tok.getLocation(), diag::err_anonymous_enum_bitfield);5382} else if (CanHaveEnumBase || !ColonIsSacred) {5383SourceLocation ColonLoc = ConsumeToken();53845385// Parse a type-specifier-seq as a type. We can't just ParseTypeName here,5386// because under -fms-extensions,5387// enum E : int *p;5388// declares 'enum E : int; E *p;' not 'enum E : int*; E p;'.5389DeclSpec DS(AttrFactory);5390// enum-base is not assumed to be a type and therefore requires the5391// typename keyword [p0634r3].5392ParseSpecifierQualifierList(DS, ImplicitTypenameContext::No, AS,5393DeclSpecContext::DSC_type_specifier);5394Declarator DeclaratorInfo(DS, ParsedAttributesView::none(),5395DeclaratorContext::TypeName);5396BaseType = Actions.ActOnTypeName(DeclaratorInfo);53975398BaseRange = SourceRange(ColonLoc, DeclaratorInfo.getSourceRange().getEnd());53995400if (!getLangOpts().ObjC && !getLangOpts().C23) {5401if (getLangOpts().CPlusPlus11)5402Diag(ColonLoc, diag::warn_cxx98_compat_enum_fixed_underlying_type)5403<< BaseRange;5404else if (getLangOpts().CPlusPlus)5405Diag(ColonLoc, diag::ext_cxx11_enum_fixed_underlying_type)5406<< BaseRange;5407else if (getLangOpts().MicrosoftExt)5408Diag(ColonLoc, diag::ext_ms_c_enum_fixed_underlying_type)5409<< BaseRange;5410else5411Diag(ColonLoc, diag::ext_clang_c_enum_fixed_underlying_type)5412<< BaseRange;5413}5414}5415}54165417// There are four options here. If we have 'friend enum foo;' then this is a5418// friend declaration, and cannot have an accompanying definition. If we have5419// 'enum foo;', then this is a forward declaration. If we have5420// 'enum foo {...' then this is a definition. Otherwise we have something5421// like 'enum foo xyz', a reference.5422//5423// This is needed to handle stuff like this right (C99 6.7.2.3p11):5424// enum foo {..}; void bar() { enum foo; } <- new foo in bar.5425// enum foo {..}; void bar() { enum foo x; } <- use of old foo.5426//5427TagUseKind TUK;5428if (AllowEnumSpecifier == AllowDefiningTypeSpec::No)5429TUK = TagUseKind::Reference;5430else if (Tok.is(tok::l_brace)) {5431if (DS.isFriendSpecified()) {5432Diag(Tok.getLocation(), diag::err_friend_decl_defines_type)5433<< SourceRange(DS.getFriendSpecLoc());5434ConsumeBrace();5435SkipUntil(tok::r_brace, StopAtSemi);5436// Discard any other definition-only pieces.5437attrs.clear();5438ScopedEnumKWLoc = SourceLocation();5439IsScopedUsingClassTag = false;5440BaseType = TypeResult();5441TUK = TagUseKind::Friend;5442} else {5443TUK = TagUseKind::Definition;5444}5445} else if (!isTypeSpecifier(DSC) &&5446(Tok.is(tok::semi) ||5447(Tok.isAtStartOfLine() &&5448!isValidAfterTypeSpecifier(CanBeBitfield)))) {5449// An opaque-enum-declaration is required to be standalone (no preceding or5450// following tokens in the declaration). Sema enforces this separately by5451// diagnosing anything else in the DeclSpec.5452TUK = DS.isFriendSpecified() ? TagUseKind::Friend : TagUseKind::Declaration;5453if (Tok.isNot(tok::semi)) {5454// A semicolon was missing after this declaration. Diagnose and recover.5455ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");5456PP.EnterToken(Tok, /*IsReinject=*/true);5457Tok.setKind(tok::semi);5458}5459} else {5460TUK = TagUseKind::Reference;5461}54625463bool IsElaboratedTypeSpecifier =5464TUK == TagUseKind::Reference || TUK == TagUseKind::Friend;54655466// If this is an elaborated type specifier nested in a larger declaration,5467// and we delayed diagnostics before, just merge them into the current pool.5468if (TUK == TagUseKind::Reference && shouldDelayDiagsInTag) {5469diagsFromTag.redelay();5470}54715472MultiTemplateParamsArg TParams;5473if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&5474TUK != TagUseKind::Reference) {5475if (!getLangOpts().CPlusPlus11 || !SS.isSet()) {5476// Skip the rest of this declarator, up until the comma or semicolon.5477Diag(Tok, diag::err_enum_template);5478SkipUntil(tok::comma, StopAtSemi);5479return;5480}54815482if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {5483// Enumerations can't be explicitly instantiated.5484DS.SetTypeSpecError();5485Diag(StartLoc, diag::err_explicit_instantiation_enum);5486return;5487}54885489assert(TemplateInfo.TemplateParams && "no template parameters");5490TParams = MultiTemplateParamsArg(TemplateInfo.TemplateParams->data(),5491TemplateInfo.TemplateParams->size());5492SS.setTemplateParamLists(TParams);5493}54945495if (!Name && TUK != TagUseKind::Definition) {5496Diag(Tok, diag::err_enumerator_unnamed_no_def);54975498DS.SetTypeSpecError();5499// Skip the rest of this declarator, up until the comma or semicolon.5500SkipUntil(tok::comma, StopAtSemi);5501return;5502}55035504// An elaborated-type-specifier has a much more constrained grammar:5505//5506// 'enum' nested-name-specifier[opt] identifier5507//5508// If we parsed any other bits, reject them now.5509//5510// MSVC and (for now at least) Objective-C permit a full enum-specifier5511// or opaque-enum-declaration anywhere.5512if (IsElaboratedTypeSpecifier && !getLangOpts().MicrosoftExt &&5513!getLangOpts().ObjC) {5514ProhibitCXX11Attributes(attrs, diag::err_attributes_not_allowed,5515diag::err_keyword_not_allowed,5516/*DiagnoseEmptyAttrs=*/true);5517if (BaseType.isUsable())5518Diag(BaseRange.getBegin(), diag::ext_enum_base_in_type_specifier)5519<< (AllowEnumSpecifier == AllowDefiningTypeSpec::Yes) << BaseRange;5520else if (ScopedEnumKWLoc.isValid())5521Diag(ScopedEnumKWLoc, diag::ext_elaborated_enum_class)5522<< FixItHint::CreateRemoval(ScopedEnumKWLoc) << IsScopedUsingClassTag;5523}55245525stripTypeAttributesOffDeclSpec(attrs, DS, TUK);55265527SkipBodyInfo SkipBody;5528if (!Name && TUK == TagUseKind::Definition && Tok.is(tok::l_brace) &&5529NextToken().is(tok::identifier))5530SkipBody = Actions.shouldSkipAnonEnumBody(getCurScope(),5531NextToken().getIdentifierInfo(),5532NextToken().getLocation());55335534bool Owned = false;5535bool IsDependent = false;5536const char *PrevSpec = nullptr;5537unsigned DiagID;5538Decl *TagDecl =5539Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS,5540Name, NameLoc, attrs, AS, DS.getModulePrivateSpecLoc(),5541TParams, Owned, IsDependent, ScopedEnumKWLoc,5542IsScopedUsingClassTag,5543BaseType, DSC == DeclSpecContext::DSC_type_specifier,5544DSC == DeclSpecContext::DSC_template_param ||5545DSC == DeclSpecContext::DSC_template_type_arg,5546OffsetOfState, &SkipBody).get();55475548if (SkipBody.ShouldSkip) {5549assert(TUK == TagUseKind::Definition && "can only skip a definition");55505551BalancedDelimiterTracker T(*this, tok::l_brace);5552T.consumeOpen();5553T.skipToEnd();55545555if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,5556NameLoc.isValid() ? NameLoc : StartLoc,5557PrevSpec, DiagID, TagDecl, Owned,5558Actions.getASTContext().getPrintingPolicy()))5559Diag(StartLoc, DiagID) << PrevSpec;5560return;5561}55625563if (IsDependent) {5564// This enum has a dependent nested-name-specifier. Handle it as a5565// dependent tag.5566if (!Name) {5567DS.SetTypeSpecError();5568Diag(Tok, diag::err_expected_type_name_after_typename);5569return;5570}55715572TypeResult Type = Actions.ActOnDependentTag(5573getCurScope(), DeclSpec::TST_enum, TUK, SS, Name, StartLoc, NameLoc);5574if (Type.isInvalid()) {5575DS.SetTypeSpecError();5576return;5577}55785579if (DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc,5580NameLoc.isValid() ? NameLoc : StartLoc,5581PrevSpec, DiagID, Type.get(),5582Actions.getASTContext().getPrintingPolicy()))5583Diag(StartLoc, DiagID) << PrevSpec;55845585return;5586}55875588if (!TagDecl) {5589// The action failed to produce an enumeration tag. If this is a5590// definition, consume the entire definition.5591if (Tok.is(tok::l_brace) && TUK != TagUseKind::Reference) {5592ConsumeBrace();5593SkipUntil(tok::r_brace, StopAtSemi);5594}55955596DS.SetTypeSpecError();5597return;5598}55995600if (Tok.is(tok::l_brace) && TUK == TagUseKind::Definition) {5601Decl *D = SkipBody.CheckSameAsPrevious ? SkipBody.New : TagDecl;5602ParseEnumBody(StartLoc, D);5603if (SkipBody.CheckSameAsPrevious &&5604!Actions.ActOnDuplicateDefinition(TagDecl, SkipBody)) {5605DS.SetTypeSpecError();5606return;5607}5608}56095610if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,5611NameLoc.isValid() ? NameLoc : StartLoc,5612PrevSpec, DiagID, TagDecl, Owned,5613Actions.getASTContext().getPrintingPolicy()))5614Diag(StartLoc, DiagID) << PrevSpec;5615}56165617/// ParseEnumBody - Parse a {} enclosed enumerator-list.5618/// enumerator-list:5619/// enumerator5620/// enumerator-list ',' enumerator5621/// enumerator:5622/// enumeration-constant attributes[opt]5623/// enumeration-constant attributes[opt] '=' constant-expression5624/// enumeration-constant:5625/// identifier5626///5627void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {5628// Enter the scope of the enum body and start the definition.5629ParseScope EnumScope(this, Scope::DeclScope | Scope::EnumScope);5630Actions.ActOnTagStartDefinition(getCurScope(), EnumDecl);56315632BalancedDelimiterTracker T(*this, tok::l_brace);5633T.consumeOpen();56345635// C does not allow an empty enumerator-list, C++ does [dcl.enum].5636if (Tok.is(tok::r_brace) && !getLangOpts().CPlusPlus)5637Diag(Tok, diag::err_empty_enum);56385639SmallVector<Decl *, 32> EnumConstantDecls;5640SmallVector<SuppressAccessChecks, 32> EnumAvailabilityDiags;56415642Decl *LastEnumConstDecl = nullptr;56435644// Parse the enumerator-list.5645while (Tok.isNot(tok::r_brace)) {5646// Parse enumerator. If failed, try skipping till the start of the next5647// enumerator definition.5648if (Tok.isNot(tok::identifier)) {5649Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;5650if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch) &&5651TryConsumeToken(tok::comma))5652continue;5653break;5654}5655IdentifierInfo *Ident = Tok.getIdentifierInfo();5656SourceLocation IdentLoc = ConsumeToken();56575658// If attributes exist after the enumerator, parse them.5659ParsedAttributes attrs(AttrFactory);5660MaybeParseGNUAttributes(attrs);5661if (isAllowedCXX11AttributeSpecifier()) {5662if (getLangOpts().CPlusPlus)5663Diag(Tok.getLocation(), getLangOpts().CPlusPlus175664? diag::warn_cxx14_compat_ns_enum_attribute5665: diag::ext_ns_enum_attribute)5666<< 1 /*enumerator*/;5667ParseCXX11Attributes(attrs);5668}56695670SourceLocation EqualLoc;5671ExprResult AssignedVal;5672EnumAvailabilityDiags.emplace_back(*this);56735674EnterExpressionEvaluationContext ConstantEvaluated(5675Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);5676if (TryConsumeToken(tok::equal, EqualLoc)) {5677AssignedVal = ParseConstantExpressionInExprEvalContext();5678if (AssignedVal.isInvalid())5679SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch);5680}56815682// Install the enumerator constant into EnumDecl.5683Decl *EnumConstDecl = Actions.ActOnEnumConstant(5684getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, attrs,5685EqualLoc, AssignedVal.get());5686EnumAvailabilityDiags.back().done();56875688EnumConstantDecls.push_back(EnumConstDecl);5689LastEnumConstDecl = EnumConstDecl;56905691if (Tok.is(tok::identifier)) {5692// We're missing a comma between enumerators.5693SourceLocation Loc = getEndOfPreviousToken();5694Diag(Loc, diag::err_enumerator_list_missing_comma)5695<< FixItHint::CreateInsertion(Loc, ", ");5696continue;5697}56985699// Emumerator definition must be finished, only comma or r_brace are5700// allowed here.5701SourceLocation CommaLoc;5702if (Tok.isNot(tok::r_brace) && !TryConsumeToken(tok::comma, CommaLoc)) {5703if (EqualLoc.isValid())5704Diag(Tok.getLocation(), diag::err_expected_either) << tok::r_brace5705<< tok::comma;5706else5707Diag(Tok.getLocation(), diag::err_expected_end_of_enumerator);5708if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch)) {5709if (TryConsumeToken(tok::comma, CommaLoc))5710continue;5711} else {5712break;5713}5714}57155716// If comma is followed by r_brace, emit appropriate warning.5717if (Tok.is(tok::r_brace) && CommaLoc.isValid()) {5718if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11)5719Diag(CommaLoc, getLangOpts().CPlusPlus ?5720diag::ext_enumerator_list_comma_cxx :5721diag::ext_enumerator_list_comma_c)5722<< FixItHint::CreateRemoval(CommaLoc);5723else if (getLangOpts().CPlusPlus11)5724Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma)5725<< FixItHint::CreateRemoval(CommaLoc);5726break;5727}5728}57295730// Eat the }.5731T.consumeClose();57325733// If attributes exist after the identifier list, parse them.5734ParsedAttributes attrs(AttrFactory);5735MaybeParseGNUAttributes(attrs);57365737Actions.ActOnEnumBody(StartLoc, T.getRange(), EnumDecl, EnumConstantDecls,5738getCurScope(), attrs);57395740// Now handle enum constant availability diagnostics.5741assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size());5742for (size_t i = 0, e = EnumConstantDecls.size(); i != e; ++i) {5743ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);5744EnumAvailabilityDiags[i].redelay();5745PD.complete(EnumConstantDecls[i]);5746}57475748EnumScope.Exit();5749Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl, T.getRange());57505751// The next token must be valid after an enum definition. If not, a ';'5752// was probably forgotten.5753bool CanBeBitfield = getCurScope()->isClassScope();5754if (!isValidAfterTypeSpecifier(CanBeBitfield)) {5755ExpectAndConsume(tok::semi, diag::err_expected_after, "enum");5756// Push this token back into the preprocessor and change our current token5757// to ';' so that the rest of the code recovers as though there were an5758// ';' after the definition.5759PP.EnterToken(Tok, /*IsReinject=*/true);5760Tok.setKind(tok::semi);5761}5762}57635764/// isKnownToBeTypeSpecifier - Return true if we know that the specified token5765/// is definitely a type-specifier. Return false if it isn't part of a type5766/// specifier or if we're not sure.5767bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const {5768switch (Tok.getKind()) {5769default: return false;5770// type-specifiers5771case tok::kw_short:5772case tok::kw_long:5773case tok::kw___int64:5774case tok::kw___int128:5775case tok::kw_signed:5776case tok::kw_unsigned:5777case tok::kw__Complex:5778case tok::kw__Imaginary:5779case tok::kw_void:5780case tok::kw_char:5781case tok::kw_wchar_t:5782case tok::kw_char8_t:5783case tok::kw_char16_t:5784case tok::kw_char32_t:5785case tok::kw_int:5786case tok::kw__ExtInt:5787case tok::kw__BitInt:5788case tok::kw___bf16:5789case tok::kw_half:5790case tok::kw_float:5791case tok::kw_double:5792case tok::kw__Accum:5793case tok::kw__Fract:5794case tok::kw__Float16:5795case tok::kw___float128:5796case tok::kw___ibm128:5797case tok::kw_bool:5798case tok::kw__Bool:5799case tok::kw__Decimal32:5800case tok::kw__Decimal64:5801case tok::kw__Decimal128:5802case tok::kw___vector:5803#define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:5804#include "clang/Basic/OpenCLImageTypes.def"58055806// struct-or-union-specifier (C99) or class-specifier (C++)5807case tok::kw_class:5808case tok::kw_struct:5809case tok::kw___interface:5810case tok::kw_union:5811// enum-specifier5812case tok::kw_enum:58135814// typedef-name5815case tok::annot_typename:5816return true;5817}5818}58195820/// isTypeSpecifierQualifier - Return true if the current token could be the5821/// start of a specifier-qualifier-list.5822bool Parser::isTypeSpecifierQualifier() {5823switch (Tok.getKind()) {5824default: return false;58255826case tok::identifier: // foo::bar5827if (TryAltiVecVectorToken())5828return true;5829[[fallthrough]];5830case tok::kw_typename: // typename T::type5831// Annotate typenames and C++ scope specifiers. If we get one, just5832// recurse to handle whatever we get.5833if (TryAnnotateTypeOrScopeToken())5834return true;5835if (Tok.is(tok::identifier))5836return false;5837return isTypeSpecifierQualifier();58385839case tok::coloncolon: // ::foo::bar5840if (NextToken().is(tok::kw_new) || // ::new5841NextToken().is(tok::kw_delete)) // ::delete5842return false;58435844if (TryAnnotateTypeOrScopeToken())5845return true;5846return isTypeSpecifierQualifier();58475848// GNU attributes support.5849case tok::kw___attribute:5850// C23/GNU typeof support.5851case tok::kw_typeof:5852case tok::kw_typeof_unqual:58535854// type-specifiers5855case tok::kw_short:5856case tok::kw_long:5857case tok::kw___int64:5858case tok::kw___int128:5859case tok::kw_signed:5860case tok::kw_unsigned:5861case tok::kw__Complex:5862case tok::kw__Imaginary:5863case tok::kw_void:5864case tok::kw_char:5865case tok::kw_wchar_t:5866case tok::kw_char8_t:5867case tok::kw_char16_t:5868case tok::kw_char32_t:5869case tok::kw_int:5870case tok::kw__ExtInt:5871case tok::kw__BitInt:5872case tok::kw_half:5873case tok::kw___bf16:5874case tok::kw_float:5875case tok::kw_double:5876case tok::kw__Accum:5877case tok::kw__Fract:5878case tok::kw__Float16:5879case tok::kw___float128:5880case tok::kw___ibm128:5881case tok::kw_bool:5882case tok::kw__Bool:5883case tok::kw__Decimal32:5884case tok::kw__Decimal64:5885case tok::kw__Decimal128:5886case tok::kw___vector:5887#define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:5888#include "clang/Basic/OpenCLImageTypes.def"58895890// struct-or-union-specifier (C99) or class-specifier (C++)5891case tok::kw_class:5892case tok::kw_struct:5893case tok::kw___interface:5894case tok::kw_union:5895// enum-specifier5896case tok::kw_enum:58975898// type-qualifier5899case tok::kw_const:5900case tok::kw_volatile:5901case tok::kw_restrict:5902case tok::kw__Sat:59035904// Debugger support.5905case tok::kw___unknown_anytype:59065907// typedef-name5908case tok::annot_typename:5909return true;59105911// GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.5912case tok::less:5913return getLangOpts().ObjC;59145915case tok::kw___cdecl:5916case tok::kw___stdcall:5917case tok::kw___fastcall:5918case tok::kw___thiscall:5919case tok::kw___regcall:5920case tok::kw___vectorcall:5921case tok::kw___w64:5922case tok::kw___ptr64:5923case tok::kw___ptr32:5924case tok::kw___pascal:5925case tok::kw___unaligned:59265927case tok::kw__Nonnull:5928case tok::kw__Nullable:5929case tok::kw__Nullable_result:5930case tok::kw__Null_unspecified:59315932case tok::kw___kindof:59335934case tok::kw___private:5935case tok::kw___local:5936case tok::kw___global:5937case tok::kw___constant:5938case tok::kw___generic:5939case tok::kw___read_only:5940case tok::kw___read_write:5941case tok::kw___write_only:5942case tok::kw___funcref:5943return true;59445945case tok::kw_private:5946return getLangOpts().OpenCL;59475948// C11 _Atomic5949case tok::kw__Atomic:5950return true;59515952// HLSL type qualifiers5953case tok::kw_groupshared:5954case tok::kw_in:5955case tok::kw_inout:5956case tok::kw_out:5957return getLangOpts().HLSL;5958}5959}59605961Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() {5962assert(PP.isIncrementalProcessingEnabled() && "Not in incremental mode");59635964// Parse a top-level-stmt.5965Parser::StmtVector Stmts;5966ParsedStmtContext SubStmtCtx = ParsedStmtContext();5967ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope |5968Scope::CompoundStmtScope);5969TopLevelStmtDecl *TLSD = Actions.ActOnStartTopLevelStmtDecl(getCurScope());5970StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);5971if (!R.isUsable())5972return nullptr;59735974Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get());59755976if (Tok.is(tok::annot_repl_input_end) &&5977Tok.getAnnotationValue() != nullptr) {5978ConsumeAnnotationToken();5979TLSD->setSemiMissing();5980}59815982SmallVector<Decl *, 2> DeclsInGroup;5983DeclsInGroup.push_back(TLSD);59845985// Currently happens for things like -fms-extensions and use `__if_exists`.5986for (Stmt *S : Stmts) {5987// Here we should be safe as `__if_exists` and friends are not introducing5988// new variables which need to live outside file scope.5989TopLevelStmtDecl *D = Actions.ActOnStartTopLevelStmtDecl(getCurScope());5990Actions.ActOnFinishTopLevelStmtDecl(D, S);5991DeclsInGroup.push_back(D);5992}59935994return Actions.BuildDeclaratorGroup(DeclsInGroup);5995}59965997/// isDeclarationSpecifier() - Return true if the current token is part of a5998/// declaration specifier.5999///6000/// \param AllowImplicitTypename whether this is a context where T::type [T6001/// dependent] can appear.6002/// \param DisambiguatingWithExpression True to indicate that the purpose of6003/// this check is to disambiguate between an expression and a declaration.6004bool Parser::isDeclarationSpecifier(6005ImplicitTypenameContext AllowImplicitTypename,6006bool DisambiguatingWithExpression) {6007switch (Tok.getKind()) {6008default: return false;60096010// OpenCL 2.0 and later define this keyword.6011case tok::kw_pipe:6012return getLangOpts().OpenCL &&6013getLangOpts().getOpenCLCompatibleVersion() >= 200;60146015case tok::identifier: // foo::bar6016// Unfortunate hack to support "Class.factoryMethod" notation.6017if (getLangOpts().ObjC && NextToken().is(tok::period))6018return false;6019if (TryAltiVecVectorToken())6020return true;6021[[fallthrough]];6022case tok::kw_decltype: // decltype(T())::type6023case tok::kw_typename: // typename T::type6024// Annotate typenames and C++ scope specifiers. If we get one, just6025// recurse to handle whatever we get.6026if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename))6027return true;6028if (TryAnnotateTypeConstraint())6029return true;6030if (Tok.is(tok::identifier))6031return false;60326033// If we're in Objective-C and we have an Objective-C class type followed6034// by an identifier and then either ':' or ']', in a place where an6035// expression is permitted, then this is probably a class message send6036// missing the initial '['. In this case, we won't consider this to be6037// the start of a declaration.6038if (DisambiguatingWithExpression &&6039isStartOfObjCClassMessageMissingOpenBracket())6040return false;60416042return isDeclarationSpecifier(AllowImplicitTypename);60436044case tok::coloncolon: // ::foo::bar6045if (!getLangOpts().CPlusPlus)6046return false;6047if (NextToken().is(tok::kw_new) || // ::new6048NextToken().is(tok::kw_delete)) // ::delete6049return false;60506051// Annotate typenames and C++ scope specifiers. If we get one, just6052// recurse to handle whatever we get.6053if (TryAnnotateTypeOrScopeToken())6054return true;6055return isDeclarationSpecifier(ImplicitTypenameContext::No);60566057// storage-class-specifier6058case tok::kw_typedef:6059case tok::kw_extern:6060case tok::kw___private_extern__:6061case tok::kw_static:6062case tok::kw_auto:6063case tok::kw___auto_type:6064case tok::kw_register:6065case tok::kw___thread:6066case tok::kw_thread_local:6067case tok::kw__Thread_local:60686069// Modules6070case tok::kw___module_private__:60716072// Debugger support6073case tok::kw___unknown_anytype:60746075// type-specifiers6076case tok::kw_short:6077case tok::kw_long:6078case tok::kw___int64:6079case tok::kw___int128:6080case tok::kw_signed:6081case tok::kw_unsigned:6082case tok::kw__Complex:6083case tok::kw__Imaginary:6084case tok::kw_void:6085case tok::kw_char:6086case tok::kw_wchar_t:6087case tok::kw_char8_t:6088case tok::kw_char16_t:6089case tok::kw_char32_t:60906091case tok::kw_int:6092case tok::kw__ExtInt:6093case tok::kw__BitInt:6094case tok::kw_half:6095case tok::kw___bf16:6096case tok::kw_float:6097case tok::kw_double:6098case tok::kw__Accum:6099case tok::kw__Fract:6100case tok::kw__Float16:6101case tok::kw___float128:6102case tok::kw___ibm128:6103case tok::kw_bool:6104case tok::kw__Bool:6105case tok::kw__Decimal32:6106case tok::kw__Decimal64:6107case tok::kw__Decimal128:6108case tok::kw___vector:61096110// struct-or-union-specifier (C99) or class-specifier (C++)6111case tok::kw_class:6112case tok::kw_struct:6113case tok::kw_union:6114case tok::kw___interface:6115// enum-specifier6116case tok::kw_enum:61176118// type-qualifier6119case tok::kw_const:6120case tok::kw_volatile:6121case tok::kw_restrict:6122case tok::kw__Sat:61236124// function-specifier6125case tok::kw_inline:6126case tok::kw_virtual:6127case tok::kw_explicit:6128case tok::kw__Noreturn:61296130// alignment-specifier6131case tok::kw__Alignas:61326133// friend keyword.6134case tok::kw_friend:61356136// static_assert-declaration6137case tok::kw_static_assert:6138case tok::kw__Static_assert:61396140// C23/GNU typeof support.6141case tok::kw_typeof:6142case tok::kw_typeof_unqual:61436144// GNU attributes.6145case tok::kw___attribute:61466147// C++11 decltype and constexpr.6148case tok::annot_decltype:6149case tok::annot_pack_indexing_type:6150case tok::kw_constexpr:61516152// C++20 consteval and constinit.6153case tok::kw_consteval:6154case tok::kw_constinit:61556156// C11 _Atomic6157case tok::kw__Atomic:6158return true;61596160case tok::kw_alignas:6161// alignas is a type-specifier-qualifier in C23, which is a kind of6162// declaration-specifier. Outside of C23 mode (including in C++), it is not.6163return getLangOpts().C23;61646165// GNU ObjC bizarre protocol extension: <proto1,proto2> with implicit 'id'.6166case tok::less:6167return getLangOpts().ObjC;61686169// typedef-name6170case tok::annot_typename:6171return !DisambiguatingWithExpression ||6172!isStartOfObjCClassMessageMissingOpenBracket();61736174// placeholder-type-specifier6175case tok::annot_template_id: {6176TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);6177if (TemplateId->hasInvalidName())6178return true;6179// FIXME: What about type templates that have only been annotated as6180// annot_template_id, not as annot_typename?6181return isTypeConstraintAnnotation() &&6182(NextToken().is(tok::kw_auto) || NextToken().is(tok::kw_decltype));6183}61846185case tok::annot_cxxscope: {6186TemplateIdAnnotation *TemplateId =6187NextToken().is(tok::annot_template_id)6188? takeTemplateIdAnnotation(NextToken())6189: nullptr;6190if (TemplateId && TemplateId->hasInvalidName())6191return true;6192// FIXME: What about type templates that have only been annotated as6193// annot_template_id, not as annot_typename?6194if (NextToken().is(tok::identifier) && TryAnnotateTypeConstraint())6195return true;6196return isTypeConstraintAnnotation() &&6197GetLookAheadToken(2).isOneOf(tok::kw_auto, tok::kw_decltype);6198}61996200case tok::kw___declspec:6201case tok::kw___cdecl:6202case tok::kw___stdcall:6203case tok::kw___fastcall:6204case tok::kw___thiscall:6205case tok::kw___regcall:6206case tok::kw___vectorcall:6207case tok::kw___w64:6208case tok::kw___sptr:6209case tok::kw___uptr:6210case tok::kw___ptr64:6211case tok::kw___ptr32:6212case tok::kw___forceinline:6213case tok::kw___pascal:6214case tok::kw___unaligned:62156216case tok::kw__Nonnull:6217case tok::kw__Nullable:6218case tok::kw__Nullable_result:6219case tok::kw__Null_unspecified:62206221case tok::kw___kindof:62226223case tok::kw___private:6224case tok::kw___local:6225case tok::kw___global:6226case tok::kw___constant:6227case tok::kw___generic:6228case tok::kw___read_only:6229case tok::kw___read_write:6230case tok::kw___write_only:6231#define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:6232#include "clang/Basic/OpenCLImageTypes.def"62336234case tok::kw___funcref:6235case tok::kw_groupshared:6236return true;62376238case tok::kw_private:6239return getLangOpts().OpenCL;6240}6241}62426243bool Parser::isConstructorDeclarator(bool IsUnqualified, bool DeductionGuide,6244DeclSpec::FriendSpecified IsFriend,6245const ParsedTemplateInfo *TemplateInfo) {6246RevertingTentativeParsingAction TPA(*this);6247// Parse the C++ scope specifier.6248CXXScopeSpec SS;6249if (TemplateInfo && TemplateInfo->TemplateParams)6250SS.setTemplateParamLists(*TemplateInfo->TemplateParams);62516252if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,6253/*ObjectHasErrors=*/false,6254/*EnteringContext=*/true)) {6255return false;6256}62576258// Parse the constructor name.6259if (Tok.is(tok::identifier)) {6260// We already know that we have a constructor name; just consume6261// the token.6262ConsumeToken();6263} else if (Tok.is(tok::annot_template_id)) {6264ConsumeAnnotationToken();6265} else {6266return false;6267}62686269// There may be attributes here, appertaining to the constructor name or type6270// we just stepped past.6271SkipCXX11Attributes();62726273// Current class name must be followed by a left parenthesis.6274if (Tok.isNot(tok::l_paren)) {6275return false;6276}6277ConsumeParen();62786279// A right parenthesis, or ellipsis followed by a right parenthesis signals6280// that we have a constructor.6281if (Tok.is(tok::r_paren) ||6282(Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren))) {6283return true;6284}62856286// A C++11 attribute here signals that we have a constructor, and is an6287// attribute on the first constructor parameter.6288if (getLangOpts().CPlusPlus11 &&6289isCXX11AttributeSpecifier(/*Disambiguate*/ false,6290/*OuterMightBeMessageSend*/ true)) {6291return true;6292}62936294// If we need to, enter the specified scope.6295DeclaratorScopeObj DeclScopeObj(*this, SS);6296if (SS.isSet() && Actions.ShouldEnterDeclaratorScope(getCurScope(), SS))6297DeclScopeObj.EnterDeclaratorScope();62986299// Optionally skip Microsoft attributes.6300ParsedAttributes Attrs(AttrFactory);6301MaybeParseMicrosoftAttributes(Attrs);63026303// Check whether the next token(s) are part of a declaration6304// specifier, in which case we have the start of a parameter and,6305// therefore, we know that this is a constructor.6306// Due to an ambiguity with implicit typename, the above is not enough.6307// Additionally, check to see if we are a friend.6308// If we parsed a scope specifier as well as friend,6309// we might be parsing a friend constructor.6310bool IsConstructor = false;6311ImplicitTypenameContext ITC = IsFriend && !SS.isSet()6312? ImplicitTypenameContext::No6313: ImplicitTypenameContext::Yes;6314// Constructors cannot have this parameters, but we support that scenario here6315// to improve diagnostic.6316if (Tok.is(tok::kw_this)) {6317ConsumeToken();6318return isDeclarationSpecifier(ITC);6319}63206321if (isDeclarationSpecifier(ITC))6322IsConstructor = true;6323else if (Tok.is(tok::identifier) ||6324(Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) {6325// We've seen "C ( X" or "C ( X::Y", but "X" / "X::Y" is not a type.6326// This might be a parenthesized member name, but is more likely to6327// be a constructor declaration with an invalid argument type. Keep6328// looking.6329if (Tok.is(tok::annot_cxxscope))6330ConsumeAnnotationToken();6331ConsumeToken();63326333// If this is not a constructor, we must be parsing a declarator,6334// which must have one of the following syntactic forms (see the6335// grammar extract at the start of ParseDirectDeclarator):6336switch (Tok.getKind()) {6337case tok::l_paren:6338// C(X ( int));6339case tok::l_square:6340// C(X [ 5]);6341// C(X [ [attribute]]);6342case tok::coloncolon:6343// C(X :: Y);6344// C(X :: *p);6345// Assume this isn't a constructor, rather than assuming it's a6346// constructor with an unnamed parameter of an ill-formed type.6347break;63486349case tok::r_paren:6350// C(X )63516352// Skip past the right-paren and any following attributes to get to6353// the function body or trailing-return-type.6354ConsumeParen();6355SkipCXX11Attributes();63566357if (DeductionGuide) {6358// C(X) -> ... is a deduction guide.6359IsConstructor = Tok.is(tok::arrow);6360break;6361}6362if (Tok.is(tok::colon) || Tok.is(tok::kw_try)) {6363// Assume these were meant to be constructors:6364// C(X) : (the name of a bit-field cannot be parenthesized).6365// C(X) try (this is otherwise ill-formed).6366IsConstructor = true;6367}6368if (Tok.is(tok::semi) || Tok.is(tok::l_brace)) {6369// If we have a constructor name within the class definition,6370// assume these were meant to be constructors:6371// C(X) {6372// C(X) ;6373// ... because otherwise we would be declaring a non-static data6374// member that is ill-formed because it's of the same type as its6375// surrounding class.6376//6377// FIXME: We can actually do this whether or not the name is qualified,6378// because if it is qualified in this context it must be being used as6379// a constructor name.6380// currently, so we're somewhat conservative here.6381IsConstructor = IsUnqualified;6382}6383break;63846385default:6386IsConstructor = true;6387break;6388}6389}6390return IsConstructor;6391}63926393/// ParseTypeQualifierListOpt6394/// type-qualifier-list: [C99 6.7.5]6395/// type-qualifier6396/// [vendor] attributes6397/// [ only if AttrReqs & AR_VendorAttributesParsed ]6398/// type-qualifier-list type-qualifier6399/// [vendor] type-qualifier-list attributes6400/// [ only if AttrReqs & AR_VendorAttributesParsed ]6401/// [C++0x] attribute-specifier[opt] is allowed before cv-qualifier-seq6402/// [ only if AttReqs & AR_CXX11AttributesParsed ]6403/// Note: vendor can be GNU, MS, etc and can be explicitly controlled via6404/// AttrRequirements bitmask values.6405void Parser::ParseTypeQualifierListOpt(6406DeclSpec &DS, unsigned AttrReqs, bool AtomicAllowed,6407bool IdentifierRequired,6408std::optional<llvm::function_ref<void()>> CodeCompletionHandler) {6409if ((AttrReqs & AR_CXX11AttributesParsed) &&6410isAllowedCXX11AttributeSpecifier()) {6411ParsedAttributes Attrs(AttrFactory);6412ParseCXX11Attributes(Attrs);6413DS.takeAttributesFrom(Attrs);6414}64156416SourceLocation EndLoc;64176418while (true) {6419bool isInvalid = false;6420const char *PrevSpec = nullptr;6421unsigned DiagID = 0;6422SourceLocation Loc = Tok.getLocation();64236424switch (Tok.getKind()) {6425case tok::code_completion:6426cutOffParsing();6427if (CodeCompletionHandler)6428(*CodeCompletionHandler)();6429else6430Actions.CodeCompletion().CodeCompleteTypeQualifiers(DS);6431return;64326433case tok::kw_const:6434isInvalid = DS.SetTypeQual(DeclSpec::TQ_const , Loc, PrevSpec, DiagID,6435getLangOpts());6436break;6437case tok::kw_volatile:6438isInvalid = DS.SetTypeQual(DeclSpec::TQ_volatile, Loc, PrevSpec, DiagID,6439getLangOpts());6440break;6441case tok::kw_restrict:6442isInvalid = DS.SetTypeQual(DeclSpec::TQ_restrict, Loc, PrevSpec, DiagID,6443getLangOpts());6444break;6445case tok::kw__Atomic:6446if (!AtomicAllowed)6447goto DoneWithTypeQuals;6448diagnoseUseOfC11Keyword(Tok);6449isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,6450getLangOpts());6451break;64526453// OpenCL qualifiers:6454case tok::kw_private:6455if (!getLangOpts().OpenCL)6456goto DoneWithTypeQuals;6457[[fallthrough]];6458case tok::kw___private:6459case tok::kw___global:6460case tok::kw___local:6461case tok::kw___constant:6462case tok::kw___generic:6463case tok::kw___read_only:6464case tok::kw___write_only:6465case tok::kw___read_write:6466ParseOpenCLQualifiers(DS.getAttributes());6467break;64686469case tok::kw_groupshared:6470case tok::kw_in:6471case tok::kw_inout:6472case tok::kw_out:6473// NOTE: ParseHLSLQualifiers will consume the qualifier token.6474ParseHLSLQualifiers(DS.getAttributes());6475continue;64766477case tok::kw___unaligned:6478isInvalid = DS.SetTypeQual(DeclSpec::TQ_unaligned, Loc, PrevSpec, DiagID,6479getLangOpts());6480break;6481case tok::kw___uptr:6482// GNU libc headers in C mode use '__uptr' as an identifier which conflicts6483// with the MS modifier keyword.6484if ((AttrReqs & AR_DeclspecAttributesParsed) && !getLangOpts().CPlusPlus &&6485IdentifierRequired && DS.isEmpty() && NextToken().is(tok::semi)) {6486if (TryKeywordIdentFallback(false))6487continue;6488}6489[[fallthrough]];6490case tok::kw___sptr:6491case tok::kw___w64:6492case tok::kw___ptr64:6493case tok::kw___ptr32:6494case tok::kw___cdecl:6495case tok::kw___stdcall:6496case tok::kw___fastcall:6497case tok::kw___thiscall:6498case tok::kw___regcall:6499case tok::kw___vectorcall:6500if (AttrReqs & AR_DeclspecAttributesParsed) {6501ParseMicrosoftTypeAttributes(DS.getAttributes());6502continue;6503}6504goto DoneWithTypeQuals;65056506case tok::kw___funcref:6507ParseWebAssemblyFuncrefTypeAttribute(DS.getAttributes());6508continue;6509goto DoneWithTypeQuals;65106511case tok::kw___pascal:6512if (AttrReqs & AR_VendorAttributesParsed) {6513ParseBorlandTypeAttributes(DS.getAttributes());6514continue;6515}6516goto DoneWithTypeQuals;65176518// Nullability type specifiers.6519case tok::kw__Nonnull:6520case tok::kw__Nullable:6521case tok::kw__Nullable_result:6522case tok::kw__Null_unspecified:6523ParseNullabilityTypeSpecifiers(DS.getAttributes());6524continue;65256526// Objective-C 'kindof' types.6527case tok::kw___kindof:6528DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc,6529nullptr, 0, tok::kw___kindof);6530(void)ConsumeToken();6531continue;65326533case tok::kw___attribute:6534if (AttrReqs & AR_GNUAttributesParsedAndRejected)6535// When GNU attributes are expressly forbidden, diagnose their usage.6536Diag(Tok, diag::err_attributes_not_allowed);65376538// Parse the attributes even if they are rejected to ensure that error6539// recovery is graceful.6540if (AttrReqs & AR_GNUAttributesParsed ||6541AttrReqs & AR_GNUAttributesParsedAndRejected) {6542ParseGNUAttributes(DS.getAttributes());6543continue; // do *not* consume the next token!6544}6545// otherwise, FALL THROUGH!6546[[fallthrough]];6547default:6548DoneWithTypeQuals:6549// If this is not a type-qualifier token, we're done reading type6550// qualifiers. First verify that DeclSpec's are consistent.6551DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy());6552if (EndLoc.isValid())6553DS.SetRangeEnd(EndLoc);6554return;6555}65566557// If the specifier combination wasn't legal, issue a diagnostic.6558if (isInvalid) {6559assert(PrevSpec && "Method did not return previous specifier!");6560Diag(Tok, DiagID) << PrevSpec;6561}6562EndLoc = ConsumeToken();6563}6564}65656566/// ParseDeclarator - Parse and verify a newly-initialized declarator.6567void Parser::ParseDeclarator(Declarator &D) {6568/// This implements the 'declarator' production in the C grammar, then checks6569/// for well-formedness and issues diagnostics.6570Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] {6571ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);6572});6573}65746575static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,6576DeclaratorContext TheContext) {6577if (Kind == tok::star || Kind == tok::caret)6578return true;65796580// OpenCL 2.0 and later define this keyword.6581if (Kind == tok::kw_pipe && Lang.OpenCL &&6582Lang.getOpenCLCompatibleVersion() >= 200)6583return true;65846585if (!Lang.CPlusPlus)6586return false;65876588if (Kind == tok::amp)6589return true;65906591// We parse rvalue refs in C++03, because otherwise the errors are scary.6592// But we must not parse them in conversion-type-ids and new-type-ids, since6593// those can be legitimately followed by a && operator.6594// (The same thing can in theory happen after a trailing-return-type, but6595// since those are a C++11 feature, there is no rejects-valid issue there.)6596if (Kind == tok::ampamp)6597return Lang.CPlusPlus11 || (TheContext != DeclaratorContext::ConversionId &&6598TheContext != DeclaratorContext::CXXNew);65996600return false;6601}66026603// Indicates whether the given declarator is a pipe declarator.6604static bool isPipeDeclarator(const Declarator &D) {6605const unsigned NumTypes = D.getNumTypeObjects();66066607for (unsigned Idx = 0; Idx != NumTypes; ++Idx)6608if (DeclaratorChunk::Pipe == D.getTypeObject(Idx).Kind)6609return true;66106611return false;6612}66136614/// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator6615/// is parsed by the function passed to it. Pass null, and the direct-declarator6616/// isn't parsed at all, making this function effectively parse the C++6617/// ptr-operator production.6618///6619/// If the grammar of this construct is extended, matching changes must also be6620/// made to TryParseDeclarator and MightBeDeclarator, and possibly to6621/// isConstructorDeclarator.6622///6623/// declarator: [C99 6.7.5] [C++ 8p4, dcl.decl]6624/// [C] pointer[opt] direct-declarator6625/// [C++] direct-declarator6626/// [C++] ptr-operator declarator6627///6628/// pointer: [C99 6.7.5]6629/// '*' type-qualifier-list[opt]6630/// '*' type-qualifier-list[opt] pointer6631///6632/// ptr-operator:6633/// '*' cv-qualifier-seq[opt]6634/// '&'6635/// [C++0x] '&&'6636/// [GNU] '&' restrict[opt] attributes[opt]6637/// [GNU?] '&&' restrict[opt] attributes[opt]6638/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]6639void Parser::ParseDeclaratorInternal(Declarator &D,6640DirectDeclParseFunction DirectDeclParser) {6641if (Diags.hasAllExtensionsSilenced())6642D.setExtension();66436644// C++ member pointers start with a '::' or a nested-name.6645// Member pointers get special handling, since there's no place for the6646// scope spec in the generic path below.6647if (getLangOpts().CPlusPlus &&6648(Tok.is(tok::coloncolon) || Tok.is(tok::kw_decltype) ||6649(Tok.is(tok::identifier) &&6650(NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) ||6651Tok.is(tok::annot_cxxscope))) {6652bool EnteringContext = D.getContext() == DeclaratorContext::File ||6653D.getContext() == DeclaratorContext::Member;6654CXXScopeSpec SS;6655SS.setTemplateParamLists(D.getTemplateParameterLists());6656ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,6657/*ObjectHasErrors=*/false, EnteringContext);66586659if (SS.isNotEmpty()) {6660if (Tok.isNot(tok::star)) {6661// The scope spec really belongs to the direct-declarator.6662if (D.mayHaveIdentifier())6663D.getCXXScopeSpec() = SS;6664else6665AnnotateScopeToken(SS, true);66666667if (DirectDeclParser)6668(this->*DirectDeclParser)(D);6669return;6670}66716672if (SS.isValid()) {6673checkCompoundToken(SS.getEndLoc(), tok::coloncolon,6674CompoundToken::MemberPtr);6675}66766677SourceLocation StarLoc = ConsumeToken();6678D.SetRangeEnd(StarLoc);6679DeclSpec DS(AttrFactory);6680ParseTypeQualifierListOpt(DS);6681D.ExtendWithDeclSpec(DS);66826683// Recurse to parse whatever is left.6684Actions.runWithSufficientStackSpace(D.getBeginLoc(), [&] {6685ParseDeclaratorInternal(D, DirectDeclParser);6686});66876688// Sema will have to catch (syntactically invalid) pointers into global6689// scope. It has to catch pointers into namespace scope anyway.6690D.AddTypeInfo(DeclaratorChunk::getMemberPointer(6691SS, DS.getTypeQualifiers(), StarLoc, DS.getEndLoc()),6692std::move(DS.getAttributes()),6693/* Don't replace range end. */ SourceLocation());6694return;6695}6696}66976698tok::TokenKind Kind = Tok.getKind();66996700if (D.getDeclSpec().isTypeSpecPipe() && !isPipeDeclarator(D)) {6701DeclSpec DS(AttrFactory);6702ParseTypeQualifierListOpt(DS);67036704D.AddTypeInfo(6705DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()),6706std::move(DS.getAttributes()), SourceLocation());6707}67086709// Not a pointer, C++ reference, or block.6710if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) {6711if (DirectDeclParser)6712(this->*DirectDeclParser)(D);6713return;6714}67156716// Otherwise, '*' -> pointer, '^' -> block, '&' -> lvalue reference,6717// '&&' -> rvalue reference6718SourceLocation Loc = ConsumeToken(); // Eat the *, ^, & or &&.6719D.SetRangeEnd(Loc);67206721if (Kind == tok::star || Kind == tok::caret) {6722// Is a pointer.6723DeclSpec DS(AttrFactory);67246725// GNU attributes are not allowed here in a new-type-id, but Declspec and6726// C++11 attributes are allowed.6727unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed |6728((D.getContext() != DeclaratorContext::CXXNew)6729? AR_GNUAttributesParsed6730: AR_GNUAttributesParsedAndRejected);6731ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier());6732D.ExtendWithDeclSpec(DS);67336734// Recursively parse the declarator.6735Actions.runWithSufficientStackSpace(6736D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); });6737if (Kind == tok::star)6738// Remember that we parsed a pointer type, and remember the type-quals.6739D.AddTypeInfo(DeclaratorChunk::getPointer(6740DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(),6741DS.getVolatileSpecLoc(), DS.getRestrictSpecLoc(),6742DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()),6743std::move(DS.getAttributes()), SourceLocation());6744else6745// Remember that we parsed a Block type, and remember the type-quals.6746D.AddTypeInfo(6747DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), Loc),6748std::move(DS.getAttributes()), SourceLocation());6749} else {6750// Is a reference6751DeclSpec DS(AttrFactory);67526753// Complain about rvalue references in C++03, but then go on and build6754// the declarator.6755if (Kind == tok::ampamp)6756Diag(Loc, getLangOpts().CPlusPlus11 ?6757diag::warn_cxx98_compat_rvalue_reference :6758diag::ext_rvalue_reference);67596760// GNU-style and C++11 attributes are allowed here, as is restrict.6761ParseTypeQualifierListOpt(DS);6762D.ExtendWithDeclSpec(DS);67636764// C++ 8.3.2p1: cv-qualified references are ill-formed except when the6765// cv-qualifiers are introduced through the use of a typedef or of a6766// template type argument, in which case the cv-qualifiers are ignored.6767if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {6768if (DS.getTypeQualifiers() & DeclSpec::TQ_const)6769Diag(DS.getConstSpecLoc(),6770diag::err_invalid_reference_qualifier_application) << "const";6771if (DS.getTypeQualifiers() & DeclSpec::TQ_volatile)6772Diag(DS.getVolatileSpecLoc(),6773diag::err_invalid_reference_qualifier_application) << "volatile";6774// 'restrict' is permitted as an extension.6775if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic)6776Diag(DS.getAtomicSpecLoc(),6777diag::err_invalid_reference_qualifier_application) << "_Atomic";6778}67796780// Recursively parse the declarator.6781Actions.runWithSufficientStackSpace(6782D.getBeginLoc(), [&] { ParseDeclaratorInternal(D, DirectDeclParser); });67836784if (D.getNumTypeObjects() > 0) {6785// C++ [dcl.ref]p4: There shall be no references to references.6786DeclaratorChunk& InnerChunk = D.getTypeObject(D.getNumTypeObjects() - 1);6787if (InnerChunk.Kind == DeclaratorChunk::Reference) {6788if (const IdentifierInfo *II = D.getIdentifier())6789Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)6790<< II;6791else6792Diag(InnerChunk.Loc, diag::err_illegal_decl_reference_to_reference)6793<< "type name";67946795// Once we've complained about the reference-to-reference, we6796// can go ahead and build the (technically ill-formed)6797// declarator: reference collapsing will take care of it.6798}6799}68006801// Remember that we parsed a reference type.6802D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc,6803Kind == tok::amp),6804std::move(DS.getAttributes()), SourceLocation());6805}6806}68076808// When correcting from misplaced brackets before the identifier, the location6809// is saved inside the declarator so that other diagnostic messages can use6810// them. This extracts and returns that location, or returns the provided6811// location if a stored location does not exist.6812static SourceLocation getMissingDeclaratorIdLoc(Declarator &D,6813SourceLocation Loc) {6814if (D.getName().StartLocation.isInvalid() &&6815D.getName().EndLocation.isValid())6816return D.getName().EndLocation;68176818return Loc;6819}68206821/// ParseDirectDeclarator6822/// direct-declarator: [C99 6.7.5]6823/// [C99] identifier6824/// '(' declarator ')'6825/// [GNU] '(' attributes declarator ')'6826/// [C90] direct-declarator '[' constant-expression[opt] ']'6827/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'6828/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'6829/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'6830/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'6831/// [C++11] direct-declarator '[' constant-expression[opt] ']'6832/// attribute-specifier-seq[opt]6833/// direct-declarator '(' parameter-type-list ')'6834/// direct-declarator '(' identifier-list[opt] ')'6835/// [GNU] direct-declarator '(' parameter-forward-declarations6836/// parameter-type-list[opt] ')'6837/// [C++] direct-declarator '(' parameter-declaration-clause ')'6838/// cv-qualifier-seq[opt] exception-specification[opt]6839/// [C++11] direct-declarator '(' parameter-declaration-clause ')'6840/// attribute-specifier-seq[opt] cv-qualifier-seq[opt]6841/// ref-qualifier[opt] exception-specification[opt]6842/// [C++] declarator-id6843/// [C++11] declarator-id attribute-specifier-seq[opt]6844///6845/// declarator-id: [C++ 8]6846/// '...'[opt] id-expression6847/// '::'[opt] nested-name-specifier[opt] type-name6848///6849/// id-expression: [C++ 5.1]6850/// unqualified-id6851/// qualified-id6852///6853/// unqualified-id: [C++ 5.1]6854/// identifier6855/// operator-function-id6856/// conversion-function-id6857/// '~' class-name6858/// template-id6859///6860/// C++17 adds the following, which we also handle here:6861///6862/// simple-declaration:6863/// <decl-spec> '[' identifier-list ']' brace-or-equal-initializer ';'6864///6865/// Note, any additional constructs added here may need corresponding changes6866/// in isConstructorDeclarator.6867void Parser::ParseDirectDeclarator(Declarator &D) {6868DeclaratorScopeObj DeclScopeObj(*this, D.getCXXScopeSpec());68696870if (getLangOpts().CPlusPlus && D.mayHaveIdentifier()) {6871// This might be a C++17 structured binding.6872if (Tok.is(tok::l_square) && !D.mayOmitIdentifier() &&6873D.getCXXScopeSpec().isEmpty())6874return ParseDecompositionDeclarator(D);68756876// Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in6877// this context it is a bitfield. Also in range-based for statement colon6878// may delimit for-range-declaration.6879ColonProtectionRAIIObject X(6880*this, D.getContext() == DeclaratorContext::Member ||6881(D.getContext() == DeclaratorContext::ForInit &&6882getLangOpts().CPlusPlus11));68836884// ParseDeclaratorInternal might already have parsed the scope.6885if (D.getCXXScopeSpec().isEmpty()) {6886bool EnteringContext = D.getContext() == DeclaratorContext::File ||6887D.getContext() == DeclaratorContext::Member;6888ParseOptionalCXXScopeSpecifier(6889D.getCXXScopeSpec(), /*ObjectType=*/nullptr,6890/*ObjectHasErrors=*/false, EnteringContext);6891}68926893// C++23 [basic.scope.namespace]p1:6894// For each non-friend redeclaration or specialization whose target scope6895// is or is contained by the scope, the portion after the declarator-id,6896// class-head-name, or enum-head-name is also included in the scope.6897// C++23 [basic.scope.class]p1:6898// For each non-friend redeclaration or specialization whose target scope6899// is or is contained by the scope, the portion after the declarator-id,6900// class-head-name, or enum-head-name is also included in the scope.6901//6902// FIXME: We should not be doing this for friend declarations; they have6903// their own special lookup semantics specified by [basic.lookup.unqual]p6.6904if (D.getCXXScopeSpec().isValid()) {6905if (Actions.ShouldEnterDeclaratorScope(getCurScope(),6906D.getCXXScopeSpec()))6907// Change the declaration context for name lookup, until this function6908// is exited (and the declarator has been parsed).6909DeclScopeObj.EnterDeclaratorScope();6910else if (getObjCDeclContext()) {6911// Ensure that we don't interpret the next token as an identifier when6912// dealing with declarations in an Objective-C container.6913D.SetIdentifier(nullptr, Tok.getLocation());6914D.setInvalidType(true);6915ConsumeToken();6916goto PastIdentifier;6917}6918}69196920// C++0x [dcl.fct]p14:6921// There is a syntactic ambiguity when an ellipsis occurs at the end of a6922// parameter-declaration-clause without a preceding comma. In this case,6923// the ellipsis is parsed as part of the abstract-declarator if the type6924// of the parameter either names a template parameter pack that has not6925// been expanded or contains auto; otherwise, it is parsed as part of the6926// parameter-declaration-clause.6927if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&6928!((D.getContext() == DeclaratorContext::Prototype ||6929D.getContext() == DeclaratorContext::LambdaExprParameter ||6930D.getContext() == DeclaratorContext::BlockLiteral) &&6931NextToken().is(tok::r_paren) && !D.hasGroupingParens() &&6932!Actions.containsUnexpandedParameterPacks(D) &&6933D.getDeclSpec().getTypeSpecType() != TST_auto)) {6934SourceLocation EllipsisLoc = ConsumeToken();6935if (isPtrOperatorToken(Tok.getKind(), getLangOpts(), D.getContext())) {6936// The ellipsis was put in the wrong place. Recover, and explain to6937// the user what they should have done.6938ParseDeclarator(D);6939if (EllipsisLoc.isValid())6940DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D);6941return;6942} else6943D.setEllipsisLoc(EllipsisLoc);69446945// The ellipsis can't be followed by a parenthesized declarator. We6946// check for that in ParseParenDeclarator, after we have disambiguated6947// the l_paren token.6948}69496950if (Tok.isOneOf(tok::identifier, tok::kw_operator, tok::annot_template_id,6951tok::tilde)) {6952// We found something that indicates the start of an unqualified-id.6953// Parse that unqualified-id.6954bool AllowConstructorName;6955bool AllowDeductionGuide;6956if (D.getDeclSpec().hasTypeSpecifier()) {6957AllowConstructorName = false;6958AllowDeductionGuide = false;6959} else if (D.getCXXScopeSpec().isSet()) {6960AllowConstructorName = (D.getContext() == DeclaratorContext::File ||6961D.getContext() == DeclaratorContext::Member);6962AllowDeductionGuide = false;6963} else {6964AllowConstructorName = (D.getContext() == DeclaratorContext::Member);6965AllowDeductionGuide = (D.getContext() == DeclaratorContext::File ||6966D.getContext() == DeclaratorContext::Member);6967}69686969bool HadScope = D.getCXXScopeSpec().isValid();6970SourceLocation TemplateKWLoc;6971if (ParseUnqualifiedId(D.getCXXScopeSpec(),6972/*ObjectType=*/nullptr,6973/*ObjectHadErrors=*/false,6974/*EnteringContext=*/true,6975/*AllowDestructorName=*/true, AllowConstructorName,6976AllowDeductionGuide, &TemplateKWLoc,6977D.getName()) ||6978// Once we're past the identifier, if the scope was bad, mark the6979// whole declarator bad.6980D.getCXXScopeSpec().isInvalid()) {6981D.SetIdentifier(nullptr, Tok.getLocation());6982D.setInvalidType(true);6983} else {6984// ParseUnqualifiedId might have parsed a scope specifier during error6985// recovery. If it did so, enter that scope.6986if (!HadScope && D.getCXXScopeSpec().isValid() &&6987Actions.ShouldEnterDeclaratorScope(getCurScope(),6988D.getCXXScopeSpec()))6989DeclScopeObj.EnterDeclaratorScope();69906991// Parsed the unqualified-id; update range information and move along.6992if (D.getSourceRange().getBegin().isInvalid())6993D.SetRangeBegin(D.getName().getSourceRange().getBegin());6994D.SetRangeEnd(D.getName().getSourceRange().getEnd());6995}6996goto PastIdentifier;6997}69986999if (D.getCXXScopeSpec().isNotEmpty()) {7000// We have a scope specifier but no following unqualified-id.7001Diag(PP.getLocForEndOfToken(D.getCXXScopeSpec().getEndLoc()),7002diag::err_expected_unqualified_id)7003<< /*C++*/1;7004D.SetIdentifier(nullptr, Tok.getLocation());7005goto PastIdentifier;7006}7007} else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) {7008assert(!getLangOpts().CPlusPlus &&7009"There's a C++-specific check for tok::identifier above");7010assert(Tok.getIdentifierInfo() && "Not an identifier?");7011D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());7012D.SetRangeEnd(Tok.getLocation());7013ConsumeToken();7014goto PastIdentifier;7015} else if (Tok.is(tok::identifier) && !D.mayHaveIdentifier()) {7016// We're not allowed an identifier here, but we got one. Try to figure out7017// if the user was trying to attach a name to the type, or whether the name7018// is some unrelated trailing syntax.7019bool DiagnoseIdentifier = false;7020if (D.hasGroupingParens())7021// An identifier within parens is unlikely to be intended to be anything7022// other than a name being "declared".7023DiagnoseIdentifier = true;7024else if (D.getContext() == DeclaratorContext::TemplateArg)7025// T<int N> is an accidental identifier; T<int N indicates a missing '>'.7026DiagnoseIdentifier =7027NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater);7028else if (D.getContext() == DeclaratorContext::AliasDecl ||7029D.getContext() == DeclaratorContext::AliasTemplate)7030// The most likely error is that the ';' was forgotten.7031DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi);7032else if ((D.getContext() == DeclaratorContext::TrailingReturn ||7033D.getContext() == DeclaratorContext::TrailingReturnVar) &&7034!isCXX11VirtSpecifier(Tok))7035DiagnoseIdentifier = NextToken().isOneOf(7036tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try);7037if (DiagnoseIdentifier) {7038Diag(Tok.getLocation(), diag::err_unexpected_unqualified_id)7039<< FixItHint::CreateRemoval(Tok.getLocation());7040D.SetIdentifier(nullptr, Tok.getLocation());7041ConsumeToken();7042goto PastIdentifier;7043}7044}70457046if (Tok.is(tok::l_paren)) {7047// If this might be an abstract-declarator followed by a direct-initializer,7048// check whether this is a valid declarator chunk. If it can't be, assume7049// that it's an initializer instead.7050if (D.mayOmitIdentifier() && D.mayBeFollowedByCXXDirectInit()) {7051RevertingTentativeParsingAction PA(*this);7052if (TryParseDeclarator(true, D.mayHaveIdentifier(), true,7053D.getDeclSpec().getTypeSpecType() == TST_auto) ==7054TPResult::False) {7055D.SetIdentifier(nullptr, Tok.getLocation());7056goto PastIdentifier;7057}7058}70597060// direct-declarator: '(' declarator ')'7061// direct-declarator: '(' attributes declarator ')'7062// Example: 'char (*X)' or 'int (*XX)(void)'7063ParseParenDeclarator(D);70647065// If the declarator was parenthesized, we entered the declarator7066// scope when parsing the parenthesized declarator, then exited7067// the scope already. Re-enter the scope, if we need to.7068if (D.getCXXScopeSpec().isSet()) {7069// If there was an error parsing parenthesized declarator, declarator7070// scope may have been entered before. Don't do it again.7071if (!D.isInvalidType() &&7072Actions.ShouldEnterDeclaratorScope(getCurScope(),7073D.getCXXScopeSpec()))7074// Change the declaration context for name lookup, until this function7075// is exited (and the declarator has been parsed).7076DeclScopeObj.EnterDeclaratorScope();7077}7078} else if (D.mayOmitIdentifier()) {7079// This could be something simple like "int" (in which case the declarator7080// portion is empty), if an abstract-declarator is allowed.7081D.SetIdentifier(nullptr, Tok.getLocation());70827083// The grammar for abstract-pack-declarator does not allow grouping parens.7084// FIXME: Revisit this once core issue 1488 is resolved.7085if (D.hasEllipsis() && D.hasGroupingParens())7086Diag(PP.getLocForEndOfToken(D.getEllipsisLoc()),7087diag::ext_abstract_pack_declarator_parens);7088} else {7089if (Tok.getKind() == tok::annot_pragma_parser_crash)7090LLVM_BUILTIN_TRAP;7091if (Tok.is(tok::l_square))7092return ParseMisplacedBracketDeclarator(D);7093if (D.getContext() == DeclaratorContext::Member) {7094// Objective-C++: Detect C++ keywords and try to prevent further errors by7095// treating these keyword as valid member names.7096if (getLangOpts().ObjC && getLangOpts().CPlusPlus &&7097!Tok.isAnnotation() && Tok.getIdentifierInfo() &&7098Tok.getIdentifierInfo()->isCPlusPlusKeyword(getLangOpts())) {7099Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),7100diag::err_expected_member_name_or_semi_objcxx_keyword)7101<< Tok.getIdentifierInfo()7102<< (D.getDeclSpec().isEmpty() ? SourceRange()7103: D.getDeclSpec().getSourceRange());7104D.SetIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());7105D.SetRangeEnd(Tok.getLocation());7106ConsumeToken();7107goto PastIdentifier;7108}7109Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),7110diag::err_expected_member_name_or_semi)7111<< (D.getDeclSpec().isEmpty() ? SourceRange()7112: D.getDeclSpec().getSourceRange());7113} else {7114if (Tok.getKind() == tok::TokenKind::kw_while) {7115Diag(Tok, diag::err_while_loop_outside_of_a_function);7116} else if (getLangOpts().CPlusPlus) {7117if (Tok.isOneOf(tok::period, tok::arrow))7118Diag(Tok, diag::err_invalid_operator_on_type) << Tok.is(tok::arrow);7119else {7120SourceLocation Loc = D.getCXXScopeSpec().getEndLoc();7121if (Tok.isAtStartOfLine() && Loc.isValid())7122Diag(PP.getLocForEndOfToken(Loc), diag::err_expected_unqualified_id)7123<< getLangOpts().CPlusPlus;7124else7125Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),7126diag::err_expected_unqualified_id)7127<< getLangOpts().CPlusPlus;7128}7129} else {7130Diag(getMissingDeclaratorIdLoc(D, Tok.getLocation()),7131diag::err_expected_either)7132<< tok::identifier << tok::l_paren;7133}7134}7135D.SetIdentifier(nullptr, Tok.getLocation());7136D.setInvalidType(true);7137}71387139PastIdentifier:7140assert(D.isPastIdentifier() &&7141"Haven't past the location of the identifier yet?");71427143// Don't parse attributes unless we have parsed an unparenthesized name.7144if (D.hasName() && !D.getNumTypeObjects())7145MaybeParseCXX11Attributes(D);71467147while (true) {7148if (Tok.is(tok::l_paren)) {7149bool IsFunctionDeclaration = D.isFunctionDeclaratorAFunctionDeclaration();7150// Enter function-declaration scope, limiting any declarators to the7151// function prototype scope, including parameter declarators.7152ParseScope PrototypeScope(this,7153Scope::FunctionPrototypeScope|Scope::DeclScope|7154(IsFunctionDeclaration7155? Scope::FunctionDeclarationScope : 0));71567157// The paren may be part of a C++ direct initializer, eg. "int x(1);".7158// In such a case, check if we actually have a function declarator; if it7159// is not, the declarator has been fully parsed.7160bool IsAmbiguous = false;7161if (getLangOpts().CPlusPlus && D.mayBeFollowedByCXXDirectInit()) {7162// C++2a [temp.res]p57163// A qualified-id is assumed to name a type if7164// - [...]7165// - it is a decl-specifier of the decl-specifier-seq of a7166// - [...]7167// - parameter-declaration in a member-declaration [...]7168// - parameter-declaration in a declarator of a function or function7169// template declaration whose declarator-id is qualified [...]7170auto AllowImplicitTypename = ImplicitTypenameContext::No;7171if (D.getCXXScopeSpec().isSet())7172AllowImplicitTypename =7173(ImplicitTypenameContext)Actions.isDeclaratorFunctionLike(D);7174else if (D.getContext() == DeclaratorContext::Member) {7175AllowImplicitTypename = ImplicitTypenameContext::Yes;7176}71777178// The name of the declarator, if any, is tentatively declared within7179// a possible direct initializer.7180TentativelyDeclaredIdentifiers.push_back(D.getIdentifier());7181bool IsFunctionDecl =7182isCXXFunctionDeclarator(&IsAmbiguous, AllowImplicitTypename);7183TentativelyDeclaredIdentifiers.pop_back();7184if (!IsFunctionDecl)7185break;7186}7187ParsedAttributes attrs(AttrFactory);7188BalancedDelimiterTracker T(*this, tok::l_paren);7189T.consumeOpen();7190if (IsFunctionDeclaration)7191Actions.ActOnStartFunctionDeclarationDeclarator(D,7192TemplateParameterDepth);7193ParseFunctionDeclarator(D, attrs, T, IsAmbiguous);7194if (IsFunctionDeclaration)7195Actions.ActOnFinishFunctionDeclarationDeclarator(D);7196PrototypeScope.Exit();7197} else if (Tok.is(tok::l_square)) {7198ParseBracketDeclarator(D);7199} else if (Tok.isRegularKeywordAttribute()) {7200// For consistency with attribute parsing.7201Diag(Tok, diag::err_keyword_not_allowed) << Tok.getIdentifierInfo();7202bool TakesArgs = doesKeywordAttributeTakeArgs(Tok.getKind());7203ConsumeToken();7204if (TakesArgs) {7205BalancedDelimiterTracker T(*this, tok::l_paren);7206if (!T.consumeOpen())7207T.skipToEnd();7208}7209} else if (Tok.is(tok::kw_requires) && D.hasGroupingParens()) {7210// This declarator is declaring a function, but the requires clause is7211// in the wrong place:7212// void (f() requires true);7213// instead of7214// void f() requires true;7215// or7216// void (f()) requires true;7217Diag(Tok, diag::err_requires_clause_inside_parens);7218ConsumeToken();7219ExprResult TrailingRequiresClause = Actions.CorrectDelayedTyposInExpr(7220ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));7221if (TrailingRequiresClause.isUsable() && D.isFunctionDeclarator() &&7222!D.hasTrailingRequiresClause())7223// We're already ill-formed if we got here but we'll accept it anyway.7224D.setTrailingRequiresClause(TrailingRequiresClause.get());7225} else {7226break;7227}7228}7229}72307231void Parser::ParseDecompositionDeclarator(Declarator &D) {7232assert(Tok.is(tok::l_square));72337234TentativeParsingAction PA(*this);7235BalancedDelimiterTracker T(*this, tok::l_square);7236T.consumeOpen();72377238if (isCXX11AttributeSpecifier())7239DiagnoseAndSkipCXX11Attributes();72407241// If this doesn't look like a structured binding, maybe it's a misplaced7242// array declarator.7243if (!(Tok.is(tok::identifier) &&7244NextToken().isOneOf(tok::comma, tok::r_square, tok::kw_alignas,7245tok::l_square)) &&7246!(Tok.is(tok::r_square) &&7247NextToken().isOneOf(tok::equal, tok::l_brace))) {7248PA.Revert();7249return ParseMisplacedBracketDeclarator(D);7250}72517252SmallVector<DecompositionDeclarator::Binding, 32> Bindings;7253while (Tok.isNot(tok::r_square)) {7254if (!Bindings.empty()) {7255if (Tok.is(tok::comma))7256ConsumeToken();7257else {7258if (Tok.is(tok::identifier)) {7259SourceLocation EndLoc = getEndOfPreviousToken();7260Diag(EndLoc, diag::err_expected)7261<< tok::comma << FixItHint::CreateInsertion(EndLoc, ",");7262} else {7263Diag(Tok, diag::err_expected_comma_or_rsquare);7264}72657266SkipUntil(tok::r_square, tok::comma, tok::identifier,7267StopAtSemi | StopBeforeMatch);7268if (Tok.is(tok::comma))7269ConsumeToken();7270else if (Tok.isNot(tok::identifier))7271break;7272}7273}72747275if (isCXX11AttributeSpecifier())7276DiagnoseAndSkipCXX11Attributes();72777278if (Tok.isNot(tok::identifier)) {7279Diag(Tok, diag::err_expected) << tok::identifier;7280break;7281}72827283IdentifierInfo *II = Tok.getIdentifierInfo();7284SourceLocation Loc = Tok.getLocation();7285ConsumeToken();72867287ParsedAttributes Attrs(AttrFactory);7288if (isCXX11AttributeSpecifier()) {7289Diag(Tok, getLangOpts().CPlusPlus267290? diag::warn_cxx23_compat_decl_attrs_on_binding7291: diag::ext_decl_attrs_on_binding);7292MaybeParseCXX11Attributes(Attrs);7293}72947295Bindings.push_back({II, Loc, std::move(Attrs)});7296}72977298if (Tok.isNot(tok::r_square))7299// We've already diagnosed a problem here.7300T.skipToEnd();7301else {7302// C++17 does not allow the identifier-list in a structured binding7303// to be empty.7304if (Bindings.empty())7305Diag(Tok.getLocation(), diag::ext_decomp_decl_empty);73067307T.consumeClose();7308}73097310PA.Commit();73117312return D.setDecompositionBindings(T.getOpenLocation(), Bindings,7313T.getCloseLocation());7314}73157316/// ParseParenDeclarator - We parsed the declarator D up to a paren. This is7317/// only called before the identifier, so these are most likely just grouping7318/// parens for precedence. If we find that these are actually function7319/// parameter parens in an abstract-declarator, we call ParseFunctionDeclarator.7320///7321/// direct-declarator:7322/// '(' declarator ')'7323/// [GNU] '(' attributes declarator ')'7324/// direct-declarator '(' parameter-type-list ')'7325/// direct-declarator '(' identifier-list[opt] ')'7326/// [GNU] direct-declarator '(' parameter-forward-declarations7327/// parameter-type-list[opt] ')'7328///7329void Parser::ParseParenDeclarator(Declarator &D) {7330BalancedDelimiterTracker T(*this, tok::l_paren);7331T.consumeOpen();73327333assert(!D.isPastIdentifier() && "Should be called before passing identifier");73347335// Eat any attributes before we look at whether this is a grouping or function7336// declarator paren. If this is a grouping paren, the attribute applies to7337// the type being built up, for example:7338// int (__attribute__(()) *x)(long y)7339// If this ends up not being a grouping paren, the attribute applies to the7340// first argument, for example:7341// int (__attribute__(()) int x)7342// In either case, we need to eat any attributes to be able to determine what7343// sort of paren this is.7344//7345ParsedAttributes attrs(AttrFactory);7346bool RequiresArg = false;7347if (Tok.is(tok::kw___attribute)) {7348ParseGNUAttributes(attrs);73497350// We require that the argument list (if this is a non-grouping paren) be7351// present even if the attribute list was empty.7352RequiresArg = true;7353}73547355// Eat any Microsoft extensions.7356ParseMicrosoftTypeAttributes(attrs);73577358// Eat any Borland extensions.7359if (Tok.is(tok::kw___pascal))7360ParseBorlandTypeAttributes(attrs);73617362// If we haven't past the identifier yet (or where the identifier would be7363// stored, if this is an abstract declarator), then this is probably just7364// grouping parens. However, if this could be an abstract-declarator, then7365// this could also be the start of function arguments (consider 'void()').7366bool isGrouping;73677368if (!D.mayOmitIdentifier()) {7369// If this can't be an abstract-declarator, this *must* be a grouping7370// paren, because we haven't seen the identifier yet.7371isGrouping = true;7372} else if (Tok.is(tok::r_paren) || // 'int()' is a function.7373(getLangOpts().CPlusPlus && Tok.is(tok::ellipsis) &&7374NextToken().is(tok::r_paren)) || // C++ int(...)7375isDeclarationSpecifier(7376ImplicitTypenameContext::No) || // 'int(int)' is a function.7377isCXX11AttributeSpecifier()) { // 'int([[]]int)' is a function.7378// This handles C99 6.7.5.3p11: in "typedef int X; void foo(X)", X is7379// considered to be a type, not a K&R identifier-list.7380isGrouping = false;7381} else {7382// Otherwise, this is a grouping paren, e.g. 'int (*X)' or 'int(X)'.7383isGrouping = true;7384}73857386// If this is a grouping paren, handle:7387// direct-declarator: '(' declarator ')'7388// direct-declarator: '(' attributes declarator ')'7389if (isGrouping) {7390SourceLocation EllipsisLoc = D.getEllipsisLoc();7391D.setEllipsisLoc(SourceLocation());73927393bool hadGroupingParens = D.hasGroupingParens();7394D.setGroupingParens(true);7395ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);7396// Match the ')'.7397T.consumeClose();7398D.AddTypeInfo(7399DeclaratorChunk::getParen(T.getOpenLocation(), T.getCloseLocation()),7400std::move(attrs), T.getCloseLocation());74017402D.setGroupingParens(hadGroupingParens);74037404// An ellipsis cannot be placed outside parentheses.7405if (EllipsisLoc.isValid())7406DiagnoseMisplacedEllipsisInDeclarator(EllipsisLoc, D);74077408return;7409}74107411// Okay, if this wasn't a grouping paren, it must be the start of a function7412// argument list. Recognize that this declarator will never have an7413// identifier (and remember where it would have been), then call into7414// ParseFunctionDeclarator to handle of argument list.7415D.SetIdentifier(nullptr, Tok.getLocation());74167417// Enter function-declaration scope, limiting any declarators to the7418// function prototype scope, including parameter declarators.7419ParseScope PrototypeScope(this,7420Scope::FunctionPrototypeScope | Scope::DeclScope |7421(D.isFunctionDeclaratorAFunctionDeclaration()7422? Scope::FunctionDeclarationScope : 0));7423ParseFunctionDeclarator(D, attrs, T, false, RequiresArg);7424PrototypeScope.Exit();7425}74267427void Parser::InitCXXThisScopeForDeclaratorIfRelevant(7428const Declarator &D, const DeclSpec &DS,7429std::optional<Sema::CXXThisScopeRAII> &ThisScope) {7430// C++11 [expr.prim.general]p3:7431// If a declaration declares a member function or member function7432// template of a class X, the expression this is a prvalue of type7433// "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq7434// and the end of the function-definition, member-declarator, or7435// declarator.7436// FIXME: currently, "static" case isn't handled correctly.7437bool IsCXX11MemberFunction =7438getLangOpts().CPlusPlus11 &&7439D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&7440(D.getContext() == DeclaratorContext::Member7441? !D.getDeclSpec().isFriendSpecified()7442: D.getContext() == DeclaratorContext::File &&7443D.getCXXScopeSpec().isValid() &&7444Actions.CurContext->isRecord());7445if (!IsCXX11MemberFunction)7446return;74477448Qualifiers Q = Qualifiers::fromCVRUMask(DS.getTypeQualifiers());7449if (D.getDeclSpec().hasConstexprSpecifier() && !getLangOpts().CPlusPlus14)7450Q.addConst();7451// FIXME: Collect C++ address spaces.7452// If there are multiple different address spaces, the source is invalid.7453// Carry on using the first addr space for the qualifiers of 'this'.7454// The diagnostic will be given later while creating the function7455// prototype for the method.7456if (getLangOpts().OpenCLCPlusPlus) {7457for (ParsedAttr &attr : DS.getAttributes()) {7458LangAS ASIdx = attr.asOpenCLLangAS();7459if (ASIdx != LangAS::Default) {7460Q.addAddressSpace(ASIdx);7461break;7462}7463}7464}7465ThisScope.emplace(Actions, dyn_cast<CXXRecordDecl>(Actions.CurContext), Q,7466IsCXX11MemberFunction);7467}74687469/// ParseFunctionDeclarator - We are after the identifier and have parsed the7470/// declarator D up to a paren, which indicates that we are parsing function7471/// arguments.7472///7473/// If FirstArgAttrs is non-null, then the caller parsed those attributes7474/// immediately after the open paren - they will be applied to the DeclSpec7475/// of the first parameter.7476///7477/// If RequiresArg is true, then the first argument of the function is required7478/// to be present and required to not be an identifier list.7479///7480/// For C++, after the parameter-list, it also parses the cv-qualifier-seq[opt],7481/// (C++11) ref-qualifier[opt], exception-specification[opt],7482/// (C++11) attribute-specifier-seq[opt], (C++11) trailing-return-type[opt] and7483/// (C++2a) the trailing requires-clause.7484///7485/// [C++11] exception-specification:7486/// dynamic-exception-specification7487/// noexcept-specification7488///7489void Parser::ParseFunctionDeclarator(Declarator &D,7490ParsedAttributes &FirstArgAttrs,7491BalancedDelimiterTracker &Tracker,7492bool IsAmbiguous,7493bool RequiresArg) {7494assert(getCurScope()->isFunctionPrototypeScope() &&7495"Should call from a Function scope");7496// lparen is already consumed!7497assert(D.isPastIdentifier() && "Should not call before identifier!");74987499// This should be true when the function has typed arguments.7500// Otherwise, it is treated as a K&R-style function.7501bool HasProto = false;7502// Build up an array of information about the parsed arguments.7503SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;7504// Remember where we see an ellipsis, if any.7505SourceLocation EllipsisLoc;75067507DeclSpec DS(AttrFactory);7508bool RefQualifierIsLValueRef = true;7509SourceLocation RefQualifierLoc;7510ExceptionSpecificationType ESpecType = EST_None;7511SourceRange ESpecRange;7512SmallVector<ParsedType, 2> DynamicExceptions;7513SmallVector<SourceRange, 2> DynamicExceptionRanges;7514ExprResult NoexceptExpr;7515CachedTokens *ExceptionSpecTokens = nullptr;7516ParsedAttributes FnAttrs(AttrFactory);7517TypeResult TrailingReturnType;7518SourceLocation TrailingReturnTypeLoc;75197520/* LocalEndLoc is the end location for the local FunctionTypeLoc.7521EndLoc is the end location for the function declarator.7522They differ for trailing return types. */7523SourceLocation StartLoc, LocalEndLoc, EndLoc;7524SourceLocation LParenLoc, RParenLoc;7525LParenLoc = Tracker.getOpenLocation();7526StartLoc = LParenLoc;75277528if (isFunctionDeclaratorIdentifierList()) {7529if (RequiresArg)7530Diag(Tok, diag::err_argument_required_after_attribute);75317532ParseFunctionDeclaratorIdentifierList(D, ParamInfo);75337534Tracker.consumeClose();7535RParenLoc = Tracker.getCloseLocation();7536LocalEndLoc = RParenLoc;7537EndLoc = RParenLoc;75387539// If there are attributes following the identifier list, parse them and7540// prohibit them.7541MaybeParseCXX11Attributes(FnAttrs);7542ProhibitAttributes(FnAttrs);7543} else {7544if (Tok.isNot(tok::r_paren))7545ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc);7546else if (RequiresArg)7547Diag(Tok, diag::err_argument_required_after_attribute);75487549// OpenCL disallows functions without a prototype, but it doesn't enforce7550// strict prototypes as in C23 because it allows a function definition to7551// have an identifier list. See OpenCL 3.0 6.11/g for more details.7552HasProto = ParamInfo.size() || getLangOpts().requiresStrictPrototypes() ||7553getLangOpts().OpenCL;75547555// If we have the closing ')', eat it.7556Tracker.consumeClose();7557RParenLoc = Tracker.getCloseLocation();7558LocalEndLoc = RParenLoc;7559EndLoc = RParenLoc;75607561if (getLangOpts().CPlusPlus) {7562// FIXME: Accept these components in any order, and produce fixits to7563// correct the order if the user gets it wrong. Ideally we should deal7564// with the pure-specifier in the same way.75657566// Parse cv-qualifier-seq[opt].7567ParseTypeQualifierListOpt(7568DS, AR_NoAttributesParsed,7569/*AtomicAllowed*/ false,7570/*IdentifierRequired=*/false, llvm::function_ref<void()>([&]() {7571Actions.CodeCompletion().CodeCompleteFunctionQualifiers(DS, D);7572}));7573if (!DS.getSourceRange().getEnd().isInvalid()) {7574EndLoc = DS.getSourceRange().getEnd();7575}75767577// Parse ref-qualifier[opt].7578if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc))7579EndLoc = RefQualifierLoc;75807581std::optional<Sema::CXXThisScopeRAII> ThisScope;7582InitCXXThisScopeForDeclaratorIfRelevant(D, DS, ThisScope);75837584// C++ [class.mem.general]p8:7585// A complete-class context of a class (template) is a7586// - function body,7587// - default argument,7588// - default template argument,7589// - noexcept-specifier, or7590// - default member initializer7591// within the member-specification of the class or class template.7592//7593// Parse exception-specification[opt]. If we are in the7594// member-specification of a class or class template, this is a7595// complete-class context and parsing of the noexcept-specifier should be7596// delayed (even if this is a friend declaration).7597bool Delayed = D.getContext() == DeclaratorContext::Member &&7598D.isFunctionDeclaratorAFunctionDeclaration();7599if (Delayed && Actions.isLibstdcxxEagerExceptionSpecHack(D) &&7600GetLookAheadToken(0).is(tok::kw_noexcept) &&7601GetLookAheadToken(1).is(tok::l_paren) &&7602GetLookAheadToken(2).is(tok::kw_noexcept) &&7603GetLookAheadToken(3).is(tok::l_paren) &&7604GetLookAheadToken(4).is(tok::identifier) &&7605GetLookAheadToken(4).getIdentifierInfo()->isStr("swap")) {7606// HACK: We've got an exception-specification7607// noexcept(noexcept(swap(...)))7608// or7609// noexcept(noexcept(swap(...)) && noexcept(swap(...)))7610// on a 'swap' member function. This is a libstdc++ bug; the lookup7611// for 'swap' will only find the function we're currently declaring,7612// whereas it expects to find a non-member swap through ADL. Turn off7613// delayed parsing to give it a chance to find what it expects.7614Delayed = false;7615}7616ESpecType = tryParseExceptionSpecification(Delayed,7617ESpecRange,7618DynamicExceptions,7619DynamicExceptionRanges,7620NoexceptExpr,7621ExceptionSpecTokens);7622if (ESpecType != EST_None)7623EndLoc = ESpecRange.getEnd();76247625// Parse attribute-specifier-seq[opt]. Per DR 979 and DR 1297, this goes7626// after the exception-specification.7627MaybeParseCXX11Attributes(FnAttrs);76287629// Parse trailing-return-type[opt].7630LocalEndLoc = EndLoc;7631if (getLangOpts().CPlusPlus11 && Tok.is(tok::arrow)) {7632Diag(Tok, diag::warn_cxx98_compat_trailing_return_type);7633if (D.getDeclSpec().getTypeSpecType() == TST_auto)7634StartLoc = D.getDeclSpec().getTypeSpecTypeLoc();7635LocalEndLoc = Tok.getLocation();7636SourceRange Range;7637TrailingReturnType =7638ParseTrailingReturnType(Range, D.mayBeFollowedByCXXDirectInit());7639TrailingReturnTypeLoc = Range.getBegin();7640EndLoc = Range.getEnd();7641}7642} else {7643MaybeParseCXX11Attributes(FnAttrs);7644}7645}76467647// Collect non-parameter declarations from the prototype if this is a function7648// declaration. They will be moved into the scope of the function. Only do7649// this in C and not C++, where the decls will continue to live in the7650// surrounding context.7651SmallVector<NamedDecl *, 0> DeclsInPrototype;7652if (getCurScope()->isFunctionDeclarationScope() && !getLangOpts().CPlusPlus) {7653for (Decl *D : getCurScope()->decls()) {7654NamedDecl *ND = dyn_cast<NamedDecl>(D);7655if (!ND || isa<ParmVarDecl>(ND))7656continue;7657DeclsInPrototype.push_back(ND);7658}7659// Sort DeclsInPrototype based on raw encoding of the source location.7660// Scope::decls() is iterating over a SmallPtrSet so sort the Decls before7661// moving to DeclContext. This provides a stable ordering for traversing7662// Decls in DeclContext, which is important for tasks like ASTWriter for7663// deterministic output.7664llvm::sort(DeclsInPrototype, [](Decl *D1, Decl *D2) {7665return D1->getLocation().getRawEncoding() <7666D2->getLocation().getRawEncoding();7667});7668}76697670// Remember that we parsed a function type, and remember the attributes.7671D.AddTypeInfo(DeclaratorChunk::getFunction(7672HasProto, IsAmbiguous, LParenLoc, ParamInfo.data(),7673ParamInfo.size(), EllipsisLoc, RParenLoc,7674RefQualifierIsLValueRef, RefQualifierLoc,7675/*MutableLoc=*/SourceLocation(),7676ESpecType, ESpecRange, DynamicExceptions.data(),7677DynamicExceptionRanges.data(), DynamicExceptions.size(),7678NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr,7679ExceptionSpecTokens, DeclsInPrototype, StartLoc,7680LocalEndLoc, D, TrailingReturnType, TrailingReturnTypeLoc,7681&DS),7682std::move(FnAttrs), EndLoc);7683}76847685/// ParseRefQualifier - Parses a member function ref-qualifier. Returns7686/// true if a ref-qualifier is found.7687bool Parser::ParseRefQualifier(bool &RefQualifierIsLValueRef,7688SourceLocation &RefQualifierLoc) {7689if (Tok.isOneOf(tok::amp, tok::ampamp)) {7690Diag(Tok, getLangOpts().CPlusPlus11 ?7691diag::warn_cxx98_compat_ref_qualifier :7692diag::ext_ref_qualifier);76937694RefQualifierIsLValueRef = Tok.is(tok::amp);7695RefQualifierLoc = ConsumeToken();7696return true;7697}7698return false;7699}77007701/// isFunctionDeclaratorIdentifierList - This parameter list may have an7702/// identifier list form for a K&R-style function: void foo(a,b,c)7703///7704/// Note that identifier-lists are only allowed for normal declarators, not for7705/// abstract-declarators.7706bool Parser::isFunctionDeclaratorIdentifierList() {7707return !getLangOpts().requiresStrictPrototypes()7708&& Tok.is(tok::identifier)7709&& !TryAltiVecVectorToken()7710// K&R identifier lists can't have typedefs as identifiers, per C997711// 6.7.5.3p11.7712&& (TryAnnotateTypeOrScopeToken() || !Tok.is(tok::annot_typename))7713// Identifier lists follow a really simple grammar: the identifiers can7714// be followed *only* by a ", identifier" or ")". However, K&R7715// identifier lists are really rare in the brave new modern world, and7716// it is very common for someone to typo a type in a non-K&R style7717// list. If we are presented with something like: "void foo(intptr x,7718// float y)", we don't want to start parsing the function declarator as7719// though it is a K&R style declarator just because intptr is an7720// invalid type.7721//7722// To handle this, we check to see if the token after the first7723// identifier is a "," or ")". Only then do we parse it as an7724// identifier list.7725&& (!Tok.is(tok::eof) &&7726(NextToken().is(tok::comma) || NextToken().is(tok::r_paren)));7727}77287729/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator7730/// we found a K&R-style identifier list instead of a typed parameter list.7731///7732/// After returning, ParamInfo will hold the parsed parameters.7733///7734/// identifier-list: [C99 6.7.5]7735/// identifier7736/// identifier-list ',' identifier7737///7738void Parser::ParseFunctionDeclaratorIdentifierList(7739Declarator &D,7740SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo) {7741// We should never reach this point in C23 or C++.7742assert(!getLangOpts().requiresStrictPrototypes() &&7743"Cannot parse an identifier list in C23 or C++");77447745// If there was no identifier specified for the declarator, either we are in7746// an abstract-declarator, or we are in a parameter declarator which was found7747// to be abstract. In abstract-declarators, identifier lists are not valid:7748// diagnose this.7749if (!D.getIdentifier())7750Diag(Tok, diag::ext_ident_list_in_param);77517752// Maintain an efficient lookup of params we have seen so far.7753llvm::SmallSet<const IdentifierInfo*, 16> ParamsSoFar;77547755do {7756// If this isn't an identifier, report the error and skip until ')'.7757if (Tok.isNot(tok::identifier)) {7758Diag(Tok, diag::err_expected) << tok::identifier;7759SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);7760// Forget we parsed anything.7761ParamInfo.clear();7762return;7763}77647765IdentifierInfo *ParmII = Tok.getIdentifierInfo();77667767// Reject 'typedef int y; int test(x, y)', but continue parsing.7768if (Actions.getTypeName(*ParmII, Tok.getLocation(), getCurScope()))7769Diag(Tok, diag::err_unexpected_typedef_ident) << ParmII;77707771// Verify that the argument identifier has not already been mentioned.7772if (!ParamsSoFar.insert(ParmII).second) {7773Diag(Tok, diag::err_param_redefinition) << ParmII;7774} else {7775// Remember this identifier in ParamInfo.7776ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,7777Tok.getLocation(),7778nullptr));7779}77807781// Eat the identifier.7782ConsumeToken();7783// The list continues if we see a comma.7784} while (TryConsumeToken(tok::comma));7785}77867787/// ParseParameterDeclarationClause - Parse a (possibly empty) parameter-list7788/// after the opening parenthesis. This function will not parse a K&R-style7789/// identifier list.7790///7791/// DeclContext is the context of the declarator being parsed. If FirstArgAttrs7792/// is non-null, then the caller parsed those attributes immediately after the7793/// open paren - they will be applied to the DeclSpec of the first parameter.7794///7795/// After returning, ParamInfo will hold the parsed parameters. EllipsisLoc will7796/// be the location of the ellipsis, if any was parsed.7797///7798/// parameter-type-list: [C99 6.7.5]7799/// parameter-list7800/// parameter-list ',' '...'7801/// [C++] parameter-list '...'7802///7803/// parameter-list: [C99 6.7.5]7804/// parameter-declaration7805/// parameter-list ',' parameter-declaration7806///7807/// parameter-declaration: [C99 6.7.5]7808/// declaration-specifiers declarator7809/// [C++] declaration-specifiers declarator '=' assignment-expression7810/// [C++11] initializer-clause7811/// [GNU] declaration-specifiers declarator attributes7812/// declaration-specifiers abstract-declarator[opt]7813/// [C++] declaration-specifiers abstract-declarator[opt]7814/// '=' assignment-expression7815/// [GNU] declaration-specifiers abstract-declarator[opt] attributes7816/// [C++11] attribute-specifier-seq parameter-declaration7817/// [C++2b] attribute-specifier-seq 'this' parameter-declaration7818///7819void Parser::ParseParameterDeclarationClause(7820DeclaratorContext DeclaratorCtx, ParsedAttributes &FirstArgAttrs,7821SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,7822SourceLocation &EllipsisLoc, bool IsACXXFunctionDeclaration) {78237824// Avoid exceeding the maximum function scope depth.7825// See https://bugs.llvm.org/show_bug.cgi?id=196077826// Note Sema::ActOnParamDeclarator calls ParmVarDecl::setScopeInfo with7827// getFunctionPrototypeDepth() - 1.7828if (getCurScope()->getFunctionPrototypeDepth() - 1 >7829ParmVarDecl::getMaxFunctionScopeDepth()) {7830Diag(Tok.getLocation(), diag::err_function_scope_depth_exceeded)7831<< ParmVarDecl::getMaxFunctionScopeDepth();7832cutOffParsing();7833return;7834}78357836// C++2a [temp.res]p57837// A qualified-id is assumed to name a type if7838// - [...]7839// - it is a decl-specifier of the decl-specifier-seq of a7840// - [...]7841// - parameter-declaration in a member-declaration [...]7842// - parameter-declaration in a declarator of a function or function7843// template declaration whose declarator-id is qualified [...]7844// - parameter-declaration in a lambda-declarator [...]7845auto AllowImplicitTypename = ImplicitTypenameContext::No;7846if (DeclaratorCtx == DeclaratorContext::Member ||7847DeclaratorCtx == DeclaratorContext::LambdaExpr ||7848DeclaratorCtx == DeclaratorContext::RequiresExpr ||7849IsACXXFunctionDeclaration) {7850AllowImplicitTypename = ImplicitTypenameContext::Yes;7851}78527853do {7854// FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq7855// before deciding this was a parameter-declaration-clause.7856if (TryConsumeToken(tok::ellipsis, EllipsisLoc))7857break;78587859// Parse the declaration-specifiers.7860// Just use the ParsingDeclaration "scope" of the declarator.7861DeclSpec DS(AttrFactory);78627863ParsedAttributes ArgDeclAttrs(AttrFactory);7864ParsedAttributes ArgDeclSpecAttrs(AttrFactory);78657866if (FirstArgAttrs.Range.isValid()) {7867// If the caller parsed attributes for the first argument, add them now.7868// Take them so that we only apply the attributes to the first parameter.7869// We have already started parsing the decl-specifier sequence, so don't7870// parse any parameter-declaration pieces that precede it.7871ArgDeclSpecAttrs.takeAllFrom(FirstArgAttrs);7872} else {7873// Parse any C++11 attributes.7874MaybeParseCXX11Attributes(ArgDeclAttrs);78757876// Skip any Microsoft attributes before a param.7877MaybeParseMicrosoftAttributes(ArgDeclSpecAttrs);7878}78797880SourceLocation DSStart = Tok.getLocation();78817882// Parse a C++23 Explicit Object Parameter7883// We do that in all language modes to produce a better diagnostic.7884SourceLocation ThisLoc;7885if (getLangOpts().CPlusPlus && Tok.is(tok::kw_this)) {7886ThisLoc = ConsumeToken();7887// C++23 [dcl.fct]p6:7888// An explicit-object-parameter-declaration is a parameter-declaration7889// with a this specifier. An explicit-object-parameter-declaration7890// shall appear only as the first parameter-declaration of a7891// parameter-declaration-list of either:7892// - a member-declarator that declares a member function, or7893// - a lambda-declarator.7894//7895// The parameter-declaration-list of a requires-expression is not such7896// a context.7897if (DeclaratorCtx == DeclaratorContext::RequiresExpr)7898Diag(ThisLoc, diag::err_requires_expr_explicit_object_parameter);7899}79007901ParsedTemplateInfo TemplateInfo;7902ParseDeclarationSpecifiers(DS, TemplateInfo, AS_none,7903DeclSpecContext::DSC_normal,7904/*LateAttrs=*/nullptr, AllowImplicitTypename);79057906DS.takeAttributesFrom(ArgDeclSpecAttrs);79077908// Parse the declarator. This is "PrototypeContext" or7909// "LambdaExprParameterContext", because we must accept either7910// 'declarator' or 'abstract-declarator' here.7911Declarator ParmDeclarator(DS, ArgDeclAttrs,7912DeclaratorCtx == DeclaratorContext::RequiresExpr7913? DeclaratorContext::RequiresExpr7914: DeclaratorCtx == DeclaratorContext::LambdaExpr7915? DeclaratorContext::LambdaExprParameter7916: DeclaratorContext::Prototype);7917ParseDeclarator(ParmDeclarator);79187919if (ThisLoc.isValid())7920ParmDeclarator.SetRangeBegin(ThisLoc);79217922// Parse GNU attributes, if present.7923MaybeParseGNUAttributes(ParmDeclarator);7924if (getLangOpts().HLSL)7925MaybeParseHLSLAnnotations(DS.getAttributes());79267927if (Tok.is(tok::kw_requires)) {7928// User tried to define a requires clause in a parameter declaration,7929// which is surely not a function declaration.7930// void f(int (*g)(int, int) requires true);7931Diag(Tok,7932diag::err_requires_clause_on_declarator_not_declaring_a_function);7933ConsumeToken();7934Actions.CorrectDelayedTyposInExpr(7935ParseConstraintLogicalOrExpression(/*IsTrailingRequiresClause=*/true));7936}79377938// Remember this parsed parameter in ParamInfo.7939const IdentifierInfo *ParmII = ParmDeclarator.getIdentifier();79407941// DefArgToks is used when the parsing of default arguments needs7942// to be delayed.7943std::unique_ptr<CachedTokens> DefArgToks;79447945// If no parameter was specified, verify that *something* was specified,7946// otherwise we have a missing type and identifier.7947if (DS.isEmpty() && ParmDeclarator.getIdentifier() == nullptr &&7948ParmDeclarator.getNumTypeObjects() == 0) {7949// Completely missing, emit error.7950Diag(DSStart, diag::err_missing_param);7951} else {7952// Otherwise, we have something. Add it and let semantic analysis try7953// to grok it and add the result to the ParamInfo we are building.79547955// Last chance to recover from a misplaced ellipsis in an attempted7956// parameter pack declaration.7957if (Tok.is(tok::ellipsis) &&7958(NextToken().isNot(tok::r_paren) ||7959(!ParmDeclarator.getEllipsisLoc().isValid() &&7960!Actions.isUnexpandedParameterPackPermitted())) &&7961Actions.containsUnexpandedParameterPacks(ParmDeclarator))7962DiagnoseMisplacedEllipsisInDeclarator(ConsumeToken(), ParmDeclarator);79637964// Now we are at the point where declarator parsing is finished.7965//7966// Try to catch keywords in place of the identifier in a declarator, and7967// in particular the common case where:7968// 1 identifier comes at the end of the declarator7969// 2 if the identifier is dropped, the declarator is valid but anonymous7970// (no identifier)7971// 3 declarator parsing succeeds, and then we have a trailing keyword,7972// which is never valid in a param list (e.g. missing a ',')7973// And we can't handle this in ParseDeclarator because in general keywords7974// may be allowed to follow the declarator. (And in some cases there'd be7975// better recovery like inserting punctuation). ParseDeclarator is just7976// treating this as an anonymous parameter, and fortunately at this point7977// we've already almost done that.7978//7979// We care about case 1) where the declarator type should be known, and7980// the identifier should be null.7981if (!ParmDeclarator.isInvalidType() && !ParmDeclarator.hasName() &&7982Tok.isNot(tok::raw_identifier) && !Tok.isAnnotation() &&7983Tok.getIdentifierInfo() &&7984Tok.getIdentifierInfo()->isKeyword(getLangOpts())) {7985Diag(Tok, diag::err_keyword_as_parameter) << PP.getSpelling(Tok);7986// Consume the keyword.7987ConsumeToken();7988}7989// Inform the actions module about the parameter declarator, so it gets7990// added to the current scope.7991Decl *Param =7992Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator, ThisLoc);7993// Parse the default argument, if any. We parse the default7994// arguments in all dialects; the semantic analysis in7995// ActOnParamDefaultArgument will reject the default argument in7996// C.7997if (Tok.is(tok::equal)) {7998SourceLocation EqualLoc = Tok.getLocation();79998000// Parse the default argument8001if (DeclaratorCtx == DeclaratorContext::Member) {8002// If we're inside a class definition, cache the tokens8003// corresponding to the default argument. We'll actually parse8004// them when we see the end of the class definition.8005DefArgToks.reset(new CachedTokens);80068007SourceLocation ArgStartLoc = NextToken().getLocation();8008ConsumeAndStoreInitializer(*DefArgToks, CIK_DefaultArgument);8009Actions.ActOnParamUnparsedDefaultArgument(Param, EqualLoc,8010ArgStartLoc);8011} else {8012// Consume the '='.8013ConsumeToken();80148015// The argument isn't actually potentially evaluated unless it is8016// used.8017EnterExpressionEvaluationContext Eval(8018Actions,8019Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed,8020Param);80218022ExprResult DefArgResult;8023if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {8024Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);8025DefArgResult = ParseBraceInitializer();8026} else {8027if (Tok.is(tok::l_paren) && NextToken().is(tok::l_brace)) {8028Diag(Tok, diag::err_stmt_expr_in_default_arg) << 0;8029Actions.ActOnParamDefaultArgumentError(Param, EqualLoc,8030/*DefaultArg=*/nullptr);8031// Skip the statement expression and continue parsing8032SkipUntil(tok::comma, StopBeforeMatch);8033continue;8034}8035DefArgResult = ParseAssignmentExpression();8036}8037DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult);8038if (DefArgResult.isInvalid()) {8039Actions.ActOnParamDefaultArgumentError(Param, EqualLoc,8040/*DefaultArg=*/nullptr);8041SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch);8042} else {8043// Inform the actions module about the default argument8044Actions.ActOnParamDefaultArgument(Param, EqualLoc,8045DefArgResult.get());8046}8047}8048}80498050ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,8051ParmDeclarator.getIdentifierLoc(),8052Param, std::move(DefArgToks)));8053}80548055if (TryConsumeToken(tok::ellipsis, EllipsisLoc)) {8056if (!getLangOpts().CPlusPlus) {8057// We have ellipsis without a preceding ',', which is ill-formed8058// in C. Complain and provide the fix.8059Diag(EllipsisLoc, diag::err_missing_comma_before_ellipsis)8060<< FixItHint::CreateInsertion(EllipsisLoc, ", ");8061} else if (ParmDeclarator.getEllipsisLoc().isValid() ||8062Actions.containsUnexpandedParameterPacks(ParmDeclarator)) {8063// It looks like this was supposed to be a parameter pack. Warn and8064// point out where the ellipsis should have gone.8065SourceLocation ParmEllipsis = ParmDeclarator.getEllipsisLoc();8066Diag(EllipsisLoc, diag::warn_misplaced_ellipsis_vararg)8067<< ParmEllipsis.isValid() << ParmEllipsis;8068if (ParmEllipsis.isValid()) {8069Diag(ParmEllipsis,8070diag::note_misplaced_ellipsis_vararg_existing_ellipsis);8071} else {8072Diag(ParmDeclarator.getIdentifierLoc(),8073diag::note_misplaced_ellipsis_vararg_add_ellipsis)8074<< FixItHint::CreateInsertion(ParmDeclarator.getIdentifierLoc(),8075"...")8076<< !ParmDeclarator.hasName();8077}8078Diag(EllipsisLoc, diag::note_misplaced_ellipsis_vararg_add_comma)8079<< FixItHint::CreateInsertion(EllipsisLoc, ", ");8080}80818082// We can't have any more parameters after an ellipsis.8083break;8084}80858086// If the next token is a comma, consume it and keep reading arguments.8087} while (TryConsumeToken(tok::comma));8088}80898090/// [C90] direct-declarator '[' constant-expression[opt] ']'8091/// [C99] direct-declarator '[' type-qual-list[opt] assignment-expr[opt] ']'8092/// [C99] direct-declarator '[' 'static' type-qual-list[opt] assign-expr ']'8093/// [C99] direct-declarator '[' type-qual-list 'static' assignment-expr ']'8094/// [C99] direct-declarator '[' type-qual-list[opt] '*' ']'8095/// [C++11] direct-declarator '[' constant-expression[opt] ']'8096/// attribute-specifier-seq[opt]8097void Parser::ParseBracketDeclarator(Declarator &D) {8098if (CheckProhibitedCXX11Attribute())8099return;81008101BalancedDelimiterTracker T(*this, tok::l_square);8102T.consumeOpen();81038104// C array syntax has many features, but by-far the most common is [] and [4].8105// This code does a fast path to handle some of the most obvious cases.8106if (Tok.getKind() == tok::r_square) {8107T.consumeClose();8108ParsedAttributes attrs(AttrFactory);8109MaybeParseCXX11Attributes(attrs);81108111// Remember that we parsed the empty array type.8112D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr,8113T.getOpenLocation(),8114T.getCloseLocation()),8115std::move(attrs), T.getCloseLocation());8116return;8117} else if (Tok.getKind() == tok::numeric_constant &&8118GetLookAheadToken(1).is(tok::r_square)) {8119// [4] is very common. Parse the numeric constant expression.8120ExprResult ExprRes(Actions.ActOnNumericConstant(Tok, getCurScope()));8121ConsumeToken();81228123T.consumeClose();8124ParsedAttributes attrs(AttrFactory);8125MaybeParseCXX11Attributes(attrs);81268127// Remember that we parsed a array type, and remember its features.8128D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, ExprRes.get(),8129T.getOpenLocation(),8130T.getCloseLocation()),8131std::move(attrs), T.getCloseLocation());8132return;8133} else if (Tok.getKind() == tok::code_completion) {8134cutOffParsing();8135Actions.CodeCompletion().CodeCompleteBracketDeclarator(getCurScope());8136return;8137}81388139// If valid, this location is the position where we read the 'static' keyword.8140SourceLocation StaticLoc;8141TryConsumeToken(tok::kw_static, StaticLoc);81428143// If there is a type-qualifier-list, read it now.8144// Type qualifiers in an array subscript are a C99 feature.8145DeclSpec DS(AttrFactory);8146ParseTypeQualifierListOpt(DS, AR_CXX11AttributesParsed);81478148// If we haven't already read 'static', check to see if there is one after the8149// type-qualifier-list.8150if (!StaticLoc.isValid())8151TryConsumeToken(tok::kw_static, StaticLoc);81528153// Handle "direct-declarator [ type-qual-list[opt] * ]".8154bool isStar = false;8155ExprResult NumElements;81568157// Handle the case where we have '[*]' as the array size. However, a leading8158// star could be the start of an expression, for example 'X[*p + 4]'. Verify8159// the token after the star is a ']'. Since stars in arrays are8160// infrequent, use of lookahead is not costly here.8161if (Tok.is(tok::star) && GetLookAheadToken(1).is(tok::r_square)) {8162ConsumeToken(); // Eat the '*'.81638164if (StaticLoc.isValid()) {8165Diag(StaticLoc, diag::err_unspecified_vla_size_with_static);8166StaticLoc = SourceLocation(); // Drop the static.8167}8168isStar = true;8169} else if (Tok.isNot(tok::r_square)) {8170// Note, in C89, this production uses the constant-expr production instead8171// of assignment-expr. The only difference is that assignment-expr allows8172// things like '=' and '*='. Sema rejects these in C89 mode because they8173// are not i-c-e's, so we don't need to distinguish between the two here.81748175// Parse the constant-expression or assignment-expression now (depending8176// on dialect).8177if (getLangOpts().CPlusPlus) {8178NumElements = ParseArrayBoundExpression();8179} else {8180EnterExpressionEvaluationContext Unevaluated(8181Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);8182NumElements =8183Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());8184}8185} else {8186if (StaticLoc.isValid()) {8187Diag(StaticLoc, diag::err_unspecified_size_with_static);8188StaticLoc = SourceLocation(); // Drop the static.8189}8190}81918192// If there was an error parsing the assignment-expression, recover.8193if (NumElements.isInvalid()) {8194D.setInvalidType(true);8195// If the expression was invalid, skip it.8196SkipUntil(tok::r_square, StopAtSemi);8197return;8198}81998200T.consumeClose();82018202MaybeParseCXX11Attributes(DS.getAttributes());82038204// Remember that we parsed a array type, and remember its features.8205D.AddTypeInfo(8206DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(),8207isStar, NumElements.get(), T.getOpenLocation(),8208T.getCloseLocation()),8209std::move(DS.getAttributes()), T.getCloseLocation());8210}82118212/// Diagnose brackets before an identifier.8213void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {8214assert(Tok.is(tok::l_square) && "Missing opening bracket");8215assert(!D.mayOmitIdentifier() && "Declarator cannot omit identifier");82168217SourceLocation StartBracketLoc = Tok.getLocation();8218Declarator TempDeclarator(D.getDeclSpec(), ParsedAttributesView::none(),8219D.getContext());82208221while (Tok.is(tok::l_square)) {8222ParseBracketDeclarator(TempDeclarator);8223}82248225// Stuff the location of the start of the brackets into the Declarator.8226// The diagnostics from ParseDirectDeclarator will make more sense if8227// they use this location instead.8228if (Tok.is(tok::semi))8229D.getName().EndLocation = StartBracketLoc;82308231SourceLocation SuggestParenLoc = Tok.getLocation();82328233// Now that the brackets are removed, try parsing the declarator again.8234ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator);82358236// Something went wrong parsing the brackets, in which case,8237// ParseBracketDeclarator has emitted an error, and we don't need to emit8238// one here.8239if (TempDeclarator.getNumTypeObjects() == 0)8240return;82418242// Determine if parens will need to be suggested in the diagnostic.8243bool NeedParens = false;8244if (D.getNumTypeObjects() != 0) {8245switch (D.getTypeObject(D.getNumTypeObjects() - 1).Kind) {8246case DeclaratorChunk::Pointer:8247case DeclaratorChunk::Reference:8248case DeclaratorChunk::BlockPointer:8249case DeclaratorChunk::MemberPointer:8250case DeclaratorChunk::Pipe:8251NeedParens = true;8252break;8253case DeclaratorChunk::Array:8254case DeclaratorChunk::Function:8255case DeclaratorChunk::Paren:8256break;8257}8258}82598260if (NeedParens) {8261// Create a DeclaratorChunk for the inserted parens.8262SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc());8263D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc),8264SourceLocation());8265}82668267// Adding back the bracket info to the end of the Declarator.8268for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) {8269const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i);8270D.AddTypeInfo(Chunk, TempDeclarator.getAttributePool(), SourceLocation());8271}82728273// The missing identifier would have been diagnosed in ParseDirectDeclarator.8274// If parentheses are required, always suggest them.8275if (!D.getIdentifier() && !NeedParens)8276return;82778278SourceLocation EndBracketLoc = TempDeclarator.getEndLoc();82798280// Generate the move bracket error message.8281SourceRange BracketRange(StartBracketLoc, EndBracketLoc);8282SourceLocation EndLoc = PP.getLocForEndOfToken(D.getEndLoc());82838284if (NeedParens) {8285Diag(EndLoc, diag::err_brackets_go_after_unqualified_id)8286<< getLangOpts().CPlusPlus8287<< FixItHint::CreateInsertion(SuggestParenLoc, "(")8288<< FixItHint::CreateInsertion(EndLoc, ")")8289<< FixItHint::CreateInsertionFromRange(8290EndLoc, CharSourceRange(BracketRange, true))8291<< FixItHint::CreateRemoval(BracketRange);8292} else {8293Diag(EndLoc, diag::err_brackets_go_after_unqualified_id)8294<< getLangOpts().CPlusPlus8295<< FixItHint::CreateInsertionFromRange(8296EndLoc, CharSourceRange(BracketRange, true))8297<< FixItHint::CreateRemoval(BracketRange);8298}8299}83008301/// [GNU] typeof-specifier:8302/// typeof ( expressions )8303/// typeof ( type-name )8304/// [GNU/C++] typeof unary-expression8305/// [C23] typeof-specifier:8306/// typeof '(' typeof-specifier-argument ')'8307/// typeof_unqual '(' typeof-specifier-argument ')'8308///8309/// typeof-specifier-argument:8310/// expression8311/// type-name8312///8313void Parser::ParseTypeofSpecifier(DeclSpec &DS) {8314assert(Tok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual) &&8315"Not a typeof specifier");83168317bool IsUnqual = Tok.is(tok::kw_typeof_unqual);8318const IdentifierInfo *II = Tok.getIdentifierInfo();8319if (getLangOpts().C23 && !II->getName().starts_with("__"))8320Diag(Tok.getLocation(), diag::warn_c23_compat_keyword) << Tok.getName();83218322Token OpTok = Tok;8323SourceLocation StartLoc = ConsumeToken();8324bool HasParens = Tok.is(tok::l_paren);83258326EnterExpressionEvaluationContext Unevaluated(8327Actions, Sema::ExpressionEvaluationContext::Unevaluated,8328Sema::ReuseLambdaContextDecl);83298330bool isCastExpr;8331ParsedType CastTy;8332SourceRange CastRange;8333ExprResult Operand = Actions.CorrectDelayedTyposInExpr(8334ParseExprAfterUnaryExprOrTypeTrait(OpTok, isCastExpr, CastTy, CastRange));8335if (HasParens)8336DS.setTypeArgumentRange(CastRange);83378338if (CastRange.getEnd().isInvalid())8339// FIXME: Not accurate, the range gets one token more than it should.8340DS.SetRangeEnd(Tok.getLocation());8341else8342DS.SetRangeEnd(CastRange.getEnd());83438344if (isCastExpr) {8345if (!CastTy) {8346DS.SetTypeSpecError();8347return;8348}83498350const char *PrevSpec = nullptr;8351unsigned DiagID;8352// Check for duplicate type specifiers (e.g. "int typeof(int)").8353if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualType8354: DeclSpec::TST_typeofType,8355StartLoc, PrevSpec,8356DiagID, CastTy,8357Actions.getASTContext().getPrintingPolicy()))8358Diag(StartLoc, DiagID) << PrevSpec;8359return;8360}83618362// If we get here, the operand to the typeof was an expression.8363if (Operand.isInvalid()) {8364DS.SetTypeSpecError();8365return;8366}83678368// We might need to transform the operand if it is potentially evaluated.8369Operand = Actions.HandleExprEvaluationContextForTypeof(Operand.get());8370if (Operand.isInvalid()) {8371DS.SetTypeSpecError();8372return;8373}83748375const char *PrevSpec = nullptr;8376unsigned DiagID;8377// Check for duplicate type specifiers (e.g. "int typeof(int)").8378if (DS.SetTypeSpecType(IsUnqual ? DeclSpec::TST_typeof_unqualExpr8379: DeclSpec::TST_typeofExpr,8380StartLoc, PrevSpec,8381DiagID, Operand.get(),8382Actions.getASTContext().getPrintingPolicy()))8383Diag(StartLoc, DiagID) << PrevSpec;8384}83858386/// [C11] atomic-specifier:8387/// _Atomic ( type-name )8388///8389void Parser::ParseAtomicSpecifier(DeclSpec &DS) {8390assert(Tok.is(tok::kw__Atomic) && NextToken().is(tok::l_paren) &&8391"Not an atomic specifier");83928393SourceLocation StartLoc = ConsumeToken();8394BalancedDelimiterTracker T(*this, tok::l_paren);8395if (T.consumeOpen())8396return;83978398TypeResult Result = ParseTypeName();8399if (Result.isInvalid()) {8400SkipUntil(tok::r_paren, StopAtSemi);8401return;8402}84038404// Match the ')'8405T.consumeClose();84068407if (T.getCloseLocation().isInvalid())8408return;84098410DS.setTypeArgumentRange(T.getRange());8411DS.SetRangeEnd(T.getCloseLocation());84128413const char *PrevSpec = nullptr;8414unsigned DiagID;8415if (DS.SetTypeSpecType(DeclSpec::TST_atomic, StartLoc, PrevSpec,8416DiagID, Result.get(),8417Actions.getASTContext().getPrintingPolicy()))8418Diag(StartLoc, DiagID) << PrevSpec;8419}84208421/// TryAltiVecVectorTokenOutOfLine - Out of line body that should only be called8422/// from TryAltiVecVectorToken.8423bool Parser::TryAltiVecVectorTokenOutOfLine() {8424Token Next = NextToken();8425switch (Next.getKind()) {8426default: return false;8427case tok::kw_short:8428case tok::kw_long:8429case tok::kw_signed:8430case tok::kw_unsigned:8431case tok::kw_void:8432case tok::kw_char:8433case tok::kw_int:8434case tok::kw_float:8435case tok::kw_double:8436case tok::kw_bool:8437case tok::kw__Bool:8438case tok::kw___bool:8439case tok::kw___pixel:8440Tok.setKind(tok::kw___vector);8441return true;8442case tok::identifier:8443if (Next.getIdentifierInfo() == Ident_pixel) {8444Tok.setKind(tok::kw___vector);8445return true;8446}8447if (Next.getIdentifierInfo() == Ident_bool ||8448Next.getIdentifierInfo() == Ident_Bool) {8449Tok.setKind(tok::kw___vector);8450return true;8451}8452return false;8453}8454}84558456bool Parser::TryAltiVecTokenOutOfLine(DeclSpec &DS, SourceLocation Loc,8457const char *&PrevSpec, unsigned &DiagID,8458bool &isInvalid) {8459const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();8460if (Tok.getIdentifierInfo() == Ident_vector) {8461Token Next = NextToken();8462switch (Next.getKind()) {8463case tok::kw_short:8464case tok::kw_long:8465case tok::kw_signed:8466case tok::kw_unsigned:8467case tok::kw_void:8468case tok::kw_char:8469case tok::kw_int:8470case tok::kw_float:8471case tok::kw_double:8472case tok::kw_bool:8473case tok::kw__Bool:8474case tok::kw___bool:8475case tok::kw___pixel:8476isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);8477return true;8478case tok::identifier:8479if (Next.getIdentifierInfo() == Ident_pixel) {8480isInvalid = DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID,Policy);8481return true;8482}8483if (Next.getIdentifierInfo() == Ident_bool ||8484Next.getIdentifierInfo() == Ident_Bool) {8485isInvalid =8486DS.SetTypeAltiVecVector(true, Loc, PrevSpec, DiagID, Policy);8487return true;8488}8489break;8490default:8491break;8492}8493} else if ((Tok.getIdentifierInfo() == Ident_pixel) &&8494DS.isTypeAltiVecVector()) {8495isInvalid = DS.SetTypeAltiVecPixel(true, Loc, PrevSpec, DiagID, Policy);8496return true;8497} else if ((Tok.getIdentifierInfo() == Ident_bool) &&8498DS.isTypeAltiVecVector()) {8499isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);8500return true;8501}8502return false;8503}85048505TypeResult Parser::ParseTypeFromString(StringRef TypeStr, StringRef Context,8506SourceLocation IncludeLoc) {8507// Consume (unexpanded) tokens up to the end-of-directive.8508SmallVector<Token, 4> Tokens;8509{8510// Create a new buffer from which we will parse the type.8511auto &SourceMgr = PP.getSourceManager();8512FileID FID = SourceMgr.createFileID(8513llvm::MemoryBuffer::getMemBufferCopy(TypeStr, Context), SrcMgr::C_User,85140, 0, IncludeLoc);85158516// Form a new lexer that references the buffer.8517Lexer L(FID, SourceMgr.getBufferOrFake(FID), PP);8518L.setParsingPreprocessorDirective(true);85198520// Lex the tokens from that buffer.8521Token Tok;8522do {8523L.Lex(Tok);8524Tokens.push_back(Tok);8525} while (Tok.isNot(tok::eod));8526}85278528// Replace the "eod" token with an "eof" token identifying the end of8529// the provided string.8530Token &EndToken = Tokens.back();8531EndToken.startToken();8532EndToken.setKind(tok::eof);8533EndToken.setLocation(Tok.getLocation());8534EndToken.setEofData(TypeStr.data());85358536// Add the current token back.8537Tokens.push_back(Tok);85388539// Enter the tokens into the token stream.8540PP.EnterTokenStream(Tokens, /*DisableMacroExpansion=*/false,8541/*IsReinject=*/false);85428543// Consume the current token so that we'll start parsing the tokens we8544// added to the stream.8545ConsumeAnyToken();85468547// Enter a new scope.8548ParseScope LocalScope(this, 0);85498550// Parse the type.8551TypeResult Result = ParseTypeName(nullptr);85528553// Check if we parsed the whole thing.8554if (Result.isUsable() &&8555(Tok.isNot(tok::eof) || Tok.getEofData() != TypeStr.data())) {8556Diag(Tok.getLocation(), diag::err_type_unparsed);8557}85588559// There could be leftover tokens (e.g. because of an error).8560// Skip through until we reach the 'end of directive' token.8561while (Tok.isNot(tok::eof))8562ConsumeAnyToken();85638564// Consume the end token.8565if (Tok.is(tok::eof) && Tok.getEofData() == TypeStr.data())8566ConsumeAnyToken();8567return Result;8568}85698570void Parser::DiagnoseBitIntUse(const Token &Tok) {8571// If the token is for _ExtInt, diagnose it as being deprecated. Otherwise,8572// the token is about _BitInt and gets (potentially) diagnosed as use of an8573// extension.8574assert(Tok.isOneOf(tok::kw__ExtInt, tok::kw__BitInt) &&8575"expected either an _ExtInt or _BitInt token!");85768577SourceLocation Loc = Tok.getLocation();8578if (Tok.is(tok::kw__ExtInt)) {8579Diag(Loc, diag::warn_ext_int_deprecated)8580<< FixItHint::CreateReplacement(Loc, "_BitInt");8581} else {8582// In C23 mode, diagnose that the use is not compatible with pre-C23 modes.8583// Otherwise, diagnose that the use is a Clang extension.8584if (getLangOpts().C23)8585Diag(Loc, diag::warn_c23_compat_keyword) << Tok.getName();8586else8587Diag(Loc, diag::ext_bit_int) << getLangOpts().CPlusPlus;8588}8589}859085918592