Path: blob/main/contrib/llvm-project/clang/lib/Parse/ParseTentative.cpp
35233 views
//===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//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 tentative parsing portions of the Parser9// interfaces, for ambiguity resolution.10//11//===----------------------------------------------------------------------===//1213#include "clang/Parse/Parser.h"14#include "clang/Parse/ParseDiagnostic.h"15#include "clang/Sema/ParsedTemplate.h"16using namespace clang;1718/// isCXXDeclarationStatement - C++-specialized function that disambiguates19/// between a declaration or an expression statement, when parsing function20/// bodies. Returns true for declaration, false for expression.21///22/// declaration-statement:23/// block-declaration24///25/// block-declaration:26/// simple-declaration27/// asm-definition28/// namespace-alias-definition29/// using-declaration30/// using-directive31/// [C++0x] static_assert-declaration32///33/// asm-definition:34/// 'asm' '(' string-literal ')' ';'35///36/// namespace-alias-definition:37/// 'namespace' identifier = qualified-namespace-specifier ';'38///39/// using-declaration:40/// 'using' typename[opt] '::'[opt] nested-name-specifier41/// unqualified-id ';'42/// 'using' '::' unqualified-id ;43///44/// using-directive:45/// 'using' 'namespace' '::'[opt] nested-name-specifier[opt]46/// namespace-name ';'47///48bool Parser::isCXXDeclarationStatement(49bool DisambiguatingWithExpression /*=false*/) {50assert(getLangOpts().CPlusPlus && "Must be called for C++ only.");5152switch (Tok.getKind()) {53// asm-definition54case tok::kw_asm:55// namespace-alias-definition56case tok::kw_namespace:57// using-declaration58// using-directive59case tok::kw_using:60// static_assert-declaration61case tok::kw_static_assert:62case tok::kw__Static_assert:63return true;64case tok::coloncolon:65case tok::identifier: {66if (DisambiguatingWithExpression) {67RevertingTentativeParsingAction TPA(*this);68// Parse the C++ scope specifier.69CXXScopeSpec SS;70ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,71/*ObjectHasErrors=*/false,72/*EnteringContext=*/true);7374switch (Tok.getKind()) {75case tok::identifier: {76IdentifierInfo *II = Tok.getIdentifierInfo();77bool isDeductionGuide = Actions.isDeductionGuideName(78getCurScope(), *II, Tok.getLocation(), SS, /*Template=*/nullptr);79if (Actions.isCurrentClassName(*II, getCurScope(), &SS) ||80isDeductionGuide) {81if (isConstructorDeclarator(82/*Unqualified=*/SS.isEmpty(), isDeductionGuide,83/*IsFriend=*/DeclSpec::FriendSpecified::No))84return true;85} else if (SS.isNotEmpty()) {86// If the scope is not empty, it could alternatively be something like87// a typedef or using declaration. That declaration might be private88// in the global context, which would be diagnosed by calling into89// isCXXSimpleDeclaration, but may actually be fine in the context of90// member functions and static variable definitions. Check if the next91// token is also an identifier and assume a declaration.92// We cannot check if the scopes match because the declarations could93// involve namespaces and friend declarations.94if (NextToken().is(tok::identifier))95return true;96}97break;98}99case tok::kw_operator:100return true;101case tok::tilde:102return true;103default:104break;105}106}107}108[[fallthrough]];109// simple-declaration110default:111return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);112}113}114115/// isCXXSimpleDeclaration - C++-specialized function that disambiguates116/// between a simple-declaration or an expression-statement.117/// If during the disambiguation process a parsing error is encountered,118/// the function returns true to let the declaration parsing code handle it.119/// Returns false if the statement is disambiguated as expression.120///121/// simple-declaration:122/// decl-specifier-seq init-declarator-list[opt] ';'123/// decl-specifier-seq ref-qualifier[opt] '[' identifier-list ']'124/// brace-or-equal-initializer ';' [C++17]125///126/// (if AllowForRangeDecl specified)127/// for ( for-range-declaration : for-range-initializer ) statement128///129/// for-range-declaration:130/// decl-specifier-seq declarator131/// decl-specifier-seq ref-qualifier[opt] '[' identifier-list ']'132///133/// In any of the above cases there can be a preceding attribute-specifier-seq,134/// but the caller is expected to handle that.135bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {136// C++ 6.8p1:137// There is an ambiguity in the grammar involving expression-statements and138// declarations: An expression-statement with a function-style explicit type139// conversion (5.2.3) as its leftmost subexpression can be indistinguishable140// from a declaration where the first declarator starts with a '('. In those141// cases the statement is a declaration. [Note: To disambiguate, the whole142// statement might have to be examined to determine if it is an143// expression-statement or a declaration].144145// C++ 6.8p3:146// The disambiguation is purely syntactic; that is, the meaning of the names147// occurring in such a statement, beyond whether they are type-names or not,148// is not generally used in or changed by the disambiguation. Class149// templates are instantiated as necessary to determine if a qualified name150// is a type-name. Disambiguation precedes parsing, and a statement151// disambiguated as a declaration may be an ill-formed declaration.152153// We don't have to parse all of the decl-specifier-seq part. There's only154// an ambiguity if the first decl-specifier is155// simple-type-specifier/typename-specifier followed by a '(', which may156// indicate a function-style cast expression.157// isCXXDeclarationSpecifier will return TPResult::Ambiguous only in such158// a case.159160bool InvalidAsDeclaration = false;161TPResult TPR = isCXXDeclarationSpecifier(162ImplicitTypenameContext::No, TPResult::False, &InvalidAsDeclaration);163if (TPR != TPResult::Ambiguous)164return TPR != TPResult::False; // Returns true for TPResult::True or165// TPResult::Error.166167// FIXME: TryParseSimpleDeclaration doesn't look past the first initializer,168// and so gets some cases wrong. We can't carry on if we've already seen169// something which makes this statement invalid as a declaration in this case,170// since it can cause us to misparse valid code. Revisit this once171// TryParseInitDeclaratorList is fixed.172if (InvalidAsDeclaration)173return false;174175// FIXME: Add statistics about the number of ambiguous statements encountered176// and how they were resolved (number of declarations+number of expressions).177178// Ok, we have a simple-type-specifier/typename-specifier followed by a '(',179// or an identifier which doesn't resolve as anything. We need tentative180// parsing...181182{183RevertingTentativeParsingAction PA(*this);184TPR = TryParseSimpleDeclaration(AllowForRangeDecl);185}186187// In case of an error, let the declaration parsing code handle it.188if (TPR == TPResult::Error)189return true;190191// Declarations take precedence over expressions.192if (TPR == TPResult::Ambiguous)193TPR = TPResult::True;194195assert(TPR == TPResult::True || TPR == TPResult::False);196return TPR == TPResult::True;197}198199/// Try to consume a token sequence that we've already identified as200/// (potentially) starting a decl-specifier.201Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {202switch (Tok.getKind()) {203case tok::kw__Atomic:204if (NextToken().isNot(tok::l_paren)) {205ConsumeToken();206break;207}208[[fallthrough]];209case tok::kw_typeof:210case tok::kw___attribute:211#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:212#include "clang/Basic/TransformTypeTraits.def"213{214ConsumeToken();215if (Tok.isNot(tok::l_paren))216return TPResult::Error;217ConsumeParen();218if (!SkipUntil(tok::r_paren))219return TPResult::Error;220break;221}222223case tok::kw_class:224case tok::kw_struct:225case tok::kw_union:226case tok::kw___interface:227case tok::kw_enum:228// elaborated-type-specifier:229// class-key attribute-specifier-seq[opt]230// nested-name-specifier[opt] identifier231// class-key nested-name-specifier[opt] template[opt] simple-template-id232// enum nested-name-specifier[opt] identifier233//234// FIXME: We don't support class-specifiers nor enum-specifiers here.235ConsumeToken();236237// Skip attributes.238if (!TrySkipAttributes())239return TPResult::Error;240241if (TryAnnotateOptionalCXXScopeToken())242return TPResult::Error;243if (Tok.is(tok::annot_cxxscope))244ConsumeAnnotationToken();245if (Tok.is(tok::identifier))246ConsumeToken();247else if (Tok.is(tok::annot_template_id))248ConsumeAnnotationToken();249else250return TPResult::Error;251break;252253case tok::annot_cxxscope:254ConsumeAnnotationToken();255[[fallthrough]];256default:257ConsumeAnyToken();258259if (getLangOpts().ObjC && Tok.is(tok::less))260return TryParseProtocolQualifiers();261break;262}263264return TPResult::Ambiguous;265}266267/// simple-declaration:268/// decl-specifier-seq init-declarator-list[opt] ';'269///270/// (if AllowForRangeDecl specified)271/// for ( for-range-declaration : for-range-initializer ) statement272/// for-range-declaration:273/// attribute-specifier-seqopt type-specifier-seq declarator274///275Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {276bool DeclSpecifierIsAuto = Tok.is(tok::kw_auto);277if (TryConsumeDeclarationSpecifier() == TPResult::Error)278return TPResult::Error;279280// Two decl-specifiers in a row conclusively disambiguate this as being a281// simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the282// overwhelmingly common case that the next token is a '('.283if (Tok.isNot(tok::l_paren)) {284TPResult TPR = isCXXDeclarationSpecifier(ImplicitTypenameContext::No);285if (TPR == TPResult::Ambiguous)286return TPResult::True;287if (TPR == TPResult::True || TPR == TPResult::Error)288return TPR;289assert(TPR == TPResult::False);290}291292TPResult TPR = TryParseInitDeclaratorList(293/*mayHaveTrailingReturnType=*/DeclSpecifierIsAuto);294if (TPR != TPResult::Ambiguous)295return TPR;296297if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))298return TPResult::False;299300return TPResult::Ambiguous;301}302303/// Tentatively parse an init-declarator-list in order to disambiguate it from304/// an expression.305///306/// init-declarator-list:307/// init-declarator308/// init-declarator-list ',' init-declarator309///310/// init-declarator:311/// declarator initializer[opt]312/// [GNU] declarator simple-asm-expr[opt] attributes[opt] initializer[opt]313///314/// initializer:315/// brace-or-equal-initializer316/// '(' expression-list ')'317///318/// brace-or-equal-initializer:319/// '=' initializer-clause320/// [C++11] braced-init-list321///322/// initializer-clause:323/// assignment-expression324/// braced-init-list325///326/// braced-init-list:327/// '{' initializer-list ','[opt] '}'328/// '{' '}'329///330Parser::TPResult331Parser::TryParseInitDeclaratorList(bool MayHaveTrailingReturnType) {332while (true) {333// declarator334TPResult TPR = TryParseDeclarator(335/*mayBeAbstract=*/false,336/*mayHaveIdentifier=*/true,337/*mayHaveDirectInit=*/false,338/*mayHaveTrailingReturnType=*/MayHaveTrailingReturnType);339if (TPR != TPResult::Ambiguous)340return TPR;341342// [GNU] simple-asm-expr[opt] attributes[opt]343if (Tok.isOneOf(tok::kw_asm, tok::kw___attribute))344return TPResult::True;345346// initializer[opt]347if (Tok.is(tok::l_paren)) {348// Parse through the parens.349ConsumeParen();350if (!SkipUntil(tok::r_paren, StopAtSemi))351return TPResult::Error;352} else if (Tok.is(tok::l_brace)) {353// A left-brace here is sufficient to disambiguate the parse; an354// expression can never be followed directly by a braced-init-list.355return TPResult::True;356} else if (Tok.is(tok::equal) || isTokIdentifier_in()) {357// MSVC and g++ won't examine the rest of declarators if '=' is358// encountered; they just conclude that we have a declaration.359// EDG parses the initializer completely, which is the proper behavior360// for this case.361//362// At present, Clang follows MSVC and g++, since the parser does not have363// the ability to parse an expression fully without recording the364// results of that parse.365// FIXME: Handle this case correctly.366//367// Also allow 'in' after an Objective-C declaration as in:368// for (int (^b)(void) in array). Ideally this should be done in the369// context of parsing for-init-statement of a foreach statement only. But,370// in any other context 'in' is invalid after a declaration and parser371// issues the error regardless of outcome of this decision.372// FIXME: Change if above assumption does not hold.373return TPResult::True;374}375376if (!TryConsumeToken(tok::comma))377break;378}379380return TPResult::Ambiguous;381}382383struct Parser::ConditionDeclarationOrInitStatementState {384Parser &P;385bool CanBeExpression = true;386bool CanBeCondition = true;387bool CanBeInitStatement;388bool CanBeForRangeDecl;389390ConditionDeclarationOrInitStatementState(Parser &P, bool CanBeInitStatement,391bool CanBeForRangeDecl)392: P(P), CanBeInitStatement(CanBeInitStatement),393CanBeForRangeDecl(CanBeForRangeDecl) {}394395bool resolved() {396return CanBeExpression + CanBeCondition + CanBeInitStatement +397CanBeForRangeDecl < 2;398}399400void markNotExpression() {401CanBeExpression = false;402403if (!resolved()) {404// FIXME: Unify the parsing codepaths for condition variables and405// simple-declarations so that we don't need to eagerly figure out which406// kind we have here. (Just parse init-declarators until we reach a407// semicolon or right paren.)408RevertingTentativeParsingAction PA(P);409if (CanBeForRangeDecl) {410// Skip until we hit a ')', ';', or a ':' with no matching '?'.411// The final case is a for range declaration, the rest are not.412unsigned QuestionColonDepth = 0;413while (true) {414P.SkipUntil({tok::r_paren, tok::semi, tok::question, tok::colon},415StopBeforeMatch);416if (P.Tok.is(tok::question))417++QuestionColonDepth;418else if (P.Tok.is(tok::colon)) {419if (QuestionColonDepth)420--QuestionColonDepth;421else {422CanBeCondition = CanBeInitStatement = false;423return;424}425} else {426CanBeForRangeDecl = false;427break;428}429P.ConsumeToken();430}431} else {432// Just skip until we hit a ')' or ';'.433P.SkipUntil(tok::r_paren, tok::semi, StopBeforeMatch);434}435if (P.Tok.isNot(tok::r_paren))436CanBeCondition = CanBeForRangeDecl = false;437if (P.Tok.isNot(tok::semi))438CanBeInitStatement = false;439}440}441442bool markNotCondition() {443CanBeCondition = false;444return resolved();445}446447bool markNotForRangeDecl() {448CanBeForRangeDecl = false;449return resolved();450}451452bool update(TPResult IsDecl) {453switch (IsDecl) {454case TPResult::True:455markNotExpression();456assert(resolved() && "can't continue after tentative parsing bails out");457break;458case TPResult::False:459CanBeCondition = CanBeInitStatement = CanBeForRangeDecl = false;460break;461case TPResult::Ambiguous:462break;463case TPResult::Error:464CanBeExpression = CanBeCondition = CanBeInitStatement =465CanBeForRangeDecl = false;466break;467}468return resolved();469}470471ConditionOrInitStatement result() const {472assert(CanBeExpression + CanBeCondition + CanBeInitStatement +473CanBeForRangeDecl < 2 &&474"result called but not yet resolved");475if (CanBeExpression)476return ConditionOrInitStatement::Expression;477if (CanBeCondition)478return ConditionOrInitStatement::ConditionDecl;479if (CanBeInitStatement)480return ConditionOrInitStatement::InitStmtDecl;481if (CanBeForRangeDecl)482return ConditionOrInitStatement::ForRangeDecl;483return ConditionOrInitStatement::Error;484}485};486487bool Parser::isEnumBase(bool AllowSemi) {488assert(Tok.is(tok::colon) && "should be looking at the ':'");489490RevertingTentativeParsingAction PA(*this);491// ':'492ConsumeToken();493494// type-specifier-seq495bool InvalidAsDeclSpec = false;496// FIXME: We could disallow non-type decl-specifiers here, but it makes no497// difference: those specifiers are ill-formed regardless of the498// interpretation.499TPResult R = isCXXDeclarationSpecifier(ImplicitTypenameContext::No,500/*BracedCastResult=*/TPResult::True,501&InvalidAsDeclSpec);502if (R == TPResult::Ambiguous) {503// We either have a decl-specifier followed by '(' or an undeclared504// identifier.505if (TryConsumeDeclarationSpecifier() == TPResult::Error)506return true;507508// If we get to the end of the enum-base, we hit either a '{' or a ';'.509// Don't bother checking the enumerator-list.510if (Tok.is(tok::l_brace) || (AllowSemi && Tok.is(tok::semi)))511return true;512513// A second decl-specifier unambiguously indicatges an enum-base.514R = isCXXDeclarationSpecifier(ImplicitTypenameContext::No, TPResult::True,515&InvalidAsDeclSpec);516}517518return R != TPResult::False;519}520521/// Disambiguates between a declaration in a condition, a522/// simple-declaration in an init-statement, and an expression for523/// a condition of a if/switch statement.524///525/// condition:526/// expression527/// type-specifier-seq declarator '=' assignment-expression528/// [C++11] type-specifier-seq declarator '=' initializer-clause529/// [C++11] type-specifier-seq declarator braced-init-list530/// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]531/// '=' assignment-expression532/// simple-declaration:533/// decl-specifier-seq init-declarator-list[opt] ';'534///535/// Note that, unlike isCXXSimpleDeclaration, we must disambiguate all the way536/// to the ';' to disambiguate cases like 'int(x))' (an expression) from537/// 'int(x);' (a simple-declaration in an init-statement).538Parser::ConditionOrInitStatement539Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement,540bool CanBeForRangeDecl) {541ConditionDeclarationOrInitStatementState State(*this, CanBeInitStatement,542CanBeForRangeDecl);543544if (CanBeInitStatement && Tok.is(tok::kw_using))545return ConditionOrInitStatement::InitStmtDecl;546if (State.update(isCXXDeclarationSpecifier(ImplicitTypenameContext::No)))547return State.result();548549// It might be a declaration; we need tentative parsing.550RevertingTentativeParsingAction PA(*this);551552// FIXME: A tag definition unambiguously tells us this is an init-statement.553bool MayHaveTrailingReturnType = Tok.is(tok::kw_auto);554if (State.update(TryConsumeDeclarationSpecifier()))555return State.result();556assert(Tok.is(tok::l_paren) && "Expected '('");557558while (true) {559// Consume a declarator.560if (State.update(TryParseDeclarator(561/*mayBeAbstract=*/false,562/*mayHaveIdentifier=*/true,563/*mayHaveDirectInit=*/false,564/*mayHaveTrailingReturnType=*/MayHaveTrailingReturnType)))565return State.result();566567// Attributes, asm label, or an initializer imply this is not an expression.568// FIXME: Disambiguate properly after an = instead of assuming that it's a569// valid declaration.570if (Tok.isOneOf(tok::equal, tok::kw_asm, tok::kw___attribute) ||571(getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))) {572State.markNotExpression();573return State.result();574}575576// A colon here identifies a for-range declaration.577if (State.CanBeForRangeDecl && Tok.is(tok::colon))578return ConditionOrInitStatement::ForRangeDecl;579580// At this point, it can't be a condition any more, because a condition581// must have a brace-or-equal-initializer.582if (State.markNotCondition())583return State.result();584585// Likewise, it can't be a for-range declaration any more.586if (State.markNotForRangeDecl())587return State.result();588589// A parenthesized initializer could be part of an expression or a590// simple-declaration.591if (Tok.is(tok::l_paren)) {592ConsumeParen();593SkipUntil(tok::r_paren, StopAtSemi);594}595596if (!TryConsumeToken(tok::comma))597break;598}599600// We reached the end. If it can now be some kind of decl, then it is.601if (State.CanBeCondition && Tok.is(tok::r_paren))602return ConditionOrInitStatement::ConditionDecl;603else if (State.CanBeInitStatement && Tok.is(tok::semi))604return ConditionOrInitStatement::InitStmtDecl;605else606return ConditionOrInitStatement::Expression;607}608609/// Determine whether the next set of tokens contains a type-id.610///611/// The context parameter states what context we're parsing right612/// now, which affects how this routine copes with the token613/// following the type-id. If the context is TypeIdInParens, we have614/// already parsed the '(' and we will cease lookahead when we hit615/// the corresponding ')'. If the context is616/// TypeIdAsTemplateArgument, we've already parsed the '<' or ','617/// before this template argument, and will cease lookahead when we618/// hit a '>', '>>' (in C++0x), or ','; or, in C++0x, an ellipsis immediately619/// preceding such. Returns true for a type-id and false for an expression.620/// If during the disambiguation process a parsing error is encountered,621/// the function returns true to let the declaration parsing code handle it.622///623/// type-id:624/// type-specifier-seq abstract-declarator[opt]625///626bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {627628isAmbiguous = false;629630// C++ 8.2p2:631// The ambiguity arising from the similarity between a function-style cast and632// a type-id can occur in different contexts. The ambiguity appears as a633// choice between a function-style cast expression and a declaration of a634// type. The resolution is that any construct that could possibly be a type-id635// in its syntactic context shall be considered a type-id.636637TPResult TPR = isCXXDeclarationSpecifier(ImplicitTypenameContext::No);638if (TPR != TPResult::Ambiguous)639return TPR != TPResult::False; // Returns true for TPResult::True or640// TPResult::Error.641642// FIXME: Add statistics about the number of ambiguous statements encountered643// and how they were resolved (number of declarations+number of expressions).644645// Ok, we have a simple-type-specifier/typename-specifier followed by a '('.646// We need tentative parsing...647648RevertingTentativeParsingAction PA(*this);649bool MayHaveTrailingReturnType = Tok.is(tok::kw_auto);650651// type-specifier-seq652TryConsumeDeclarationSpecifier();653assert(Tok.is(tok::l_paren) && "Expected '('");654655// declarator656TPR = TryParseDeclarator(true /*mayBeAbstract*/, false /*mayHaveIdentifier*/,657/*mayHaveDirectInit=*/false,658MayHaveTrailingReturnType);659660// In case of an error, let the declaration parsing code handle it.661if (TPR == TPResult::Error)662TPR = TPResult::True;663664if (TPR == TPResult::Ambiguous) {665// We are supposed to be inside parens, so if after the abstract declarator666// we encounter a ')' this is a type-id, otherwise it's an expression.667if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {668TPR = TPResult::True;669isAmbiguous = true;670// We are supposed to be inside the first operand to a _Generic selection671// expression, so if we find a comma after the declarator, we've found a672// type and not an expression.673} else if (Context == TypeIdAsGenericSelectionArgument && Tok.is(tok::comma)) {674TPR = TPResult::True;675isAmbiguous = true;676// We are supposed to be inside a template argument, so if after677// the abstract declarator we encounter a '>', '>>' (in C++0x), or678// ','; or, in C++0x, an ellipsis immediately preceding such, this679// is a type-id. Otherwise, it's an expression.680} else if (Context == TypeIdAsTemplateArgument &&681(Tok.isOneOf(tok::greater, tok::comma) ||682(getLangOpts().CPlusPlus11 &&683(Tok.isOneOf(tok::greatergreater,684tok::greatergreatergreater) ||685(Tok.is(tok::ellipsis) &&686NextToken().isOneOf(tok::greater, tok::greatergreater,687tok::greatergreatergreater,688tok::comma)))))) {689TPR = TPResult::True;690isAmbiguous = true;691692} else if (Context == TypeIdInTrailingReturnType) {693TPR = TPResult::True;694isAmbiguous = true;695} else696TPR = TPResult::False;697}698699assert(TPR == TPResult::True || TPR == TPResult::False);700return TPR == TPResult::True;701}702703/// Returns true if this is a C++11 attribute-specifier. Per704/// C++11 [dcl.attr.grammar]p6, two consecutive left square bracket tokens705/// always introduce an attribute. In Objective-C++11, this rule does not706/// apply if either '[' begins a message-send.707///708/// If Disambiguate is true, we try harder to determine whether a '[[' starts709/// an attribute-specifier, and return CAK_InvalidAttributeSpecifier if not.710///711/// If OuterMightBeMessageSend is true, we assume the outer '[' is either an712/// Obj-C message send or the start of an attribute. Otherwise, we assume it713/// is not an Obj-C message send.714///715/// C++11 [dcl.attr.grammar]:716///717/// attribute-specifier:718/// '[' '[' attribute-list ']' ']'719/// alignment-specifier720///721/// attribute-list:722/// attribute[opt]723/// attribute-list ',' attribute[opt]724/// attribute '...'725/// attribute-list ',' attribute '...'726///727/// attribute:728/// attribute-token attribute-argument-clause[opt]729///730/// attribute-token:731/// identifier732/// identifier '::' identifier733///734/// attribute-argument-clause:735/// '(' balanced-token-seq ')'736Parser::CXX11AttributeKind737Parser::isCXX11AttributeSpecifier(bool Disambiguate,738bool OuterMightBeMessageSend) {739// alignas is an attribute specifier in C++ but not in C23.740if (Tok.is(tok::kw_alignas) && !getLangOpts().C23)741return CAK_AttributeSpecifier;742743if (Tok.isRegularKeywordAttribute())744return CAK_AttributeSpecifier;745746if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))747return CAK_NotAttributeSpecifier;748749// No tentative parsing if we don't need to look for ']]' or a lambda.750if (!Disambiguate && !getLangOpts().ObjC)751return CAK_AttributeSpecifier;752753// '[[using ns: ...]]' is an attribute.754if (GetLookAheadToken(2).is(tok::kw_using))755return CAK_AttributeSpecifier;756757RevertingTentativeParsingAction PA(*this);758759// Opening brackets were checked for above.760ConsumeBracket();761762if (!getLangOpts().ObjC) {763ConsumeBracket();764765bool IsAttribute = SkipUntil(tok::r_square);766IsAttribute &= Tok.is(tok::r_square);767768return IsAttribute ? CAK_AttributeSpecifier : CAK_InvalidAttributeSpecifier;769}770771// In Obj-C++11, we need to distinguish four situations:772// 1a) int x[[attr]]; C++11 attribute.773// 1b) [[attr]]; C++11 statement attribute.774// 2) int x[[obj](){ return 1; }()]; Lambda in array size/index.775// 3a) int x[[obj get]]; Message send in array size/index.776// 3b) [[Class alloc] init]; Message send in message send.777// 4) [[obj]{ return self; }() doStuff]; Lambda in message send.778// (1) is an attribute, (2) is ill-formed, and (3) and (4) are accepted.779780// Check to see if this is a lambda-expression.781// FIXME: If this disambiguation is too slow, fold the tentative lambda parse782// into the tentative attribute parse below.783{784RevertingTentativeParsingAction LambdaTPA(*this);785LambdaIntroducer Intro;786LambdaIntroducerTentativeParse Tentative;787if (ParseLambdaIntroducer(Intro, &Tentative)) {788// We hit a hard error after deciding this was not an attribute.789// FIXME: Don't parse and annotate expressions when disambiguating790// against an attribute.791return CAK_NotAttributeSpecifier;792}793794switch (Tentative) {795case LambdaIntroducerTentativeParse::MessageSend:796// Case 3: The inner construct is definitely a message send, so the797// outer construct is definitely not an attribute.798return CAK_NotAttributeSpecifier;799800case LambdaIntroducerTentativeParse::Success:801case LambdaIntroducerTentativeParse::Incomplete:802// This is a lambda-introducer or attribute-specifier.803if (Tok.is(tok::r_square))804// Case 1: C++11 attribute.805return CAK_AttributeSpecifier;806807if (OuterMightBeMessageSend)808// Case 4: Lambda in message send.809return CAK_NotAttributeSpecifier;810811// Case 2: Lambda in array size / index.812return CAK_InvalidAttributeSpecifier;813814case LambdaIntroducerTentativeParse::Invalid:815// No idea what this is; we couldn't parse it as a lambda-introducer.816// Might still be an attribute-specifier or a message send.817break;818}819}820821ConsumeBracket();822823// If we don't have a lambda-introducer, then we have an attribute or a824// message-send.825bool IsAttribute = true;826while (Tok.isNot(tok::r_square)) {827if (Tok.is(tok::comma)) {828// Case 1: Stray commas can only occur in attributes.829return CAK_AttributeSpecifier;830}831832// Parse the attribute-token, if present.833// C++11 [dcl.attr.grammar]:834// If a keyword or an alternative token that satisfies the syntactic835// requirements of an identifier is contained in an attribute-token,836// it is considered an identifier.837SourceLocation Loc;838if (!TryParseCXX11AttributeIdentifier(Loc)) {839IsAttribute = false;840break;841}842if (Tok.is(tok::coloncolon)) {843ConsumeToken();844if (!TryParseCXX11AttributeIdentifier(Loc)) {845IsAttribute = false;846break;847}848}849850// Parse the attribute-argument-clause, if present.851if (Tok.is(tok::l_paren)) {852ConsumeParen();853if (!SkipUntil(tok::r_paren)) {854IsAttribute = false;855break;856}857}858859TryConsumeToken(tok::ellipsis);860861if (!TryConsumeToken(tok::comma))862break;863}864865// An attribute must end ']]'.866if (IsAttribute) {867if (Tok.is(tok::r_square)) {868ConsumeBracket();869IsAttribute = Tok.is(tok::r_square);870} else {871IsAttribute = false;872}873}874875if (IsAttribute)876// Case 1: C++11 statement attribute.877return CAK_AttributeSpecifier;878879// Case 3: Message send.880return CAK_NotAttributeSpecifier;881}882883bool Parser::TrySkipAttributes() {884while (Tok.isOneOf(tok::l_square, tok::kw___attribute, tok::kw___declspec,885tok::kw_alignas) ||886Tok.isRegularKeywordAttribute()) {887if (Tok.is(tok::l_square)) {888ConsumeBracket();889if (Tok.isNot(tok::l_square))890return false;891ConsumeBracket();892if (!SkipUntil(tok::r_square) || Tok.isNot(tok::r_square))893return false;894// Note that explicitly checking for `[[` and `]]` allows to fail as895// expected in the case of the Objective-C message send syntax.896ConsumeBracket();897} else if (Tok.isRegularKeywordAttribute() &&898!doesKeywordAttributeTakeArgs(Tok.getKind())) {899ConsumeToken();900} else {901ConsumeToken();902if (Tok.isNot(tok::l_paren))903return false;904ConsumeParen();905if (!SkipUntil(tok::r_paren))906return false;907}908}909910return true;911}912913Parser::TPResult Parser::TryParsePtrOperatorSeq() {914while (true) {915if (TryAnnotateOptionalCXXScopeToken(true))916return TPResult::Error;917918if (Tok.isOneOf(tok::star, tok::amp, tok::caret, tok::ampamp) ||919(Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {920// ptr-operator921ConsumeAnyToken();922923// Skip attributes.924if (!TrySkipAttributes())925return TPResult::Error;926927while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict,928tok::kw__Nonnull, tok::kw__Nullable,929tok::kw__Nullable_result, tok::kw__Null_unspecified,930tok::kw__Atomic))931ConsumeToken();932} else {933return TPResult::True;934}935}936}937938/// operator-function-id:939/// 'operator' operator940///941/// operator: one of942/// new delete new[] delete[] + - * / % ^ [...]943///944/// conversion-function-id:945/// 'operator' conversion-type-id946///947/// conversion-type-id:948/// type-specifier-seq conversion-declarator[opt]949///950/// conversion-declarator:951/// ptr-operator conversion-declarator[opt]952///953/// literal-operator-id:954/// 'operator' string-literal identifier955/// 'operator' user-defined-string-literal956Parser::TPResult Parser::TryParseOperatorId() {957assert(Tok.is(tok::kw_operator));958ConsumeToken();959960// Maybe this is an operator-function-id.961switch (Tok.getKind()) {962case tok::kw_new: case tok::kw_delete:963ConsumeToken();964if (Tok.is(tok::l_square) && NextToken().is(tok::r_square)) {965ConsumeBracket();966ConsumeBracket();967}968return TPResult::True;969970#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemOnly) \971case tok::Token:972#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemOnly)973#include "clang/Basic/OperatorKinds.def"974ConsumeToken();975return TPResult::True;976977case tok::l_square:978if (NextToken().is(tok::r_square)) {979ConsumeBracket();980ConsumeBracket();981return TPResult::True;982}983break;984985case tok::l_paren:986if (NextToken().is(tok::r_paren)) {987ConsumeParen();988ConsumeParen();989return TPResult::True;990}991break;992993default:994break;995}996997// Maybe this is a literal-operator-id.998if (getLangOpts().CPlusPlus11 && isTokenStringLiteral()) {999bool FoundUDSuffix = false;1000do {1001FoundUDSuffix |= Tok.hasUDSuffix();1002ConsumeStringToken();1003} while (isTokenStringLiteral());10041005if (!FoundUDSuffix) {1006if (Tok.is(tok::identifier))1007ConsumeToken();1008else1009return TPResult::Error;1010}1011return TPResult::True;1012}10131014// Maybe this is a conversion-function-id.1015bool AnyDeclSpecifiers = false;1016while (true) {1017TPResult TPR = isCXXDeclarationSpecifier(ImplicitTypenameContext::No);1018if (TPR == TPResult::Error)1019return TPR;1020if (TPR == TPResult::False) {1021if (!AnyDeclSpecifiers)1022return TPResult::Error;1023break;1024}1025if (TryConsumeDeclarationSpecifier() == TPResult::Error)1026return TPResult::Error;1027AnyDeclSpecifiers = true;1028}1029return TryParsePtrOperatorSeq();1030}10311032/// declarator:1033/// direct-declarator1034/// ptr-operator declarator1035///1036/// direct-declarator:1037/// declarator-id1038/// direct-declarator '(' parameter-declaration-clause ')'1039/// cv-qualifier-seq[opt] exception-specification[opt]1040/// direct-declarator '[' constant-expression[opt] ']'1041/// '(' declarator ')'1042/// [GNU] '(' attributes declarator ')'1043///1044/// abstract-declarator:1045/// ptr-operator abstract-declarator[opt]1046/// direct-abstract-declarator1047///1048/// direct-abstract-declarator:1049/// direct-abstract-declarator[opt]1050/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]1051/// exception-specification[opt]1052/// direct-abstract-declarator[opt] '[' constant-expression[opt] ']'1053/// '(' abstract-declarator ')'1054/// [C++0x] ...1055///1056/// ptr-operator:1057/// '*' cv-qualifier-seq[opt]1058/// '&'1059/// [C++0x] '&&' [TODO]1060/// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]1061///1062/// cv-qualifier-seq:1063/// cv-qualifier cv-qualifier-seq[opt]1064///1065/// cv-qualifier:1066/// 'const'1067/// 'volatile'1068///1069/// declarator-id:1070/// '...'[opt] id-expression1071///1072/// id-expression:1073/// unqualified-id1074/// qualified-id [TODO]1075///1076/// unqualified-id:1077/// identifier1078/// operator-function-id1079/// conversion-function-id1080/// literal-operator-id1081/// '~' class-name [TODO]1082/// '~' decltype-specifier [TODO]1083/// template-id [TODO]1084///1085Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,1086bool mayHaveIdentifier,1087bool mayHaveDirectInit,1088bool mayHaveTrailingReturnType) {1089// declarator:1090// direct-declarator1091// ptr-operator declarator1092if (TryParsePtrOperatorSeq() == TPResult::Error)1093return TPResult::Error;10941095// direct-declarator:1096// direct-abstract-declarator:1097if (Tok.is(tok::ellipsis))1098ConsumeToken();10991100if ((Tok.isOneOf(tok::identifier, tok::kw_operator) ||1101(Tok.is(tok::annot_cxxscope) && (NextToken().is(tok::identifier) ||1102NextToken().is(tok::kw_operator)))) &&1103mayHaveIdentifier) {1104// declarator-id1105if (Tok.is(tok::annot_cxxscope)) {1106CXXScopeSpec SS;1107Actions.RestoreNestedNameSpecifierAnnotation(1108Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS);1109if (SS.isInvalid())1110return TPResult::Error;1111ConsumeAnnotationToken();1112} else if (Tok.is(tok::identifier)) {1113TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo());1114}1115if (Tok.is(tok::kw_operator)) {1116if (TryParseOperatorId() == TPResult::Error)1117return TPResult::Error;1118} else1119ConsumeToken();1120} else if (Tok.is(tok::l_paren)) {1121ConsumeParen();1122if (mayBeAbstract &&1123(Tok.is(tok::r_paren) || // 'int()' is a function.1124// 'int(...)' is a function.1125(Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren)) ||1126isDeclarationSpecifier(1127ImplicitTypenameContext::No))) { // 'int(int)' is a function.1128// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]1129// exception-specification[opt]1130TPResult TPR = TryParseFunctionDeclarator(mayHaveTrailingReturnType);1131if (TPR != TPResult::Ambiguous)1132return TPR;1133} else {1134// '(' declarator ')'1135// '(' attributes declarator ')'1136// '(' abstract-declarator ')'1137if (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec, tok::kw___cdecl,1138tok::kw___stdcall, tok::kw___fastcall, tok::kw___thiscall,1139tok::kw___regcall, tok::kw___vectorcall))1140return TPResult::True; // attributes indicate declaration1141TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);1142if (TPR != TPResult::Ambiguous)1143return TPR;1144if (Tok.isNot(tok::r_paren))1145return TPResult::False;1146ConsumeParen();1147}1148} else if (!mayBeAbstract) {1149return TPResult::False;1150}11511152if (mayHaveDirectInit)1153return TPResult::Ambiguous;11541155while (true) {1156TPResult TPR(TPResult::Ambiguous);11571158if (Tok.is(tok::l_paren)) {1159// Check whether we have a function declarator or a possible ctor-style1160// initializer that follows the declarator. Note that ctor-style1161// initializers are not possible in contexts where abstract declarators1162// are allowed.1163if (!mayBeAbstract && !isCXXFunctionDeclarator())1164break;11651166// direct-declarator '(' parameter-declaration-clause ')'1167// cv-qualifier-seq[opt] exception-specification[opt]1168ConsumeParen();1169TPR = TryParseFunctionDeclarator(mayHaveTrailingReturnType);1170} else if (Tok.is(tok::l_square)) {1171// direct-declarator '[' constant-expression[opt] ']'1172// direct-abstract-declarator[opt] '[' constant-expression[opt] ']'1173TPR = TryParseBracketDeclarator();1174} else if (Tok.is(tok::kw_requires)) {1175// declarator requires-clause1176// A requires clause indicates a function declaration.1177TPR = TPResult::True;1178} else {1179break;1180}11811182if (TPR != TPResult::Ambiguous)1183return TPR;1184}11851186return TPResult::Ambiguous;1187}11881189bool Parser::isTentativelyDeclared(IdentifierInfo *II) {1190return llvm::is_contained(TentativelyDeclaredIdentifiers, II);1191}11921193namespace {1194class TentativeParseCCC final : public CorrectionCandidateCallback {1195public:1196TentativeParseCCC(const Token &Next) {1197WantRemainingKeywords = false;1198WantTypeSpecifiers =1199Next.isOneOf(tok::l_paren, tok::r_paren, tok::greater, tok::l_brace,1200tok::identifier, tok::comma);1201}12021203bool ValidateCandidate(const TypoCorrection &Candidate) override {1204// Reject any candidate that only resolves to instance members since they1205// aren't viable as standalone identifiers instead of member references.1206if (Candidate.isResolved() && !Candidate.isKeyword() &&1207llvm::all_of(Candidate,1208[](NamedDecl *ND) { return ND->isCXXInstanceMember(); }))1209return false;12101211return CorrectionCandidateCallback::ValidateCandidate(Candidate);1212}12131214std::unique_ptr<CorrectionCandidateCallback> clone() override {1215return std::make_unique<TentativeParseCCC>(*this);1216}1217};1218}1219/// isCXXDeclarationSpecifier - Returns TPResult::True if it is a declaration1220/// specifier, TPResult::False if it is not, TPResult::Ambiguous if it could1221/// be either a decl-specifier or a function-style cast, and TPResult::Error1222/// if a parsing error was found and reported.1223///1224/// If InvalidAsDeclSpec is not null, some cases that would be ill-formed as1225/// declaration specifiers but possibly valid as some other kind of construct1226/// return TPResult::Ambiguous instead of TPResult::False. When this happens,1227/// the intent is to keep trying to disambiguate, on the basis that we might1228/// find a better reason to treat this construct as a declaration later on.1229/// When this happens and the name could possibly be valid in some other1230/// syntactic context, *InvalidAsDeclSpec is set to 'true'. The current cases1231/// that trigger this are:1232///1233/// * When parsing X::Y (with no 'typename') where X is dependent1234/// * When parsing X<Y> where X is undeclared1235///1236/// decl-specifier:1237/// storage-class-specifier1238/// type-specifier1239/// function-specifier1240/// 'friend'1241/// 'typedef'1242/// [C++11] 'constexpr'1243/// [C++20] 'consteval'1244/// [GNU] attributes declaration-specifiers[opt]1245///1246/// storage-class-specifier:1247/// 'register'1248/// 'static'1249/// 'extern'1250/// 'mutable'1251/// 'auto'1252/// [GNU] '__thread'1253/// [C++11] 'thread_local'1254/// [C11] '_Thread_local'1255///1256/// function-specifier:1257/// 'inline'1258/// 'virtual'1259/// 'explicit'1260///1261/// typedef-name:1262/// identifier1263///1264/// type-specifier:1265/// simple-type-specifier1266/// class-specifier1267/// enum-specifier1268/// elaborated-type-specifier1269/// typename-specifier1270/// cv-qualifier1271///1272/// simple-type-specifier:1273/// '::'[opt] nested-name-specifier[opt] type-name1274/// '::'[opt] nested-name-specifier 'template'1275/// simple-template-id [TODO]1276/// 'char'1277/// 'wchar_t'1278/// 'bool'1279/// 'short'1280/// 'int'1281/// 'long'1282/// 'signed'1283/// 'unsigned'1284/// 'float'1285/// 'double'1286/// 'void'1287/// [GNU] typeof-specifier1288/// [GNU] '_Complex'1289/// [C++11] 'auto'1290/// [GNU] '__auto_type'1291/// [C++11] 'decltype' ( expression )1292/// [C++1y] 'decltype' ( 'auto' )1293///1294/// type-name:1295/// class-name1296/// enum-name1297/// typedef-name1298///1299/// elaborated-type-specifier:1300/// class-key '::'[opt] nested-name-specifier[opt] identifier1301/// class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]1302/// simple-template-id1303/// 'enum' '::'[opt] nested-name-specifier[opt] identifier1304///1305/// enum-name:1306/// identifier1307///1308/// enum-specifier:1309/// 'enum' identifier[opt] '{' enumerator-list[opt] '}'1310/// 'enum' identifier[opt] '{' enumerator-list ',' '}'1311///1312/// class-specifier:1313/// class-head '{' member-specification[opt] '}'1314///1315/// class-head:1316/// class-key identifier[opt] base-clause[opt]1317/// class-key nested-name-specifier identifier base-clause[opt]1318/// class-key nested-name-specifier[opt] simple-template-id1319/// base-clause[opt]1320///1321/// class-key:1322/// 'class'1323/// 'struct'1324/// 'union'1325///1326/// cv-qualifier:1327/// 'const'1328/// 'volatile'1329/// [GNU] restrict1330///1331Parser::TPResult1332Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,1333Parser::TPResult BracedCastResult,1334bool *InvalidAsDeclSpec) {1335auto IsPlaceholderSpecifier = [&](TemplateIdAnnotation *TemplateId,1336int Lookahead) {1337// We have a placeholder-constraint (we check for 'auto' or 'decltype' to1338// distinguish 'C<int>;' from 'C<int> auto c = 1;')1339return TemplateId->Kind == TNK_Concept_template &&1340(GetLookAheadToken(Lookahead + 1)1341.isOneOf(tok::kw_auto, tok::kw_decltype,1342// If we have an identifier here, the user probably1343// forgot the 'auto' in the placeholder constraint,1344// e.g. 'C<int> x = 2;' This will be diagnosed nicely1345// later, so disambiguate as a declaration.1346tok::identifier,1347// CVR qualifierslikely the same situation for the1348// user, so let this be diagnosed nicely later. We1349// cannot handle references here, as `C<int> & Other`1350// and `C<int> && Other` are both legal.1351tok::kw_const, tok::kw_volatile, tok::kw_restrict) ||1352// While `C<int> && Other` is legal, doing so while not specifying a1353// template argument is NOT, so see if we can fix up in that case at1354// minimum. Concepts require at least 1 template parameter, so we1355// can count on the argument count.1356// FIXME: In the future, we migth be able to have SEMA look up the1357// declaration for this concept, and see how many template1358// parameters it has. If the concept isn't fully specified, it is1359// possibly a situation where we want deduction, such as:1360// `BinaryConcept<int> auto f = bar();`1361(TemplateId->NumArgs == 0 &&1362GetLookAheadToken(Lookahead + 1).isOneOf(tok::amp, tok::ampamp)));1363};1364switch (Tok.getKind()) {1365case tok::identifier: {1366if (GetLookAheadToken(1).is(tok::ellipsis) &&1367GetLookAheadToken(2).is(tok::l_square)) {13681369if (TryAnnotateTypeOrScopeToken())1370return TPResult::Error;1371if (Tok.is(tok::identifier))1372return TPResult::False;1373return isCXXDeclarationSpecifier(ImplicitTypenameContext::No,1374BracedCastResult, InvalidAsDeclSpec);1375}13761377// Check for need to substitute AltiVec __vector keyword1378// for "vector" identifier.1379if (TryAltiVecVectorToken())1380return TPResult::True;13811382const Token &Next = NextToken();1383// In 'foo bar', 'foo' is always a type name outside of Objective-C.1384if (!getLangOpts().ObjC && Next.is(tok::identifier))1385return TPResult::True;13861387// If this identifier was reverted from a token ID, and the next token1388// is a '(', we assume it to be a use of a type trait, so this1389// can never be a type name.1390if (Next.is(tok::l_paren) &&1391Tok.getIdentifierInfo()->hasRevertedTokenIDToIdentifier() &&1392isRevertibleTypeTrait(Tok.getIdentifierInfo())) {1393return TPResult::False;1394}13951396if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {1397// Determine whether this is a valid expression. If not, we will hit1398// a parse error one way or another. In that case, tell the caller that1399// this is ambiguous. Typo-correct to type and expression keywords and1400// to types and identifiers, in order to try to recover from errors.1401TentativeParseCCC CCC(Next);1402switch (TryAnnotateName(&CCC)) {1403case ANK_Error:1404return TPResult::Error;1405case ANK_TentativeDecl:1406return TPResult::False;1407case ANK_TemplateName:1408// In C++17, this could be a type template for class template argument1409// deduction. Try to form a type annotation for it. If we're in a1410// template template argument, we'll undo this when checking the1411// validity of the argument.1412if (getLangOpts().CPlusPlus17) {1413if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename))1414return TPResult::Error;1415if (Tok.isNot(tok::identifier))1416break;1417}14181419// A bare type template-name which can't be a template template1420// argument is an error, and was probably intended to be a type.1421return GreaterThanIsOperator ? TPResult::True : TPResult::False;1422case ANK_Unresolved:1423return InvalidAsDeclSpec ? TPResult::Ambiguous : TPResult::False;1424case ANK_Success:1425break;1426}1427assert(Tok.isNot(tok::identifier) &&1428"TryAnnotateName succeeded without producing an annotation");1429} else {1430// This might possibly be a type with a dependent scope specifier and1431// a missing 'typename' keyword. Don't use TryAnnotateName in this case,1432// since it will annotate as a primary expression, and we want to use the1433// "missing 'typename'" logic.1434if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename))1435return TPResult::Error;1436// If annotation failed, assume it's a non-type.1437// FIXME: If this happens due to an undeclared identifier, treat it as1438// ambiguous.1439if (Tok.is(tok::identifier))1440return TPResult::False;1441}14421443// We annotated this token as something. Recurse to handle whatever we got.1444return isCXXDeclarationSpecifier(AllowImplicitTypename, BracedCastResult,1445InvalidAsDeclSpec);1446}14471448case tok::kw_typename: // typename T::type1449// Annotate typenames and C++ scope specifiers. If we get one, just1450// recurse to handle whatever we get.1451if (TryAnnotateTypeOrScopeToken(ImplicitTypenameContext::Yes))1452return TPResult::Error;1453return isCXXDeclarationSpecifier(ImplicitTypenameContext::Yes,1454BracedCastResult, InvalidAsDeclSpec);14551456case tok::kw_auto: {1457if (!getLangOpts().CPlusPlus23)1458return TPResult::True;1459if (NextToken().is(tok::l_brace))1460return TPResult::False;1461if (NextToken().is(tok::l_paren))1462return TPResult::Ambiguous;1463return TPResult::True;1464}14651466case tok::coloncolon: { // ::foo::bar1467const Token &Next = NextToken();1468if (Next.isOneOf(tok::kw_new, // ::new1469tok::kw_delete)) // ::delete1470return TPResult::False;1471[[fallthrough]];1472}1473case tok::kw___super:1474case tok::kw_decltype:1475// Annotate typenames and C++ scope specifiers. If we get one, just1476// recurse to handle whatever we get.1477if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename))1478return TPResult::Error;1479return isCXXDeclarationSpecifier(AllowImplicitTypename, BracedCastResult,1480InvalidAsDeclSpec);14811482// decl-specifier:1483// storage-class-specifier1484// type-specifier1485// function-specifier1486// 'friend'1487// 'typedef'1488// 'constexpr'1489case tok::kw_friend:1490case tok::kw_typedef:1491case tok::kw_constexpr:1492case tok::kw_consteval:1493case tok::kw_constinit:1494// storage-class-specifier1495case tok::kw_register:1496case tok::kw_static:1497case tok::kw_extern:1498case tok::kw_mutable:1499case tok::kw___thread:1500case tok::kw_thread_local:1501case tok::kw__Thread_local:1502// function-specifier1503case tok::kw_inline:1504case tok::kw_virtual:1505case tok::kw_explicit:15061507// Modules1508case tok::kw___module_private__:15091510// Debugger support1511case tok::kw___unknown_anytype:15121513// type-specifier:1514// simple-type-specifier1515// class-specifier1516// enum-specifier1517// elaborated-type-specifier1518// typename-specifier1519// cv-qualifier15201521// class-specifier1522// elaborated-type-specifier1523case tok::kw_class:1524case tok::kw_struct:1525case tok::kw_union:1526case tok::kw___interface:1527// enum-specifier1528case tok::kw_enum:1529// cv-qualifier1530case tok::kw_const:1531case tok::kw_volatile:1532return TPResult::True;15331534// OpenCL address space qualifiers1535case tok::kw_private:1536if (!getLangOpts().OpenCL)1537return TPResult::False;1538[[fallthrough]];1539case tok::kw___private:1540case tok::kw___local:1541case tok::kw___global:1542case tok::kw___constant:1543case tok::kw___generic:1544// OpenCL access qualifiers1545case tok::kw___read_only:1546case tok::kw___write_only:1547case tok::kw___read_write:1548// OpenCL pipe1549case tok::kw_pipe:15501551// HLSL address space qualifiers1552case tok::kw_groupshared:1553case tok::kw_in:1554case tok::kw_inout:1555case tok::kw_out:15561557// GNU1558case tok::kw_restrict:1559case tok::kw__Complex:1560case tok::kw___attribute:1561case tok::kw___auto_type:1562return TPResult::True;15631564// Microsoft1565case tok::kw___declspec:1566case tok::kw___cdecl:1567case tok::kw___stdcall:1568case tok::kw___fastcall:1569case tok::kw___thiscall:1570case tok::kw___regcall:1571case tok::kw___vectorcall:1572case tok::kw___w64:1573case tok::kw___sptr:1574case tok::kw___uptr:1575case tok::kw___ptr64:1576case tok::kw___ptr32:1577case tok::kw___forceinline:1578case tok::kw___unaligned:1579case tok::kw__Nonnull:1580case tok::kw__Nullable:1581case tok::kw__Nullable_result:1582case tok::kw__Null_unspecified:1583case tok::kw___kindof:1584return TPResult::True;15851586// WebAssemblyFuncref1587case tok::kw___funcref:1588return TPResult::True;15891590// Borland1591case tok::kw___pascal:1592return TPResult::True;15931594// AltiVec1595case tok::kw___vector:1596return TPResult::True;15971598case tok::kw_this: {1599// Try to parse a C++23 Explicit Object Parameter1600// We do that in all language modes to produce a better diagnostic.1601if (getLangOpts().CPlusPlus) {1602RevertingTentativeParsingAction PA(*this);1603ConsumeToken();1604return isCXXDeclarationSpecifier(AllowImplicitTypename, BracedCastResult,1605InvalidAsDeclSpec);1606}1607return TPResult::False;1608}1609case tok::annot_template_id: {1610TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);1611// If lookup for the template-name found nothing, don't assume we have a1612// definitive disambiguation result yet.1613if ((TemplateId->hasInvalidName() ||1614TemplateId->Kind == TNK_Undeclared_template) &&1615InvalidAsDeclSpec) {1616// 'template-id(' can be a valid expression but not a valid decl spec if1617// the template-name is not declared, but we don't consider this to be a1618// definitive disambiguation. In any other context, it's an error either1619// way.1620*InvalidAsDeclSpec = NextToken().is(tok::l_paren);1621return TPResult::Ambiguous;1622}1623if (TemplateId->hasInvalidName())1624return TPResult::Error;1625if (IsPlaceholderSpecifier(TemplateId, /*Lookahead=*/0))1626return TPResult::True;1627if (TemplateId->Kind != TNK_Type_template)1628return TPResult::False;1629CXXScopeSpec SS;1630AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename);1631assert(Tok.is(tok::annot_typename));1632goto case_typename;1633}16341635case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed1636// We've already annotated a scope; try to annotate a type.1637if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename))1638return TPResult::Error;1639if (!Tok.is(tok::annot_typename)) {1640if (Tok.is(tok::annot_cxxscope) &&1641NextToken().is(tok::annot_template_id)) {1642TemplateIdAnnotation *TemplateId =1643takeTemplateIdAnnotation(NextToken());1644if (TemplateId->hasInvalidName()) {1645if (InvalidAsDeclSpec) {1646*InvalidAsDeclSpec = NextToken().is(tok::l_paren);1647return TPResult::Ambiguous;1648}1649return TPResult::Error;1650}1651if (IsPlaceholderSpecifier(TemplateId, /*Lookahead=*/1))1652return TPResult::True;1653}1654// If the next token is an identifier or a type qualifier, then this1655// can't possibly be a valid expression either.1656if (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier)) {1657CXXScopeSpec SS;1658Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),1659Tok.getAnnotationRange(),1660SS);1661if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) {1662RevertingTentativeParsingAction PA(*this);1663ConsumeAnnotationToken();1664ConsumeToken();1665bool isIdentifier = Tok.is(tok::identifier);1666TPResult TPR = TPResult::False;1667if (!isIdentifier)1668TPR = isCXXDeclarationSpecifier(1669AllowImplicitTypename, BracedCastResult, InvalidAsDeclSpec);16701671if (isIdentifier ||1672TPR == TPResult::True || TPR == TPResult::Error)1673return TPResult::Error;16741675if (InvalidAsDeclSpec) {1676// We can't tell whether this is a missing 'typename' or a valid1677// expression.1678*InvalidAsDeclSpec = true;1679return TPResult::Ambiguous;1680} else {1681// In MS mode, if InvalidAsDeclSpec is not provided, and the tokens1682// are or the form *) or &) *> or &> &&>, this can't be an expression.1683// The typename must be missing.1684if (getLangOpts().MSVCCompat) {1685if (((Tok.is(tok::amp) || Tok.is(tok::star)) &&1686(NextToken().is(tok::r_paren) ||1687NextToken().is(tok::greater))) ||1688(Tok.is(tok::ampamp) && NextToken().is(tok::greater)))1689return TPResult::True;1690}1691}1692} else {1693// Try to resolve the name. If it doesn't exist, assume it was1694// intended to name a type and keep disambiguating.1695switch (TryAnnotateName(/*CCC=*/nullptr, AllowImplicitTypename)) {1696case ANK_Error:1697return TPResult::Error;1698case ANK_TentativeDecl:1699return TPResult::False;1700case ANK_TemplateName:1701// In C++17, this could be a type template for class template1702// argument deduction.1703if (getLangOpts().CPlusPlus17) {1704if (TryAnnotateTypeOrScopeToken())1705return TPResult::Error;1706// If we annotated then the current token should not still be ::1707// FIXME we may want to also check for tok::annot_typename but1708// currently don't have a test case.1709if (Tok.isNot(tok::annot_cxxscope))1710break;1711}17121713// A bare type template-name which can't be a template template1714// argument is an error, and was probably intended to be a type.1715// In C++17, this could be class template argument deduction.1716return (getLangOpts().CPlusPlus17 || GreaterThanIsOperator)1717? TPResult::True1718: TPResult::False;1719case ANK_Unresolved:1720return InvalidAsDeclSpec ? TPResult::Ambiguous : TPResult::False;1721case ANK_Success:1722break;1723}17241725// Annotated it, check again.1726assert(Tok.isNot(tok::annot_cxxscope) ||1727NextToken().isNot(tok::identifier));1728return isCXXDeclarationSpecifier(AllowImplicitTypename,1729BracedCastResult, InvalidAsDeclSpec);1730}1731}1732return TPResult::False;1733}1734// If that succeeded, fallthrough into the generic simple-type-id case.1735[[fallthrough]];17361737// The ambiguity resides in a simple-type-specifier/typename-specifier1738// followed by a '('. The '(' could either be the start of:1739//1740// direct-declarator:1741// '(' declarator ')'1742//1743// direct-abstract-declarator:1744// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]1745// exception-specification[opt]1746// '(' abstract-declarator ')'1747//1748// or part of a function-style cast expression:1749//1750// simple-type-specifier '(' expression-list[opt] ')'1751//17521753// simple-type-specifier:17541755case tok::annot_typename:1756case_typename:1757// In Objective-C, we might have a protocol-qualified type.1758if (getLangOpts().ObjC && NextToken().is(tok::less)) {1759// Tentatively parse the protocol qualifiers.1760RevertingTentativeParsingAction PA(*this);1761ConsumeAnyToken(); // The type token17621763TPResult TPR = TryParseProtocolQualifiers();1764bool isFollowedByParen = Tok.is(tok::l_paren);1765bool isFollowedByBrace = Tok.is(tok::l_brace);17661767if (TPR == TPResult::Error)1768return TPResult::Error;17691770if (isFollowedByParen)1771return TPResult::Ambiguous;17721773if (getLangOpts().CPlusPlus11 && isFollowedByBrace)1774return BracedCastResult;17751776return TPResult::True;1777}17781779[[fallthrough]];17801781case tok::kw_char:1782case tok::kw_wchar_t:1783case tok::kw_char8_t:1784case tok::kw_char16_t:1785case tok::kw_char32_t:1786case tok::kw_bool:1787case tok::kw_short:1788case tok::kw_int:1789case tok::kw_long:1790case tok::kw___int64:1791case tok::kw___int128:1792case tok::kw_signed:1793case tok::kw_unsigned:1794case tok::kw_half:1795case tok::kw_float:1796case tok::kw_double:1797case tok::kw___bf16:1798case tok::kw__Float16:1799case tok::kw___float128:1800case tok::kw___ibm128:1801case tok::kw_void:1802case tok::annot_decltype:1803case tok::kw__Accum:1804case tok::kw__Fract:1805case tok::kw__Sat:1806case tok::annot_pack_indexing_type:1807#define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:1808#include "clang/Basic/OpenCLImageTypes.def"1809if (NextToken().is(tok::l_paren))1810return TPResult::Ambiguous;18111812// This is a function-style cast in all cases we disambiguate other than1813// one:1814// struct S {1815// enum E : int { a = 4 }; // enum1816// enum E : int { 4 }; // bit-field1817// };1818if (getLangOpts().CPlusPlus11 && NextToken().is(tok::l_brace))1819return BracedCastResult;18201821if (isStartOfObjCClassMessageMissingOpenBracket())1822return TPResult::False;18231824return TPResult::True;18251826// GNU typeof support.1827case tok::kw_typeof: {1828if (NextToken().isNot(tok::l_paren))1829return TPResult::True;18301831RevertingTentativeParsingAction PA(*this);18321833TPResult TPR = TryParseTypeofSpecifier();1834bool isFollowedByParen = Tok.is(tok::l_paren);1835bool isFollowedByBrace = Tok.is(tok::l_brace);18361837if (TPR == TPResult::Error)1838return TPResult::Error;18391840if (isFollowedByParen)1841return TPResult::Ambiguous;18421843if (getLangOpts().CPlusPlus11 && isFollowedByBrace)1844return BracedCastResult;18451846return TPResult::True;1847}18481849#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:1850#include "clang/Basic/TransformTypeTraits.def"1851return TPResult::True;18521853// C11 _Alignas1854case tok::kw__Alignas:1855return TPResult::True;1856// C11 _Atomic1857case tok::kw__Atomic:1858return TPResult::True;18591860case tok::kw__BitInt:1861case tok::kw__ExtInt: {1862if (NextToken().isNot(tok::l_paren))1863return TPResult::Error;1864RevertingTentativeParsingAction PA(*this);1865ConsumeToken();1866ConsumeParen();18671868if (!SkipUntil(tok::r_paren, StopAtSemi))1869return TPResult::Error;18701871if (Tok.is(tok::l_paren))1872return TPResult::Ambiguous;18731874if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))1875return BracedCastResult;18761877return TPResult::True;1878}1879default:1880return TPResult::False;1881}1882}18831884bool Parser::isCXXDeclarationSpecifierAType() {1885switch (Tok.getKind()) {1886// typename-specifier1887case tok::annot_decltype:1888case tok::annot_pack_indexing_type:1889case tok::annot_template_id:1890case tok::annot_typename:1891case tok::kw_typeof:1892#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:1893#include "clang/Basic/TransformTypeTraits.def"1894return true;18951896// elaborated-type-specifier1897case tok::kw_class:1898case tok::kw_struct:1899case tok::kw_union:1900case tok::kw___interface:1901case tok::kw_enum:1902return true;19031904// simple-type-specifier1905case tok::kw_char:1906case tok::kw_wchar_t:1907case tok::kw_char8_t:1908case tok::kw_char16_t:1909case tok::kw_char32_t:1910case tok::kw_bool:1911case tok::kw_short:1912case tok::kw_int:1913case tok::kw__ExtInt:1914case tok::kw__BitInt:1915case tok::kw_long:1916case tok::kw___int64:1917case tok::kw___int128:1918case tok::kw_signed:1919case tok::kw_unsigned:1920case tok::kw_half:1921case tok::kw_float:1922case tok::kw_double:1923case tok::kw___bf16:1924case tok::kw__Float16:1925case tok::kw___float128:1926case tok::kw___ibm128:1927case tok::kw_void:1928case tok::kw___unknown_anytype:1929case tok::kw___auto_type:1930case tok::kw__Accum:1931case tok::kw__Fract:1932case tok::kw__Sat:1933#define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:1934#include "clang/Basic/OpenCLImageTypes.def"1935return true;19361937case tok::kw_auto:1938return getLangOpts().CPlusPlus11;19391940case tok::kw__Atomic:1941// "_Atomic foo"1942return NextToken().is(tok::l_paren);19431944default:1945return false;1946}1947}19481949/// [GNU] typeof-specifier:1950/// 'typeof' '(' expressions ')'1951/// 'typeof' '(' type-name ')'1952///1953Parser::TPResult Parser::TryParseTypeofSpecifier() {1954assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");1955ConsumeToken();19561957assert(Tok.is(tok::l_paren) && "Expected '('");1958// Parse through the parens after 'typeof'.1959ConsumeParen();1960if (!SkipUntil(tok::r_paren, StopAtSemi))1961return TPResult::Error;19621963return TPResult::Ambiguous;1964}19651966/// [ObjC] protocol-qualifiers:1967//// '<' identifier-list '>'1968Parser::TPResult Parser::TryParseProtocolQualifiers() {1969assert(Tok.is(tok::less) && "Expected '<' for qualifier list");1970ConsumeToken();1971do {1972if (Tok.isNot(tok::identifier))1973return TPResult::Error;1974ConsumeToken();19751976if (Tok.is(tok::comma)) {1977ConsumeToken();1978continue;1979}19801981if (Tok.is(tok::greater)) {1982ConsumeToken();1983return TPResult::Ambiguous;1984}1985} while (false);19861987return TPResult::Error;1988}19891990/// isCXXFunctionDeclarator - Disambiguates between a function declarator or1991/// a constructor-style initializer, when parsing declaration statements.1992/// Returns true for function declarator and false for constructor-style1993/// initializer.1994/// If during the disambiguation process a parsing error is encountered,1995/// the function returns true to let the declaration parsing code handle it.1996///1997/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]1998/// exception-specification[opt]1999///2000bool Parser::isCXXFunctionDeclarator(2001bool *IsAmbiguous, ImplicitTypenameContext AllowImplicitTypename) {20022003// C++ 8.2p1:2004// The ambiguity arising from the similarity between a function-style cast and2005// a declaration mentioned in 6.8 can also occur in the context of a2006// declaration. In that context, the choice is between a function declaration2007// with a redundant set of parentheses around a parameter name and an object2008// declaration with a function-style cast as the initializer. Just as for the2009// ambiguities mentioned in 6.8, the resolution is to consider any construct2010// that could possibly be a declaration a declaration.20112012RevertingTentativeParsingAction PA(*this);20132014ConsumeParen();2015bool InvalidAsDeclaration = false;2016TPResult TPR = TryParseParameterDeclarationClause(2017&InvalidAsDeclaration, /*VersusTemplateArgument=*/false,2018AllowImplicitTypename);2019if (TPR == TPResult::Ambiguous) {2020if (Tok.isNot(tok::r_paren))2021TPR = TPResult::False;2022else {2023const Token &Next = NextToken();2024if (Next.isOneOf(tok::amp, tok::ampamp, tok::kw_const, tok::kw_volatile,2025tok::kw_throw, tok::kw_noexcept, tok::l_square,2026tok::l_brace, tok::kw_try, tok::equal, tok::arrow) ||2027isCXX11VirtSpecifier(Next))2028// The next token cannot appear after a constructor-style initializer,2029// and can appear next in a function definition. This must be a function2030// declarator.2031TPR = TPResult::True;2032else if (InvalidAsDeclaration)2033// Use the absence of 'typename' as a tie-breaker.2034TPR = TPResult::False;2035}2036}20372038if (IsAmbiguous && TPR == TPResult::Ambiguous)2039*IsAmbiguous = true;20402041// In case of an error, let the declaration parsing code handle it.2042return TPR != TPResult::False;2043}20442045/// parameter-declaration-clause:2046/// parameter-declaration-list[opt] '...'[opt]2047/// parameter-declaration-list ',' '...'2048///2049/// parameter-declaration-list:2050/// parameter-declaration2051/// parameter-declaration-list ',' parameter-declaration2052///2053/// parameter-declaration:2054/// attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]2055/// attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]2056/// '=' assignment-expression2057/// attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]2058/// attributes[opt]2059/// attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]2060/// attributes[opt] '=' assignment-expression2061///2062Parser::TPResult Parser::TryParseParameterDeclarationClause(2063bool *InvalidAsDeclaration, bool VersusTemplateArgument,2064ImplicitTypenameContext AllowImplicitTypename) {20652066if (Tok.is(tok::r_paren))2067return TPResult::Ambiguous;20682069// parameter-declaration-list[opt] '...'[opt]2070// parameter-declaration-list ',' '...'2071//2072// parameter-declaration-list:2073// parameter-declaration2074// parameter-declaration-list ',' parameter-declaration2075//2076while (true) {2077// '...'[opt]2078if (Tok.is(tok::ellipsis)) {2079ConsumeToken();2080if (Tok.is(tok::r_paren))2081return TPResult::True; // '...)' is a sign of a function declarator.2082else2083return TPResult::False;2084}20852086// An attribute-specifier-seq here is a sign of a function declarator.2087if (isCXX11AttributeSpecifier(/*Disambiguate*/false,2088/*OuterMightBeMessageSend*/true))2089return TPResult::True;20902091ParsedAttributes attrs(AttrFactory);2092MaybeParseMicrosoftAttributes(attrs);20932094// decl-specifier-seq2095// A parameter-declaration's initializer must be preceded by an '=', so2096// decl-specifier-seq '{' is not a parameter in C++11.2097TPResult TPR = isCXXDeclarationSpecifier(2098AllowImplicitTypename, TPResult::False, InvalidAsDeclaration);2099// A declaration-specifier (not followed by '(' or '{') means this can't be2100// an expression, but it could still be a template argument.2101if (TPR != TPResult::Ambiguous &&2102!(VersusTemplateArgument && TPR == TPResult::True))2103return TPR;21042105bool SeenType = false;2106bool DeclarationSpecifierIsAuto = Tok.is(tok::kw_auto);2107do {2108SeenType |= isCXXDeclarationSpecifierAType();2109if (TryConsumeDeclarationSpecifier() == TPResult::Error)2110return TPResult::Error;21112112// If we see a parameter name, this can't be a template argument.2113if (SeenType && Tok.is(tok::identifier))2114return TPResult::True;21152116TPR = isCXXDeclarationSpecifier(AllowImplicitTypename, TPResult::False,2117InvalidAsDeclaration);2118if (TPR == TPResult::Error)2119return TPR;21202121// Two declaration-specifiers means this can't be an expression.2122if (TPR == TPResult::True && !VersusTemplateArgument)2123return TPR;2124} while (TPR != TPResult::False);21252126// declarator2127// abstract-declarator[opt]2128TPR = TryParseDeclarator(2129/*mayBeAbstract=*/true,2130/*mayHaveIdentifier=*/true,2131/*mayHaveDirectInit=*/false,2132/*mayHaveTrailingReturnType=*/DeclarationSpecifierIsAuto);2133if (TPR != TPResult::Ambiguous)2134return TPR;21352136// [GNU] attributes[opt]2137if (Tok.is(tok::kw___attribute))2138return TPResult::True;21392140// If we're disambiguating a template argument in a default argument in2141// a class definition versus a parameter declaration, an '=' here2142// disambiguates the parse one way or the other.2143// If this is a parameter, it must have a default argument because2144// (a) the previous parameter did, and2145// (b) this must be the first declaration of the function, so we can't2146// inherit any default arguments from elsewhere.2147// FIXME: If we reach a ')' without consuming any '>'s, then this must2148// also be a function parameter (that's missing its default argument).2149if (VersusTemplateArgument)2150return Tok.is(tok::equal) ? TPResult::True : TPResult::False;21512152if (Tok.is(tok::equal)) {2153// '=' assignment-expression2154// Parse through assignment-expression.2155if (!SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch))2156return TPResult::Error;2157}21582159if (Tok.is(tok::ellipsis)) {2160ConsumeToken();2161if (Tok.is(tok::r_paren))2162return TPResult::True; // '...)' is a sign of a function declarator.2163else2164return TPResult::False;2165}21662167if (!TryConsumeToken(tok::comma))2168break;2169}21702171return TPResult::Ambiguous;2172}21732174/// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue2175/// parsing as a function declarator.2176/// If TryParseFunctionDeclarator fully parsed the function declarator, it will2177/// return TPResult::Ambiguous, otherwise it will return either False() or2178/// Error().2179///2180/// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]2181/// exception-specification[opt]2182///2183/// exception-specification:2184/// 'throw' '(' type-id-list[opt] ')'2185///2186Parser::TPResult2187Parser::TryParseFunctionDeclarator(bool MayHaveTrailingReturnType) {2188// The '(' is already parsed.21892190TPResult TPR = TryParseParameterDeclarationClause();2191if (TPR == TPResult::Ambiguous && Tok.isNot(tok::r_paren))2192TPR = TPResult::False;21932194if (TPR == TPResult::False || TPR == TPResult::Error)2195return TPR;21962197// Parse through the parens.2198if (!SkipUntil(tok::r_paren, StopAtSemi))2199return TPResult::Error;22002201// cv-qualifier-seq2202while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw___unaligned,2203tok::kw_restrict))2204ConsumeToken();22052206// ref-qualifier[opt]2207if (Tok.isOneOf(tok::amp, tok::ampamp))2208ConsumeToken();22092210// exception-specification2211if (Tok.is(tok::kw_throw)) {2212ConsumeToken();2213if (Tok.isNot(tok::l_paren))2214return TPResult::Error;22152216// Parse through the parens after 'throw'.2217ConsumeParen();2218if (!SkipUntil(tok::r_paren, StopAtSemi))2219return TPResult::Error;2220}2221if (Tok.is(tok::kw_noexcept)) {2222ConsumeToken();2223// Possibly an expression as well.2224if (Tok.is(tok::l_paren)) {2225// Find the matching rparen.2226ConsumeParen();2227if (!SkipUntil(tok::r_paren, StopAtSemi))2228return TPResult::Error;2229}2230}22312232// attribute-specifier-seq2233if (!TrySkipAttributes())2234return TPResult::Ambiguous;22352236// trailing-return-type2237if (Tok.is(tok::arrow) && MayHaveTrailingReturnType) {2238if (TPR == TPResult::True)2239return TPR;2240ConsumeToken();2241if (Tok.is(tok::identifier) && NameAfterArrowIsNonType()) {2242return TPResult::False;2243}2244if (isCXXTypeId(TentativeCXXTypeIdContext::TypeIdInTrailingReturnType))2245return TPResult::True;2246}22472248return TPResult::Ambiguous;2249}22502251// When parsing an identifier after an arrow it may be a member expression,2252// in which case we should not annotate it as an independant expression2253// so we just lookup that name, if it's not a type the construct is not2254// a function declaration.2255bool Parser::NameAfterArrowIsNonType() {2256assert(Tok.is(tok::identifier));2257Token Next = NextToken();2258if (Next.is(tok::coloncolon))2259return false;2260IdentifierInfo *Name = Tok.getIdentifierInfo();2261SourceLocation NameLoc = Tok.getLocation();2262CXXScopeSpec SS;2263TentativeParseCCC CCC(Next);2264Sema::NameClassification Classification =2265Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next, &CCC);2266switch (Classification.getKind()) {2267case Sema::NC_OverloadSet:2268case Sema::NC_NonType:2269case Sema::NC_VarTemplate:2270case Sema::NC_FunctionTemplate:2271return true;2272default:2273break;2274}2275return false;2276}22772278/// '[' constant-expression[opt] ']'2279///2280Parser::TPResult Parser::TryParseBracketDeclarator() {2281ConsumeBracket();22822283// A constant-expression cannot begin with a '{', but the2284// expr-or-braced-init-list of a postfix-expression can.2285if (Tok.is(tok::l_brace))2286return TPResult::False;22872288if (!SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch))2289return TPResult::Error;22902291// If we hit a comma before the ']', this is not a constant-expression,2292// but might still be the expr-or-braced-init-list of a postfix-expression.2293if (Tok.isNot(tok::r_square))2294return TPResult::False;22952296ConsumeBracket();2297return TPResult::Ambiguous;2298}22992300/// Determine whether we might be looking at the '<' template-argument-list '>'2301/// of a template-id or simple-template-id, rather than a less-than comparison.2302/// This will often fail and produce an ambiguity, but should never be wrong2303/// if it returns True or False.2304Parser::TPResult Parser::isTemplateArgumentList(unsigned TokensToSkip) {2305if (!TokensToSkip) {2306if (Tok.isNot(tok::less))2307return TPResult::False;2308if (NextToken().is(tok::greater))2309return TPResult::True;2310}23112312RevertingTentativeParsingAction PA(*this);23132314while (TokensToSkip) {2315ConsumeAnyToken();2316--TokensToSkip;2317}23182319if (!TryConsumeToken(tok::less))2320return TPResult::False;23212322// We can't do much to tell an expression apart from a template-argument,2323// but one good distinguishing factor is that a "decl-specifier" not2324// followed by '(' or '{' can't appear in an expression.2325bool InvalidAsTemplateArgumentList = false;2326if (isCXXDeclarationSpecifier(ImplicitTypenameContext::No, TPResult::False,2327&InvalidAsTemplateArgumentList) ==2328TPResult::True)2329return TPResult::True;2330if (InvalidAsTemplateArgumentList)2331return TPResult::False;23322333// FIXME: In many contexts, X<thing1, Type> can only be a2334// template-argument-list. But that's not true in general:2335//2336// using b = int;2337// void f() {2338// int a = A<B, b, c = C>D; // OK, declares b, not a template-id.2339//2340// X<Y<0, int> // ', int>' might be end of X's template argument list2341//2342// We might be able to disambiguate a few more cases if we're careful.23432344// A template-argument-list must be terminated by a '>'.2345if (SkipUntil({tok::greater, tok::greatergreater, tok::greatergreatergreater},2346StopAtSemi | StopBeforeMatch))2347return TPResult::Ambiguous;2348return TPResult::False;2349}23502351/// Determine whether we might be looking at the '(' of a C++20 explicit(bool)2352/// in an earlier language mode.2353Parser::TPResult Parser::isExplicitBool() {2354assert(Tok.is(tok::l_paren) && "expected to be looking at a '(' token");23552356RevertingTentativeParsingAction PA(*this);2357ConsumeParen();23582359// We can only have 'explicit' on a constructor, conversion function, or2360// deduction guide. The declarator of a deduction guide cannot be2361// parenthesized, so we know this isn't a deduction guide. So the only2362// thing we need to check for is some number of parens followed by either2363// the current class name or 'operator'.2364while (Tok.is(tok::l_paren))2365ConsumeParen();23662367if (TryAnnotateOptionalCXXScopeToken())2368return TPResult::Error;23692370// Class-scope constructor and conversion function names can't really be2371// qualified, but we get better diagnostics if we assume they can be.2372CXXScopeSpec SS;2373if (Tok.is(tok::annot_cxxscope)) {2374Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),2375Tok.getAnnotationRange(),2376SS);2377ConsumeAnnotationToken();2378}23792380// 'explicit(operator' might be explicit(bool) or the declaration of a2381// conversion function, but it's probably a conversion function.2382if (Tok.is(tok::kw_operator))2383return TPResult::Ambiguous;23842385// If this can't be a constructor name, it can only be explicit(bool).2386if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))2387return TPResult::True;2388if (!Actions.isCurrentClassName(Tok.is(tok::identifier)2389? *Tok.getIdentifierInfo()2390: *takeTemplateIdAnnotation(Tok)->Name,2391getCurScope(), &SS))2392return TPResult::True;2393// Formally, we must have a right-paren after the constructor name to match2394// the grammar for a constructor. But clang permits a parenthesized2395// constructor declarator, so also allow a constructor declarator to follow2396// with no ')' token after the constructor name.2397if (!NextToken().is(tok::r_paren) &&2398!isConstructorDeclarator(/*Unqualified=*/SS.isEmpty(),2399/*DeductionGuide=*/false))2400return TPResult::True;24012402// Might be explicit(bool) or a parenthesized constructor name.2403return TPResult::Ambiguous;2404}240524062407