17330f729Sjoerg //===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file implements the tentative parsing portions of the Parser
107330f729Sjoerg // interfaces, for ambiguity resolution.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg
147330f729Sjoerg #include "clang/Parse/Parser.h"
157330f729Sjoerg #include "clang/Parse/ParseDiagnostic.h"
167330f729Sjoerg #include "clang/Sema/ParsedTemplate.h"
177330f729Sjoerg using namespace clang;
187330f729Sjoerg
197330f729Sjoerg /// isCXXDeclarationStatement - C++-specialized function that disambiguates
207330f729Sjoerg /// between a declaration or an expression statement, when parsing function
217330f729Sjoerg /// bodies. Returns true for declaration, false for expression.
227330f729Sjoerg ///
237330f729Sjoerg /// declaration-statement:
247330f729Sjoerg /// block-declaration
257330f729Sjoerg ///
267330f729Sjoerg /// block-declaration:
277330f729Sjoerg /// simple-declaration
287330f729Sjoerg /// asm-definition
297330f729Sjoerg /// namespace-alias-definition
307330f729Sjoerg /// using-declaration
317330f729Sjoerg /// using-directive
327330f729Sjoerg /// [C++0x] static_assert-declaration
337330f729Sjoerg ///
347330f729Sjoerg /// asm-definition:
357330f729Sjoerg /// 'asm' '(' string-literal ')' ';'
367330f729Sjoerg ///
377330f729Sjoerg /// namespace-alias-definition:
387330f729Sjoerg /// 'namespace' identifier = qualified-namespace-specifier ';'
397330f729Sjoerg ///
407330f729Sjoerg /// using-declaration:
417330f729Sjoerg /// 'using' typename[opt] '::'[opt] nested-name-specifier
427330f729Sjoerg /// unqualified-id ';'
437330f729Sjoerg /// 'using' '::' unqualified-id ;
447330f729Sjoerg ///
457330f729Sjoerg /// using-directive:
467330f729Sjoerg /// 'using' 'namespace' '::'[opt] nested-name-specifier[opt]
477330f729Sjoerg /// namespace-name ';'
487330f729Sjoerg ///
isCXXDeclarationStatement()497330f729Sjoerg bool Parser::isCXXDeclarationStatement() {
507330f729Sjoerg switch (Tok.getKind()) {
517330f729Sjoerg // asm-definition
527330f729Sjoerg case tok::kw_asm:
537330f729Sjoerg // namespace-alias-definition
547330f729Sjoerg case tok::kw_namespace:
557330f729Sjoerg // using-declaration
567330f729Sjoerg // using-directive
577330f729Sjoerg case tok::kw_using:
587330f729Sjoerg // static_assert-declaration
597330f729Sjoerg case tok::kw_static_assert:
607330f729Sjoerg case tok::kw__Static_assert:
617330f729Sjoerg return true;
627330f729Sjoerg // simple-declaration
637330f729Sjoerg default:
647330f729Sjoerg return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);
657330f729Sjoerg }
667330f729Sjoerg }
677330f729Sjoerg
687330f729Sjoerg /// isCXXSimpleDeclaration - C++-specialized function that disambiguates
697330f729Sjoerg /// between a simple-declaration or an expression-statement.
707330f729Sjoerg /// If during the disambiguation process a parsing error is encountered,
717330f729Sjoerg /// the function returns true to let the declaration parsing code handle it.
727330f729Sjoerg /// Returns false if the statement is disambiguated as expression.
737330f729Sjoerg ///
747330f729Sjoerg /// simple-declaration:
757330f729Sjoerg /// decl-specifier-seq init-declarator-list[opt] ';'
767330f729Sjoerg /// decl-specifier-seq ref-qualifier[opt] '[' identifier-list ']'
777330f729Sjoerg /// brace-or-equal-initializer ';' [C++17]
787330f729Sjoerg ///
797330f729Sjoerg /// (if AllowForRangeDecl specified)
807330f729Sjoerg /// for ( for-range-declaration : for-range-initializer ) statement
817330f729Sjoerg ///
827330f729Sjoerg /// for-range-declaration:
837330f729Sjoerg /// decl-specifier-seq declarator
847330f729Sjoerg /// decl-specifier-seq ref-qualifier[opt] '[' identifier-list ']'
857330f729Sjoerg ///
867330f729Sjoerg /// In any of the above cases there can be a preceding attribute-specifier-seq,
877330f729Sjoerg /// but the caller is expected to handle that.
isCXXSimpleDeclaration(bool AllowForRangeDecl)887330f729Sjoerg bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
897330f729Sjoerg // C++ 6.8p1:
907330f729Sjoerg // There is an ambiguity in the grammar involving expression-statements and
917330f729Sjoerg // declarations: An expression-statement with a function-style explicit type
927330f729Sjoerg // conversion (5.2.3) as its leftmost subexpression can be indistinguishable
937330f729Sjoerg // from a declaration where the first declarator starts with a '('. In those
947330f729Sjoerg // cases the statement is a declaration. [Note: To disambiguate, the whole
957330f729Sjoerg // statement might have to be examined to determine if it is an
967330f729Sjoerg // expression-statement or a declaration].
977330f729Sjoerg
987330f729Sjoerg // C++ 6.8p3:
997330f729Sjoerg // The disambiguation is purely syntactic; that is, the meaning of the names
1007330f729Sjoerg // occurring in such a statement, beyond whether they are type-names or not,
1017330f729Sjoerg // is not generally used in or changed by the disambiguation. Class
1027330f729Sjoerg // templates are instantiated as necessary to determine if a qualified name
1037330f729Sjoerg // is a type-name. Disambiguation precedes parsing, and a statement
1047330f729Sjoerg // disambiguated as a declaration may be an ill-formed declaration.
1057330f729Sjoerg
1067330f729Sjoerg // We don't have to parse all of the decl-specifier-seq part. There's only
1077330f729Sjoerg // an ambiguity if the first decl-specifier is
1087330f729Sjoerg // simple-type-specifier/typename-specifier followed by a '(', which may
1097330f729Sjoerg // indicate a function-style cast expression.
1107330f729Sjoerg // isCXXDeclarationSpecifier will return TPResult::Ambiguous only in such
1117330f729Sjoerg // a case.
1127330f729Sjoerg
1137330f729Sjoerg bool InvalidAsDeclaration = false;
1147330f729Sjoerg TPResult TPR = isCXXDeclarationSpecifier(TPResult::False,
1157330f729Sjoerg &InvalidAsDeclaration);
1167330f729Sjoerg if (TPR != TPResult::Ambiguous)
1177330f729Sjoerg return TPR != TPResult::False; // Returns true for TPResult::True or
1187330f729Sjoerg // TPResult::Error.
1197330f729Sjoerg
1207330f729Sjoerg // FIXME: TryParseSimpleDeclaration doesn't look past the first initializer,
1217330f729Sjoerg // and so gets some cases wrong. We can't carry on if we've already seen
1227330f729Sjoerg // something which makes this statement invalid as a declaration in this case,
1237330f729Sjoerg // since it can cause us to misparse valid code. Revisit this once
1247330f729Sjoerg // TryParseInitDeclaratorList is fixed.
1257330f729Sjoerg if (InvalidAsDeclaration)
1267330f729Sjoerg return false;
1277330f729Sjoerg
1287330f729Sjoerg // FIXME: Add statistics about the number of ambiguous statements encountered
1297330f729Sjoerg // and how they were resolved (number of declarations+number of expressions).
1307330f729Sjoerg
1317330f729Sjoerg // Ok, we have a simple-type-specifier/typename-specifier followed by a '(',
1327330f729Sjoerg // or an identifier which doesn't resolve as anything. We need tentative
1337330f729Sjoerg // parsing...
1347330f729Sjoerg
1357330f729Sjoerg {
1367330f729Sjoerg RevertingTentativeParsingAction PA(*this);
1377330f729Sjoerg TPR = TryParseSimpleDeclaration(AllowForRangeDecl);
1387330f729Sjoerg }
1397330f729Sjoerg
1407330f729Sjoerg // In case of an error, let the declaration parsing code handle it.
1417330f729Sjoerg if (TPR == TPResult::Error)
1427330f729Sjoerg return true;
1437330f729Sjoerg
1447330f729Sjoerg // Declarations take precedence over expressions.
1457330f729Sjoerg if (TPR == TPResult::Ambiguous)
1467330f729Sjoerg TPR = TPResult::True;
1477330f729Sjoerg
1487330f729Sjoerg assert(TPR == TPResult::True || TPR == TPResult::False);
1497330f729Sjoerg return TPR == TPResult::True;
1507330f729Sjoerg }
1517330f729Sjoerg
1527330f729Sjoerg /// Try to consume a token sequence that we've already identified as
1537330f729Sjoerg /// (potentially) starting a decl-specifier.
TryConsumeDeclarationSpecifier()1547330f729Sjoerg Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
1557330f729Sjoerg switch (Tok.getKind()) {
1567330f729Sjoerg case tok::kw__Atomic:
1577330f729Sjoerg if (NextToken().isNot(tok::l_paren)) {
1587330f729Sjoerg ConsumeToken();
1597330f729Sjoerg break;
1607330f729Sjoerg }
1617330f729Sjoerg LLVM_FALLTHROUGH;
1627330f729Sjoerg case tok::kw_typeof:
1637330f729Sjoerg case tok::kw___attribute:
1647330f729Sjoerg case tok::kw___underlying_type: {
1657330f729Sjoerg ConsumeToken();
1667330f729Sjoerg if (Tok.isNot(tok::l_paren))
1677330f729Sjoerg return TPResult::Error;
1687330f729Sjoerg ConsumeParen();
1697330f729Sjoerg if (!SkipUntil(tok::r_paren))
1707330f729Sjoerg return TPResult::Error;
1717330f729Sjoerg break;
1727330f729Sjoerg }
1737330f729Sjoerg
1747330f729Sjoerg case tok::kw_class:
1757330f729Sjoerg case tok::kw_struct:
1767330f729Sjoerg case tok::kw_union:
1777330f729Sjoerg case tok::kw___interface:
1787330f729Sjoerg case tok::kw_enum:
1797330f729Sjoerg // elaborated-type-specifier:
1807330f729Sjoerg // class-key attribute-specifier-seq[opt]
1817330f729Sjoerg // nested-name-specifier[opt] identifier
1827330f729Sjoerg // class-key nested-name-specifier[opt] template[opt] simple-template-id
1837330f729Sjoerg // enum nested-name-specifier[opt] identifier
1847330f729Sjoerg //
1857330f729Sjoerg // FIXME: We don't support class-specifiers nor enum-specifiers here.
1867330f729Sjoerg ConsumeToken();
1877330f729Sjoerg
1887330f729Sjoerg // Skip attributes.
189*e038c9c4Sjoerg if (!TrySkipAttributes())
1907330f729Sjoerg return TPResult::Error;
1917330f729Sjoerg
192*e038c9c4Sjoerg if (TryAnnotateOptionalCXXScopeToken())
1937330f729Sjoerg return TPResult::Error;
1947330f729Sjoerg if (Tok.is(tok::annot_cxxscope))
1957330f729Sjoerg ConsumeAnnotationToken();
1967330f729Sjoerg if (Tok.is(tok::identifier))
1977330f729Sjoerg ConsumeToken();
1987330f729Sjoerg else if (Tok.is(tok::annot_template_id))
1997330f729Sjoerg ConsumeAnnotationToken();
2007330f729Sjoerg else
2017330f729Sjoerg return TPResult::Error;
2027330f729Sjoerg break;
2037330f729Sjoerg
2047330f729Sjoerg case tok::annot_cxxscope:
2057330f729Sjoerg ConsumeAnnotationToken();
2067330f729Sjoerg LLVM_FALLTHROUGH;
2077330f729Sjoerg default:
2087330f729Sjoerg ConsumeAnyToken();
2097330f729Sjoerg
2107330f729Sjoerg if (getLangOpts().ObjC && Tok.is(tok::less))
2117330f729Sjoerg return TryParseProtocolQualifiers();
2127330f729Sjoerg break;
2137330f729Sjoerg }
2147330f729Sjoerg
2157330f729Sjoerg return TPResult::Ambiguous;
2167330f729Sjoerg }
2177330f729Sjoerg
2187330f729Sjoerg /// simple-declaration:
2197330f729Sjoerg /// decl-specifier-seq init-declarator-list[opt] ';'
2207330f729Sjoerg ///
2217330f729Sjoerg /// (if AllowForRangeDecl specified)
2227330f729Sjoerg /// for ( for-range-declaration : for-range-initializer ) statement
2237330f729Sjoerg /// for-range-declaration:
2247330f729Sjoerg /// attribute-specifier-seqopt type-specifier-seq declarator
2257330f729Sjoerg ///
TryParseSimpleDeclaration(bool AllowForRangeDecl)2267330f729Sjoerg Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
2277330f729Sjoerg if (TryConsumeDeclarationSpecifier() == TPResult::Error)
2287330f729Sjoerg return TPResult::Error;
2297330f729Sjoerg
2307330f729Sjoerg // Two decl-specifiers in a row conclusively disambiguate this as being a
2317330f729Sjoerg // simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the
2327330f729Sjoerg // overwhelmingly common case that the next token is a '('.
2337330f729Sjoerg if (Tok.isNot(tok::l_paren)) {
2347330f729Sjoerg TPResult TPR = isCXXDeclarationSpecifier();
2357330f729Sjoerg if (TPR == TPResult::Ambiguous)
2367330f729Sjoerg return TPResult::True;
2377330f729Sjoerg if (TPR == TPResult::True || TPR == TPResult::Error)
2387330f729Sjoerg return TPR;
2397330f729Sjoerg assert(TPR == TPResult::False);
2407330f729Sjoerg }
2417330f729Sjoerg
2427330f729Sjoerg TPResult TPR = TryParseInitDeclaratorList();
2437330f729Sjoerg if (TPR != TPResult::Ambiguous)
2447330f729Sjoerg return TPR;
2457330f729Sjoerg
2467330f729Sjoerg if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))
2477330f729Sjoerg return TPResult::False;
2487330f729Sjoerg
2497330f729Sjoerg return TPResult::Ambiguous;
2507330f729Sjoerg }
2517330f729Sjoerg
2527330f729Sjoerg /// Tentatively parse an init-declarator-list in order to disambiguate it from
2537330f729Sjoerg /// an expression.
2547330f729Sjoerg ///
2557330f729Sjoerg /// init-declarator-list:
2567330f729Sjoerg /// init-declarator
2577330f729Sjoerg /// init-declarator-list ',' init-declarator
2587330f729Sjoerg ///
2597330f729Sjoerg /// init-declarator:
2607330f729Sjoerg /// declarator initializer[opt]
2617330f729Sjoerg /// [GNU] declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
2627330f729Sjoerg ///
2637330f729Sjoerg /// initializer:
2647330f729Sjoerg /// brace-or-equal-initializer
2657330f729Sjoerg /// '(' expression-list ')'
2667330f729Sjoerg ///
2677330f729Sjoerg /// brace-or-equal-initializer:
2687330f729Sjoerg /// '=' initializer-clause
2697330f729Sjoerg /// [C++11] braced-init-list
2707330f729Sjoerg ///
2717330f729Sjoerg /// initializer-clause:
2727330f729Sjoerg /// assignment-expression
2737330f729Sjoerg /// braced-init-list
2747330f729Sjoerg ///
2757330f729Sjoerg /// braced-init-list:
2767330f729Sjoerg /// '{' initializer-list ','[opt] '}'
2777330f729Sjoerg /// '{' '}'
2787330f729Sjoerg ///
TryParseInitDeclaratorList()2797330f729Sjoerg Parser::TPResult Parser::TryParseInitDeclaratorList() {
2807330f729Sjoerg while (1) {
2817330f729Sjoerg // declarator
2827330f729Sjoerg TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
2837330f729Sjoerg if (TPR != TPResult::Ambiguous)
2847330f729Sjoerg return TPR;
2857330f729Sjoerg
2867330f729Sjoerg // [GNU] simple-asm-expr[opt] attributes[opt]
2877330f729Sjoerg if (Tok.isOneOf(tok::kw_asm, tok::kw___attribute))
2887330f729Sjoerg return TPResult::True;
2897330f729Sjoerg
2907330f729Sjoerg // initializer[opt]
2917330f729Sjoerg if (Tok.is(tok::l_paren)) {
2927330f729Sjoerg // Parse through the parens.
2937330f729Sjoerg ConsumeParen();
2947330f729Sjoerg if (!SkipUntil(tok::r_paren, StopAtSemi))
2957330f729Sjoerg return TPResult::Error;
2967330f729Sjoerg } else if (Tok.is(tok::l_brace)) {
2977330f729Sjoerg // A left-brace here is sufficient to disambiguate the parse; an
2987330f729Sjoerg // expression can never be followed directly by a braced-init-list.
2997330f729Sjoerg return TPResult::True;
3007330f729Sjoerg } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
3017330f729Sjoerg // MSVC and g++ won't examine the rest of declarators if '=' is
3027330f729Sjoerg // encountered; they just conclude that we have a declaration.
3037330f729Sjoerg // EDG parses the initializer completely, which is the proper behavior
3047330f729Sjoerg // for this case.
3057330f729Sjoerg //
3067330f729Sjoerg // At present, Clang follows MSVC and g++, since the parser does not have
3077330f729Sjoerg // the ability to parse an expression fully without recording the
3087330f729Sjoerg // results of that parse.
3097330f729Sjoerg // FIXME: Handle this case correctly.
3107330f729Sjoerg //
3117330f729Sjoerg // Also allow 'in' after an Objective-C declaration as in:
3127330f729Sjoerg // for (int (^b)(void) in array). Ideally this should be done in the
3137330f729Sjoerg // context of parsing for-init-statement of a foreach statement only. But,
3147330f729Sjoerg // in any other context 'in' is invalid after a declaration and parser
3157330f729Sjoerg // issues the error regardless of outcome of this decision.
3167330f729Sjoerg // FIXME: Change if above assumption does not hold.
3177330f729Sjoerg return TPResult::True;
3187330f729Sjoerg }
3197330f729Sjoerg
3207330f729Sjoerg if (!TryConsumeToken(tok::comma))
3217330f729Sjoerg break;
3227330f729Sjoerg }
3237330f729Sjoerg
3247330f729Sjoerg return TPResult::Ambiguous;
3257330f729Sjoerg }
3267330f729Sjoerg
3277330f729Sjoerg struct Parser::ConditionDeclarationOrInitStatementState {
3287330f729Sjoerg Parser &P;
3297330f729Sjoerg bool CanBeExpression = true;
3307330f729Sjoerg bool CanBeCondition = true;
3317330f729Sjoerg bool CanBeInitStatement;
3327330f729Sjoerg bool CanBeForRangeDecl;
3337330f729Sjoerg
ConditionDeclarationOrInitStatementStateParser::ConditionDeclarationOrInitStatementState3347330f729Sjoerg ConditionDeclarationOrInitStatementState(Parser &P, bool CanBeInitStatement,
3357330f729Sjoerg bool CanBeForRangeDecl)
3367330f729Sjoerg : P(P), CanBeInitStatement(CanBeInitStatement),
3377330f729Sjoerg CanBeForRangeDecl(CanBeForRangeDecl) {}
3387330f729Sjoerg
resolvedParser::ConditionDeclarationOrInitStatementState3397330f729Sjoerg bool resolved() {
3407330f729Sjoerg return CanBeExpression + CanBeCondition + CanBeInitStatement +
3417330f729Sjoerg CanBeForRangeDecl < 2;
3427330f729Sjoerg }
3437330f729Sjoerg
markNotExpressionParser::ConditionDeclarationOrInitStatementState3447330f729Sjoerg void markNotExpression() {
3457330f729Sjoerg CanBeExpression = false;
3467330f729Sjoerg
3477330f729Sjoerg if (!resolved()) {
3487330f729Sjoerg // FIXME: Unify the parsing codepaths for condition variables and
3497330f729Sjoerg // simple-declarations so that we don't need to eagerly figure out which
3507330f729Sjoerg // kind we have here. (Just parse init-declarators until we reach a
3517330f729Sjoerg // semicolon or right paren.)
3527330f729Sjoerg RevertingTentativeParsingAction PA(P);
3537330f729Sjoerg if (CanBeForRangeDecl) {
3547330f729Sjoerg // Skip until we hit a ')', ';', or a ':' with no matching '?'.
3557330f729Sjoerg // The final case is a for range declaration, the rest are not.
3567330f729Sjoerg unsigned QuestionColonDepth = 0;
357*e038c9c4Sjoerg while (true) {
3587330f729Sjoerg P.SkipUntil({tok::r_paren, tok::semi, tok::question, tok::colon},
3597330f729Sjoerg StopBeforeMatch);
3607330f729Sjoerg if (P.Tok.is(tok::question))
3617330f729Sjoerg ++QuestionColonDepth;
3627330f729Sjoerg else if (P.Tok.is(tok::colon)) {
3637330f729Sjoerg if (QuestionColonDepth)
3647330f729Sjoerg --QuestionColonDepth;
3657330f729Sjoerg else {
3667330f729Sjoerg CanBeCondition = CanBeInitStatement = false;
3677330f729Sjoerg return;
3687330f729Sjoerg }
3697330f729Sjoerg } else {
3707330f729Sjoerg CanBeForRangeDecl = false;
3717330f729Sjoerg break;
3727330f729Sjoerg }
3737330f729Sjoerg P.ConsumeToken();
3747330f729Sjoerg }
3757330f729Sjoerg } else {
3767330f729Sjoerg // Just skip until we hit a ')' or ';'.
3777330f729Sjoerg P.SkipUntil(tok::r_paren, tok::semi, StopBeforeMatch);
3787330f729Sjoerg }
3797330f729Sjoerg if (P.Tok.isNot(tok::r_paren))
3807330f729Sjoerg CanBeCondition = CanBeForRangeDecl = false;
3817330f729Sjoerg if (P.Tok.isNot(tok::semi))
3827330f729Sjoerg CanBeInitStatement = false;
3837330f729Sjoerg }
3847330f729Sjoerg }
3857330f729Sjoerg
markNotConditionParser::ConditionDeclarationOrInitStatementState3867330f729Sjoerg bool markNotCondition() {
3877330f729Sjoerg CanBeCondition = false;
3887330f729Sjoerg return resolved();
3897330f729Sjoerg }
3907330f729Sjoerg
markNotForRangeDeclParser::ConditionDeclarationOrInitStatementState3917330f729Sjoerg bool markNotForRangeDecl() {
3927330f729Sjoerg CanBeForRangeDecl = false;
3937330f729Sjoerg return resolved();
3947330f729Sjoerg }
3957330f729Sjoerg
updateParser::ConditionDeclarationOrInitStatementState3967330f729Sjoerg bool update(TPResult IsDecl) {
3977330f729Sjoerg switch (IsDecl) {
3987330f729Sjoerg case TPResult::True:
3997330f729Sjoerg markNotExpression();
4007330f729Sjoerg assert(resolved() && "can't continue after tentative parsing bails out");
4017330f729Sjoerg break;
4027330f729Sjoerg case TPResult::False:
4037330f729Sjoerg CanBeCondition = CanBeInitStatement = CanBeForRangeDecl = false;
4047330f729Sjoerg break;
4057330f729Sjoerg case TPResult::Ambiguous:
4067330f729Sjoerg break;
4077330f729Sjoerg case TPResult::Error:
4087330f729Sjoerg CanBeExpression = CanBeCondition = CanBeInitStatement =
4097330f729Sjoerg CanBeForRangeDecl = false;
4107330f729Sjoerg break;
4117330f729Sjoerg }
4127330f729Sjoerg return resolved();
4137330f729Sjoerg }
4147330f729Sjoerg
resultParser::ConditionDeclarationOrInitStatementState4157330f729Sjoerg ConditionOrInitStatement result() const {
4167330f729Sjoerg assert(CanBeExpression + CanBeCondition + CanBeInitStatement +
4177330f729Sjoerg CanBeForRangeDecl < 2 &&
4187330f729Sjoerg "result called but not yet resolved");
4197330f729Sjoerg if (CanBeExpression)
4207330f729Sjoerg return ConditionOrInitStatement::Expression;
4217330f729Sjoerg if (CanBeCondition)
4227330f729Sjoerg return ConditionOrInitStatement::ConditionDecl;
4237330f729Sjoerg if (CanBeInitStatement)
4247330f729Sjoerg return ConditionOrInitStatement::InitStmtDecl;
4257330f729Sjoerg if (CanBeForRangeDecl)
4267330f729Sjoerg return ConditionOrInitStatement::ForRangeDecl;
4277330f729Sjoerg return ConditionOrInitStatement::Error;
4287330f729Sjoerg }
4297330f729Sjoerg };
4307330f729Sjoerg
isEnumBase(bool AllowSemi)431*e038c9c4Sjoerg bool Parser::isEnumBase(bool AllowSemi) {
432*e038c9c4Sjoerg assert(Tok.is(tok::colon) && "should be looking at the ':'");
433*e038c9c4Sjoerg
434*e038c9c4Sjoerg RevertingTentativeParsingAction PA(*this);
435*e038c9c4Sjoerg // ':'
436*e038c9c4Sjoerg ConsumeToken();
437*e038c9c4Sjoerg
438*e038c9c4Sjoerg // type-specifier-seq
439*e038c9c4Sjoerg bool InvalidAsDeclSpec = false;
440*e038c9c4Sjoerg // FIXME: We could disallow non-type decl-specifiers here, but it makes no
441*e038c9c4Sjoerg // difference: those specifiers are ill-formed regardless of the
442*e038c9c4Sjoerg // interpretation.
443*e038c9c4Sjoerg TPResult R = isCXXDeclarationSpecifier(/*BracedCastResult*/ TPResult::True,
444*e038c9c4Sjoerg &InvalidAsDeclSpec);
445*e038c9c4Sjoerg if (R == TPResult::Ambiguous) {
446*e038c9c4Sjoerg // We either have a decl-specifier followed by '(' or an undeclared
447*e038c9c4Sjoerg // identifier.
448*e038c9c4Sjoerg if (TryConsumeDeclarationSpecifier() == TPResult::Error)
449*e038c9c4Sjoerg return true;
450*e038c9c4Sjoerg
451*e038c9c4Sjoerg // If we get to the end of the enum-base, we hit either a '{' or a ';'.
452*e038c9c4Sjoerg // Don't bother checking the enumerator-list.
453*e038c9c4Sjoerg if (Tok.is(tok::l_brace) || (AllowSemi && Tok.is(tok::semi)))
454*e038c9c4Sjoerg return true;
455*e038c9c4Sjoerg
456*e038c9c4Sjoerg // A second decl-specifier unambiguously indicatges an enum-base.
457*e038c9c4Sjoerg R = isCXXDeclarationSpecifier(TPResult::True, &InvalidAsDeclSpec);
458*e038c9c4Sjoerg }
459*e038c9c4Sjoerg
460*e038c9c4Sjoerg return R != TPResult::False;
461*e038c9c4Sjoerg }
462*e038c9c4Sjoerg
4637330f729Sjoerg /// Disambiguates between a declaration in a condition, a
4647330f729Sjoerg /// simple-declaration in an init-statement, and an expression for
4657330f729Sjoerg /// a condition of a if/switch statement.
4667330f729Sjoerg ///
4677330f729Sjoerg /// condition:
4687330f729Sjoerg /// expression
4697330f729Sjoerg /// type-specifier-seq declarator '=' assignment-expression
4707330f729Sjoerg /// [C++11] type-specifier-seq declarator '=' initializer-clause
4717330f729Sjoerg /// [C++11] type-specifier-seq declarator braced-init-list
4727330f729Sjoerg /// [GNU] type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
4737330f729Sjoerg /// '=' assignment-expression
4747330f729Sjoerg /// simple-declaration:
4757330f729Sjoerg /// decl-specifier-seq init-declarator-list[opt] ';'
4767330f729Sjoerg ///
4777330f729Sjoerg /// Note that, unlike isCXXSimpleDeclaration, we must disambiguate all the way
4787330f729Sjoerg /// to the ';' to disambiguate cases like 'int(x))' (an expression) from
4797330f729Sjoerg /// 'int(x);' (a simple-declaration in an init-statement).
4807330f729Sjoerg Parser::ConditionOrInitStatement
isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement,bool CanBeForRangeDecl)4817330f729Sjoerg Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement,
4827330f729Sjoerg bool CanBeForRangeDecl) {
4837330f729Sjoerg ConditionDeclarationOrInitStatementState State(*this, CanBeInitStatement,
4847330f729Sjoerg CanBeForRangeDecl);
4857330f729Sjoerg
4867330f729Sjoerg if (State.update(isCXXDeclarationSpecifier()))
4877330f729Sjoerg return State.result();
4887330f729Sjoerg
4897330f729Sjoerg // It might be a declaration; we need tentative parsing.
4907330f729Sjoerg RevertingTentativeParsingAction PA(*this);
4917330f729Sjoerg
4927330f729Sjoerg // FIXME: A tag definition unambiguously tells us this is an init-statement.
4937330f729Sjoerg if (State.update(TryConsumeDeclarationSpecifier()))
4947330f729Sjoerg return State.result();
4957330f729Sjoerg assert(Tok.is(tok::l_paren) && "Expected '('");
4967330f729Sjoerg
4977330f729Sjoerg while (true) {
4987330f729Sjoerg // Consume a declarator.
4997330f729Sjoerg if (State.update(TryParseDeclarator(false/*mayBeAbstract*/)))
5007330f729Sjoerg return State.result();
5017330f729Sjoerg
5027330f729Sjoerg // Attributes, asm label, or an initializer imply this is not an expression.
5037330f729Sjoerg // FIXME: Disambiguate properly after an = instead of assuming that it's a
5047330f729Sjoerg // valid declaration.
5057330f729Sjoerg if (Tok.isOneOf(tok::equal, tok::kw_asm, tok::kw___attribute) ||
5067330f729Sjoerg (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))) {
5077330f729Sjoerg State.markNotExpression();
5087330f729Sjoerg return State.result();
5097330f729Sjoerg }
5107330f729Sjoerg
5117330f729Sjoerg // A colon here identifies a for-range declaration.
5127330f729Sjoerg if (State.CanBeForRangeDecl && Tok.is(tok::colon))
5137330f729Sjoerg return ConditionOrInitStatement::ForRangeDecl;
5147330f729Sjoerg
5157330f729Sjoerg // At this point, it can't be a condition any more, because a condition
5167330f729Sjoerg // must have a brace-or-equal-initializer.
5177330f729Sjoerg if (State.markNotCondition())
5187330f729Sjoerg return State.result();
5197330f729Sjoerg
5207330f729Sjoerg // Likewise, it can't be a for-range declaration any more.
5217330f729Sjoerg if (State.markNotForRangeDecl())
5227330f729Sjoerg return State.result();
5237330f729Sjoerg
5247330f729Sjoerg // A parenthesized initializer could be part of an expression or a
5257330f729Sjoerg // simple-declaration.
5267330f729Sjoerg if (Tok.is(tok::l_paren)) {
5277330f729Sjoerg ConsumeParen();
5287330f729Sjoerg SkipUntil(tok::r_paren, StopAtSemi);
5297330f729Sjoerg }
5307330f729Sjoerg
5317330f729Sjoerg if (!TryConsumeToken(tok::comma))
5327330f729Sjoerg break;
5337330f729Sjoerg }
5347330f729Sjoerg
5357330f729Sjoerg // We reached the end. If it can now be some kind of decl, then it is.
5367330f729Sjoerg if (State.CanBeCondition && Tok.is(tok::r_paren))
5377330f729Sjoerg return ConditionOrInitStatement::ConditionDecl;
5387330f729Sjoerg else if (State.CanBeInitStatement && Tok.is(tok::semi))
5397330f729Sjoerg return ConditionOrInitStatement::InitStmtDecl;
5407330f729Sjoerg else
5417330f729Sjoerg return ConditionOrInitStatement::Expression;
5427330f729Sjoerg }
5437330f729Sjoerg
5447330f729Sjoerg /// Determine whether the next set of tokens contains a type-id.
5457330f729Sjoerg ///
5467330f729Sjoerg /// The context parameter states what context we're parsing right
5477330f729Sjoerg /// now, which affects how this routine copes with the token
5487330f729Sjoerg /// following the type-id. If the context is TypeIdInParens, we have
5497330f729Sjoerg /// already parsed the '(' and we will cease lookahead when we hit
5507330f729Sjoerg /// the corresponding ')'. If the context is
5517330f729Sjoerg /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
5527330f729Sjoerg /// before this template argument, and will cease lookahead when we
5537330f729Sjoerg /// hit a '>', '>>' (in C++0x), or ','; or, in C++0x, an ellipsis immediately
5547330f729Sjoerg /// preceding such. Returns true for a type-id and false for an expression.
5557330f729Sjoerg /// If during the disambiguation process a parsing error is encountered,
5567330f729Sjoerg /// the function returns true to let the declaration parsing code handle it.
5577330f729Sjoerg ///
5587330f729Sjoerg /// type-id:
5597330f729Sjoerg /// type-specifier-seq abstract-declarator[opt]
5607330f729Sjoerg ///
isCXXTypeId(TentativeCXXTypeIdContext Context,bool & isAmbiguous)5617330f729Sjoerg bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
5627330f729Sjoerg
5637330f729Sjoerg isAmbiguous = false;
5647330f729Sjoerg
5657330f729Sjoerg // C++ 8.2p2:
5667330f729Sjoerg // The ambiguity arising from the similarity between a function-style cast and
5677330f729Sjoerg // a type-id can occur in different contexts. The ambiguity appears as a
5687330f729Sjoerg // choice between a function-style cast expression and a declaration of a
5697330f729Sjoerg // type. The resolution is that any construct that could possibly be a type-id
5707330f729Sjoerg // in its syntactic context shall be considered a type-id.
5717330f729Sjoerg
5727330f729Sjoerg TPResult TPR = isCXXDeclarationSpecifier();
5737330f729Sjoerg if (TPR != TPResult::Ambiguous)
5747330f729Sjoerg return TPR != TPResult::False; // Returns true for TPResult::True or
5757330f729Sjoerg // TPResult::Error.
5767330f729Sjoerg
5777330f729Sjoerg // FIXME: Add statistics about the number of ambiguous statements encountered
5787330f729Sjoerg // and how they were resolved (number of declarations+number of expressions).
5797330f729Sjoerg
5807330f729Sjoerg // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
5817330f729Sjoerg // We need tentative parsing...
5827330f729Sjoerg
5837330f729Sjoerg RevertingTentativeParsingAction PA(*this);
5847330f729Sjoerg
5857330f729Sjoerg // type-specifier-seq
5867330f729Sjoerg TryConsumeDeclarationSpecifier();
5877330f729Sjoerg assert(Tok.is(tok::l_paren) && "Expected '('");
5887330f729Sjoerg
5897330f729Sjoerg // declarator
5907330f729Sjoerg TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
5917330f729Sjoerg
5927330f729Sjoerg // In case of an error, let the declaration parsing code handle it.
5937330f729Sjoerg if (TPR == TPResult::Error)
5947330f729Sjoerg TPR = TPResult::True;
5957330f729Sjoerg
5967330f729Sjoerg if (TPR == TPResult::Ambiguous) {
5977330f729Sjoerg // We are supposed to be inside parens, so if after the abstract declarator
5987330f729Sjoerg // we encounter a ')' this is a type-id, otherwise it's an expression.
5997330f729Sjoerg if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
6007330f729Sjoerg TPR = TPResult::True;
6017330f729Sjoerg isAmbiguous = true;
6027330f729Sjoerg
6037330f729Sjoerg // We are supposed to be inside a template argument, so if after
6047330f729Sjoerg // the abstract declarator we encounter a '>', '>>' (in C++0x), or
6057330f729Sjoerg // ','; or, in C++0x, an ellipsis immediately preceding such, this
6067330f729Sjoerg // is a type-id. Otherwise, it's an expression.
6077330f729Sjoerg } else if (Context == TypeIdAsTemplateArgument &&
6087330f729Sjoerg (Tok.isOneOf(tok::greater, tok::comma) ||
6097330f729Sjoerg (getLangOpts().CPlusPlus11 &&
6107330f729Sjoerg (Tok.isOneOf(tok::greatergreater,
6117330f729Sjoerg tok::greatergreatergreater) ||
6127330f729Sjoerg (Tok.is(tok::ellipsis) &&
6137330f729Sjoerg NextToken().isOneOf(tok::greater, tok::greatergreater,
6147330f729Sjoerg tok::greatergreatergreater,
6157330f729Sjoerg tok::comma)))))) {
6167330f729Sjoerg TPR = TPResult::True;
6177330f729Sjoerg isAmbiguous = true;
6187330f729Sjoerg
6197330f729Sjoerg } else
6207330f729Sjoerg TPR = TPResult::False;
6217330f729Sjoerg }
6227330f729Sjoerg
6237330f729Sjoerg assert(TPR == TPResult::True || TPR == TPResult::False);
6247330f729Sjoerg return TPR == TPResult::True;
6257330f729Sjoerg }
6267330f729Sjoerg
6277330f729Sjoerg /// Returns true if this is a C++11 attribute-specifier. Per
6287330f729Sjoerg /// C++11 [dcl.attr.grammar]p6, two consecutive left square bracket tokens
6297330f729Sjoerg /// always introduce an attribute. In Objective-C++11, this rule does not
6307330f729Sjoerg /// apply if either '[' begins a message-send.
6317330f729Sjoerg ///
6327330f729Sjoerg /// If Disambiguate is true, we try harder to determine whether a '[[' starts
6337330f729Sjoerg /// an attribute-specifier, and return CAK_InvalidAttributeSpecifier if not.
6347330f729Sjoerg ///
6357330f729Sjoerg /// If OuterMightBeMessageSend is true, we assume the outer '[' is either an
6367330f729Sjoerg /// Obj-C message send or the start of an attribute. Otherwise, we assume it
6377330f729Sjoerg /// is not an Obj-C message send.
6387330f729Sjoerg ///
6397330f729Sjoerg /// C++11 [dcl.attr.grammar]:
6407330f729Sjoerg ///
6417330f729Sjoerg /// attribute-specifier:
6427330f729Sjoerg /// '[' '[' attribute-list ']' ']'
6437330f729Sjoerg /// alignment-specifier
6447330f729Sjoerg ///
6457330f729Sjoerg /// attribute-list:
6467330f729Sjoerg /// attribute[opt]
6477330f729Sjoerg /// attribute-list ',' attribute[opt]
6487330f729Sjoerg /// attribute '...'
6497330f729Sjoerg /// attribute-list ',' attribute '...'
6507330f729Sjoerg ///
6517330f729Sjoerg /// attribute:
6527330f729Sjoerg /// attribute-token attribute-argument-clause[opt]
6537330f729Sjoerg ///
6547330f729Sjoerg /// attribute-token:
6557330f729Sjoerg /// identifier
6567330f729Sjoerg /// identifier '::' identifier
6577330f729Sjoerg ///
6587330f729Sjoerg /// attribute-argument-clause:
6597330f729Sjoerg /// '(' balanced-token-seq ')'
6607330f729Sjoerg Parser::CXX11AttributeKind
isCXX11AttributeSpecifier(bool Disambiguate,bool OuterMightBeMessageSend)6617330f729Sjoerg Parser::isCXX11AttributeSpecifier(bool Disambiguate,
6627330f729Sjoerg bool OuterMightBeMessageSend) {
6637330f729Sjoerg if (Tok.is(tok::kw_alignas))
6647330f729Sjoerg return CAK_AttributeSpecifier;
6657330f729Sjoerg
6667330f729Sjoerg if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
6677330f729Sjoerg return CAK_NotAttributeSpecifier;
6687330f729Sjoerg
6697330f729Sjoerg // No tentative parsing if we don't need to look for ']]' or a lambda.
6707330f729Sjoerg if (!Disambiguate && !getLangOpts().ObjC)
6717330f729Sjoerg return CAK_AttributeSpecifier;
6727330f729Sjoerg
6737330f729Sjoerg // '[[using ns: ...]]' is an attribute.
6747330f729Sjoerg if (GetLookAheadToken(2).is(tok::kw_using))
6757330f729Sjoerg return CAK_AttributeSpecifier;
6767330f729Sjoerg
6777330f729Sjoerg RevertingTentativeParsingAction PA(*this);
6787330f729Sjoerg
6797330f729Sjoerg // Opening brackets were checked for above.
6807330f729Sjoerg ConsumeBracket();
6817330f729Sjoerg
6827330f729Sjoerg if (!getLangOpts().ObjC) {
6837330f729Sjoerg ConsumeBracket();
6847330f729Sjoerg
6857330f729Sjoerg bool IsAttribute = SkipUntil(tok::r_square);
6867330f729Sjoerg IsAttribute &= Tok.is(tok::r_square);
6877330f729Sjoerg
6887330f729Sjoerg return IsAttribute ? CAK_AttributeSpecifier : CAK_InvalidAttributeSpecifier;
6897330f729Sjoerg }
6907330f729Sjoerg
6917330f729Sjoerg // In Obj-C++11, we need to distinguish four situations:
6927330f729Sjoerg // 1a) int x[[attr]]; C++11 attribute.
6937330f729Sjoerg // 1b) [[attr]]; C++11 statement attribute.
6947330f729Sjoerg // 2) int x[[obj](){ return 1; }()]; Lambda in array size/index.
6957330f729Sjoerg // 3a) int x[[obj get]]; Message send in array size/index.
6967330f729Sjoerg // 3b) [[Class alloc] init]; Message send in message send.
6977330f729Sjoerg // 4) [[obj]{ return self; }() doStuff]; Lambda in message send.
6987330f729Sjoerg // (1) is an attribute, (2) is ill-formed, and (3) and (4) are accepted.
6997330f729Sjoerg
7007330f729Sjoerg // Check to see if this is a lambda-expression.
7017330f729Sjoerg // FIXME: If this disambiguation is too slow, fold the tentative lambda parse
7027330f729Sjoerg // into the tentative attribute parse below.
7037330f729Sjoerg {
7047330f729Sjoerg RevertingTentativeParsingAction LambdaTPA(*this);
7057330f729Sjoerg LambdaIntroducer Intro;
7067330f729Sjoerg LambdaIntroducerTentativeParse Tentative;
7077330f729Sjoerg if (ParseLambdaIntroducer(Intro, &Tentative)) {
7087330f729Sjoerg // We hit a hard error after deciding this was not an attribute.
7097330f729Sjoerg // FIXME: Don't parse and annotate expressions when disambiguating
7107330f729Sjoerg // against an attribute.
7117330f729Sjoerg return CAK_NotAttributeSpecifier;
7127330f729Sjoerg }
7137330f729Sjoerg
7147330f729Sjoerg switch (Tentative) {
7157330f729Sjoerg case LambdaIntroducerTentativeParse::MessageSend:
7167330f729Sjoerg // Case 3: The inner construct is definitely a message send, so the
7177330f729Sjoerg // outer construct is definitely not an attribute.
7187330f729Sjoerg return CAK_NotAttributeSpecifier;
7197330f729Sjoerg
7207330f729Sjoerg case LambdaIntroducerTentativeParse::Success:
7217330f729Sjoerg case LambdaIntroducerTentativeParse::Incomplete:
7227330f729Sjoerg // This is a lambda-introducer or attribute-specifier.
7237330f729Sjoerg if (Tok.is(tok::r_square))
7247330f729Sjoerg // Case 1: C++11 attribute.
7257330f729Sjoerg return CAK_AttributeSpecifier;
7267330f729Sjoerg
7277330f729Sjoerg if (OuterMightBeMessageSend)
7287330f729Sjoerg // Case 4: Lambda in message send.
7297330f729Sjoerg return CAK_NotAttributeSpecifier;
7307330f729Sjoerg
7317330f729Sjoerg // Case 2: Lambda in array size / index.
7327330f729Sjoerg return CAK_InvalidAttributeSpecifier;
7337330f729Sjoerg
7347330f729Sjoerg case LambdaIntroducerTentativeParse::Invalid:
7357330f729Sjoerg // No idea what this is; we couldn't parse it as a lambda-introducer.
7367330f729Sjoerg // Might still be an attribute-specifier or a message send.
7377330f729Sjoerg break;
7387330f729Sjoerg }
7397330f729Sjoerg }
7407330f729Sjoerg
7417330f729Sjoerg ConsumeBracket();
7427330f729Sjoerg
7437330f729Sjoerg // If we don't have a lambda-introducer, then we have an attribute or a
7447330f729Sjoerg // message-send.
7457330f729Sjoerg bool IsAttribute = true;
7467330f729Sjoerg while (Tok.isNot(tok::r_square)) {
7477330f729Sjoerg if (Tok.is(tok::comma)) {
7487330f729Sjoerg // Case 1: Stray commas can only occur in attributes.
7497330f729Sjoerg return CAK_AttributeSpecifier;
7507330f729Sjoerg }
7517330f729Sjoerg
7527330f729Sjoerg // Parse the attribute-token, if present.
7537330f729Sjoerg // C++11 [dcl.attr.grammar]:
7547330f729Sjoerg // If a keyword or an alternative token that satisfies the syntactic
7557330f729Sjoerg // requirements of an identifier is contained in an attribute-token,
7567330f729Sjoerg // it is considered an identifier.
7577330f729Sjoerg SourceLocation Loc;
7587330f729Sjoerg if (!TryParseCXX11AttributeIdentifier(Loc)) {
7597330f729Sjoerg IsAttribute = false;
7607330f729Sjoerg break;
7617330f729Sjoerg }
7627330f729Sjoerg if (Tok.is(tok::coloncolon)) {
7637330f729Sjoerg ConsumeToken();
7647330f729Sjoerg if (!TryParseCXX11AttributeIdentifier(Loc)) {
7657330f729Sjoerg IsAttribute = false;
7667330f729Sjoerg break;
7677330f729Sjoerg }
7687330f729Sjoerg }
7697330f729Sjoerg
7707330f729Sjoerg // Parse the attribute-argument-clause, if present.
7717330f729Sjoerg if (Tok.is(tok::l_paren)) {
7727330f729Sjoerg ConsumeParen();
7737330f729Sjoerg if (!SkipUntil(tok::r_paren)) {
7747330f729Sjoerg IsAttribute = false;
7757330f729Sjoerg break;
7767330f729Sjoerg }
7777330f729Sjoerg }
7787330f729Sjoerg
7797330f729Sjoerg TryConsumeToken(tok::ellipsis);
7807330f729Sjoerg
7817330f729Sjoerg if (!TryConsumeToken(tok::comma))
7827330f729Sjoerg break;
7837330f729Sjoerg }
7847330f729Sjoerg
7857330f729Sjoerg // An attribute must end ']]'.
7867330f729Sjoerg if (IsAttribute) {
7877330f729Sjoerg if (Tok.is(tok::r_square)) {
7887330f729Sjoerg ConsumeBracket();
7897330f729Sjoerg IsAttribute = Tok.is(tok::r_square);
7907330f729Sjoerg } else {
7917330f729Sjoerg IsAttribute = false;
7927330f729Sjoerg }
7937330f729Sjoerg }
7947330f729Sjoerg
7957330f729Sjoerg if (IsAttribute)
7967330f729Sjoerg // Case 1: C++11 statement attribute.
7977330f729Sjoerg return CAK_AttributeSpecifier;
7987330f729Sjoerg
7997330f729Sjoerg // Case 3: Message send.
8007330f729Sjoerg return CAK_NotAttributeSpecifier;
8017330f729Sjoerg }
8027330f729Sjoerg
TrySkipAttributes()803*e038c9c4Sjoerg bool Parser::TrySkipAttributes() {
804*e038c9c4Sjoerg while (Tok.isOneOf(tok::l_square, tok::kw___attribute, tok::kw___declspec,
805*e038c9c4Sjoerg tok::kw_alignas)) {
806*e038c9c4Sjoerg if (Tok.is(tok::l_square)) {
807*e038c9c4Sjoerg ConsumeBracket();
808*e038c9c4Sjoerg if (Tok.isNot(tok::l_square))
809*e038c9c4Sjoerg return false;
810*e038c9c4Sjoerg ConsumeBracket();
811*e038c9c4Sjoerg if (!SkipUntil(tok::r_square) || Tok.isNot(tok::r_square))
812*e038c9c4Sjoerg return false;
813*e038c9c4Sjoerg // Note that explicitly checking for `[[` and `]]` allows to fail as
814*e038c9c4Sjoerg // expected in the case of the Objective-C message send syntax.
815*e038c9c4Sjoerg ConsumeBracket();
816*e038c9c4Sjoerg } else {
817*e038c9c4Sjoerg ConsumeToken();
818*e038c9c4Sjoerg if (Tok.isNot(tok::l_paren))
819*e038c9c4Sjoerg return false;
820*e038c9c4Sjoerg ConsumeParen();
821*e038c9c4Sjoerg if (!SkipUntil(tok::r_paren))
822*e038c9c4Sjoerg return false;
823*e038c9c4Sjoerg }
824*e038c9c4Sjoerg }
825*e038c9c4Sjoerg
826*e038c9c4Sjoerg return true;
827*e038c9c4Sjoerg }
828*e038c9c4Sjoerg
TryParsePtrOperatorSeq()8297330f729Sjoerg Parser::TPResult Parser::TryParsePtrOperatorSeq() {
8307330f729Sjoerg while (true) {
831*e038c9c4Sjoerg if (TryAnnotateOptionalCXXScopeToken(true))
8327330f729Sjoerg return TPResult::Error;
8337330f729Sjoerg
8347330f729Sjoerg if (Tok.isOneOf(tok::star, tok::amp, tok::caret, tok::ampamp) ||
8357330f729Sjoerg (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
8367330f729Sjoerg // ptr-operator
8377330f729Sjoerg ConsumeAnyToken();
838*e038c9c4Sjoerg
839*e038c9c4Sjoerg // Skip attributes.
840*e038c9c4Sjoerg if (!TrySkipAttributes())
841*e038c9c4Sjoerg return TPResult::Error;
842*e038c9c4Sjoerg
8437330f729Sjoerg while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict,
8447330f729Sjoerg tok::kw__Nonnull, tok::kw__Nullable,
845*e038c9c4Sjoerg tok::kw__Nullable_result, tok::kw__Null_unspecified,
846*e038c9c4Sjoerg tok::kw__Atomic))
8477330f729Sjoerg ConsumeToken();
8487330f729Sjoerg } else {
8497330f729Sjoerg return TPResult::True;
8507330f729Sjoerg }
8517330f729Sjoerg }
8527330f729Sjoerg }
8537330f729Sjoerg
8547330f729Sjoerg /// operator-function-id:
8557330f729Sjoerg /// 'operator' operator
8567330f729Sjoerg ///
8577330f729Sjoerg /// operator: one of
8587330f729Sjoerg /// new delete new[] delete[] + - * / % ^ [...]
8597330f729Sjoerg ///
8607330f729Sjoerg /// conversion-function-id:
8617330f729Sjoerg /// 'operator' conversion-type-id
8627330f729Sjoerg ///
8637330f729Sjoerg /// conversion-type-id:
8647330f729Sjoerg /// type-specifier-seq conversion-declarator[opt]
8657330f729Sjoerg ///
8667330f729Sjoerg /// conversion-declarator:
8677330f729Sjoerg /// ptr-operator conversion-declarator[opt]
8687330f729Sjoerg ///
8697330f729Sjoerg /// literal-operator-id:
8707330f729Sjoerg /// 'operator' string-literal identifier
8717330f729Sjoerg /// 'operator' user-defined-string-literal
TryParseOperatorId()8727330f729Sjoerg Parser::TPResult Parser::TryParseOperatorId() {
8737330f729Sjoerg assert(Tok.is(tok::kw_operator));
8747330f729Sjoerg ConsumeToken();
8757330f729Sjoerg
8767330f729Sjoerg // Maybe this is an operator-function-id.
8777330f729Sjoerg switch (Tok.getKind()) {
8787330f729Sjoerg case tok::kw_new: case tok::kw_delete:
8797330f729Sjoerg ConsumeToken();
8807330f729Sjoerg if (Tok.is(tok::l_square) && NextToken().is(tok::r_square)) {
8817330f729Sjoerg ConsumeBracket();
8827330f729Sjoerg ConsumeBracket();
8837330f729Sjoerg }
8847330f729Sjoerg return TPResult::True;
8857330f729Sjoerg
8867330f729Sjoerg #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemOnly) \
8877330f729Sjoerg case tok::Token:
8887330f729Sjoerg #define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemOnly)
8897330f729Sjoerg #include "clang/Basic/OperatorKinds.def"
8907330f729Sjoerg ConsumeToken();
8917330f729Sjoerg return TPResult::True;
8927330f729Sjoerg
8937330f729Sjoerg case tok::l_square:
8947330f729Sjoerg if (NextToken().is(tok::r_square)) {
8957330f729Sjoerg ConsumeBracket();
8967330f729Sjoerg ConsumeBracket();
8977330f729Sjoerg return TPResult::True;
8987330f729Sjoerg }
8997330f729Sjoerg break;
9007330f729Sjoerg
9017330f729Sjoerg case tok::l_paren:
9027330f729Sjoerg if (NextToken().is(tok::r_paren)) {
9037330f729Sjoerg ConsumeParen();
9047330f729Sjoerg ConsumeParen();
9057330f729Sjoerg return TPResult::True;
9067330f729Sjoerg }
9077330f729Sjoerg break;
9087330f729Sjoerg
9097330f729Sjoerg default:
9107330f729Sjoerg break;
9117330f729Sjoerg }
9127330f729Sjoerg
9137330f729Sjoerg // Maybe this is a literal-operator-id.
9147330f729Sjoerg if (getLangOpts().CPlusPlus11 && isTokenStringLiteral()) {
9157330f729Sjoerg bool FoundUDSuffix = false;
9167330f729Sjoerg do {
9177330f729Sjoerg FoundUDSuffix |= Tok.hasUDSuffix();
9187330f729Sjoerg ConsumeStringToken();
9197330f729Sjoerg } while (isTokenStringLiteral());
9207330f729Sjoerg
9217330f729Sjoerg if (!FoundUDSuffix) {
9227330f729Sjoerg if (Tok.is(tok::identifier))
9237330f729Sjoerg ConsumeToken();
9247330f729Sjoerg else
9257330f729Sjoerg return TPResult::Error;
9267330f729Sjoerg }
9277330f729Sjoerg return TPResult::True;
9287330f729Sjoerg }
9297330f729Sjoerg
9307330f729Sjoerg // Maybe this is a conversion-function-id.
9317330f729Sjoerg bool AnyDeclSpecifiers = false;
9327330f729Sjoerg while (true) {
9337330f729Sjoerg TPResult TPR = isCXXDeclarationSpecifier();
9347330f729Sjoerg if (TPR == TPResult::Error)
9357330f729Sjoerg return TPR;
9367330f729Sjoerg if (TPR == TPResult::False) {
9377330f729Sjoerg if (!AnyDeclSpecifiers)
9387330f729Sjoerg return TPResult::Error;
9397330f729Sjoerg break;
9407330f729Sjoerg }
9417330f729Sjoerg if (TryConsumeDeclarationSpecifier() == TPResult::Error)
9427330f729Sjoerg return TPResult::Error;
9437330f729Sjoerg AnyDeclSpecifiers = true;
9447330f729Sjoerg }
9457330f729Sjoerg return TryParsePtrOperatorSeq();
9467330f729Sjoerg }
9477330f729Sjoerg
9487330f729Sjoerg /// declarator:
9497330f729Sjoerg /// direct-declarator
9507330f729Sjoerg /// ptr-operator declarator
9517330f729Sjoerg ///
9527330f729Sjoerg /// direct-declarator:
9537330f729Sjoerg /// declarator-id
9547330f729Sjoerg /// direct-declarator '(' parameter-declaration-clause ')'
9557330f729Sjoerg /// cv-qualifier-seq[opt] exception-specification[opt]
9567330f729Sjoerg /// direct-declarator '[' constant-expression[opt] ']'
9577330f729Sjoerg /// '(' declarator ')'
9587330f729Sjoerg /// [GNU] '(' attributes declarator ')'
9597330f729Sjoerg ///
9607330f729Sjoerg /// abstract-declarator:
9617330f729Sjoerg /// ptr-operator abstract-declarator[opt]
9627330f729Sjoerg /// direct-abstract-declarator
9637330f729Sjoerg ///
9647330f729Sjoerg /// direct-abstract-declarator:
9657330f729Sjoerg /// direct-abstract-declarator[opt]
9667330f729Sjoerg /// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
9677330f729Sjoerg /// exception-specification[opt]
9687330f729Sjoerg /// direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
9697330f729Sjoerg /// '(' abstract-declarator ')'
9707330f729Sjoerg /// [C++0x] ...
9717330f729Sjoerg ///
9727330f729Sjoerg /// ptr-operator:
9737330f729Sjoerg /// '*' cv-qualifier-seq[opt]
9747330f729Sjoerg /// '&'
9757330f729Sjoerg /// [C++0x] '&&' [TODO]
9767330f729Sjoerg /// '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
9777330f729Sjoerg ///
9787330f729Sjoerg /// cv-qualifier-seq:
9797330f729Sjoerg /// cv-qualifier cv-qualifier-seq[opt]
9807330f729Sjoerg ///
9817330f729Sjoerg /// cv-qualifier:
9827330f729Sjoerg /// 'const'
9837330f729Sjoerg /// 'volatile'
9847330f729Sjoerg ///
9857330f729Sjoerg /// declarator-id:
9867330f729Sjoerg /// '...'[opt] id-expression
9877330f729Sjoerg ///
9887330f729Sjoerg /// id-expression:
9897330f729Sjoerg /// unqualified-id
9907330f729Sjoerg /// qualified-id [TODO]
9917330f729Sjoerg ///
9927330f729Sjoerg /// unqualified-id:
9937330f729Sjoerg /// identifier
9947330f729Sjoerg /// operator-function-id
9957330f729Sjoerg /// conversion-function-id
9967330f729Sjoerg /// literal-operator-id
9977330f729Sjoerg /// '~' class-name [TODO]
9987330f729Sjoerg /// '~' decltype-specifier [TODO]
9997330f729Sjoerg /// template-id [TODO]
10007330f729Sjoerg ///
TryParseDeclarator(bool mayBeAbstract,bool mayHaveIdentifier,bool mayHaveDirectInit)10017330f729Sjoerg Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
10027330f729Sjoerg bool mayHaveIdentifier,
10037330f729Sjoerg bool mayHaveDirectInit) {
10047330f729Sjoerg // declarator:
10057330f729Sjoerg // direct-declarator
10067330f729Sjoerg // ptr-operator declarator
10077330f729Sjoerg if (TryParsePtrOperatorSeq() == TPResult::Error)
10087330f729Sjoerg return TPResult::Error;
10097330f729Sjoerg
10107330f729Sjoerg // direct-declarator:
10117330f729Sjoerg // direct-abstract-declarator:
10127330f729Sjoerg if (Tok.is(tok::ellipsis))
10137330f729Sjoerg ConsumeToken();
10147330f729Sjoerg
10157330f729Sjoerg if ((Tok.isOneOf(tok::identifier, tok::kw_operator) ||
10167330f729Sjoerg (Tok.is(tok::annot_cxxscope) && (NextToken().is(tok::identifier) ||
10177330f729Sjoerg NextToken().is(tok::kw_operator)))) &&
10187330f729Sjoerg mayHaveIdentifier) {
10197330f729Sjoerg // declarator-id
1020*e038c9c4Sjoerg if (Tok.is(tok::annot_cxxscope)) {
1021*e038c9c4Sjoerg CXXScopeSpec SS;
1022*e038c9c4Sjoerg Actions.RestoreNestedNameSpecifierAnnotation(
1023*e038c9c4Sjoerg Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS);
1024*e038c9c4Sjoerg if (SS.isInvalid())
1025*e038c9c4Sjoerg return TPResult::Error;
10267330f729Sjoerg ConsumeAnnotationToken();
1027*e038c9c4Sjoerg } else if (Tok.is(tok::identifier)) {
10287330f729Sjoerg TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo());
1029*e038c9c4Sjoerg }
10307330f729Sjoerg if (Tok.is(tok::kw_operator)) {
10317330f729Sjoerg if (TryParseOperatorId() == TPResult::Error)
10327330f729Sjoerg return TPResult::Error;
10337330f729Sjoerg } else
10347330f729Sjoerg ConsumeToken();
10357330f729Sjoerg } else if (Tok.is(tok::l_paren)) {
10367330f729Sjoerg ConsumeParen();
10377330f729Sjoerg if (mayBeAbstract &&
10387330f729Sjoerg (Tok.is(tok::r_paren) || // 'int()' is a function.
10397330f729Sjoerg // 'int(...)' is a function.
10407330f729Sjoerg (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren)) ||
10417330f729Sjoerg isDeclarationSpecifier())) { // 'int(int)' is a function.
10427330f729Sjoerg // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
10437330f729Sjoerg // exception-specification[opt]
10447330f729Sjoerg TPResult TPR = TryParseFunctionDeclarator();
10457330f729Sjoerg if (TPR != TPResult::Ambiguous)
10467330f729Sjoerg return TPR;
10477330f729Sjoerg } else {
10487330f729Sjoerg // '(' declarator ')'
10497330f729Sjoerg // '(' attributes declarator ')'
10507330f729Sjoerg // '(' abstract-declarator ')'
10517330f729Sjoerg if (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec, tok::kw___cdecl,
10527330f729Sjoerg tok::kw___stdcall, tok::kw___fastcall, tok::kw___thiscall,
10537330f729Sjoerg tok::kw___regcall, tok::kw___vectorcall))
10547330f729Sjoerg return TPResult::True; // attributes indicate declaration
10557330f729Sjoerg TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
10567330f729Sjoerg if (TPR != TPResult::Ambiguous)
10577330f729Sjoerg return TPR;
10587330f729Sjoerg if (Tok.isNot(tok::r_paren))
10597330f729Sjoerg return TPResult::False;
10607330f729Sjoerg ConsumeParen();
10617330f729Sjoerg }
10627330f729Sjoerg } else if (!mayBeAbstract) {
10637330f729Sjoerg return TPResult::False;
10647330f729Sjoerg }
10657330f729Sjoerg
10667330f729Sjoerg if (mayHaveDirectInit)
10677330f729Sjoerg return TPResult::Ambiguous;
10687330f729Sjoerg
10697330f729Sjoerg while (1) {
10707330f729Sjoerg TPResult TPR(TPResult::Ambiguous);
10717330f729Sjoerg
10727330f729Sjoerg if (Tok.is(tok::l_paren)) {
10737330f729Sjoerg // Check whether we have a function declarator or a possible ctor-style
10747330f729Sjoerg // initializer that follows the declarator. Note that ctor-style
10757330f729Sjoerg // initializers are not possible in contexts where abstract declarators
10767330f729Sjoerg // are allowed.
10777330f729Sjoerg if (!mayBeAbstract && !isCXXFunctionDeclarator())
10787330f729Sjoerg break;
10797330f729Sjoerg
10807330f729Sjoerg // direct-declarator '(' parameter-declaration-clause ')'
10817330f729Sjoerg // cv-qualifier-seq[opt] exception-specification[opt]
10827330f729Sjoerg ConsumeParen();
10837330f729Sjoerg TPR = TryParseFunctionDeclarator();
10847330f729Sjoerg } else if (Tok.is(tok::l_square)) {
10857330f729Sjoerg // direct-declarator '[' constant-expression[opt] ']'
10867330f729Sjoerg // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
10877330f729Sjoerg TPR = TryParseBracketDeclarator();
1088*e038c9c4Sjoerg } else if (Tok.is(tok::kw_requires)) {
1089*e038c9c4Sjoerg // declarator requires-clause
1090*e038c9c4Sjoerg // A requires clause indicates a function declaration.
1091*e038c9c4Sjoerg TPR = TPResult::True;
10927330f729Sjoerg } else {
10937330f729Sjoerg break;
10947330f729Sjoerg }
10957330f729Sjoerg
10967330f729Sjoerg if (TPR != TPResult::Ambiguous)
10977330f729Sjoerg return TPR;
10987330f729Sjoerg }
10997330f729Sjoerg
11007330f729Sjoerg return TPResult::Ambiguous;
11017330f729Sjoerg }
11027330f729Sjoerg
isTentativelyDeclared(IdentifierInfo * II)11037330f729Sjoerg bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
11047330f729Sjoerg return std::find(TentativelyDeclaredIdentifiers.begin(),
11057330f729Sjoerg TentativelyDeclaredIdentifiers.end(), II)
11067330f729Sjoerg != TentativelyDeclaredIdentifiers.end();
11077330f729Sjoerg }
11087330f729Sjoerg
11097330f729Sjoerg namespace {
11107330f729Sjoerg class TentativeParseCCC final : public CorrectionCandidateCallback {
11117330f729Sjoerg public:
TentativeParseCCC(const Token & Next)11127330f729Sjoerg TentativeParseCCC(const Token &Next) {
11137330f729Sjoerg WantRemainingKeywords = false;
1114*e038c9c4Sjoerg WantTypeSpecifiers =
1115*e038c9c4Sjoerg Next.isOneOf(tok::l_paren, tok::r_paren, tok::greater, tok::l_brace,
1116*e038c9c4Sjoerg tok::identifier, tok::comma);
11177330f729Sjoerg }
11187330f729Sjoerg
ValidateCandidate(const TypoCorrection & Candidate)11197330f729Sjoerg bool ValidateCandidate(const TypoCorrection &Candidate) override {
11207330f729Sjoerg // Reject any candidate that only resolves to instance members since they
11217330f729Sjoerg // aren't viable as standalone identifiers instead of member references.
11227330f729Sjoerg if (Candidate.isResolved() && !Candidate.isKeyword() &&
11237330f729Sjoerg llvm::all_of(Candidate,
11247330f729Sjoerg [](NamedDecl *ND) { return ND->isCXXInstanceMember(); }))
11257330f729Sjoerg return false;
11267330f729Sjoerg
11277330f729Sjoerg return CorrectionCandidateCallback::ValidateCandidate(Candidate);
11287330f729Sjoerg }
11297330f729Sjoerg
clone()11307330f729Sjoerg std::unique_ptr<CorrectionCandidateCallback> clone() override {
11317330f729Sjoerg return std::make_unique<TentativeParseCCC>(*this);
11327330f729Sjoerg }
11337330f729Sjoerg };
11347330f729Sjoerg }
11357330f729Sjoerg /// isCXXDeclarationSpecifier - Returns TPResult::True if it is a declaration
11367330f729Sjoerg /// specifier, TPResult::False if it is not, TPResult::Ambiguous if it could
11377330f729Sjoerg /// be either a decl-specifier or a function-style cast, and TPResult::Error
11387330f729Sjoerg /// if a parsing error was found and reported.
11397330f729Sjoerg ///
11407330f729Sjoerg /// If InvalidAsDeclSpec is not null, some cases that would be ill-formed as
11417330f729Sjoerg /// declaration specifiers but possibly valid as some other kind of construct
11427330f729Sjoerg /// return TPResult::Ambiguous instead of TPResult::False. When this happens,
11437330f729Sjoerg /// the intent is to keep trying to disambiguate, on the basis that we might
11447330f729Sjoerg /// find a better reason to treat this construct as a declaration later on.
11457330f729Sjoerg /// When this happens and the name could possibly be valid in some other
11467330f729Sjoerg /// syntactic context, *InvalidAsDeclSpec is set to 'true'. The current cases
11477330f729Sjoerg /// that trigger this are:
11487330f729Sjoerg ///
11497330f729Sjoerg /// * When parsing X::Y (with no 'typename') where X is dependent
11507330f729Sjoerg /// * When parsing X<Y> where X is undeclared
11517330f729Sjoerg ///
11527330f729Sjoerg /// decl-specifier:
11537330f729Sjoerg /// storage-class-specifier
11547330f729Sjoerg /// type-specifier
11557330f729Sjoerg /// function-specifier
11567330f729Sjoerg /// 'friend'
11577330f729Sjoerg /// 'typedef'
11587330f729Sjoerg /// [C++11] 'constexpr'
11597330f729Sjoerg /// [C++20] 'consteval'
11607330f729Sjoerg /// [GNU] attributes declaration-specifiers[opt]
11617330f729Sjoerg ///
11627330f729Sjoerg /// storage-class-specifier:
11637330f729Sjoerg /// 'register'
11647330f729Sjoerg /// 'static'
11657330f729Sjoerg /// 'extern'
11667330f729Sjoerg /// 'mutable'
11677330f729Sjoerg /// 'auto'
11687330f729Sjoerg /// [GNU] '__thread'
11697330f729Sjoerg /// [C++11] 'thread_local'
11707330f729Sjoerg /// [C11] '_Thread_local'
11717330f729Sjoerg ///
11727330f729Sjoerg /// function-specifier:
11737330f729Sjoerg /// 'inline'
11747330f729Sjoerg /// 'virtual'
11757330f729Sjoerg /// 'explicit'
11767330f729Sjoerg ///
11777330f729Sjoerg /// typedef-name:
11787330f729Sjoerg /// identifier
11797330f729Sjoerg ///
11807330f729Sjoerg /// type-specifier:
11817330f729Sjoerg /// simple-type-specifier
11827330f729Sjoerg /// class-specifier
11837330f729Sjoerg /// enum-specifier
11847330f729Sjoerg /// elaborated-type-specifier
11857330f729Sjoerg /// typename-specifier
11867330f729Sjoerg /// cv-qualifier
11877330f729Sjoerg ///
11887330f729Sjoerg /// simple-type-specifier:
11897330f729Sjoerg /// '::'[opt] nested-name-specifier[opt] type-name
11907330f729Sjoerg /// '::'[opt] nested-name-specifier 'template'
11917330f729Sjoerg /// simple-template-id [TODO]
11927330f729Sjoerg /// 'char'
11937330f729Sjoerg /// 'wchar_t'
11947330f729Sjoerg /// 'bool'
11957330f729Sjoerg /// 'short'
11967330f729Sjoerg /// 'int'
11977330f729Sjoerg /// 'long'
11987330f729Sjoerg /// 'signed'
11997330f729Sjoerg /// 'unsigned'
12007330f729Sjoerg /// 'float'
12017330f729Sjoerg /// 'double'
12027330f729Sjoerg /// 'void'
12037330f729Sjoerg /// [GNU] typeof-specifier
12047330f729Sjoerg /// [GNU] '_Complex'
12057330f729Sjoerg /// [C++11] 'auto'
12067330f729Sjoerg /// [GNU] '__auto_type'
12077330f729Sjoerg /// [C++11] 'decltype' ( expression )
12087330f729Sjoerg /// [C++1y] 'decltype' ( 'auto' )
12097330f729Sjoerg ///
12107330f729Sjoerg /// type-name:
12117330f729Sjoerg /// class-name
12127330f729Sjoerg /// enum-name
12137330f729Sjoerg /// typedef-name
12147330f729Sjoerg ///
12157330f729Sjoerg /// elaborated-type-specifier:
12167330f729Sjoerg /// class-key '::'[opt] nested-name-specifier[opt] identifier
12177330f729Sjoerg /// class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]
12187330f729Sjoerg /// simple-template-id
12197330f729Sjoerg /// 'enum' '::'[opt] nested-name-specifier[opt] identifier
12207330f729Sjoerg ///
12217330f729Sjoerg /// enum-name:
12227330f729Sjoerg /// identifier
12237330f729Sjoerg ///
12247330f729Sjoerg /// enum-specifier:
12257330f729Sjoerg /// 'enum' identifier[opt] '{' enumerator-list[opt] '}'
12267330f729Sjoerg /// 'enum' identifier[opt] '{' enumerator-list ',' '}'
12277330f729Sjoerg ///
12287330f729Sjoerg /// class-specifier:
12297330f729Sjoerg /// class-head '{' member-specification[opt] '}'
12307330f729Sjoerg ///
12317330f729Sjoerg /// class-head:
12327330f729Sjoerg /// class-key identifier[opt] base-clause[opt]
12337330f729Sjoerg /// class-key nested-name-specifier identifier base-clause[opt]
12347330f729Sjoerg /// class-key nested-name-specifier[opt] simple-template-id
12357330f729Sjoerg /// base-clause[opt]
12367330f729Sjoerg ///
12377330f729Sjoerg /// class-key:
12387330f729Sjoerg /// 'class'
12397330f729Sjoerg /// 'struct'
12407330f729Sjoerg /// 'union'
12417330f729Sjoerg ///
12427330f729Sjoerg /// cv-qualifier:
12437330f729Sjoerg /// 'const'
12447330f729Sjoerg /// 'volatile'
12457330f729Sjoerg /// [GNU] restrict
12467330f729Sjoerg ///
12477330f729Sjoerg Parser::TPResult
isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,bool * InvalidAsDeclSpec)12487330f729Sjoerg Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
12497330f729Sjoerg bool *InvalidAsDeclSpec) {
1250*e038c9c4Sjoerg auto IsPlaceholderSpecifier = [&] (TemplateIdAnnotation *TemplateId,
1251*e038c9c4Sjoerg int Lookahead) {
1252*e038c9c4Sjoerg // We have a placeholder-constraint (we check for 'auto' or 'decltype' to
1253*e038c9c4Sjoerg // distinguish 'C<int>;' from 'C<int> auto c = 1;')
1254*e038c9c4Sjoerg return TemplateId->Kind == TNK_Concept_template &&
1255*e038c9c4Sjoerg GetLookAheadToken(Lookahead + 1).isOneOf(tok::kw_auto, tok::kw_decltype,
1256*e038c9c4Sjoerg // If we have an identifier here, the user probably forgot the
1257*e038c9c4Sjoerg // 'auto' in the placeholder constraint, e.g. 'C<int> x = 2;'
1258*e038c9c4Sjoerg // This will be diagnosed nicely later, so disambiguate as a
1259*e038c9c4Sjoerg // declaration.
1260*e038c9c4Sjoerg tok::identifier);
1261*e038c9c4Sjoerg };
12627330f729Sjoerg switch (Tok.getKind()) {
12637330f729Sjoerg case tok::identifier: {
12647330f729Sjoerg // Check for need to substitute AltiVec __vector keyword
12657330f729Sjoerg // for "vector" identifier.
12667330f729Sjoerg if (TryAltiVecVectorToken())
12677330f729Sjoerg return TPResult::True;
12687330f729Sjoerg
12697330f729Sjoerg const Token &Next = NextToken();
12707330f729Sjoerg // In 'foo bar', 'foo' is always a type name outside of Objective-C.
12717330f729Sjoerg if (!getLangOpts().ObjC && Next.is(tok::identifier))
12727330f729Sjoerg return TPResult::True;
12737330f729Sjoerg
12747330f729Sjoerg if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {
12757330f729Sjoerg // Determine whether this is a valid expression. If not, we will hit
12767330f729Sjoerg // a parse error one way or another. In that case, tell the caller that
12777330f729Sjoerg // this is ambiguous. Typo-correct to type and expression keywords and
12787330f729Sjoerg // to types and identifiers, in order to try to recover from errors.
12797330f729Sjoerg TentativeParseCCC CCC(Next);
12807330f729Sjoerg switch (TryAnnotateName(&CCC)) {
12817330f729Sjoerg case ANK_Error:
12827330f729Sjoerg return TPResult::Error;
12837330f729Sjoerg case ANK_TentativeDecl:
12847330f729Sjoerg return TPResult::False;
12857330f729Sjoerg case ANK_TemplateName:
12867330f729Sjoerg // In C++17, this could be a type template for class template argument
12877330f729Sjoerg // deduction. Try to form a type annotation for it. If we're in a
12887330f729Sjoerg // template template argument, we'll undo this when checking the
12897330f729Sjoerg // validity of the argument.
12907330f729Sjoerg if (getLangOpts().CPlusPlus17) {
12917330f729Sjoerg if (TryAnnotateTypeOrScopeToken())
12927330f729Sjoerg return TPResult::Error;
12937330f729Sjoerg if (Tok.isNot(tok::identifier))
12947330f729Sjoerg break;
12957330f729Sjoerg }
12967330f729Sjoerg
12977330f729Sjoerg // A bare type template-name which can't be a template template
12987330f729Sjoerg // argument is an error, and was probably intended to be a type.
12997330f729Sjoerg return GreaterThanIsOperator ? TPResult::True : TPResult::False;
13007330f729Sjoerg case ANK_Unresolved:
13017330f729Sjoerg return InvalidAsDeclSpec ? TPResult::Ambiguous : TPResult::False;
13027330f729Sjoerg case ANK_Success:
13037330f729Sjoerg break;
13047330f729Sjoerg }
13057330f729Sjoerg assert(Tok.isNot(tok::identifier) &&
13067330f729Sjoerg "TryAnnotateName succeeded without producing an annotation");
13077330f729Sjoerg } else {
13087330f729Sjoerg // This might possibly be a type with a dependent scope specifier and
13097330f729Sjoerg // a missing 'typename' keyword. Don't use TryAnnotateName in this case,
13107330f729Sjoerg // since it will annotate as a primary expression, and we want to use the
13117330f729Sjoerg // "missing 'typename'" logic.
13127330f729Sjoerg if (TryAnnotateTypeOrScopeToken())
13137330f729Sjoerg return TPResult::Error;
13147330f729Sjoerg // If annotation failed, assume it's a non-type.
13157330f729Sjoerg // FIXME: If this happens due to an undeclared identifier, treat it as
13167330f729Sjoerg // ambiguous.
13177330f729Sjoerg if (Tok.is(tok::identifier))
13187330f729Sjoerg return TPResult::False;
13197330f729Sjoerg }
13207330f729Sjoerg
13217330f729Sjoerg // We annotated this token as something. Recurse to handle whatever we got.
13227330f729Sjoerg return isCXXDeclarationSpecifier(BracedCastResult, InvalidAsDeclSpec);
13237330f729Sjoerg }
13247330f729Sjoerg
13257330f729Sjoerg case tok::kw_typename: // typename T::type
13267330f729Sjoerg // Annotate typenames and C++ scope specifiers. If we get one, just
13277330f729Sjoerg // recurse to handle whatever we get.
13287330f729Sjoerg if (TryAnnotateTypeOrScopeToken())
13297330f729Sjoerg return TPResult::Error;
13307330f729Sjoerg return isCXXDeclarationSpecifier(BracedCastResult, InvalidAsDeclSpec);
13317330f729Sjoerg
13327330f729Sjoerg case tok::coloncolon: { // ::foo::bar
13337330f729Sjoerg const Token &Next = NextToken();
13347330f729Sjoerg if (Next.isOneOf(tok::kw_new, // ::new
13357330f729Sjoerg tok::kw_delete)) // ::delete
13367330f729Sjoerg return TPResult::False;
13377330f729Sjoerg LLVM_FALLTHROUGH;
13387330f729Sjoerg }
13397330f729Sjoerg case tok::kw___super:
13407330f729Sjoerg case tok::kw_decltype:
13417330f729Sjoerg // Annotate typenames and C++ scope specifiers. If we get one, just
13427330f729Sjoerg // recurse to handle whatever we get.
13437330f729Sjoerg if (TryAnnotateTypeOrScopeToken())
13447330f729Sjoerg return TPResult::Error;
13457330f729Sjoerg return isCXXDeclarationSpecifier(BracedCastResult, InvalidAsDeclSpec);
13467330f729Sjoerg
13477330f729Sjoerg // decl-specifier:
13487330f729Sjoerg // storage-class-specifier
13497330f729Sjoerg // type-specifier
13507330f729Sjoerg // function-specifier
13517330f729Sjoerg // 'friend'
13527330f729Sjoerg // 'typedef'
13537330f729Sjoerg // 'constexpr'
13547330f729Sjoerg case tok::kw_friend:
13557330f729Sjoerg case tok::kw_typedef:
13567330f729Sjoerg case tok::kw_constexpr:
13577330f729Sjoerg case tok::kw_consteval:
13587330f729Sjoerg case tok::kw_constinit:
13597330f729Sjoerg // storage-class-specifier
13607330f729Sjoerg case tok::kw_register:
13617330f729Sjoerg case tok::kw_static:
13627330f729Sjoerg case tok::kw_extern:
13637330f729Sjoerg case tok::kw_mutable:
13647330f729Sjoerg case tok::kw_auto:
13657330f729Sjoerg case tok::kw___thread:
13667330f729Sjoerg case tok::kw_thread_local:
13677330f729Sjoerg case tok::kw__Thread_local:
13687330f729Sjoerg // function-specifier
13697330f729Sjoerg case tok::kw_inline:
13707330f729Sjoerg case tok::kw_virtual:
13717330f729Sjoerg case tok::kw_explicit:
13727330f729Sjoerg
13737330f729Sjoerg // Modules
13747330f729Sjoerg case tok::kw___module_private__:
13757330f729Sjoerg
13767330f729Sjoerg // Debugger support
13777330f729Sjoerg case tok::kw___unknown_anytype:
13787330f729Sjoerg
13797330f729Sjoerg // type-specifier:
13807330f729Sjoerg // simple-type-specifier
13817330f729Sjoerg // class-specifier
13827330f729Sjoerg // enum-specifier
13837330f729Sjoerg // elaborated-type-specifier
13847330f729Sjoerg // typename-specifier
13857330f729Sjoerg // cv-qualifier
13867330f729Sjoerg
13877330f729Sjoerg // class-specifier
13887330f729Sjoerg // elaborated-type-specifier
13897330f729Sjoerg case tok::kw_class:
13907330f729Sjoerg case tok::kw_struct:
13917330f729Sjoerg case tok::kw_union:
13927330f729Sjoerg case tok::kw___interface:
13937330f729Sjoerg // enum-specifier
13947330f729Sjoerg case tok::kw_enum:
13957330f729Sjoerg // cv-qualifier
13967330f729Sjoerg case tok::kw_const:
13977330f729Sjoerg case tok::kw_volatile:
13987330f729Sjoerg return TPResult::True;
13997330f729Sjoerg
14007330f729Sjoerg // OpenCL address space qualifiers
14017330f729Sjoerg case tok::kw_private:
14027330f729Sjoerg if (!getLangOpts().OpenCL)
14037330f729Sjoerg return TPResult::False;
14047330f729Sjoerg LLVM_FALLTHROUGH;
14057330f729Sjoerg case tok::kw___private:
14067330f729Sjoerg case tok::kw___local:
14077330f729Sjoerg case tok::kw___global:
14087330f729Sjoerg case tok::kw___constant:
14097330f729Sjoerg case tok::kw___generic:
14107330f729Sjoerg // OpenCL access qualifiers
14117330f729Sjoerg case tok::kw___read_only:
14127330f729Sjoerg case tok::kw___write_only:
14137330f729Sjoerg case tok::kw___read_write:
14147330f729Sjoerg // OpenCL pipe
14157330f729Sjoerg case tok::kw_pipe:
14167330f729Sjoerg
14177330f729Sjoerg // GNU
14187330f729Sjoerg case tok::kw_restrict:
14197330f729Sjoerg case tok::kw__Complex:
14207330f729Sjoerg case tok::kw___attribute:
14217330f729Sjoerg case tok::kw___auto_type:
14227330f729Sjoerg return TPResult::True;
14237330f729Sjoerg
14247330f729Sjoerg // Microsoft
14257330f729Sjoerg case tok::kw___declspec:
14267330f729Sjoerg case tok::kw___cdecl:
14277330f729Sjoerg case tok::kw___stdcall:
14287330f729Sjoerg case tok::kw___fastcall:
14297330f729Sjoerg case tok::kw___thiscall:
14307330f729Sjoerg case tok::kw___regcall:
14317330f729Sjoerg case tok::kw___vectorcall:
14327330f729Sjoerg case tok::kw___w64:
14337330f729Sjoerg case tok::kw___sptr:
14347330f729Sjoerg case tok::kw___uptr:
14357330f729Sjoerg case tok::kw___ptr64:
14367330f729Sjoerg case tok::kw___ptr32:
14377330f729Sjoerg case tok::kw___forceinline:
14387330f729Sjoerg case tok::kw___unaligned:
14397330f729Sjoerg case tok::kw__Nonnull:
14407330f729Sjoerg case tok::kw__Nullable:
1441*e038c9c4Sjoerg case tok::kw__Nullable_result:
14427330f729Sjoerg case tok::kw__Null_unspecified:
14437330f729Sjoerg case tok::kw___kindof:
14447330f729Sjoerg return TPResult::True;
14457330f729Sjoerg
14467330f729Sjoerg // Borland
14477330f729Sjoerg case tok::kw___pascal:
14487330f729Sjoerg return TPResult::True;
14497330f729Sjoerg
14507330f729Sjoerg // AltiVec
14517330f729Sjoerg case tok::kw___vector:
14527330f729Sjoerg return TPResult::True;
14537330f729Sjoerg
14547330f729Sjoerg case tok::annot_template_id: {
14557330f729Sjoerg TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
14567330f729Sjoerg // If lookup for the template-name found nothing, don't assume we have a
14577330f729Sjoerg // definitive disambiguation result yet.
1458*e038c9c4Sjoerg if ((TemplateId->hasInvalidName() ||
1459*e038c9c4Sjoerg TemplateId->Kind == TNK_Undeclared_template) &&
1460*e038c9c4Sjoerg InvalidAsDeclSpec) {
14617330f729Sjoerg // 'template-id(' can be a valid expression but not a valid decl spec if
14627330f729Sjoerg // the template-name is not declared, but we don't consider this to be a
14637330f729Sjoerg // definitive disambiguation. In any other context, it's an error either
14647330f729Sjoerg // way.
14657330f729Sjoerg *InvalidAsDeclSpec = NextToken().is(tok::l_paren);
14667330f729Sjoerg return TPResult::Ambiguous;
14677330f729Sjoerg }
1468*e038c9c4Sjoerg if (TemplateId->hasInvalidName())
1469*e038c9c4Sjoerg return TPResult::Error;
1470*e038c9c4Sjoerg if (IsPlaceholderSpecifier(TemplateId, /*Lookahead=*/0))
1471*e038c9c4Sjoerg return TPResult::True;
14727330f729Sjoerg if (TemplateId->Kind != TNK_Type_template)
14737330f729Sjoerg return TPResult::False;
14747330f729Sjoerg CXXScopeSpec SS;
1475*e038c9c4Sjoerg AnnotateTemplateIdTokenAsType(SS);
14767330f729Sjoerg assert(Tok.is(tok::annot_typename));
14777330f729Sjoerg goto case_typename;
14787330f729Sjoerg }
14797330f729Sjoerg
14807330f729Sjoerg case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
14817330f729Sjoerg // We've already annotated a scope; try to annotate a type.
14827330f729Sjoerg if (TryAnnotateTypeOrScopeToken())
14837330f729Sjoerg return TPResult::Error;
14847330f729Sjoerg if (!Tok.is(tok::annot_typename)) {
1485*e038c9c4Sjoerg if (Tok.is(tok::annot_cxxscope) &&
1486*e038c9c4Sjoerg NextToken().is(tok::annot_template_id)) {
1487*e038c9c4Sjoerg TemplateIdAnnotation *TemplateId =
1488*e038c9c4Sjoerg takeTemplateIdAnnotation(NextToken());
1489*e038c9c4Sjoerg if (TemplateId->hasInvalidName()) {
1490*e038c9c4Sjoerg if (InvalidAsDeclSpec) {
1491*e038c9c4Sjoerg *InvalidAsDeclSpec = NextToken().is(tok::l_paren);
1492*e038c9c4Sjoerg return TPResult::Ambiguous;
1493*e038c9c4Sjoerg }
1494*e038c9c4Sjoerg return TPResult::Error;
1495*e038c9c4Sjoerg }
1496*e038c9c4Sjoerg if (IsPlaceholderSpecifier(TemplateId, /*Lookahead=*/1))
1497*e038c9c4Sjoerg return TPResult::True;
1498*e038c9c4Sjoerg }
14997330f729Sjoerg // If the next token is an identifier or a type qualifier, then this
15007330f729Sjoerg // can't possibly be a valid expression either.
15017330f729Sjoerg if (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier)) {
15027330f729Sjoerg CXXScopeSpec SS;
15037330f729Sjoerg Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
15047330f729Sjoerg Tok.getAnnotationRange(),
15057330f729Sjoerg SS);
15067330f729Sjoerg if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) {
15077330f729Sjoerg RevertingTentativeParsingAction PA(*this);
15087330f729Sjoerg ConsumeAnnotationToken();
15097330f729Sjoerg ConsumeToken();
15107330f729Sjoerg bool isIdentifier = Tok.is(tok::identifier);
15117330f729Sjoerg TPResult TPR = TPResult::False;
15127330f729Sjoerg if (!isIdentifier)
15137330f729Sjoerg TPR = isCXXDeclarationSpecifier(BracedCastResult,
15147330f729Sjoerg InvalidAsDeclSpec);
15157330f729Sjoerg
15167330f729Sjoerg if (isIdentifier ||
15177330f729Sjoerg TPR == TPResult::True || TPR == TPResult::Error)
15187330f729Sjoerg return TPResult::Error;
15197330f729Sjoerg
15207330f729Sjoerg if (InvalidAsDeclSpec) {
15217330f729Sjoerg // We can't tell whether this is a missing 'typename' or a valid
15227330f729Sjoerg // expression.
15237330f729Sjoerg *InvalidAsDeclSpec = true;
15247330f729Sjoerg return TPResult::Ambiguous;
15257330f729Sjoerg } else {
15267330f729Sjoerg // In MS mode, if InvalidAsDeclSpec is not provided, and the tokens
15277330f729Sjoerg // are or the form *) or &) *> or &> &&>, this can't be an expression.
15287330f729Sjoerg // The typename must be missing.
15297330f729Sjoerg if (getLangOpts().MSVCCompat) {
15307330f729Sjoerg if (((Tok.is(tok::amp) || Tok.is(tok::star)) &&
15317330f729Sjoerg (NextToken().is(tok::r_paren) ||
15327330f729Sjoerg NextToken().is(tok::greater))) ||
15337330f729Sjoerg (Tok.is(tok::ampamp) && NextToken().is(tok::greater)))
15347330f729Sjoerg return TPResult::True;
15357330f729Sjoerg }
15367330f729Sjoerg }
15377330f729Sjoerg } else {
15387330f729Sjoerg // Try to resolve the name. If it doesn't exist, assume it was
15397330f729Sjoerg // intended to name a type and keep disambiguating.
15407330f729Sjoerg switch (TryAnnotateName()) {
15417330f729Sjoerg case ANK_Error:
15427330f729Sjoerg return TPResult::Error;
15437330f729Sjoerg case ANK_TentativeDecl:
15447330f729Sjoerg return TPResult::False;
15457330f729Sjoerg case ANK_TemplateName:
15467330f729Sjoerg // In C++17, this could be a type template for class template
15477330f729Sjoerg // argument deduction.
15487330f729Sjoerg if (getLangOpts().CPlusPlus17) {
15497330f729Sjoerg if (TryAnnotateTypeOrScopeToken())
15507330f729Sjoerg return TPResult::Error;
15517330f729Sjoerg if (Tok.isNot(tok::identifier))
15527330f729Sjoerg break;
15537330f729Sjoerg }
15547330f729Sjoerg
15557330f729Sjoerg // A bare type template-name which can't be a template template
15567330f729Sjoerg // argument is an error, and was probably intended to be a type.
15577330f729Sjoerg // In C++17, this could be class template argument deduction.
15587330f729Sjoerg return (getLangOpts().CPlusPlus17 || GreaterThanIsOperator)
15597330f729Sjoerg ? TPResult::True
15607330f729Sjoerg : TPResult::False;
15617330f729Sjoerg case ANK_Unresolved:
15627330f729Sjoerg return InvalidAsDeclSpec ? TPResult::Ambiguous : TPResult::False;
15637330f729Sjoerg case ANK_Success:
15647330f729Sjoerg break;
15657330f729Sjoerg }
15667330f729Sjoerg
15677330f729Sjoerg // Annotated it, check again.
15687330f729Sjoerg assert(Tok.isNot(tok::annot_cxxscope) ||
15697330f729Sjoerg NextToken().isNot(tok::identifier));
15707330f729Sjoerg return isCXXDeclarationSpecifier(BracedCastResult, InvalidAsDeclSpec);
15717330f729Sjoerg }
15727330f729Sjoerg }
15737330f729Sjoerg return TPResult::False;
15747330f729Sjoerg }
15757330f729Sjoerg // If that succeeded, fallthrough into the generic simple-type-id case.
15767330f729Sjoerg LLVM_FALLTHROUGH;
15777330f729Sjoerg
15787330f729Sjoerg // The ambiguity resides in a simple-type-specifier/typename-specifier
15797330f729Sjoerg // followed by a '('. The '(' could either be the start of:
15807330f729Sjoerg //
15817330f729Sjoerg // direct-declarator:
15827330f729Sjoerg // '(' declarator ')'
15837330f729Sjoerg //
15847330f729Sjoerg // direct-abstract-declarator:
15857330f729Sjoerg // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
15867330f729Sjoerg // exception-specification[opt]
15877330f729Sjoerg // '(' abstract-declarator ')'
15887330f729Sjoerg //
15897330f729Sjoerg // or part of a function-style cast expression:
15907330f729Sjoerg //
15917330f729Sjoerg // simple-type-specifier '(' expression-list[opt] ')'
15927330f729Sjoerg //
15937330f729Sjoerg
15947330f729Sjoerg // simple-type-specifier:
15957330f729Sjoerg
15967330f729Sjoerg case tok::annot_typename:
15977330f729Sjoerg case_typename:
15987330f729Sjoerg // In Objective-C, we might have a protocol-qualified type.
15997330f729Sjoerg if (getLangOpts().ObjC && NextToken().is(tok::less)) {
16007330f729Sjoerg // Tentatively parse the protocol qualifiers.
16017330f729Sjoerg RevertingTentativeParsingAction PA(*this);
16027330f729Sjoerg ConsumeAnyToken(); // The type token
16037330f729Sjoerg
16047330f729Sjoerg TPResult TPR = TryParseProtocolQualifiers();
16057330f729Sjoerg bool isFollowedByParen = Tok.is(tok::l_paren);
16067330f729Sjoerg bool isFollowedByBrace = Tok.is(tok::l_brace);
16077330f729Sjoerg
16087330f729Sjoerg if (TPR == TPResult::Error)
16097330f729Sjoerg return TPResult::Error;
16107330f729Sjoerg
16117330f729Sjoerg if (isFollowedByParen)
16127330f729Sjoerg return TPResult::Ambiguous;
16137330f729Sjoerg
16147330f729Sjoerg if (getLangOpts().CPlusPlus11 && isFollowedByBrace)
16157330f729Sjoerg return BracedCastResult;
16167330f729Sjoerg
16177330f729Sjoerg return TPResult::True;
16187330f729Sjoerg }
16197330f729Sjoerg LLVM_FALLTHROUGH;
16207330f729Sjoerg
16217330f729Sjoerg case tok::kw_char:
16227330f729Sjoerg case tok::kw_wchar_t:
16237330f729Sjoerg case tok::kw_char8_t:
16247330f729Sjoerg case tok::kw_char16_t:
16257330f729Sjoerg case tok::kw_char32_t:
16267330f729Sjoerg case tok::kw_bool:
16277330f729Sjoerg case tok::kw_short:
16287330f729Sjoerg case tok::kw_int:
16297330f729Sjoerg case tok::kw_long:
16307330f729Sjoerg case tok::kw___int64:
16317330f729Sjoerg case tok::kw___int128:
16327330f729Sjoerg case tok::kw_signed:
16337330f729Sjoerg case tok::kw_unsigned:
16347330f729Sjoerg case tok::kw_half:
16357330f729Sjoerg case tok::kw_float:
16367330f729Sjoerg case tok::kw_double:
1637*e038c9c4Sjoerg case tok::kw___bf16:
16387330f729Sjoerg case tok::kw__Float16:
16397330f729Sjoerg case tok::kw___float128:
16407330f729Sjoerg case tok::kw_void:
16417330f729Sjoerg case tok::annot_decltype:
16427330f729Sjoerg #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
16437330f729Sjoerg #include "clang/Basic/OpenCLImageTypes.def"
16447330f729Sjoerg if (NextToken().is(tok::l_paren))
16457330f729Sjoerg return TPResult::Ambiguous;
16467330f729Sjoerg
16477330f729Sjoerg // This is a function-style cast in all cases we disambiguate other than
16487330f729Sjoerg // one:
16497330f729Sjoerg // struct S {
16507330f729Sjoerg // enum E : int { a = 4 }; // enum
16517330f729Sjoerg // enum E : int { 4 }; // bit-field
16527330f729Sjoerg // };
16537330f729Sjoerg if (getLangOpts().CPlusPlus11 && NextToken().is(tok::l_brace))
16547330f729Sjoerg return BracedCastResult;
16557330f729Sjoerg
16567330f729Sjoerg if (isStartOfObjCClassMessageMissingOpenBracket())
16577330f729Sjoerg return TPResult::False;
16587330f729Sjoerg
16597330f729Sjoerg return TPResult::True;
16607330f729Sjoerg
16617330f729Sjoerg // GNU typeof support.
16627330f729Sjoerg case tok::kw_typeof: {
16637330f729Sjoerg if (NextToken().isNot(tok::l_paren))
16647330f729Sjoerg return TPResult::True;
16657330f729Sjoerg
16667330f729Sjoerg RevertingTentativeParsingAction PA(*this);
16677330f729Sjoerg
16687330f729Sjoerg TPResult TPR = TryParseTypeofSpecifier();
16697330f729Sjoerg bool isFollowedByParen = Tok.is(tok::l_paren);
16707330f729Sjoerg bool isFollowedByBrace = Tok.is(tok::l_brace);
16717330f729Sjoerg
16727330f729Sjoerg if (TPR == TPResult::Error)
16737330f729Sjoerg return TPResult::Error;
16747330f729Sjoerg
16757330f729Sjoerg if (isFollowedByParen)
16767330f729Sjoerg return TPResult::Ambiguous;
16777330f729Sjoerg
16787330f729Sjoerg if (getLangOpts().CPlusPlus11 && isFollowedByBrace)
16797330f729Sjoerg return BracedCastResult;
16807330f729Sjoerg
16817330f729Sjoerg return TPResult::True;
16827330f729Sjoerg }
16837330f729Sjoerg
16847330f729Sjoerg // C++0x type traits support
16857330f729Sjoerg case tok::kw___underlying_type:
16867330f729Sjoerg return TPResult::True;
16877330f729Sjoerg
16887330f729Sjoerg // C11 _Atomic
16897330f729Sjoerg case tok::kw__Atomic:
16907330f729Sjoerg return TPResult::True;
16917330f729Sjoerg
1692*e038c9c4Sjoerg case tok::kw__ExtInt: {
1693*e038c9c4Sjoerg if (NextToken().isNot(tok::l_paren))
1694*e038c9c4Sjoerg return TPResult::Error;
1695*e038c9c4Sjoerg RevertingTentativeParsingAction PA(*this);
1696*e038c9c4Sjoerg ConsumeToken();
1697*e038c9c4Sjoerg ConsumeParen();
1698*e038c9c4Sjoerg
1699*e038c9c4Sjoerg if (!SkipUntil(tok::r_paren, StopAtSemi))
1700*e038c9c4Sjoerg return TPResult::Error;
1701*e038c9c4Sjoerg
1702*e038c9c4Sjoerg if (Tok.is(tok::l_paren))
1703*e038c9c4Sjoerg return TPResult::Ambiguous;
1704*e038c9c4Sjoerg
1705*e038c9c4Sjoerg if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))
1706*e038c9c4Sjoerg return BracedCastResult;
1707*e038c9c4Sjoerg
1708*e038c9c4Sjoerg return TPResult::True;
1709*e038c9c4Sjoerg }
17107330f729Sjoerg default:
17117330f729Sjoerg return TPResult::False;
17127330f729Sjoerg }
17137330f729Sjoerg }
17147330f729Sjoerg
isCXXDeclarationSpecifierAType()17157330f729Sjoerg bool Parser::isCXXDeclarationSpecifierAType() {
17167330f729Sjoerg switch (Tok.getKind()) {
17177330f729Sjoerg // typename-specifier
17187330f729Sjoerg case tok::annot_decltype:
17197330f729Sjoerg case tok::annot_template_id:
17207330f729Sjoerg case tok::annot_typename:
17217330f729Sjoerg case tok::kw_typeof:
17227330f729Sjoerg case tok::kw___underlying_type:
17237330f729Sjoerg return true;
17247330f729Sjoerg
17257330f729Sjoerg // elaborated-type-specifier
17267330f729Sjoerg case tok::kw_class:
17277330f729Sjoerg case tok::kw_struct:
17287330f729Sjoerg case tok::kw_union:
17297330f729Sjoerg case tok::kw___interface:
17307330f729Sjoerg case tok::kw_enum:
17317330f729Sjoerg return true;
17327330f729Sjoerg
17337330f729Sjoerg // simple-type-specifier
17347330f729Sjoerg case tok::kw_char:
17357330f729Sjoerg case tok::kw_wchar_t:
17367330f729Sjoerg case tok::kw_char8_t:
17377330f729Sjoerg case tok::kw_char16_t:
17387330f729Sjoerg case tok::kw_char32_t:
17397330f729Sjoerg case tok::kw_bool:
17407330f729Sjoerg case tok::kw_short:
17417330f729Sjoerg case tok::kw_int:
1742*e038c9c4Sjoerg case tok::kw__ExtInt:
17437330f729Sjoerg case tok::kw_long:
17447330f729Sjoerg case tok::kw___int64:
17457330f729Sjoerg case tok::kw___int128:
17467330f729Sjoerg case tok::kw_signed:
17477330f729Sjoerg case tok::kw_unsigned:
17487330f729Sjoerg case tok::kw_half:
17497330f729Sjoerg case tok::kw_float:
17507330f729Sjoerg case tok::kw_double:
1751*e038c9c4Sjoerg case tok::kw___bf16:
17527330f729Sjoerg case tok::kw__Float16:
17537330f729Sjoerg case tok::kw___float128:
17547330f729Sjoerg case tok::kw_void:
17557330f729Sjoerg case tok::kw___unknown_anytype:
17567330f729Sjoerg case tok::kw___auto_type:
17577330f729Sjoerg #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
17587330f729Sjoerg #include "clang/Basic/OpenCLImageTypes.def"
17597330f729Sjoerg return true;
17607330f729Sjoerg
17617330f729Sjoerg case tok::kw_auto:
17627330f729Sjoerg return getLangOpts().CPlusPlus11;
17637330f729Sjoerg
17647330f729Sjoerg case tok::kw__Atomic:
17657330f729Sjoerg // "_Atomic foo"
17667330f729Sjoerg return NextToken().is(tok::l_paren);
17677330f729Sjoerg
17687330f729Sjoerg default:
17697330f729Sjoerg return false;
17707330f729Sjoerg }
17717330f729Sjoerg }
17727330f729Sjoerg
17737330f729Sjoerg /// [GNU] typeof-specifier:
17747330f729Sjoerg /// 'typeof' '(' expressions ')'
17757330f729Sjoerg /// 'typeof' '(' type-name ')'
17767330f729Sjoerg ///
TryParseTypeofSpecifier()17777330f729Sjoerg Parser::TPResult Parser::TryParseTypeofSpecifier() {
17787330f729Sjoerg assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");
17797330f729Sjoerg ConsumeToken();
17807330f729Sjoerg
17817330f729Sjoerg assert(Tok.is(tok::l_paren) && "Expected '('");
17827330f729Sjoerg // Parse through the parens after 'typeof'.
17837330f729Sjoerg ConsumeParen();
17847330f729Sjoerg if (!SkipUntil(tok::r_paren, StopAtSemi))
17857330f729Sjoerg return TPResult::Error;
17867330f729Sjoerg
17877330f729Sjoerg return TPResult::Ambiguous;
17887330f729Sjoerg }
17897330f729Sjoerg
17907330f729Sjoerg /// [ObjC] protocol-qualifiers:
17917330f729Sjoerg //// '<' identifier-list '>'
TryParseProtocolQualifiers()17927330f729Sjoerg Parser::TPResult Parser::TryParseProtocolQualifiers() {
17937330f729Sjoerg assert(Tok.is(tok::less) && "Expected '<' for qualifier list");
17947330f729Sjoerg ConsumeToken();
17957330f729Sjoerg do {
17967330f729Sjoerg if (Tok.isNot(tok::identifier))
17977330f729Sjoerg return TPResult::Error;
17987330f729Sjoerg ConsumeToken();
17997330f729Sjoerg
18007330f729Sjoerg if (Tok.is(tok::comma)) {
18017330f729Sjoerg ConsumeToken();
18027330f729Sjoerg continue;
18037330f729Sjoerg }
18047330f729Sjoerg
18057330f729Sjoerg if (Tok.is(tok::greater)) {
18067330f729Sjoerg ConsumeToken();
18077330f729Sjoerg return TPResult::Ambiguous;
18087330f729Sjoerg }
18097330f729Sjoerg } while (false);
18107330f729Sjoerg
18117330f729Sjoerg return TPResult::Error;
18127330f729Sjoerg }
18137330f729Sjoerg
18147330f729Sjoerg /// isCXXFunctionDeclarator - Disambiguates between a function declarator or
18157330f729Sjoerg /// a constructor-style initializer, when parsing declaration statements.
18167330f729Sjoerg /// Returns true for function declarator and false for constructor-style
18177330f729Sjoerg /// initializer.
18187330f729Sjoerg /// If during the disambiguation process a parsing error is encountered,
18197330f729Sjoerg /// the function returns true to let the declaration parsing code handle it.
18207330f729Sjoerg ///
18217330f729Sjoerg /// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
18227330f729Sjoerg /// exception-specification[opt]
18237330f729Sjoerg ///
isCXXFunctionDeclarator(bool * IsAmbiguous)18247330f729Sjoerg bool Parser::isCXXFunctionDeclarator(bool *IsAmbiguous) {
18257330f729Sjoerg
18267330f729Sjoerg // C++ 8.2p1:
18277330f729Sjoerg // The ambiguity arising from the similarity between a function-style cast and
18287330f729Sjoerg // a declaration mentioned in 6.8 can also occur in the context of a
18297330f729Sjoerg // declaration. In that context, the choice is between a function declaration
18307330f729Sjoerg // with a redundant set of parentheses around a parameter name and an object
18317330f729Sjoerg // declaration with a function-style cast as the initializer. Just as for the
18327330f729Sjoerg // ambiguities mentioned in 6.8, the resolution is to consider any construct
18337330f729Sjoerg // that could possibly be a declaration a declaration.
18347330f729Sjoerg
18357330f729Sjoerg RevertingTentativeParsingAction PA(*this);
18367330f729Sjoerg
18377330f729Sjoerg ConsumeParen();
18387330f729Sjoerg bool InvalidAsDeclaration = false;
18397330f729Sjoerg TPResult TPR = TryParseParameterDeclarationClause(&InvalidAsDeclaration);
18407330f729Sjoerg if (TPR == TPResult::Ambiguous) {
18417330f729Sjoerg if (Tok.isNot(tok::r_paren))
18427330f729Sjoerg TPR = TPResult::False;
18437330f729Sjoerg else {
18447330f729Sjoerg const Token &Next = NextToken();
18457330f729Sjoerg if (Next.isOneOf(tok::amp, tok::ampamp, tok::kw_const, tok::kw_volatile,
18467330f729Sjoerg tok::kw_throw, tok::kw_noexcept, tok::l_square,
18477330f729Sjoerg tok::l_brace, tok::kw_try, tok::equal, tok::arrow) ||
18487330f729Sjoerg isCXX11VirtSpecifier(Next))
18497330f729Sjoerg // The next token cannot appear after a constructor-style initializer,
18507330f729Sjoerg // and can appear next in a function definition. This must be a function
18517330f729Sjoerg // declarator.
18527330f729Sjoerg TPR = TPResult::True;
18537330f729Sjoerg else if (InvalidAsDeclaration)
18547330f729Sjoerg // Use the absence of 'typename' as a tie-breaker.
18557330f729Sjoerg TPR = TPResult::False;
18567330f729Sjoerg }
18577330f729Sjoerg }
18587330f729Sjoerg
18597330f729Sjoerg if (IsAmbiguous && TPR == TPResult::Ambiguous)
18607330f729Sjoerg *IsAmbiguous = true;
18617330f729Sjoerg
18627330f729Sjoerg // In case of an error, let the declaration parsing code handle it.
18637330f729Sjoerg return TPR != TPResult::False;
18647330f729Sjoerg }
18657330f729Sjoerg
18667330f729Sjoerg /// parameter-declaration-clause:
18677330f729Sjoerg /// parameter-declaration-list[opt] '...'[opt]
18687330f729Sjoerg /// parameter-declaration-list ',' '...'
18697330f729Sjoerg ///
18707330f729Sjoerg /// parameter-declaration-list:
18717330f729Sjoerg /// parameter-declaration
18727330f729Sjoerg /// parameter-declaration-list ',' parameter-declaration
18737330f729Sjoerg ///
18747330f729Sjoerg /// parameter-declaration:
18757330f729Sjoerg /// attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
18767330f729Sjoerg /// attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
18777330f729Sjoerg /// '=' assignment-expression
18787330f729Sjoerg /// attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
18797330f729Sjoerg /// attributes[opt]
18807330f729Sjoerg /// attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
18817330f729Sjoerg /// attributes[opt] '=' assignment-expression
18827330f729Sjoerg ///
18837330f729Sjoerg Parser::TPResult
TryParseParameterDeclarationClause(bool * InvalidAsDeclaration,bool VersusTemplateArgument)18847330f729Sjoerg Parser::TryParseParameterDeclarationClause(bool *InvalidAsDeclaration,
18857330f729Sjoerg bool VersusTemplateArgument) {
18867330f729Sjoerg
18877330f729Sjoerg if (Tok.is(tok::r_paren))
18887330f729Sjoerg return TPResult::Ambiguous;
18897330f729Sjoerg
18907330f729Sjoerg // parameter-declaration-list[opt] '...'[opt]
18917330f729Sjoerg // parameter-declaration-list ',' '...'
18927330f729Sjoerg //
18937330f729Sjoerg // parameter-declaration-list:
18947330f729Sjoerg // parameter-declaration
18957330f729Sjoerg // parameter-declaration-list ',' parameter-declaration
18967330f729Sjoerg //
18977330f729Sjoerg while (1) {
18987330f729Sjoerg // '...'[opt]
18997330f729Sjoerg if (Tok.is(tok::ellipsis)) {
19007330f729Sjoerg ConsumeToken();
19017330f729Sjoerg if (Tok.is(tok::r_paren))
19027330f729Sjoerg return TPResult::True; // '...)' is a sign of a function declarator.
19037330f729Sjoerg else
19047330f729Sjoerg return TPResult::False;
19057330f729Sjoerg }
19067330f729Sjoerg
19077330f729Sjoerg // An attribute-specifier-seq here is a sign of a function declarator.
19087330f729Sjoerg if (isCXX11AttributeSpecifier(/*Disambiguate*/false,
19097330f729Sjoerg /*OuterMightBeMessageSend*/true))
19107330f729Sjoerg return TPResult::True;
19117330f729Sjoerg
19127330f729Sjoerg ParsedAttributes attrs(AttrFactory);
19137330f729Sjoerg MaybeParseMicrosoftAttributes(attrs);
19147330f729Sjoerg
19157330f729Sjoerg // decl-specifier-seq
19167330f729Sjoerg // A parameter-declaration's initializer must be preceded by an '=', so
19177330f729Sjoerg // decl-specifier-seq '{' is not a parameter in C++11.
19187330f729Sjoerg TPResult TPR = isCXXDeclarationSpecifier(TPResult::False,
19197330f729Sjoerg InvalidAsDeclaration);
19207330f729Sjoerg // A declaration-specifier (not followed by '(' or '{') means this can't be
19217330f729Sjoerg // an expression, but it could still be a template argument.
19227330f729Sjoerg if (TPR != TPResult::Ambiguous &&
19237330f729Sjoerg !(VersusTemplateArgument && TPR == TPResult::True))
19247330f729Sjoerg return TPR;
19257330f729Sjoerg
19267330f729Sjoerg bool SeenType = false;
19277330f729Sjoerg do {
19287330f729Sjoerg SeenType |= isCXXDeclarationSpecifierAType();
19297330f729Sjoerg if (TryConsumeDeclarationSpecifier() == TPResult::Error)
19307330f729Sjoerg return TPResult::Error;
19317330f729Sjoerg
19327330f729Sjoerg // If we see a parameter name, this can't be a template argument.
19337330f729Sjoerg if (SeenType && Tok.is(tok::identifier))
19347330f729Sjoerg return TPResult::True;
19357330f729Sjoerg
19367330f729Sjoerg TPR = isCXXDeclarationSpecifier(TPResult::False,
19377330f729Sjoerg InvalidAsDeclaration);
19387330f729Sjoerg if (TPR == TPResult::Error)
19397330f729Sjoerg return TPR;
19407330f729Sjoerg
19417330f729Sjoerg // Two declaration-specifiers means this can't be an expression.
19427330f729Sjoerg if (TPR == TPResult::True && !VersusTemplateArgument)
19437330f729Sjoerg return TPR;
19447330f729Sjoerg } while (TPR != TPResult::False);
19457330f729Sjoerg
19467330f729Sjoerg // declarator
19477330f729Sjoerg // abstract-declarator[opt]
19487330f729Sjoerg TPR = TryParseDeclarator(true/*mayBeAbstract*/);
19497330f729Sjoerg if (TPR != TPResult::Ambiguous)
19507330f729Sjoerg return TPR;
19517330f729Sjoerg
19527330f729Sjoerg // [GNU] attributes[opt]
19537330f729Sjoerg if (Tok.is(tok::kw___attribute))
19547330f729Sjoerg return TPResult::True;
19557330f729Sjoerg
19567330f729Sjoerg // If we're disambiguating a template argument in a default argument in
19577330f729Sjoerg // a class definition versus a parameter declaration, an '=' here
19587330f729Sjoerg // disambiguates the parse one way or the other.
19597330f729Sjoerg // If this is a parameter, it must have a default argument because
19607330f729Sjoerg // (a) the previous parameter did, and
19617330f729Sjoerg // (b) this must be the first declaration of the function, so we can't
19627330f729Sjoerg // inherit any default arguments from elsewhere.
1963*e038c9c4Sjoerg // FIXME: If we reach a ')' without consuming any '>'s, then this must
1964*e038c9c4Sjoerg // also be a function parameter (that's missing its default argument).
19657330f729Sjoerg if (VersusTemplateArgument)
1966*e038c9c4Sjoerg return Tok.is(tok::equal) ? TPResult::True : TPResult::False;
19677330f729Sjoerg
19687330f729Sjoerg if (Tok.is(tok::equal)) {
19697330f729Sjoerg // '=' assignment-expression
19707330f729Sjoerg // Parse through assignment-expression.
19717330f729Sjoerg if (!SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch))
19727330f729Sjoerg return TPResult::Error;
19737330f729Sjoerg }
19747330f729Sjoerg
19757330f729Sjoerg if (Tok.is(tok::ellipsis)) {
19767330f729Sjoerg ConsumeToken();
19777330f729Sjoerg if (Tok.is(tok::r_paren))
19787330f729Sjoerg return TPResult::True; // '...)' is a sign of a function declarator.
19797330f729Sjoerg else
19807330f729Sjoerg return TPResult::False;
19817330f729Sjoerg }
19827330f729Sjoerg
19837330f729Sjoerg if (!TryConsumeToken(tok::comma))
19847330f729Sjoerg break;
19857330f729Sjoerg }
19867330f729Sjoerg
19877330f729Sjoerg return TPResult::Ambiguous;
19887330f729Sjoerg }
19897330f729Sjoerg
19907330f729Sjoerg /// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
19917330f729Sjoerg /// parsing as a function declarator.
19927330f729Sjoerg /// If TryParseFunctionDeclarator fully parsed the function declarator, it will
19937330f729Sjoerg /// return TPResult::Ambiguous, otherwise it will return either False() or
19947330f729Sjoerg /// Error().
19957330f729Sjoerg ///
19967330f729Sjoerg /// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
19977330f729Sjoerg /// exception-specification[opt]
19987330f729Sjoerg ///
19997330f729Sjoerg /// exception-specification:
20007330f729Sjoerg /// 'throw' '(' type-id-list[opt] ')'
20017330f729Sjoerg ///
TryParseFunctionDeclarator()20027330f729Sjoerg Parser::TPResult Parser::TryParseFunctionDeclarator() {
20037330f729Sjoerg // The '(' is already parsed.
20047330f729Sjoerg
20057330f729Sjoerg TPResult TPR = TryParseParameterDeclarationClause();
20067330f729Sjoerg if (TPR == TPResult::Ambiguous && Tok.isNot(tok::r_paren))
20077330f729Sjoerg TPR = TPResult::False;
20087330f729Sjoerg
20097330f729Sjoerg if (TPR == TPResult::False || TPR == TPResult::Error)
20107330f729Sjoerg return TPR;
20117330f729Sjoerg
20127330f729Sjoerg // Parse through the parens.
20137330f729Sjoerg if (!SkipUntil(tok::r_paren, StopAtSemi))
20147330f729Sjoerg return TPResult::Error;
20157330f729Sjoerg
20167330f729Sjoerg // cv-qualifier-seq
20177330f729Sjoerg while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw___unaligned,
20187330f729Sjoerg tok::kw_restrict))
20197330f729Sjoerg ConsumeToken();
20207330f729Sjoerg
20217330f729Sjoerg // ref-qualifier[opt]
20227330f729Sjoerg if (Tok.isOneOf(tok::amp, tok::ampamp))
20237330f729Sjoerg ConsumeToken();
20247330f729Sjoerg
20257330f729Sjoerg // exception-specification
20267330f729Sjoerg if (Tok.is(tok::kw_throw)) {
20277330f729Sjoerg ConsumeToken();
20287330f729Sjoerg if (Tok.isNot(tok::l_paren))
20297330f729Sjoerg return TPResult::Error;
20307330f729Sjoerg
20317330f729Sjoerg // Parse through the parens after 'throw'.
20327330f729Sjoerg ConsumeParen();
20337330f729Sjoerg if (!SkipUntil(tok::r_paren, StopAtSemi))
20347330f729Sjoerg return TPResult::Error;
20357330f729Sjoerg }
20367330f729Sjoerg if (Tok.is(tok::kw_noexcept)) {
20377330f729Sjoerg ConsumeToken();
20387330f729Sjoerg // Possibly an expression as well.
20397330f729Sjoerg if (Tok.is(tok::l_paren)) {
20407330f729Sjoerg // Find the matching rparen.
20417330f729Sjoerg ConsumeParen();
20427330f729Sjoerg if (!SkipUntil(tok::r_paren, StopAtSemi))
20437330f729Sjoerg return TPResult::Error;
20447330f729Sjoerg }
20457330f729Sjoerg }
20467330f729Sjoerg
20477330f729Sjoerg return TPResult::Ambiguous;
20487330f729Sjoerg }
20497330f729Sjoerg
20507330f729Sjoerg /// '[' constant-expression[opt] ']'
20517330f729Sjoerg ///
TryParseBracketDeclarator()20527330f729Sjoerg Parser::TPResult Parser::TryParseBracketDeclarator() {
20537330f729Sjoerg ConsumeBracket();
2054*e038c9c4Sjoerg
2055*e038c9c4Sjoerg // A constant-expression cannot begin with a '{', but the
2056*e038c9c4Sjoerg // expr-or-braced-init-list of a postfix-expression can.
2057*e038c9c4Sjoerg if (Tok.is(tok::l_brace))
2058*e038c9c4Sjoerg return TPResult::False;
2059*e038c9c4Sjoerg
2060*e038c9c4Sjoerg if (!SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch))
20617330f729Sjoerg return TPResult::Error;
20627330f729Sjoerg
2063*e038c9c4Sjoerg // If we hit a comma before the ']', this is not a constant-expression,
2064*e038c9c4Sjoerg // but might still be the expr-or-braced-init-list of a postfix-expression.
2065*e038c9c4Sjoerg if (Tok.isNot(tok::r_square))
2066*e038c9c4Sjoerg return TPResult::False;
2067*e038c9c4Sjoerg
2068*e038c9c4Sjoerg ConsumeBracket();
20697330f729Sjoerg return TPResult::Ambiguous;
20707330f729Sjoerg }
20717330f729Sjoerg
20727330f729Sjoerg /// Determine whether we might be looking at the '<' template-argument-list '>'
20737330f729Sjoerg /// of a template-id or simple-template-id, rather than a less-than comparison.
20747330f729Sjoerg /// This will often fail and produce an ambiguity, but should never be wrong
20757330f729Sjoerg /// if it returns True or False.
isTemplateArgumentList(unsigned TokensToSkip)20767330f729Sjoerg Parser::TPResult Parser::isTemplateArgumentList(unsigned TokensToSkip) {
20777330f729Sjoerg if (!TokensToSkip) {
20787330f729Sjoerg if (Tok.isNot(tok::less))
20797330f729Sjoerg return TPResult::False;
20807330f729Sjoerg if (NextToken().is(tok::greater))
20817330f729Sjoerg return TPResult::True;
20827330f729Sjoerg }
20837330f729Sjoerg
20847330f729Sjoerg RevertingTentativeParsingAction PA(*this);
20857330f729Sjoerg
20867330f729Sjoerg while (TokensToSkip) {
20877330f729Sjoerg ConsumeAnyToken();
20887330f729Sjoerg --TokensToSkip;
20897330f729Sjoerg }
20907330f729Sjoerg
20917330f729Sjoerg if (!TryConsumeToken(tok::less))
20927330f729Sjoerg return TPResult::False;
20937330f729Sjoerg
20947330f729Sjoerg // We can't do much to tell an expression apart from a template-argument,
20957330f729Sjoerg // but one good distinguishing factor is that a "decl-specifier" not
20967330f729Sjoerg // followed by '(' or '{' can't appear in an expression.
20977330f729Sjoerg bool InvalidAsTemplateArgumentList = false;
20987330f729Sjoerg if (isCXXDeclarationSpecifier(TPResult::False,
20997330f729Sjoerg &InvalidAsTemplateArgumentList) ==
21007330f729Sjoerg TPResult::True)
21017330f729Sjoerg return TPResult::True;
21027330f729Sjoerg if (InvalidAsTemplateArgumentList)
21037330f729Sjoerg return TPResult::False;
21047330f729Sjoerg
21057330f729Sjoerg // FIXME: In many contexts, X<thing1, Type> can only be a
21067330f729Sjoerg // template-argument-list. But that's not true in general:
21077330f729Sjoerg //
21087330f729Sjoerg // using b = int;
21097330f729Sjoerg // void f() {
21107330f729Sjoerg // int a = A<B, b, c = C>D; // OK, declares b, not a template-id.
21117330f729Sjoerg //
21127330f729Sjoerg // X<Y<0, int> // ', int>' might be end of X's template argument list
21137330f729Sjoerg //
21147330f729Sjoerg // We might be able to disambiguate a few more cases if we're careful.
21157330f729Sjoerg
21167330f729Sjoerg // A template-argument-list must be terminated by a '>'.
21177330f729Sjoerg if (SkipUntil({tok::greater, tok::greatergreater, tok::greatergreatergreater},
21187330f729Sjoerg StopAtSemi | StopBeforeMatch))
21197330f729Sjoerg return TPResult::Ambiguous;
21207330f729Sjoerg return TPResult::False;
21217330f729Sjoerg }
2122*e038c9c4Sjoerg
2123*e038c9c4Sjoerg /// Determine whether we might be looking at the '(' of a C++20 explicit(bool)
2124*e038c9c4Sjoerg /// in an earlier language mode.
isExplicitBool()2125*e038c9c4Sjoerg Parser::TPResult Parser::isExplicitBool() {
2126*e038c9c4Sjoerg assert(Tok.is(tok::l_paren) && "expected to be looking at a '(' token");
2127*e038c9c4Sjoerg
2128*e038c9c4Sjoerg RevertingTentativeParsingAction PA(*this);
2129*e038c9c4Sjoerg ConsumeParen();
2130*e038c9c4Sjoerg
2131*e038c9c4Sjoerg // We can only have 'explicit' on a constructor, conversion function, or
2132*e038c9c4Sjoerg // deduction guide. The declarator of a deduction guide cannot be
2133*e038c9c4Sjoerg // parenthesized, so we know this isn't a deduction guide. So the only
2134*e038c9c4Sjoerg // thing we need to check for is some number of parens followed by either
2135*e038c9c4Sjoerg // the current class name or 'operator'.
2136*e038c9c4Sjoerg while (Tok.is(tok::l_paren))
2137*e038c9c4Sjoerg ConsumeParen();
2138*e038c9c4Sjoerg
2139*e038c9c4Sjoerg if (TryAnnotateOptionalCXXScopeToken())
2140*e038c9c4Sjoerg return TPResult::Error;
2141*e038c9c4Sjoerg
2142*e038c9c4Sjoerg // Class-scope constructor and conversion function names can't really be
2143*e038c9c4Sjoerg // qualified, but we get better diagnostics if we assume they can be.
2144*e038c9c4Sjoerg CXXScopeSpec SS;
2145*e038c9c4Sjoerg if (Tok.is(tok::annot_cxxscope)) {
2146*e038c9c4Sjoerg Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
2147*e038c9c4Sjoerg Tok.getAnnotationRange(),
2148*e038c9c4Sjoerg SS);
2149*e038c9c4Sjoerg ConsumeAnnotationToken();
2150*e038c9c4Sjoerg }
2151*e038c9c4Sjoerg
2152*e038c9c4Sjoerg // 'explicit(operator' might be explicit(bool) or the declaration of a
2153*e038c9c4Sjoerg // conversion function, but it's probably a conversion function.
2154*e038c9c4Sjoerg if (Tok.is(tok::kw_operator))
2155*e038c9c4Sjoerg return TPResult::Ambiguous;
2156*e038c9c4Sjoerg
2157*e038c9c4Sjoerg // If this can't be a constructor name, it can only be explicit(bool).
2158*e038c9c4Sjoerg if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
2159*e038c9c4Sjoerg return TPResult::True;
2160*e038c9c4Sjoerg if (!Actions.isCurrentClassName(Tok.is(tok::identifier)
2161*e038c9c4Sjoerg ? *Tok.getIdentifierInfo()
2162*e038c9c4Sjoerg : *takeTemplateIdAnnotation(Tok)->Name,
2163*e038c9c4Sjoerg getCurScope(), &SS))
2164*e038c9c4Sjoerg return TPResult::True;
2165*e038c9c4Sjoerg // Formally, we must have a right-paren after the constructor name to match
2166*e038c9c4Sjoerg // the grammar for a constructor. But clang permits a parenthesized
2167*e038c9c4Sjoerg // constructor declarator, so also allow a constructor declarator to follow
2168*e038c9c4Sjoerg // with no ')' token after the constructor name.
2169*e038c9c4Sjoerg if (!NextToken().is(tok::r_paren) &&
2170*e038c9c4Sjoerg !isConstructorDeclarator(/*Unqualified=*/SS.isEmpty(),
2171*e038c9c4Sjoerg /*DeductionGuide=*/false))
2172*e038c9c4Sjoerg return TPResult::True;
2173*e038c9c4Sjoerg
2174*e038c9c4Sjoerg // Might be explicit(bool) or a parenthesized constructor name.
2175*e038c9c4Sjoerg return TPResult::Ambiguous;
2176*e038c9c4Sjoerg }
2177