xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Parse/ParseTentative.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
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