xref: /openbsd-src/gnu/llvm/clang/lib/Parse/ParseTentative.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick //  This file implements the tentative parsing portions of the Parser
10e5dd7070Spatrick //  interfaces, for ambiguity resolution.
11e5dd7070Spatrick //
12e5dd7070Spatrick //===----------------------------------------------------------------------===//
13e5dd7070Spatrick 
14e5dd7070Spatrick #include "clang/Parse/Parser.h"
15e5dd7070Spatrick #include "clang/Parse/ParseDiagnostic.h"
16e5dd7070Spatrick #include "clang/Sema/ParsedTemplate.h"
17e5dd7070Spatrick using namespace clang;
18e5dd7070Spatrick 
19e5dd7070Spatrick /// isCXXDeclarationStatement - C++-specialized function that disambiguates
20e5dd7070Spatrick /// between a declaration or an expression statement, when parsing function
21e5dd7070Spatrick /// bodies. Returns true for declaration, false for expression.
22e5dd7070Spatrick ///
23e5dd7070Spatrick ///         declaration-statement:
24e5dd7070Spatrick ///           block-declaration
25e5dd7070Spatrick ///
26e5dd7070Spatrick ///         block-declaration:
27e5dd7070Spatrick ///           simple-declaration
28e5dd7070Spatrick ///           asm-definition
29e5dd7070Spatrick ///           namespace-alias-definition
30e5dd7070Spatrick ///           using-declaration
31e5dd7070Spatrick ///           using-directive
32e5dd7070Spatrick /// [C++0x]   static_assert-declaration
33e5dd7070Spatrick ///
34e5dd7070Spatrick ///         asm-definition:
35e5dd7070Spatrick ///           'asm' '(' string-literal ')' ';'
36e5dd7070Spatrick ///
37e5dd7070Spatrick ///         namespace-alias-definition:
38e5dd7070Spatrick ///           'namespace' identifier = qualified-namespace-specifier ';'
39e5dd7070Spatrick ///
40e5dd7070Spatrick ///         using-declaration:
41e5dd7070Spatrick ///           'using' typename[opt] '::'[opt] nested-name-specifier
42e5dd7070Spatrick ///                 unqualified-id ';'
43e5dd7070Spatrick ///           'using' '::' unqualified-id ;
44e5dd7070Spatrick ///
45e5dd7070Spatrick ///         using-directive:
46e5dd7070Spatrick ///           'using' 'namespace' '::'[opt] nested-name-specifier[opt]
47e5dd7070Spatrick ///                 namespace-name ';'
48e5dd7070Spatrick ///
isCXXDeclarationStatement(bool DisambiguatingWithExpression)49*12c85518Srobert bool Parser::isCXXDeclarationStatement(
50*12c85518Srobert     bool DisambiguatingWithExpression /*=false*/) {
51*12c85518Srobert   assert(getLangOpts().CPlusPlus && "Must be called for C++ only.");
52*12c85518Srobert 
53e5dd7070Spatrick   switch (Tok.getKind()) {
54e5dd7070Spatrick     // asm-definition
55e5dd7070Spatrick   case tok::kw_asm:
56e5dd7070Spatrick     // namespace-alias-definition
57e5dd7070Spatrick   case tok::kw_namespace:
58e5dd7070Spatrick     // using-declaration
59e5dd7070Spatrick     // using-directive
60e5dd7070Spatrick   case tok::kw_using:
61e5dd7070Spatrick     // static_assert-declaration
62e5dd7070Spatrick   case tok::kw_static_assert:
63e5dd7070Spatrick   case tok::kw__Static_assert:
64e5dd7070Spatrick     return true;
65*12c85518Srobert   case tok::identifier: {
66*12c85518Srobert     if (DisambiguatingWithExpression) {
67*12c85518Srobert       RevertingTentativeParsingAction TPA(*this);
68*12c85518Srobert       // Parse the C++ scope specifier.
69*12c85518Srobert       CXXScopeSpec SS;
70*12c85518Srobert       ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr,
71*12c85518Srobert                                      /*ObjectHasErrors=*/false,
72*12c85518Srobert                                      /*EnteringContext=*/true);
73*12c85518Srobert 
74*12c85518Srobert       switch (Tok.getKind()) {
75*12c85518Srobert       case tok::identifier: {
76*12c85518Srobert         IdentifierInfo *II = Tok.getIdentifierInfo();
77*12c85518Srobert         bool isDeductionGuide =
78*12c85518Srobert             Actions.isDeductionGuideName(getCurScope(), *II, Tok.getLocation(),
79*12c85518Srobert                                          /*Template=*/nullptr);
80*12c85518Srobert         if (Actions.isCurrentClassName(*II, getCurScope(), &SS) ||
81*12c85518Srobert             isDeductionGuide) {
82*12c85518Srobert           if (isConstructorDeclarator(/*Unqualified=*/SS.isEmpty(),
83*12c85518Srobert                                       isDeductionGuide,
84*12c85518Srobert                                       DeclSpec::FriendSpecified::No))
85*12c85518Srobert             return true;
86*12c85518Srobert         }
87*12c85518Srobert         break;
88*12c85518Srobert       }
89*12c85518Srobert       case tok::kw_operator:
90*12c85518Srobert         return true;
91*12c85518Srobert       case tok::annot_cxxscope: // Check if this is a dtor.
92*12c85518Srobert         if (NextToken().is(tok::tilde))
93*12c85518Srobert           return true;
94*12c85518Srobert         break;
95*12c85518Srobert       default:
96*12c85518Srobert         break;
97*12c85518Srobert       }
98*12c85518Srobert     }
99*12c85518Srobert   }
100*12c85518Srobert     [[fallthrough]];
101e5dd7070Spatrick     // simple-declaration
102e5dd7070Spatrick   default:
103e5dd7070Spatrick     return isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);
104e5dd7070Spatrick   }
105e5dd7070Spatrick }
106e5dd7070Spatrick 
107e5dd7070Spatrick /// isCXXSimpleDeclaration - C++-specialized function that disambiguates
108e5dd7070Spatrick /// between a simple-declaration or an expression-statement.
109e5dd7070Spatrick /// If during the disambiguation process a parsing error is encountered,
110e5dd7070Spatrick /// the function returns true to let the declaration parsing code handle it.
111e5dd7070Spatrick /// Returns false if the statement is disambiguated as expression.
112e5dd7070Spatrick ///
113e5dd7070Spatrick /// simple-declaration:
114e5dd7070Spatrick ///   decl-specifier-seq init-declarator-list[opt] ';'
115e5dd7070Spatrick ///   decl-specifier-seq ref-qualifier[opt] '[' identifier-list ']'
116e5dd7070Spatrick ///                      brace-or-equal-initializer ';'    [C++17]
117e5dd7070Spatrick ///
118e5dd7070Spatrick /// (if AllowForRangeDecl specified)
119e5dd7070Spatrick /// for ( for-range-declaration : for-range-initializer ) statement
120e5dd7070Spatrick ///
121e5dd7070Spatrick /// for-range-declaration:
122e5dd7070Spatrick ///    decl-specifier-seq declarator
123e5dd7070Spatrick ///    decl-specifier-seq ref-qualifier[opt] '[' identifier-list ']'
124e5dd7070Spatrick ///
125e5dd7070Spatrick /// In any of the above cases there can be a preceding attribute-specifier-seq,
126e5dd7070Spatrick /// but the caller is expected to handle that.
isCXXSimpleDeclaration(bool AllowForRangeDecl)127e5dd7070Spatrick bool Parser::isCXXSimpleDeclaration(bool AllowForRangeDecl) {
128e5dd7070Spatrick   // C++ 6.8p1:
129e5dd7070Spatrick   // There is an ambiguity in the grammar involving expression-statements and
130e5dd7070Spatrick   // declarations: An expression-statement with a function-style explicit type
131e5dd7070Spatrick   // conversion (5.2.3) as its leftmost subexpression can be indistinguishable
132e5dd7070Spatrick   // from a declaration where the first declarator starts with a '('. In those
133e5dd7070Spatrick   // cases the statement is a declaration. [Note: To disambiguate, the whole
134e5dd7070Spatrick   // statement might have to be examined to determine if it is an
135e5dd7070Spatrick   // expression-statement or a declaration].
136e5dd7070Spatrick 
137e5dd7070Spatrick   // C++ 6.8p3:
138e5dd7070Spatrick   // The disambiguation is purely syntactic; that is, the meaning of the names
139e5dd7070Spatrick   // occurring in such a statement, beyond whether they are type-names or not,
140e5dd7070Spatrick   // is not generally used in or changed by the disambiguation. Class
141e5dd7070Spatrick   // templates are instantiated as necessary to determine if a qualified name
142e5dd7070Spatrick   // is a type-name. Disambiguation precedes parsing, and a statement
143e5dd7070Spatrick   // disambiguated as a declaration may be an ill-formed declaration.
144e5dd7070Spatrick 
145e5dd7070Spatrick   // We don't have to parse all of the decl-specifier-seq part. There's only
146e5dd7070Spatrick   // an ambiguity if the first decl-specifier is
147e5dd7070Spatrick   // simple-type-specifier/typename-specifier followed by a '(', which may
148e5dd7070Spatrick   // indicate a function-style cast expression.
149e5dd7070Spatrick   // isCXXDeclarationSpecifier will return TPResult::Ambiguous only in such
150e5dd7070Spatrick   // a case.
151e5dd7070Spatrick 
152e5dd7070Spatrick   bool InvalidAsDeclaration = false;
153*12c85518Srobert   TPResult TPR = isCXXDeclarationSpecifier(
154*12c85518Srobert       ImplicitTypenameContext::No, TPResult::False, &InvalidAsDeclaration);
155e5dd7070Spatrick   if (TPR != TPResult::Ambiguous)
156e5dd7070Spatrick     return TPR != TPResult::False; // Returns true for TPResult::True or
157e5dd7070Spatrick                                    // TPResult::Error.
158e5dd7070Spatrick 
159e5dd7070Spatrick   // FIXME: TryParseSimpleDeclaration doesn't look past the first initializer,
160e5dd7070Spatrick   // and so gets some cases wrong. We can't carry on if we've already seen
161e5dd7070Spatrick   // something which makes this statement invalid as a declaration in this case,
162e5dd7070Spatrick   // since it can cause us to misparse valid code. Revisit this once
163e5dd7070Spatrick   // TryParseInitDeclaratorList is fixed.
164e5dd7070Spatrick   if (InvalidAsDeclaration)
165e5dd7070Spatrick     return false;
166e5dd7070Spatrick 
167e5dd7070Spatrick   // FIXME: Add statistics about the number of ambiguous statements encountered
168e5dd7070Spatrick   // and how they were resolved (number of declarations+number of expressions).
169e5dd7070Spatrick 
170e5dd7070Spatrick   // Ok, we have a simple-type-specifier/typename-specifier followed by a '(',
171e5dd7070Spatrick   // or an identifier which doesn't resolve as anything. We need tentative
172e5dd7070Spatrick   // parsing...
173e5dd7070Spatrick 
174e5dd7070Spatrick   {
175e5dd7070Spatrick     RevertingTentativeParsingAction PA(*this);
176e5dd7070Spatrick     TPR = TryParseSimpleDeclaration(AllowForRangeDecl);
177e5dd7070Spatrick   }
178e5dd7070Spatrick 
179e5dd7070Spatrick   // In case of an error, let the declaration parsing code handle it.
180e5dd7070Spatrick   if (TPR == TPResult::Error)
181e5dd7070Spatrick     return true;
182e5dd7070Spatrick 
183e5dd7070Spatrick   // Declarations take precedence over expressions.
184e5dd7070Spatrick   if (TPR == TPResult::Ambiguous)
185e5dd7070Spatrick     TPR = TPResult::True;
186e5dd7070Spatrick 
187e5dd7070Spatrick   assert(TPR == TPResult::True || TPR == TPResult::False);
188e5dd7070Spatrick   return TPR == TPResult::True;
189e5dd7070Spatrick }
190e5dd7070Spatrick 
191e5dd7070Spatrick /// Try to consume a token sequence that we've already identified as
192e5dd7070Spatrick /// (potentially) starting a decl-specifier.
TryConsumeDeclarationSpecifier()193e5dd7070Spatrick Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
194e5dd7070Spatrick   switch (Tok.getKind()) {
195e5dd7070Spatrick   case tok::kw__Atomic:
196e5dd7070Spatrick     if (NextToken().isNot(tok::l_paren)) {
197e5dd7070Spatrick       ConsumeToken();
198e5dd7070Spatrick       break;
199e5dd7070Spatrick     }
200*12c85518Srobert     [[fallthrough]];
201e5dd7070Spatrick   case tok::kw_typeof:
202e5dd7070Spatrick   case tok::kw___attribute:
203*12c85518Srobert #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
204*12c85518Srobert #include "clang/Basic/TransformTypeTraits.def"
205*12c85518Srobert   {
206e5dd7070Spatrick     ConsumeToken();
207e5dd7070Spatrick     if (Tok.isNot(tok::l_paren))
208e5dd7070Spatrick       return TPResult::Error;
209e5dd7070Spatrick     ConsumeParen();
210e5dd7070Spatrick     if (!SkipUntil(tok::r_paren))
211e5dd7070Spatrick       return TPResult::Error;
212e5dd7070Spatrick     break;
213e5dd7070Spatrick   }
214e5dd7070Spatrick 
215e5dd7070Spatrick   case tok::kw_class:
216e5dd7070Spatrick   case tok::kw_struct:
217e5dd7070Spatrick   case tok::kw_union:
218e5dd7070Spatrick   case tok::kw___interface:
219e5dd7070Spatrick   case tok::kw_enum:
220e5dd7070Spatrick     // elaborated-type-specifier:
221e5dd7070Spatrick     //     class-key attribute-specifier-seq[opt]
222e5dd7070Spatrick     //         nested-name-specifier[opt] identifier
223e5dd7070Spatrick     //     class-key nested-name-specifier[opt] template[opt] simple-template-id
224e5dd7070Spatrick     //     enum nested-name-specifier[opt] identifier
225e5dd7070Spatrick     //
226e5dd7070Spatrick     // FIXME: We don't support class-specifiers nor enum-specifiers here.
227e5dd7070Spatrick     ConsumeToken();
228e5dd7070Spatrick 
229e5dd7070Spatrick     // Skip attributes.
230ec727ea7Spatrick     if (!TrySkipAttributes())
231e5dd7070Spatrick       return TPResult::Error;
232e5dd7070Spatrick 
233e5dd7070Spatrick     if (TryAnnotateOptionalCXXScopeToken())
234e5dd7070Spatrick       return TPResult::Error;
235e5dd7070Spatrick     if (Tok.is(tok::annot_cxxscope))
236e5dd7070Spatrick       ConsumeAnnotationToken();
237e5dd7070Spatrick     if (Tok.is(tok::identifier))
238e5dd7070Spatrick       ConsumeToken();
239e5dd7070Spatrick     else if (Tok.is(tok::annot_template_id))
240e5dd7070Spatrick       ConsumeAnnotationToken();
241e5dd7070Spatrick     else
242e5dd7070Spatrick       return TPResult::Error;
243e5dd7070Spatrick     break;
244e5dd7070Spatrick 
245e5dd7070Spatrick   case tok::annot_cxxscope:
246e5dd7070Spatrick     ConsumeAnnotationToken();
247*12c85518Srobert     [[fallthrough]];
248e5dd7070Spatrick   default:
249e5dd7070Spatrick     ConsumeAnyToken();
250e5dd7070Spatrick 
251e5dd7070Spatrick     if (getLangOpts().ObjC && Tok.is(tok::less))
252e5dd7070Spatrick       return TryParseProtocolQualifiers();
253e5dd7070Spatrick     break;
254e5dd7070Spatrick   }
255e5dd7070Spatrick 
256e5dd7070Spatrick   return TPResult::Ambiguous;
257e5dd7070Spatrick }
258e5dd7070Spatrick 
259e5dd7070Spatrick /// simple-declaration:
260e5dd7070Spatrick ///   decl-specifier-seq init-declarator-list[opt] ';'
261e5dd7070Spatrick ///
262e5dd7070Spatrick /// (if AllowForRangeDecl specified)
263e5dd7070Spatrick /// for ( for-range-declaration : for-range-initializer ) statement
264e5dd7070Spatrick /// for-range-declaration:
265e5dd7070Spatrick ///    attribute-specifier-seqopt type-specifier-seq declarator
266e5dd7070Spatrick ///
TryParseSimpleDeclaration(bool AllowForRangeDecl)267e5dd7070Spatrick Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
268e5dd7070Spatrick   if (TryConsumeDeclarationSpecifier() == TPResult::Error)
269e5dd7070Spatrick     return TPResult::Error;
270e5dd7070Spatrick 
271e5dd7070Spatrick   // Two decl-specifiers in a row conclusively disambiguate this as being a
272e5dd7070Spatrick   // simple-declaration. Don't bother calling isCXXDeclarationSpecifier in the
273e5dd7070Spatrick   // overwhelmingly common case that the next token is a '('.
274e5dd7070Spatrick   if (Tok.isNot(tok::l_paren)) {
275*12c85518Srobert     TPResult TPR = isCXXDeclarationSpecifier(ImplicitTypenameContext::No);
276e5dd7070Spatrick     if (TPR == TPResult::Ambiguous)
277e5dd7070Spatrick       return TPResult::True;
278e5dd7070Spatrick     if (TPR == TPResult::True || TPR == TPResult::Error)
279e5dd7070Spatrick       return TPR;
280e5dd7070Spatrick     assert(TPR == TPResult::False);
281e5dd7070Spatrick   }
282e5dd7070Spatrick 
283e5dd7070Spatrick   TPResult TPR = TryParseInitDeclaratorList();
284e5dd7070Spatrick   if (TPR != TPResult::Ambiguous)
285e5dd7070Spatrick     return TPR;
286e5dd7070Spatrick 
287e5dd7070Spatrick   if (Tok.isNot(tok::semi) && (!AllowForRangeDecl || Tok.isNot(tok::colon)))
288e5dd7070Spatrick     return TPResult::False;
289e5dd7070Spatrick 
290e5dd7070Spatrick   return TPResult::Ambiguous;
291e5dd7070Spatrick }
292e5dd7070Spatrick 
293e5dd7070Spatrick /// Tentatively parse an init-declarator-list in order to disambiguate it from
294e5dd7070Spatrick /// an expression.
295e5dd7070Spatrick ///
296e5dd7070Spatrick ///       init-declarator-list:
297e5dd7070Spatrick ///         init-declarator
298e5dd7070Spatrick ///         init-declarator-list ',' init-declarator
299e5dd7070Spatrick ///
300e5dd7070Spatrick ///       init-declarator:
301e5dd7070Spatrick ///         declarator initializer[opt]
302e5dd7070Spatrick /// [GNU]   declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
303e5dd7070Spatrick ///
304e5dd7070Spatrick ///       initializer:
305e5dd7070Spatrick ///         brace-or-equal-initializer
306e5dd7070Spatrick ///         '(' expression-list ')'
307e5dd7070Spatrick ///
308e5dd7070Spatrick ///       brace-or-equal-initializer:
309e5dd7070Spatrick ///         '=' initializer-clause
310e5dd7070Spatrick /// [C++11] braced-init-list
311e5dd7070Spatrick ///
312e5dd7070Spatrick ///       initializer-clause:
313e5dd7070Spatrick ///         assignment-expression
314e5dd7070Spatrick ///         braced-init-list
315e5dd7070Spatrick ///
316e5dd7070Spatrick ///       braced-init-list:
317e5dd7070Spatrick ///         '{' initializer-list ','[opt] '}'
318e5dd7070Spatrick ///         '{' '}'
319e5dd7070Spatrick ///
TryParseInitDeclaratorList()320e5dd7070Spatrick Parser::TPResult Parser::TryParseInitDeclaratorList() {
321*12c85518Srobert   while (true) {
322e5dd7070Spatrick     // declarator
323e5dd7070Spatrick     TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
324e5dd7070Spatrick     if (TPR != TPResult::Ambiguous)
325e5dd7070Spatrick       return TPR;
326e5dd7070Spatrick 
327e5dd7070Spatrick     // [GNU] simple-asm-expr[opt] attributes[opt]
328e5dd7070Spatrick     if (Tok.isOneOf(tok::kw_asm, tok::kw___attribute))
329e5dd7070Spatrick       return TPResult::True;
330e5dd7070Spatrick 
331e5dd7070Spatrick     // initializer[opt]
332e5dd7070Spatrick     if (Tok.is(tok::l_paren)) {
333e5dd7070Spatrick       // Parse through the parens.
334e5dd7070Spatrick       ConsumeParen();
335e5dd7070Spatrick       if (!SkipUntil(tok::r_paren, StopAtSemi))
336e5dd7070Spatrick         return TPResult::Error;
337e5dd7070Spatrick     } else if (Tok.is(tok::l_brace)) {
338e5dd7070Spatrick       // A left-brace here is sufficient to disambiguate the parse; an
339e5dd7070Spatrick       // expression can never be followed directly by a braced-init-list.
340e5dd7070Spatrick       return TPResult::True;
341e5dd7070Spatrick     } else if (Tok.is(tok::equal) || isTokIdentifier_in()) {
342e5dd7070Spatrick       // MSVC and g++ won't examine the rest of declarators if '=' is
343e5dd7070Spatrick       // encountered; they just conclude that we have a declaration.
344e5dd7070Spatrick       // EDG parses the initializer completely, which is the proper behavior
345e5dd7070Spatrick       // for this case.
346e5dd7070Spatrick       //
347e5dd7070Spatrick       // At present, Clang follows MSVC and g++, since the parser does not have
348e5dd7070Spatrick       // the ability to parse an expression fully without recording the
349e5dd7070Spatrick       // results of that parse.
350e5dd7070Spatrick       // FIXME: Handle this case correctly.
351e5dd7070Spatrick       //
352e5dd7070Spatrick       // Also allow 'in' after an Objective-C declaration as in:
353e5dd7070Spatrick       // for (int (^b)(void) in array). Ideally this should be done in the
354e5dd7070Spatrick       // context of parsing for-init-statement of a foreach statement only. But,
355e5dd7070Spatrick       // in any other context 'in' is invalid after a declaration and parser
356e5dd7070Spatrick       // issues the error regardless of outcome of this decision.
357e5dd7070Spatrick       // FIXME: Change if above assumption does not hold.
358e5dd7070Spatrick       return TPResult::True;
359e5dd7070Spatrick     }
360e5dd7070Spatrick 
361e5dd7070Spatrick     if (!TryConsumeToken(tok::comma))
362e5dd7070Spatrick       break;
363e5dd7070Spatrick   }
364e5dd7070Spatrick 
365e5dd7070Spatrick   return TPResult::Ambiguous;
366e5dd7070Spatrick }
367e5dd7070Spatrick 
368e5dd7070Spatrick struct Parser::ConditionDeclarationOrInitStatementState {
369e5dd7070Spatrick   Parser &P;
370e5dd7070Spatrick   bool CanBeExpression = true;
371e5dd7070Spatrick   bool CanBeCondition = true;
372e5dd7070Spatrick   bool CanBeInitStatement;
373e5dd7070Spatrick   bool CanBeForRangeDecl;
374e5dd7070Spatrick 
ConditionDeclarationOrInitStatementStateParser::ConditionDeclarationOrInitStatementState375e5dd7070Spatrick   ConditionDeclarationOrInitStatementState(Parser &P, bool CanBeInitStatement,
376e5dd7070Spatrick                                            bool CanBeForRangeDecl)
377e5dd7070Spatrick       : P(P), CanBeInitStatement(CanBeInitStatement),
378e5dd7070Spatrick         CanBeForRangeDecl(CanBeForRangeDecl) {}
379e5dd7070Spatrick 
resolvedParser::ConditionDeclarationOrInitStatementState380e5dd7070Spatrick   bool resolved() {
381e5dd7070Spatrick     return CanBeExpression + CanBeCondition + CanBeInitStatement +
382e5dd7070Spatrick                CanBeForRangeDecl < 2;
383e5dd7070Spatrick   }
384e5dd7070Spatrick 
markNotExpressionParser::ConditionDeclarationOrInitStatementState385e5dd7070Spatrick   void markNotExpression() {
386e5dd7070Spatrick     CanBeExpression = false;
387e5dd7070Spatrick 
388e5dd7070Spatrick     if (!resolved()) {
389e5dd7070Spatrick       // FIXME: Unify the parsing codepaths for condition variables and
390e5dd7070Spatrick       // simple-declarations so that we don't need to eagerly figure out which
391e5dd7070Spatrick       // kind we have here. (Just parse init-declarators until we reach a
392e5dd7070Spatrick       // semicolon or right paren.)
393e5dd7070Spatrick       RevertingTentativeParsingAction PA(P);
394e5dd7070Spatrick       if (CanBeForRangeDecl) {
395e5dd7070Spatrick         // Skip until we hit a ')', ';', or a ':' with no matching '?'.
396e5dd7070Spatrick         // The final case is a for range declaration, the rest are not.
397e5dd7070Spatrick         unsigned QuestionColonDepth = 0;
398a9ac8606Spatrick         while (true) {
399e5dd7070Spatrick           P.SkipUntil({tok::r_paren, tok::semi, tok::question, tok::colon},
400e5dd7070Spatrick                       StopBeforeMatch);
401e5dd7070Spatrick           if (P.Tok.is(tok::question))
402e5dd7070Spatrick             ++QuestionColonDepth;
403e5dd7070Spatrick           else if (P.Tok.is(tok::colon)) {
404e5dd7070Spatrick             if (QuestionColonDepth)
405e5dd7070Spatrick               --QuestionColonDepth;
406e5dd7070Spatrick             else {
407e5dd7070Spatrick               CanBeCondition = CanBeInitStatement = false;
408e5dd7070Spatrick               return;
409e5dd7070Spatrick             }
410e5dd7070Spatrick           } else {
411e5dd7070Spatrick             CanBeForRangeDecl = false;
412e5dd7070Spatrick             break;
413e5dd7070Spatrick           }
414e5dd7070Spatrick           P.ConsumeToken();
415e5dd7070Spatrick         }
416e5dd7070Spatrick       } else {
417e5dd7070Spatrick         // Just skip until we hit a ')' or ';'.
418e5dd7070Spatrick         P.SkipUntil(tok::r_paren, tok::semi, StopBeforeMatch);
419e5dd7070Spatrick       }
420e5dd7070Spatrick       if (P.Tok.isNot(tok::r_paren))
421e5dd7070Spatrick         CanBeCondition = CanBeForRangeDecl = false;
422e5dd7070Spatrick       if (P.Tok.isNot(tok::semi))
423e5dd7070Spatrick         CanBeInitStatement = false;
424e5dd7070Spatrick     }
425e5dd7070Spatrick   }
426e5dd7070Spatrick 
markNotConditionParser::ConditionDeclarationOrInitStatementState427e5dd7070Spatrick   bool markNotCondition() {
428e5dd7070Spatrick     CanBeCondition = false;
429e5dd7070Spatrick     return resolved();
430e5dd7070Spatrick   }
431e5dd7070Spatrick 
markNotForRangeDeclParser::ConditionDeclarationOrInitStatementState432e5dd7070Spatrick   bool markNotForRangeDecl() {
433e5dd7070Spatrick     CanBeForRangeDecl = false;
434e5dd7070Spatrick     return resolved();
435e5dd7070Spatrick   }
436e5dd7070Spatrick 
updateParser::ConditionDeclarationOrInitStatementState437e5dd7070Spatrick   bool update(TPResult IsDecl) {
438e5dd7070Spatrick     switch (IsDecl) {
439e5dd7070Spatrick     case TPResult::True:
440e5dd7070Spatrick       markNotExpression();
441e5dd7070Spatrick       assert(resolved() && "can't continue after tentative parsing bails out");
442e5dd7070Spatrick       break;
443e5dd7070Spatrick     case TPResult::False:
444e5dd7070Spatrick       CanBeCondition = CanBeInitStatement = CanBeForRangeDecl = false;
445e5dd7070Spatrick       break;
446e5dd7070Spatrick     case TPResult::Ambiguous:
447e5dd7070Spatrick       break;
448e5dd7070Spatrick     case TPResult::Error:
449e5dd7070Spatrick       CanBeExpression = CanBeCondition = CanBeInitStatement =
450e5dd7070Spatrick           CanBeForRangeDecl = false;
451e5dd7070Spatrick       break;
452e5dd7070Spatrick     }
453e5dd7070Spatrick     return resolved();
454e5dd7070Spatrick   }
455e5dd7070Spatrick 
resultParser::ConditionDeclarationOrInitStatementState456e5dd7070Spatrick   ConditionOrInitStatement result() const {
457e5dd7070Spatrick     assert(CanBeExpression + CanBeCondition + CanBeInitStatement +
458e5dd7070Spatrick                    CanBeForRangeDecl < 2 &&
459e5dd7070Spatrick            "result called but not yet resolved");
460e5dd7070Spatrick     if (CanBeExpression)
461e5dd7070Spatrick       return ConditionOrInitStatement::Expression;
462e5dd7070Spatrick     if (CanBeCondition)
463e5dd7070Spatrick       return ConditionOrInitStatement::ConditionDecl;
464e5dd7070Spatrick     if (CanBeInitStatement)
465e5dd7070Spatrick       return ConditionOrInitStatement::InitStmtDecl;
466e5dd7070Spatrick     if (CanBeForRangeDecl)
467e5dd7070Spatrick       return ConditionOrInitStatement::ForRangeDecl;
468e5dd7070Spatrick     return ConditionOrInitStatement::Error;
469e5dd7070Spatrick   }
470e5dd7070Spatrick };
471e5dd7070Spatrick 
isEnumBase(bool AllowSemi)472ec727ea7Spatrick bool Parser::isEnumBase(bool AllowSemi) {
473ec727ea7Spatrick   assert(Tok.is(tok::colon) && "should be looking at the ':'");
474ec727ea7Spatrick 
475ec727ea7Spatrick   RevertingTentativeParsingAction PA(*this);
476ec727ea7Spatrick   // ':'
477ec727ea7Spatrick   ConsumeToken();
478ec727ea7Spatrick 
479ec727ea7Spatrick   // type-specifier-seq
480ec727ea7Spatrick   bool InvalidAsDeclSpec = false;
481ec727ea7Spatrick   // FIXME: We could disallow non-type decl-specifiers here, but it makes no
482ec727ea7Spatrick   // difference: those specifiers are ill-formed regardless of the
483ec727ea7Spatrick   // interpretation.
484*12c85518Srobert   TPResult R = isCXXDeclarationSpecifier(ImplicitTypenameContext::No,
485*12c85518Srobert                                          /*BracedCastResult=*/TPResult::True,
486ec727ea7Spatrick                                          &InvalidAsDeclSpec);
487ec727ea7Spatrick   if (R == TPResult::Ambiguous) {
488ec727ea7Spatrick     // We either have a decl-specifier followed by '(' or an undeclared
489ec727ea7Spatrick     // identifier.
490ec727ea7Spatrick     if (TryConsumeDeclarationSpecifier() == TPResult::Error)
491ec727ea7Spatrick       return true;
492ec727ea7Spatrick 
493ec727ea7Spatrick     // If we get to the end of the enum-base, we hit either a '{' or a ';'.
494ec727ea7Spatrick     // Don't bother checking the enumerator-list.
495ec727ea7Spatrick     if (Tok.is(tok::l_brace) || (AllowSemi && Tok.is(tok::semi)))
496ec727ea7Spatrick       return true;
497ec727ea7Spatrick 
498ec727ea7Spatrick     // A second decl-specifier unambiguously indicatges an enum-base.
499*12c85518Srobert     R = isCXXDeclarationSpecifier(ImplicitTypenameContext::No, TPResult::True,
500*12c85518Srobert                                   &InvalidAsDeclSpec);
501ec727ea7Spatrick   }
502ec727ea7Spatrick 
503ec727ea7Spatrick   return R != TPResult::False;
504ec727ea7Spatrick }
505ec727ea7Spatrick 
506e5dd7070Spatrick /// Disambiguates between a declaration in a condition, a
507e5dd7070Spatrick /// simple-declaration in an init-statement, and an expression for
508e5dd7070Spatrick /// a condition of a if/switch statement.
509e5dd7070Spatrick ///
510e5dd7070Spatrick ///       condition:
511e5dd7070Spatrick ///         expression
512e5dd7070Spatrick ///         type-specifier-seq declarator '=' assignment-expression
513e5dd7070Spatrick /// [C++11] type-specifier-seq declarator '=' initializer-clause
514e5dd7070Spatrick /// [C++11] type-specifier-seq declarator braced-init-list
515e5dd7070Spatrick /// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
516e5dd7070Spatrick ///             '=' assignment-expression
517e5dd7070Spatrick ///       simple-declaration:
518e5dd7070Spatrick ///         decl-specifier-seq init-declarator-list[opt] ';'
519e5dd7070Spatrick ///
520e5dd7070Spatrick /// Note that, unlike isCXXSimpleDeclaration, we must disambiguate all the way
521e5dd7070Spatrick /// to the ';' to disambiguate cases like 'int(x))' (an expression) from
522e5dd7070Spatrick /// 'int(x);' (a simple-declaration in an init-statement).
523e5dd7070Spatrick Parser::ConditionOrInitStatement
isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement,bool CanBeForRangeDecl)524e5dd7070Spatrick Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement,
525e5dd7070Spatrick                                                  bool CanBeForRangeDecl) {
526e5dd7070Spatrick   ConditionDeclarationOrInitStatementState State(*this, CanBeInitStatement,
527e5dd7070Spatrick                                                  CanBeForRangeDecl);
528e5dd7070Spatrick 
529*12c85518Srobert   if (CanBeInitStatement && Tok.is(tok::kw_using))
530*12c85518Srobert     return ConditionOrInitStatement::InitStmtDecl;
531*12c85518Srobert   if (State.update(isCXXDeclarationSpecifier(ImplicitTypenameContext::No)))
532e5dd7070Spatrick     return State.result();
533e5dd7070Spatrick 
534e5dd7070Spatrick   // It might be a declaration; we need tentative parsing.
535e5dd7070Spatrick   RevertingTentativeParsingAction PA(*this);
536e5dd7070Spatrick 
537e5dd7070Spatrick   // FIXME: A tag definition unambiguously tells us this is an init-statement.
538e5dd7070Spatrick   if (State.update(TryConsumeDeclarationSpecifier()))
539e5dd7070Spatrick     return State.result();
540e5dd7070Spatrick   assert(Tok.is(tok::l_paren) && "Expected '('");
541e5dd7070Spatrick 
542e5dd7070Spatrick   while (true) {
543e5dd7070Spatrick     // Consume a declarator.
544e5dd7070Spatrick     if (State.update(TryParseDeclarator(false/*mayBeAbstract*/)))
545e5dd7070Spatrick       return State.result();
546e5dd7070Spatrick 
547e5dd7070Spatrick     // Attributes, asm label, or an initializer imply this is not an expression.
548e5dd7070Spatrick     // FIXME: Disambiguate properly after an = instead of assuming that it's a
549e5dd7070Spatrick     // valid declaration.
550e5dd7070Spatrick     if (Tok.isOneOf(tok::equal, tok::kw_asm, tok::kw___attribute) ||
551e5dd7070Spatrick         (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))) {
552e5dd7070Spatrick       State.markNotExpression();
553e5dd7070Spatrick       return State.result();
554e5dd7070Spatrick     }
555e5dd7070Spatrick 
556e5dd7070Spatrick     // A colon here identifies a for-range declaration.
557e5dd7070Spatrick     if (State.CanBeForRangeDecl && Tok.is(tok::colon))
558e5dd7070Spatrick       return ConditionOrInitStatement::ForRangeDecl;
559e5dd7070Spatrick 
560e5dd7070Spatrick     // At this point, it can't be a condition any more, because a condition
561e5dd7070Spatrick     // must have a brace-or-equal-initializer.
562e5dd7070Spatrick     if (State.markNotCondition())
563e5dd7070Spatrick       return State.result();
564e5dd7070Spatrick 
565e5dd7070Spatrick     // Likewise, it can't be a for-range declaration any more.
566e5dd7070Spatrick     if (State.markNotForRangeDecl())
567e5dd7070Spatrick       return State.result();
568e5dd7070Spatrick 
569e5dd7070Spatrick     // A parenthesized initializer could be part of an expression or a
570e5dd7070Spatrick     // simple-declaration.
571e5dd7070Spatrick     if (Tok.is(tok::l_paren)) {
572e5dd7070Spatrick       ConsumeParen();
573e5dd7070Spatrick       SkipUntil(tok::r_paren, StopAtSemi);
574e5dd7070Spatrick     }
575e5dd7070Spatrick 
576e5dd7070Spatrick     if (!TryConsumeToken(tok::comma))
577e5dd7070Spatrick       break;
578e5dd7070Spatrick   }
579e5dd7070Spatrick 
580e5dd7070Spatrick   // We reached the end. If it can now be some kind of decl, then it is.
581e5dd7070Spatrick   if (State.CanBeCondition && Tok.is(tok::r_paren))
582e5dd7070Spatrick     return ConditionOrInitStatement::ConditionDecl;
583e5dd7070Spatrick   else if (State.CanBeInitStatement && Tok.is(tok::semi))
584e5dd7070Spatrick     return ConditionOrInitStatement::InitStmtDecl;
585e5dd7070Spatrick   else
586e5dd7070Spatrick     return ConditionOrInitStatement::Expression;
587e5dd7070Spatrick }
588e5dd7070Spatrick 
589e5dd7070Spatrick   /// Determine whether the next set of tokens contains a type-id.
590e5dd7070Spatrick   ///
591e5dd7070Spatrick   /// The context parameter states what context we're parsing right
592e5dd7070Spatrick   /// now, which affects how this routine copes with the token
593e5dd7070Spatrick   /// following the type-id. If the context is TypeIdInParens, we have
594e5dd7070Spatrick   /// already parsed the '(' and we will cease lookahead when we hit
595e5dd7070Spatrick   /// the corresponding ')'. If the context is
596e5dd7070Spatrick   /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
597e5dd7070Spatrick   /// before this template argument, and will cease lookahead when we
598e5dd7070Spatrick   /// hit a '>', '>>' (in C++0x), or ','; or, in C++0x, an ellipsis immediately
599e5dd7070Spatrick   /// preceding such. Returns true for a type-id and false for an expression.
600e5dd7070Spatrick   /// If during the disambiguation process a parsing error is encountered,
601e5dd7070Spatrick   /// the function returns true to let the declaration parsing code handle it.
602e5dd7070Spatrick   ///
603e5dd7070Spatrick   /// type-id:
604e5dd7070Spatrick   ///   type-specifier-seq abstract-declarator[opt]
605e5dd7070Spatrick   ///
isCXXTypeId(TentativeCXXTypeIdContext Context,bool & isAmbiguous)606e5dd7070Spatrick bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
607e5dd7070Spatrick 
608e5dd7070Spatrick   isAmbiguous = false;
609e5dd7070Spatrick 
610e5dd7070Spatrick   // C++ 8.2p2:
611e5dd7070Spatrick   // The ambiguity arising from the similarity between a function-style cast and
612e5dd7070Spatrick   // a type-id can occur in different contexts. The ambiguity appears as a
613e5dd7070Spatrick   // choice between a function-style cast expression and a declaration of a
614e5dd7070Spatrick   // type. The resolution is that any construct that could possibly be a type-id
615e5dd7070Spatrick   // in its syntactic context shall be considered a type-id.
616e5dd7070Spatrick 
617*12c85518Srobert   TPResult TPR = isCXXDeclarationSpecifier(ImplicitTypenameContext::No);
618e5dd7070Spatrick   if (TPR != TPResult::Ambiguous)
619e5dd7070Spatrick     return TPR != TPResult::False; // Returns true for TPResult::True or
620e5dd7070Spatrick                                      // TPResult::Error.
621e5dd7070Spatrick 
622e5dd7070Spatrick   // FIXME: Add statistics about the number of ambiguous statements encountered
623e5dd7070Spatrick   // and how they were resolved (number of declarations+number of expressions).
624e5dd7070Spatrick 
625e5dd7070Spatrick   // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
626e5dd7070Spatrick   // We need tentative parsing...
627e5dd7070Spatrick 
628e5dd7070Spatrick   RevertingTentativeParsingAction PA(*this);
629e5dd7070Spatrick 
630e5dd7070Spatrick   // type-specifier-seq
631e5dd7070Spatrick   TryConsumeDeclarationSpecifier();
632e5dd7070Spatrick   assert(Tok.is(tok::l_paren) && "Expected '('");
633e5dd7070Spatrick 
634e5dd7070Spatrick   // declarator
635e5dd7070Spatrick   TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
636e5dd7070Spatrick 
637e5dd7070Spatrick   // In case of an error, let the declaration parsing code handle it.
638e5dd7070Spatrick   if (TPR == TPResult::Error)
639e5dd7070Spatrick     TPR = TPResult::True;
640e5dd7070Spatrick 
641e5dd7070Spatrick   if (TPR == TPResult::Ambiguous) {
642e5dd7070Spatrick     // We are supposed to be inside parens, so if after the abstract declarator
643e5dd7070Spatrick     // we encounter a ')' this is a type-id, otherwise it's an expression.
644e5dd7070Spatrick     if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
645e5dd7070Spatrick       TPR = TPResult::True;
646e5dd7070Spatrick       isAmbiguous = true;
647e5dd7070Spatrick 
648e5dd7070Spatrick     // We are supposed to be inside a template argument, so if after
649e5dd7070Spatrick     // the abstract declarator we encounter a '>', '>>' (in C++0x), or
650e5dd7070Spatrick     // ','; or, in C++0x, an ellipsis immediately preceding such, this
651e5dd7070Spatrick     // is a type-id. Otherwise, it's an expression.
652e5dd7070Spatrick     } else if (Context == TypeIdAsTemplateArgument &&
653e5dd7070Spatrick                (Tok.isOneOf(tok::greater, tok::comma) ||
654e5dd7070Spatrick                 (getLangOpts().CPlusPlus11 &&
655e5dd7070Spatrick                  (Tok.isOneOf(tok::greatergreater,
656e5dd7070Spatrick                               tok::greatergreatergreater) ||
657e5dd7070Spatrick                   (Tok.is(tok::ellipsis) &&
658e5dd7070Spatrick                    NextToken().isOneOf(tok::greater, tok::greatergreater,
659e5dd7070Spatrick                                        tok::greatergreatergreater,
660e5dd7070Spatrick                                        tok::comma)))))) {
661e5dd7070Spatrick       TPR = TPResult::True;
662e5dd7070Spatrick       isAmbiguous = true;
663e5dd7070Spatrick 
664e5dd7070Spatrick     } else
665e5dd7070Spatrick       TPR = TPResult::False;
666e5dd7070Spatrick   }
667e5dd7070Spatrick 
668e5dd7070Spatrick   assert(TPR == TPResult::True || TPR == TPResult::False);
669e5dd7070Spatrick   return TPR == TPResult::True;
670e5dd7070Spatrick }
671e5dd7070Spatrick 
672e5dd7070Spatrick /// Returns true if this is a C++11 attribute-specifier. Per
673e5dd7070Spatrick /// C++11 [dcl.attr.grammar]p6, two consecutive left square bracket tokens
674e5dd7070Spatrick /// always introduce an attribute. In Objective-C++11, this rule does not
675e5dd7070Spatrick /// apply if either '[' begins a message-send.
676e5dd7070Spatrick ///
677e5dd7070Spatrick /// If Disambiguate is true, we try harder to determine whether a '[[' starts
678e5dd7070Spatrick /// an attribute-specifier, and return CAK_InvalidAttributeSpecifier if not.
679e5dd7070Spatrick ///
680e5dd7070Spatrick /// If OuterMightBeMessageSend is true, we assume the outer '[' is either an
681e5dd7070Spatrick /// Obj-C message send or the start of an attribute. Otherwise, we assume it
682e5dd7070Spatrick /// is not an Obj-C message send.
683e5dd7070Spatrick ///
684e5dd7070Spatrick /// C++11 [dcl.attr.grammar]:
685e5dd7070Spatrick ///
686e5dd7070Spatrick ///     attribute-specifier:
687e5dd7070Spatrick ///         '[' '[' attribute-list ']' ']'
688e5dd7070Spatrick ///         alignment-specifier
689e5dd7070Spatrick ///
690e5dd7070Spatrick ///     attribute-list:
691e5dd7070Spatrick ///         attribute[opt]
692e5dd7070Spatrick ///         attribute-list ',' attribute[opt]
693e5dd7070Spatrick ///         attribute '...'
694e5dd7070Spatrick ///         attribute-list ',' attribute '...'
695e5dd7070Spatrick ///
696e5dd7070Spatrick ///     attribute:
697e5dd7070Spatrick ///         attribute-token attribute-argument-clause[opt]
698e5dd7070Spatrick ///
699e5dd7070Spatrick ///     attribute-token:
700e5dd7070Spatrick ///         identifier
701e5dd7070Spatrick ///         identifier '::' identifier
702e5dd7070Spatrick ///
703e5dd7070Spatrick ///     attribute-argument-clause:
704e5dd7070Spatrick ///         '(' balanced-token-seq ')'
705e5dd7070Spatrick Parser::CXX11AttributeKind
isCXX11AttributeSpecifier(bool Disambiguate,bool OuterMightBeMessageSend)706e5dd7070Spatrick Parser::isCXX11AttributeSpecifier(bool Disambiguate,
707e5dd7070Spatrick                                   bool OuterMightBeMessageSend) {
708e5dd7070Spatrick   if (Tok.is(tok::kw_alignas))
709e5dd7070Spatrick     return CAK_AttributeSpecifier;
710e5dd7070Spatrick 
711e5dd7070Spatrick   if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
712e5dd7070Spatrick     return CAK_NotAttributeSpecifier;
713e5dd7070Spatrick 
714e5dd7070Spatrick   // No tentative parsing if we don't need to look for ']]' or a lambda.
715e5dd7070Spatrick   if (!Disambiguate && !getLangOpts().ObjC)
716e5dd7070Spatrick     return CAK_AttributeSpecifier;
717e5dd7070Spatrick 
718e5dd7070Spatrick   // '[[using ns: ...]]' is an attribute.
719e5dd7070Spatrick   if (GetLookAheadToken(2).is(tok::kw_using))
720e5dd7070Spatrick     return CAK_AttributeSpecifier;
721e5dd7070Spatrick 
722e5dd7070Spatrick   RevertingTentativeParsingAction PA(*this);
723e5dd7070Spatrick 
724e5dd7070Spatrick   // Opening brackets were checked for above.
725e5dd7070Spatrick   ConsumeBracket();
726e5dd7070Spatrick 
727e5dd7070Spatrick   if (!getLangOpts().ObjC) {
728e5dd7070Spatrick     ConsumeBracket();
729e5dd7070Spatrick 
730e5dd7070Spatrick     bool IsAttribute = SkipUntil(tok::r_square);
731e5dd7070Spatrick     IsAttribute &= Tok.is(tok::r_square);
732e5dd7070Spatrick 
733e5dd7070Spatrick     return IsAttribute ? CAK_AttributeSpecifier : CAK_InvalidAttributeSpecifier;
734e5dd7070Spatrick   }
735e5dd7070Spatrick 
736e5dd7070Spatrick   // In Obj-C++11, we need to distinguish four situations:
737e5dd7070Spatrick   //  1a) int x[[attr]];                     C++11 attribute.
738e5dd7070Spatrick   //  1b) [[attr]];                          C++11 statement attribute.
739e5dd7070Spatrick   //   2) int x[[obj](){ return 1; }()];     Lambda in array size/index.
740e5dd7070Spatrick   //  3a) int x[[obj get]];                  Message send in array size/index.
741e5dd7070Spatrick   //  3b) [[Class alloc] init];              Message send in message send.
742e5dd7070Spatrick   //   4) [[obj]{ return self; }() doStuff]; Lambda in message send.
743e5dd7070Spatrick   // (1) is an attribute, (2) is ill-formed, and (3) and (4) are accepted.
744e5dd7070Spatrick 
745e5dd7070Spatrick   // Check to see if this is a lambda-expression.
746e5dd7070Spatrick   // FIXME: If this disambiguation is too slow, fold the tentative lambda parse
747e5dd7070Spatrick   // into the tentative attribute parse below.
748e5dd7070Spatrick   {
749e5dd7070Spatrick     RevertingTentativeParsingAction LambdaTPA(*this);
750e5dd7070Spatrick     LambdaIntroducer Intro;
751e5dd7070Spatrick     LambdaIntroducerTentativeParse Tentative;
752e5dd7070Spatrick     if (ParseLambdaIntroducer(Intro, &Tentative)) {
753e5dd7070Spatrick       // We hit a hard error after deciding this was not an attribute.
754e5dd7070Spatrick       // FIXME: Don't parse and annotate expressions when disambiguating
755e5dd7070Spatrick       // against an attribute.
756e5dd7070Spatrick       return CAK_NotAttributeSpecifier;
757e5dd7070Spatrick     }
758e5dd7070Spatrick 
759e5dd7070Spatrick     switch (Tentative) {
760e5dd7070Spatrick     case LambdaIntroducerTentativeParse::MessageSend:
761e5dd7070Spatrick       // Case 3: The inner construct is definitely a message send, so the
762e5dd7070Spatrick       // outer construct is definitely not an attribute.
763e5dd7070Spatrick       return CAK_NotAttributeSpecifier;
764e5dd7070Spatrick 
765e5dd7070Spatrick     case LambdaIntroducerTentativeParse::Success:
766e5dd7070Spatrick     case LambdaIntroducerTentativeParse::Incomplete:
767e5dd7070Spatrick       // This is a lambda-introducer or attribute-specifier.
768e5dd7070Spatrick       if (Tok.is(tok::r_square))
769e5dd7070Spatrick         // Case 1: C++11 attribute.
770e5dd7070Spatrick         return CAK_AttributeSpecifier;
771e5dd7070Spatrick 
772e5dd7070Spatrick       if (OuterMightBeMessageSend)
773e5dd7070Spatrick         // Case 4: Lambda in message send.
774e5dd7070Spatrick         return CAK_NotAttributeSpecifier;
775e5dd7070Spatrick 
776e5dd7070Spatrick       // Case 2: Lambda in array size / index.
777e5dd7070Spatrick       return CAK_InvalidAttributeSpecifier;
778e5dd7070Spatrick 
779e5dd7070Spatrick     case LambdaIntroducerTentativeParse::Invalid:
780e5dd7070Spatrick       // No idea what this is; we couldn't parse it as a lambda-introducer.
781e5dd7070Spatrick       // Might still be an attribute-specifier or a message send.
782e5dd7070Spatrick       break;
783e5dd7070Spatrick     }
784e5dd7070Spatrick   }
785e5dd7070Spatrick 
786e5dd7070Spatrick   ConsumeBracket();
787e5dd7070Spatrick 
788e5dd7070Spatrick   // If we don't have a lambda-introducer, then we have an attribute or a
789e5dd7070Spatrick   // message-send.
790e5dd7070Spatrick   bool IsAttribute = true;
791e5dd7070Spatrick   while (Tok.isNot(tok::r_square)) {
792e5dd7070Spatrick     if (Tok.is(tok::comma)) {
793e5dd7070Spatrick       // Case 1: Stray commas can only occur in attributes.
794e5dd7070Spatrick       return CAK_AttributeSpecifier;
795e5dd7070Spatrick     }
796e5dd7070Spatrick 
797e5dd7070Spatrick     // Parse the attribute-token, if present.
798e5dd7070Spatrick     // C++11 [dcl.attr.grammar]:
799e5dd7070Spatrick     //   If a keyword or an alternative token that satisfies the syntactic
800e5dd7070Spatrick     //   requirements of an identifier is contained in an attribute-token,
801e5dd7070Spatrick     //   it is considered an identifier.
802e5dd7070Spatrick     SourceLocation Loc;
803e5dd7070Spatrick     if (!TryParseCXX11AttributeIdentifier(Loc)) {
804e5dd7070Spatrick       IsAttribute = false;
805e5dd7070Spatrick       break;
806e5dd7070Spatrick     }
807e5dd7070Spatrick     if (Tok.is(tok::coloncolon)) {
808e5dd7070Spatrick       ConsumeToken();
809e5dd7070Spatrick       if (!TryParseCXX11AttributeIdentifier(Loc)) {
810e5dd7070Spatrick         IsAttribute = false;
811e5dd7070Spatrick         break;
812e5dd7070Spatrick       }
813e5dd7070Spatrick     }
814e5dd7070Spatrick 
815e5dd7070Spatrick     // Parse the attribute-argument-clause, if present.
816e5dd7070Spatrick     if (Tok.is(tok::l_paren)) {
817e5dd7070Spatrick       ConsumeParen();
818e5dd7070Spatrick       if (!SkipUntil(tok::r_paren)) {
819e5dd7070Spatrick         IsAttribute = false;
820e5dd7070Spatrick         break;
821e5dd7070Spatrick       }
822e5dd7070Spatrick     }
823e5dd7070Spatrick 
824e5dd7070Spatrick     TryConsumeToken(tok::ellipsis);
825e5dd7070Spatrick 
826e5dd7070Spatrick     if (!TryConsumeToken(tok::comma))
827e5dd7070Spatrick       break;
828e5dd7070Spatrick   }
829e5dd7070Spatrick 
830e5dd7070Spatrick   // An attribute must end ']]'.
831e5dd7070Spatrick   if (IsAttribute) {
832e5dd7070Spatrick     if (Tok.is(tok::r_square)) {
833e5dd7070Spatrick       ConsumeBracket();
834e5dd7070Spatrick       IsAttribute = Tok.is(tok::r_square);
835e5dd7070Spatrick     } else {
836e5dd7070Spatrick       IsAttribute = false;
837e5dd7070Spatrick     }
838e5dd7070Spatrick   }
839e5dd7070Spatrick 
840e5dd7070Spatrick   if (IsAttribute)
841e5dd7070Spatrick     // Case 1: C++11 statement attribute.
842e5dd7070Spatrick     return CAK_AttributeSpecifier;
843e5dd7070Spatrick 
844e5dd7070Spatrick   // Case 3: Message send.
845e5dd7070Spatrick   return CAK_NotAttributeSpecifier;
846e5dd7070Spatrick }
847e5dd7070Spatrick 
TrySkipAttributes()848ec727ea7Spatrick bool Parser::TrySkipAttributes() {
849ec727ea7Spatrick   while (Tok.isOneOf(tok::l_square, tok::kw___attribute, tok::kw___declspec,
850ec727ea7Spatrick                      tok::kw_alignas)) {
851ec727ea7Spatrick     if (Tok.is(tok::l_square)) {
852ec727ea7Spatrick       ConsumeBracket();
853ec727ea7Spatrick       if (Tok.isNot(tok::l_square))
854ec727ea7Spatrick         return false;
855ec727ea7Spatrick       ConsumeBracket();
856ec727ea7Spatrick       if (!SkipUntil(tok::r_square) || Tok.isNot(tok::r_square))
857ec727ea7Spatrick         return false;
858ec727ea7Spatrick       // Note that explicitly checking for `[[` and `]]` allows to fail as
859ec727ea7Spatrick       // expected in the case of the Objective-C message send syntax.
860ec727ea7Spatrick       ConsumeBracket();
861ec727ea7Spatrick     } else {
862ec727ea7Spatrick       ConsumeToken();
863ec727ea7Spatrick       if (Tok.isNot(tok::l_paren))
864ec727ea7Spatrick         return false;
865ec727ea7Spatrick       ConsumeParen();
866ec727ea7Spatrick       if (!SkipUntil(tok::r_paren))
867ec727ea7Spatrick         return false;
868ec727ea7Spatrick     }
869ec727ea7Spatrick   }
870ec727ea7Spatrick 
871ec727ea7Spatrick   return true;
872ec727ea7Spatrick }
873ec727ea7Spatrick 
TryParsePtrOperatorSeq()874e5dd7070Spatrick Parser::TPResult Parser::TryParsePtrOperatorSeq() {
875e5dd7070Spatrick   while (true) {
876e5dd7070Spatrick     if (TryAnnotateOptionalCXXScopeToken(true))
877e5dd7070Spatrick       return TPResult::Error;
878e5dd7070Spatrick 
879e5dd7070Spatrick     if (Tok.isOneOf(tok::star, tok::amp, tok::caret, tok::ampamp) ||
880e5dd7070Spatrick         (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
881e5dd7070Spatrick       // ptr-operator
882e5dd7070Spatrick       ConsumeAnyToken();
883ec727ea7Spatrick 
884ec727ea7Spatrick       // Skip attributes.
885ec727ea7Spatrick       if (!TrySkipAttributes())
886ec727ea7Spatrick         return TPResult::Error;
887ec727ea7Spatrick 
888e5dd7070Spatrick       while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict,
889e5dd7070Spatrick                          tok::kw__Nonnull, tok::kw__Nullable,
890a9ac8606Spatrick                          tok::kw__Nullable_result, tok::kw__Null_unspecified,
891a9ac8606Spatrick                          tok::kw__Atomic))
892e5dd7070Spatrick         ConsumeToken();
893e5dd7070Spatrick     } else {
894e5dd7070Spatrick       return TPResult::True;
895e5dd7070Spatrick     }
896e5dd7070Spatrick   }
897e5dd7070Spatrick }
898e5dd7070Spatrick 
899e5dd7070Spatrick ///         operator-function-id:
900e5dd7070Spatrick ///           'operator' operator
901e5dd7070Spatrick ///
902e5dd7070Spatrick ///         operator: one of
903e5dd7070Spatrick ///           new  delete  new[]  delete[]  +  -  *  /  %  ^  [...]
904e5dd7070Spatrick ///
905e5dd7070Spatrick ///         conversion-function-id:
906e5dd7070Spatrick ///           'operator' conversion-type-id
907e5dd7070Spatrick ///
908e5dd7070Spatrick ///         conversion-type-id:
909e5dd7070Spatrick ///           type-specifier-seq conversion-declarator[opt]
910e5dd7070Spatrick ///
911e5dd7070Spatrick ///         conversion-declarator:
912e5dd7070Spatrick ///           ptr-operator conversion-declarator[opt]
913e5dd7070Spatrick ///
914e5dd7070Spatrick ///         literal-operator-id:
915e5dd7070Spatrick ///           'operator' string-literal identifier
916e5dd7070Spatrick ///           'operator' user-defined-string-literal
TryParseOperatorId()917e5dd7070Spatrick Parser::TPResult Parser::TryParseOperatorId() {
918e5dd7070Spatrick   assert(Tok.is(tok::kw_operator));
919e5dd7070Spatrick   ConsumeToken();
920e5dd7070Spatrick 
921e5dd7070Spatrick   // Maybe this is an operator-function-id.
922e5dd7070Spatrick   switch (Tok.getKind()) {
923e5dd7070Spatrick   case tok::kw_new: case tok::kw_delete:
924e5dd7070Spatrick     ConsumeToken();
925e5dd7070Spatrick     if (Tok.is(tok::l_square) && NextToken().is(tok::r_square)) {
926e5dd7070Spatrick       ConsumeBracket();
927e5dd7070Spatrick       ConsumeBracket();
928e5dd7070Spatrick     }
929e5dd7070Spatrick     return TPResult::True;
930e5dd7070Spatrick 
931e5dd7070Spatrick #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemOnly) \
932e5dd7070Spatrick   case tok::Token:
933e5dd7070Spatrick #define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemOnly)
934e5dd7070Spatrick #include "clang/Basic/OperatorKinds.def"
935e5dd7070Spatrick     ConsumeToken();
936e5dd7070Spatrick     return TPResult::True;
937e5dd7070Spatrick 
938e5dd7070Spatrick   case tok::l_square:
939e5dd7070Spatrick     if (NextToken().is(tok::r_square)) {
940e5dd7070Spatrick       ConsumeBracket();
941e5dd7070Spatrick       ConsumeBracket();
942e5dd7070Spatrick       return TPResult::True;
943e5dd7070Spatrick     }
944e5dd7070Spatrick     break;
945e5dd7070Spatrick 
946e5dd7070Spatrick   case tok::l_paren:
947e5dd7070Spatrick     if (NextToken().is(tok::r_paren)) {
948e5dd7070Spatrick       ConsumeParen();
949e5dd7070Spatrick       ConsumeParen();
950e5dd7070Spatrick       return TPResult::True;
951e5dd7070Spatrick     }
952e5dd7070Spatrick     break;
953e5dd7070Spatrick 
954e5dd7070Spatrick   default:
955e5dd7070Spatrick     break;
956e5dd7070Spatrick   }
957e5dd7070Spatrick 
958e5dd7070Spatrick   // Maybe this is a literal-operator-id.
959e5dd7070Spatrick   if (getLangOpts().CPlusPlus11 && isTokenStringLiteral()) {
960e5dd7070Spatrick     bool FoundUDSuffix = false;
961e5dd7070Spatrick     do {
962e5dd7070Spatrick       FoundUDSuffix |= Tok.hasUDSuffix();
963e5dd7070Spatrick       ConsumeStringToken();
964e5dd7070Spatrick     } while (isTokenStringLiteral());
965e5dd7070Spatrick 
966e5dd7070Spatrick     if (!FoundUDSuffix) {
967e5dd7070Spatrick       if (Tok.is(tok::identifier))
968e5dd7070Spatrick         ConsumeToken();
969e5dd7070Spatrick       else
970e5dd7070Spatrick         return TPResult::Error;
971e5dd7070Spatrick     }
972e5dd7070Spatrick     return TPResult::True;
973e5dd7070Spatrick   }
974e5dd7070Spatrick 
975e5dd7070Spatrick   // Maybe this is a conversion-function-id.
976e5dd7070Spatrick   bool AnyDeclSpecifiers = false;
977e5dd7070Spatrick   while (true) {
978*12c85518Srobert     TPResult TPR = isCXXDeclarationSpecifier(ImplicitTypenameContext::No);
979e5dd7070Spatrick     if (TPR == TPResult::Error)
980e5dd7070Spatrick       return TPR;
981e5dd7070Spatrick     if (TPR == TPResult::False) {
982e5dd7070Spatrick       if (!AnyDeclSpecifiers)
983e5dd7070Spatrick         return TPResult::Error;
984e5dd7070Spatrick       break;
985e5dd7070Spatrick     }
986e5dd7070Spatrick     if (TryConsumeDeclarationSpecifier() == TPResult::Error)
987e5dd7070Spatrick       return TPResult::Error;
988e5dd7070Spatrick     AnyDeclSpecifiers = true;
989e5dd7070Spatrick   }
990e5dd7070Spatrick   return TryParsePtrOperatorSeq();
991e5dd7070Spatrick }
992e5dd7070Spatrick 
993e5dd7070Spatrick ///         declarator:
994e5dd7070Spatrick ///           direct-declarator
995e5dd7070Spatrick ///           ptr-operator declarator
996e5dd7070Spatrick ///
997e5dd7070Spatrick ///         direct-declarator:
998e5dd7070Spatrick ///           declarator-id
999e5dd7070Spatrick ///           direct-declarator '(' parameter-declaration-clause ')'
1000e5dd7070Spatrick ///                 cv-qualifier-seq[opt] exception-specification[opt]
1001e5dd7070Spatrick ///           direct-declarator '[' constant-expression[opt] ']'
1002e5dd7070Spatrick ///           '(' declarator ')'
1003e5dd7070Spatrick /// [GNU]     '(' attributes declarator ')'
1004e5dd7070Spatrick ///
1005e5dd7070Spatrick ///         abstract-declarator:
1006e5dd7070Spatrick ///           ptr-operator abstract-declarator[opt]
1007e5dd7070Spatrick ///           direct-abstract-declarator
1008e5dd7070Spatrick ///
1009e5dd7070Spatrick ///         direct-abstract-declarator:
1010e5dd7070Spatrick ///           direct-abstract-declarator[opt]
1011e5dd7070Spatrick ///                 '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
1012e5dd7070Spatrick ///                 exception-specification[opt]
1013e5dd7070Spatrick ///           direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
1014e5dd7070Spatrick ///           '(' abstract-declarator ')'
1015e5dd7070Spatrick /// [C++0x]   ...
1016e5dd7070Spatrick ///
1017e5dd7070Spatrick ///         ptr-operator:
1018e5dd7070Spatrick ///           '*' cv-qualifier-seq[opt]
1019e5dd7070Spatrick ///           '&'
1020e5dd7070Spatrick /// [C++0x]   '&&'                                                        [TODO]
1021e5dd7070Spatrick ///           '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
1022e5dd7070Spatrick ///
1023e5dd7070Spatrick ///         cv-qualifier-seq:
1024e5dd7070Spatrick ///           cv-qualifier cv-qualifier-seq[opt]
1025e5dd7070Spatrick ///
1026e5dd7070Spatrick ///         cv-qualifier:
1027e5dd7070Spatrick ///           'const'
1028e5dd7070Spatrick ///           'volatile'
1029e5dd7070Spatrick ///
1030e5dd7070Spatrick ///         declarator-id:
1031e5dd7070Spatrick ///           '...'[opt] id-expression
1032e5dd7070Spatrick ///
1033e5dd7070Spatrick ///         id-expression:
1034e5dd7070Spatrick ///           unqualified-id
1035e5dd7070Spatrick ///           qualified-id                                                [TODO]
1036e5dd7070Spatrick ///
1037e5dd7070Spatrick ///         unqualified-id:
1038e5dd7070Spatrick ///           identifier
1039e5dd7070Spatrick ///           operator-function-id
1040e5dd7070Spatrick ///           conversion-function-id
1041e5dd7070Spatrick ///           literal-operator-id
1042e5dd7070Spatrick ///           '~' class-name                                              [TODO]
1043e5dd7070Spatrick ///           '~' decltype-specifier                                      [TODO]
1044e5dd7070Spatrick ///           template-id                                                 [TODO]
1045e5dd7070Spatrick ///
TryParseDeclarator(bool mayBeAbstract,bool mayHaveIdentifier,bool mayHaveDirectInit)1046e5dd7070Spatrick Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
1047e5dd7070Spatrick                                             bool mayHaveIdentifier,
1048e5dd7070Spatrick                                             bool mayHaveDirectInit) {
1049e5dd7070Spatrick   // declarator:
1050e5dd7070Spatrick   //   direct-declarator
1051e5dd7070Spatrick   //   ptr-operator declarator
1052e5dd7070Spatrick   if (TryParsePtrOperatorSeq() == TPResult::Error)
1053e5dd7070Spatrick     return TPResult::Error;
1054e5dd7070Spatrick 
1055e5dd7070Spatrick   // direct-declarator:
1056e5dd7070Spatrick   // direct-abstract-declarator:
1057e5dd7070Spatrick   if (Tok.is(tok::ellipsis))
1058e5dd7070Spatrick     ConsumeToken();
1059e5dd7070Spatrick 
1060e5dd7070Spatrick   if ((Tok.isOneOf(tok::identifier, tok::kw_operator) ||
1061e5dd7070Spatrick        (Tok.is(tok::annot_cxxscope) && (NextToken().is(tok::identifier) ||
1062e5dd7070Spatrick                                         NextToken().is(tok::kw_operator)))) &&
1063e5dd7070Spatrick       mayHaveIdentifier) {
1064e5dd7070Spatrick     // declarator-id
1065ec727ea7Spatrick     if (Tok.is(tok::annot_cxxscope)) {
1066ec727ea7Spatrick       CXXScopeSpec SS;
1067ec727ea7Spatrick       Actions.RestoreNestedNameSpecifierAnnotation(
1068ec727ea7Spatrick           Tok.getAnnotationValue(), Tok.getAnnotationRange(), SS);
1069ec727ea7Spatrick       if (SS.isInvalid())
1070ec727ea7Spatrick         return TPResult::Error;
1071e5dd7070Spatrick       ConsumeAnnotationToken();
1072ec727ea7Spatrick     } else if (Tok.is(tok::identifier)) {
1073e5dd7070Spatrick       TentativelyDeclaredIdentifiers.push_back(Tok.getIdentifierInfo());
1074ec727ea7Spatrick     }
1075e5dd7070Spatrick     if (Tok.is(tok::kw_operator)) {
1076e5dd7070Spatrick       if (TryParseOperatorId() == TPResult::Error)
1077e5dd7070Spatrick         return TPResult::Error;
1078e5dd7070Spatrick     } else
1079e5dd7070Spatrick       ConsumeToken();
1080e5dd7070Spatrick   } else if (Tok.is(tok::l_paren)) {
1081e5dd7070Spatrick     ConsumeParen();
1082e5dd7070Spatrick     if (mayBeAbstract &&
1083e5dd7070Spatrick         (Tok.is(tok::r_paren) || // 'int()' is a function.
1084e5dd7070Spatrick                                  // 'int(...)' is a function.
1085e5dd7070Spatrick          (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren)) ||
1086*12c85518Srobert          isDeclarationSpecifier(
1087*12c85518Srobert              ImplicitTypenameContext::No))) { // 'int(int)' is a function.
1088e5dd7070Spatrick       // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
1089e5dd7070Spatrick       //        exception-specification[opt]
1090e5dd7070Spatrick       TPResult TPR = TryParseFunctionDeclarator();
1091e5dd7070Spatrick       if (TPR != TPResult::Ambiguous)
1092e5dd7070Spatrick         return TPR;
1093e5dd7070Spatrick     } else {
1094e5dd7070Spatrick       // '(' declarator ')'
1095e5dd7070Spatrick       // '(' attributes declarator ')'
1096e5dd7070Spatrick       // '(' abstract-declarator ')'
1097e5dd7070Spatrick       if (Tok.isOneOf(tok::kw___attribute, tok::kw___declspec, tok::kw___cdecl,
1098e5dd7070Spatrick                       tok::kw___stdcall, tok::kw___fastcall, tok::kw___thiscall,
1099e5dd7070Spatrick                       tok::kw___regcall, tok::kw___vectorcall))
1100e5dd7070Spatrick         return TPResult::True; // attributes indicate declaration
1101e5dd7070Spatrick       TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
1102e5dd7070Spatrick       if (TPR != TPResult::Ambiguous)
1103e5dd7070Spatrick         return TPR;
1104e5dd7070Spatrick       if (Tok.isNot(tok::r_paren))
1105e5dd7070Spatrick         return TPResult::False;
1106e5dd7070Spatrick       ConsumeParen();
1107e5dd7070Spatrick     }
1108e5dd7070Spatrick   } else if (!mayBeAbstract) {
1109e5dd7070Spatrick     return TPResult::False;
1110e5dd7070Spatrick   }
1111e5dd7070Spatrick 
1112e5dd7070Spatrick   if (mayHaveDirectInit)
1113e5dd7070Spatrick     return TPResult::Ambiguous;
1114e5dd7070Spatrick 
1115*12c85518Srobert   while (true) {
1116e5dd7070Spatrick     TPResult TPR(TPResult::Ambiguous);
1117e5dd7070Spatrick 
1118e5dd7070Spatrick     if (Tok.is(tok::l_paren)) {
1119e5dd7070Spatrick       // Check whether we have a function declarator or a possible ctor-style
1120e5dd7070Spatrick       // initializer that follows the declarator. Note that ctor-style
1121e5dd7070Spatrick       // initializers are not possible in contexts where abstract declarators
1122e5dd7070Spatrick       // are allowed.
1123e5dd7070Spatrick       if (!mayBeAbstract && !isCXXFunctionDeclarator())
1124e5dd7070Spatrick         break;
1125e5dd7070Spatrick 
1126e5dd7070Spatrick       // direct-declarator '(' parameter-declaration-clause ')'
1127e5dd7070Spatrick       //        cv-qualifier-seq[opt] exception-specification[opt]
1128e5dd7070Spatrick       ConsumeParen();
1129e5dd7070Spatrick       TPR = TryParseFunctionDeclarator();
1130e5dd7070Spatrick     } else if (Tok.is(tok::l_square)) {
1131e5dd7070Spatrick       // direct-declarator '[' constant-expression[opt] ']'
1132e5dd7070Spatrick       // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
1133e5dd7070Spatrick       TPR = TryParseBracketDeclarator();
1134e5dd7070Spatrick     } else if (Tok.is(tok::kw_requires)) {
1135e5dd7070Spatrick       // declarator requires-clause
1136e5dd7070Spatrick       // A requires clause indicates a function declaration.
1137e5dd7070Spatrick       TPR = TPResult::True;
1138e5dd7070Spatrick     } else {
1139e5dd7070Spatrick       break;
1140e5dd7070Spatrick     }
1141e5dd7070Spatrick 
1142e5dd7070Spatrick     if (TPR != TPResult::Ambiguous)
1143e5dd7070Spatrick       return TPR;
1144e5dd7070Spatrick   }
1145e5dd7070Spatrick 
1146e5dd7070Spatrick   return TPResult::Ambiguous;
1147e5dd7070Spatrick }
1148e5dd7070Spatrick 
isTentativelyDeclared(IdentifierInfo * II)1149e5dd7070Spatrick bool Parser::isTentativelyDeclared(IdentifierInfo *II) {
1150*12c85518Srobert   return llvm::is_contained(TentativelyDeclaredIdentifiers, II);
1151e5dd7070Spatrick }
1152e5dd7070Spatrick 
1153e5dd7070Spatrick namespace {
1154e5dd7070Spatrick class TentativeParseCCC final : public CorrectionCandidateCallback {
1155e5dd7070Spatrick public:
TentativeParseCCC(const Token & Next)1156e5dd7070Spatrick   TentativeParseCCC(const Token &Next) {
1157e5dd7070Spatrick     WantRemainingKeywords = false;
1158ec727ea7Spatrick     WantTypeSpecifiers =
1159ec727ea7Spatrick         Next.isOneOf(tok::l_paren, tok::r_paren, tok::greater, tok::l_brace,
1160ec727ea7Spatrick                      tok::identifier, tok::comma);
1161e5dd7070Spatrick   }
1162e5dd7070Spatrick 
ValidateCandidate(const TypoCorrection & Candidate)1163e5dd7070Spatrick   bool ValidateCandidate(const TypoCorrection &Candidate) override {
1164e5dd7070Spatrick     // Reject any candidate that only resolves to instance members since they
1165e5dd7070Spatrick     // aren't viable as standalone identifiers instead of member references.
1166e5dd7070Spatrick     if (Candidate.isResolved() && !Candidate.isKeyword() &&
1167e5dd7070Spatrick         llvm::all_of(Candidate,
1168e5dd7070Spatrick                      [](NamedDecl *ND) { return ND->isCXXInstanceMember(); }))
1169e5dd7070Spatrick       return false;
1170e5dd7070Spatrick 
1171e5dd7070Spatrick     return CorrectionCandidateCallback::ValidateCandidate(Candidate);
1172e5dd7070Spatrick   }
1173e5dd7070Spatrick 
clone()1174e5dd7070Spatrick   std::unique_ptr<CorrectionCandidateCallback> clone() override {
1175e5dd7070Spatrick     return std::make_unique<TentativeParseCCC>(*this);
1176e5dd7070Spatrick   }
1177e5dd7070Spatrick };
1178e5dd7070Spatrick }
1179e5dd7070Spatrick /// isCXXDeclarationSpecifier - Returns TPResult::True if it is a declaration
1180e5dd7070Spatrick /// specifier, TPResult::False if it is not, TPResult::Ambiguous if it could
1181e5dd7070Spatrick /// be either a decl-specifier or a function-style cast, and TPResult::Error
1182e5dd7070Spatrick /// if a parsing error was found and reported.
1183e5dd7070Spatrick ///
1184e5dd7070Spatrick /// If InvalidAsDeclSpec is not null, some cases that would be ill-formed as
1185e5dd7070Spatrick /// declaration specifiers but possibly valid as some other kind of construct
1186e5dd7070Spatrick /// return TPResult::Ambiguous instead of TPResult::False. When this happens,
1187e5dd7070Spatrick /// the intent is to keep trying to disambiguate, on the basis that we might
1188e5dd7070Spatrick /// find a better reason to treat this construct as a declaration later on.
1189e5dd7070Spatrick /// When this happens and the name could possibly be valid in some other
1190e5dd7070Spatrick /// syntactic context, *InvalidAsDeclSpec is set to 'true'. The current cases
1191e5dd7070Spatrick /// that trigger this are:
1192e5dd7070Spatrick ///
1193e5dd7070Spatrick ///   * When parsing X::Y (with no 'typename') where X is dependent
1194e5dd7070Spatrick ///   * When parsing X<Y> where X is undeclared
1195e5dd7070Spatrick ///
1196e5dd7070Spatrick ///         decl-specifier:
1197e5dd7070Spatrick ///           storage-class-specifier
1198e5dd7070Spatrick ///           type-specifier
1199e5dd7070Spatrick ///           function-specifier
1200e5dd7070Spatrick ///           'friend'
1201e5dd7070Spatrick ///           'typedef'
1202e5dd7070Spatrick /// [C++11]   'constexpr'
1203e5dd7070Spatrick /// [C++20]   'consteval'
1204e5dd7070Spatrick /// [GNU]     attributes declaration-specifiers[opt]
1205e5dd7070Spatrick ///
1206e5dd7070Spatrick ///         storage-class-specifier:
1207e5dd7070Spatrick ///           'register'
1208e5dd7070Spatrick ///           'static'
1209e5dd7070Spatrick ///           'extern'
1210e5dd7070Spatrick ///           'mutable'
1211e5dd7070Spatrick ///           'auto'
1212e5dd7070Spatrick /// [GNU]     '__thread'
1213e5dd7070Spatrick /// [C++11]   'thread_local'
1214e5dd7070Spatrick /// [C11]     '_Thread_local'
1215e5dd7070Spatrick ///
1216e5dd7070Spatrick ///         function-specifier:
1217e5dd7070Spatrick ///           'inline'
1218e5dd7070Spatrick ///           'virtual'
1219e5dd7070Spatrick ///           'explicit'
1220e5dd7070Spatrick ///
1221e5dd7070Spatrick ///         typedef-name:
1222e5dd7070Spatrick ///           identifier
1223e5dd7070Spatrick ///
1224e5dd7070Spatrick ///         type-specifier:
1225e5dd7070Spatrick ///           simple-type-specifier
1226e5dd7070Spatrick ///           class-specifier
1227e5dd7070Spatrick ///           enum-specifier
1228e5dd7070Spatrick ///           elaborated-type-specifier
1229e5dd7070Spatrick ///           typename-specifier
1230e5dd7070Spatrick ///           cv-qualifier
1231e5dd7070Spatrick ///
1232e5dd7070Spatrick ///         simple-type-specifier:
1233e5dd7070Spatrick ///           '::'[opt] nested-name-specifier[opt] type-name
1234e5dd7070Spatrick ///           '::'[opt] nested-name-specifier 'template'
1235e5dd7070Spatrick ///                 simple-template-id                              [TODO]
1236e5dd7070Spatrick ///           'char'
1237e5dd7070Spatrick ///           'wchar_t'
1238e5dd7070Spatrick ///           'bool'
1239e5dd7070Spatrick ///           'short'
1240e5dd7070Spatrick ///           'int'
1241e5dd7070Spatrick ///           'long'
1242e5dd7070Spatrick ///           'signed'
1243e5dd7070Spatrick ///           'unsigned'
1244e5dd7070Spatrick ///           'float'
1245e5dd7070Spatrick ///           'double'
1246e5dd7070Spatrick ///           'void'
1247e5dd7070Spatrick /// [GNU]     typeof-specifier
1248e5dd7070Spatrick /// [GNU]     '_Complex'
1249e5dd7070Spatrick /// [C++11]   'auto'
1250e5dd7070Spatrick /// [GNU]     '__auto_type'
1251e5dd7070Spatrick /// [C++11]   'decltype' ( expression )
1252e5dd7070Spatrick /// [C++1y]   'decltype' ( 'auto' )
1253e5dd7070Spatrick ///
1254e5dd7070Spatrick ///         type-name:
1255e5dd7070Spatrick ///           class-name
1256e5dd7070Spatrick ///           enum-name
1257e5dd7070Spatrick ///           typedef-name
1258e5dd7070Spatrick ///
1259e5dd7070Spatrick ///         elaborated-type-specifier:
1260e5dd7070Spatrick ///           class-key '::'[opt] nested-name-specifier[opt] identifier
1261e5dd7070Spatrick ///           class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]
1262e5dd7070Spatrick ///               simple-template-id
1263e5dd7070Spatrick ///           'enum' '::'[opt] nested-name-specifier[opt] identifier
1264e5dd7070Spatrick ///
1265e5dd7070Spatrick ///         enum-name:
1266e5dd7070Spatrick ///           identifier
1267e5dd7070Spatrick ///
1268e5dd7070Spatrick ///         enum-specifier:
1269e5dd7070Spatrick ///           'enum' identifier[opt] '{' enumerator-list[opt] '}'
1270e5dd7070Spatrick ///           'enum' identifier[opt] '{' enumerator-list ',' '}'
1271e5dd7070Spatrick ///
1272e5dd7070Spatrick ///         class-specifier:
1273e5dd7070Spatrick ///           class-head '{' member-specification[opt] '}'
1274e5dd7070Spatrick ///
1275e5dd7070Spatrick ///         class-head:
1276e5dd7070Spatrick ///           class-key identifier[opt] base-clause[opt]
1277e5dd7070Spatrick ///           class-key nested-name-specifier identifier base-clause[opt]
1278e5dd7070Spatrick ///           class-key nested-name-specifier[opt] simple-template-id
1279e5dd7070Spatrick ///               base-clause[opt]
1280e5dd7070Spatrick ///
1281e5dd7070Spatrick ///         class-key:
1282e5dd7070Spatrick ///           'class'
1283e5dd7070Spatrick ///           'struct'
1284e5dd7070Spatrick ///           'union'
1285e5dd7070Spatrick ///
1286e5dd7070Spatrick ///         cv-qualifier:
1287e5dd7070Spatrick ///           'const'
1288e5dd7070Spatrick ///           'volatile'
1289e5dd7070Spatrick /// [GNU]     restrict
1290e5dd7070Spatrick ///
1291e5dd7070Spatrick Parser::TPResult
isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,Parser::TPResult BracedCastResult,bool * InvalidAsDeclSpec)1292*12c85518Srobert Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
1293*12c85518Srobert                                   Parser::TPResult BracedCastResult,
1294e5dd7070Spatrick                                   bool *InvalidAsDeclSpec) {
1295e5dd7070Spatrick   auto IsPlaceholderSpecifier = [&](TemplateIdAnnotation *TemplateId,
1296e5dd7070Spatrick                                     int Lookahead) {
1297e5dd7070Spatrick     // We have a placeholder-constraint (we check for 'auto' or 'decltype' to
1298e5dd7070Spatrick     // distinguish 'C<int>;' from 'C<int> auto c = 1;')
1299e5dd7070Spatrick     return TemplateId->Kind == TNK_Concept_template &&
1300*12c85518Srobert            (GetLookAheadToken(Lookahead + 1)
1301*12c85518Srobert                 .isOneOf(tok::kw_auto, tok::kw_decltype,
1302*12c85518Srobert                          // If we have an identifier here, the user probably
1303*12c85518Srobert                          // forgot the 'auto' in the placeholder constraint,
1304*12c85518Srobert                          // e.g. 'C<int> x = 2;' This will be diagnosed nicely
1305*12c85518Srobert                          // later, so disambiguate as a declaration.
1306*12c85518Srobert                          tok::identifier,
1307*12c85518Srobert                          // CVR qualifierslikely the same situation for the
1308*12c85518Srobert                          // user, so let this be diagnosed nicely later. We
1309*12c85518Srobert                          // cannot handle references here, as `C<int> & Other`
1310*12c85518Srobert                          // and `C<int> && Other` are both legal.
1311*12c85518Srobert                          tok::kw_const, tok::kw_volatile, tok::kw_restrict) ||
1312*12c85518Srobert             // While `C<int> && Other` is legal, doing so while not specifying a
1313*12c85518Srobert             // template argument is NOT, so see if we can fix up in that case at
1314*12c85518Srobert             // minimum. Concepts require at least 1 template parameter, so we
1315*12c85518Srobert             // can count on the argument count.
1316*12c85518Srobert             // FIXME: In the future, we migth be able to have SEMA look up the
1317*12c85518Srobert             // declaration for this concept, and see how many template
1318*12c85518Srobert             // parameters it has.  If the concept isn't fully specified, it is
1319*12c85518Srobert             // possibly a situation where we want deduction, such as:
1320*12c85518Srobert             // `BinaryConcept<int> auto f = bar();`
1321*12c85518Srobert             (TemplateId->NumArgs == 0 &&
1322*12c85518Srobert              GetLookAheadToken(Lookahead + 1).isOneOf(tok::amp, tok::ampamp)));
1323e5dd7070Spatrick   };
1324e5dd7070Spatrick   switch (Tok.getKind()) {
1325e5dd7070Spatrick   case tok::identifier: {
1326e5dd7070Spatrick     // Check for need to substitute AltiVec __vector keyword
1327e5dd7070Spatrick     // for "vector" identifier.
1328e5dd7070Spatrick     if (TryAltiVecVectorToken())
1329e5dd7070Spatrick       return TPResult::True;
1330e5dd7070Spatrick 
1331e5dd7070Spatrick     const Token &Next = NextToken();
1332e5dd7070Spatrick     // In 'foo bar', 'foo' is always a type name outside of Objective-C.
1333e5dd7070Spatrick     if (!getLangOpts().ObjC && Next.is(tok::identifier))
1334e5dd7070Spatrick       return TPResult::True;
1335e5dd7070Spatrick 
1336e5dd7070Spatrick     if (Next.isNot(tok::coloncolon) && Next.isNot(tok::less)) {
1337e5dd7070Spatrick       // Determine whether this is a valid expression. If not, we will hit
1338e5dd7070Spatrick       // a parse error one way or another. In that case, tell the caller that
1339e5dd7070Spatrick       // this is ambiguous. Typo-correct to type and expression keywords and
1340e5dd7070Spatrick       // to types and identifiers, in order to try to recover from errors.
1341e5dd7070Spatrick       TentativeParseCCC CCC(Next);
1342e5dd7070Spatrick       switch (TryAnnotateName(&CCC)) {
1343e5dd7070Spatrick       case ANK_Error:
1344e5dd7070Spatrick         return TPResult::Error;
1345e5dd7070Spatrick       case ANK_TentativeDecl:
1346e5dd7070Spatrick         return TPResult::False;
1347e5dd7070Spatrick       case ANK_TemplateName:
1348e5dd7070Spatrick         // In C++17, this could be a type template for class template argument
1349e5dd7070Spatrick         // deduction. Try to form a type annotation for it. If we're in a
1350e5dd7070Spatrick         // template template argument, we'll undo this when checking the
1351e5dd7070Spatrick         // validity of the argument.
1352e5dd7070Spatrick         if (getLangOpts().CPlusPlus17) {
1353*12c85518Srobert           if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename))
1354e5dd7070Spatrick             return TPResult::Error;
1355e5dd7070Spatrick           if (Tok.isNot(tok::identifier))
1356e5dd7070Spatrick             break;
1357e5dd7070Spatrick         }
1358e5dd7070Spatrick 
1359e5dd7070Spatrick         // A bare type template-name which can't be a template template
1360e5dd7070Spatrick         // argument is an error, and was probably intended to be a type.
1361e5dd7070Spatrick         return GreaterThanIsOperator ? TPResult::True : TPResult::False;
1362e5dd7070Spatrick       case ANK_Unresolved:
1363e5dd7070Spatrick         return InvalidAsDeclSpec ? TPResult::Ambiguous : TPResult::False;
1364e5dd7070Spatrick       case ANK_Success:
1365e5dd7070Spatrick         break;
1366e5dd7070Spatrick       }
1367e5dd7070Spatrick       assert(Tok.isNot(tok::identifier) &&
1368e5dd7070Spatrick              "TryAnnotateName succeeded without producing an annotation");
1369e5dd7070Spatrick     } else {
1370e5dd7070Spatrick       // This might possibly be a type with a dependent scope specifier and
1371e5dd7070Spatrick       // a missing 'typename' keyword. Don't use TryAnnotateName in this case,
1372e5dd7070Spatrick       // since it will annotate as a primary expression, and we want to use the
1373e5dd7070Spatrick       // "missing 'typename'" logic.
1374*12c85518Srobert       if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename))
1375e5dd7070Spatrick         return TPResult::Error;
1376e5dd7070Spatrick       // If annotation failed, assume it's a non-type.
1377e5dd7070Spatrick       // FIXME: If this happens due to an undeclared identifier, treat it as
1378e5dd7070Spatrick       // ambiguous.
1379e5dd7070Spatrick       if (Tok.is(tok::identifier))
1380e5dd7070Spatrick         return TPResult::False;
1381e5dd7070Spatrick     }
1382e5dd7070Spatrick 
1383e5dd7070Spatrick     // We annotated this token as something. Recurse to handle whatever we got.
1384*12c85518Srobert     return isCXXDeclarationSpecifier(AllowImplicitTypename, BracedCastResult,
1385*12c85518Srobert                                      InvalidAsDeclSpec);
1386e5dd7070Spatrick   }
1387e5dd7070Spatrick 
1388e5dd7070Spatrick   case tok::kw_typename:  // typename T::type
1389e5dd7070Spatrick     // Annotate typenames and C++ scope specifiers.  If we get one, just
1390e5dd7070Spatrick     // recurse to handle whatever we get.
1391*12c85518Srobert     if (TryAnnotateTypeOrScopeToken(ImplicitTypenameContext::Yes))
1392e5dd7070Spatrick       return TPResult::Error;
1393*12c85518Srobert     return isCXXDeclarationSpecifier(ImplicitTypenameContext::Yes,
1394*12c85518Srobert                                      BracedCastResult, InvalidAsDeclSpec);
1395e5dd7070Spatrick 
1396e5dd7070Spatrick   case tok::coloncolon: {    // ::foo::bar
1397e5dd7070Spatrick     const Token &Next = NextToken();
1398e5dd7070Spatrick     if (Next.isOneOf(tok::kw_new,       // ::new
1399e5dd7070Spatrick                      tok::kw_delete))   // ::delete
1400e5dd7070Spatrick       return TPResult::False;
1401*12c85518Srobert     [[fallthrough]];
1402e5dd7070Spatrick   }
1403e5dd7070Spatrick   case tok::kw___super:
1404e5dd7070Spatrick   case tok::kw_decltype:
1405e5dd7070Spatrick     // Annotate typenames and C++ scope specifiers.  If we get one, just
1406e5dd7070Spatrick     // recurse to handle whatever we get.
1407*12c85518Srobert     if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename))
1408e5dd7070Spatrick       return TPResult::Error;
1409*12c85518Srobert     return isCXXDeclarationSpecifier(AllowImplicitTypename, BracedCastResult,
1410*12c85518Srobert                                      InvalidAsDeclSpec);
1411e5dd7070Spatrick 
1412e5dd7070Spatrick     // decl-specifier:
1413e5dd7070Spatrick     //   storage-class-specifier
1414e5dd7070Spatrick     //   type-specifier
1415e5dd7070Spatrick     //   function-specifier
1416e5dd7070Spatrick     //   'friend'
1417e5dd7070Spatrick     //   'typedef'
1418e5dd7070Spatrick     //   'constexpr'
1419e5dd7070Spatrick   case tok::kw_friend:
1420e5dd7070Spatrick   case tok::kw_typedef:
1421e5dd7070Spatrick   case tok::kw_constexpr:
1422e5dd7070Spatrick   case tok::kw_consteval:
1423e5dd7070Spatrick   case tok::kw_constinit:
1424e5dd7070Spatrick     // storage-class-specifier
1425e5dd7070Spatrick   case tok::kw_register:
1426e5dd7070Spatrick   case tok::kw_static:
1427e5dd7070Spatrick   case tok::kw_extern:
1428e5dd7070Spatrick   case tok::kw_mutable:
1429e5dd7070Spatrick   case tok::kw_auto:
1430e5dd7070Spatrick   case tok::kw___thread:
1431e5dd7070Spatrick   case tok::kw_thread_local:
1432e5dd7070Spatrick   case tok::kw__Thread_local:
1433e5dd7070Spatrick     // function-specifier
1434e5dd7070Spatrick   case tok::kw_inline:
1435e5dd7070Spatrick   case tok::kw_virtual:
1436e5dd7070Spatrick   case tok::kw_explicit:
1437e5dd7070Spatrick 
1438e5dd7070Spatrick     // Modules
1439e5dd7070Spatrick   case tok::kw___module_private__:
1440e5dd7070Spatrick 
1441e5dd7070Spatrick     // Debugger support
1442e5dd7070Spatrick   case tok::kw___unknown_anytype:
1443e5dd7070Spatrick 
1444e5dd7070Spatrick     // type-specifier:
1445e5dd7070Spatrick     //   simple-type-specifier
1446e5dd7070Spatrick     //   class-specifier
1447e5dd7070Spatrick     //   enum-specifier
1448e5dd7070Spatrick     //   elaborated-type-specifier
1449e5dd7070Spatrick     //   typename-specifier
1450e5dd7070Spatrick     //   cv-qualifier
1451e5dd7070Spatrick 
1452e5dd7070Spatrick     // class-specifier
1453e5dd7070Spatrick     // elaborated-type-specifier
1454e5dd7070Spatrick   case tok::kw_class:
1455e5dd7070Spatrick   case tok::kw_struct:
1456e5dd7070Spatrick   case tok::kw_union:
1457e5dd7070Spatrick   case tok::kw___interface:
1458e5dd7070Spatrick     // enum-specifier
1459e5dd7070Spatrick   case tok::kw_enum:
1460e5dd7070Spatrick     // cv-qualifier
1461e5dd7070Spatrick   case tok::kw_const:
1462e5dd7070Spatrick   case tok::kw_volatile:
1463e5dd7070Spatrick     return TPResult::True;
1464e5dd7070Spatrick 
1465e5dd7070Spatrick     // OpenCL address space qualifiers
1466e5dd7070Spatrick   case tok::kw_private:
1467e5dd7070Spatrick     if (!getLangOpts().OpenCL)
1468e5dd7070Spatrick       return TPResult::False;
1469*12c85518Srobert     [[fallthrough]];
1470e5dd7070Spatrick   case tok::kw___private:
1471e5dd7070Spatrick   case tok::kw___local:
1472e5dd7070Spatrick   case tok::kw___global:
1473e5dd7070Spatrick   case tok::kw___constant:
1474e5dd7070Spatrick   case tok::kw___generic:
1475e5dd7070Spatrick     // OpenCL access qualifiers
1476e5dd7070Spatrick   case tok::kw___read_only:
1477e5dd7070Spatrick   case tok::kw___write_only:
1478e5dd7070Spatrick   case tok::kw___read_write:
1479e5dd7070Spatrick     // OpenCL pipe
1480e5dd7070Spatrick   case tok::kw_pipe:
1481e5dd7070Spatrick 
1482*12c85518Srobert     // HLSL address space qualifiers
1483*12c85518Srobert   case tok::kw_groupshared:
1484*12c85518Srobert 
1485e5dd7070Spatrick     // GNU
1486e5dd7070Spatrick   case tok::kw_restrict:
1487e5dd7070Spatrick   case tok::kw__Complex:
1488e5dd7070Spatrick   case tok::kw___attribute:
1489e5dd7070Spatrick   case tok::kw___auto_type:
1490e5dd7070Spatrick     return TPResult::True;
1491e5dd7070Spatrick 
1492e5dd7070Spatrick     // Microsoft
1493e5dd7070Spatrick   case tok::kw___declspec:
1494e5dd7070Spatrick   case tok::kw___cdecl:
1495e5dd7070Spatrick   case tok::kw___stdcall:
1496e5dd7070Spatrick   case tok::kw___fastcall:
1497e5dd7070Spatrick   case tok::kw___thiscall:
1498e5dd7070Spatrick   case tok::kw___regcall:
1499e5dd7070Spatrick   case tok::kw___vectorcall:
1500e5dd7070Spatrick   case tok::kw___w64:
1501e5dd7070Spatrick   case tok::kw___sptr:
1502e5dd7070Spatrick   case tok::kw___uptr:
1503e5dd7070Spatrick   case tok::kw___ptr64:
1504e5dd7070Spatrick   case tok::kw___ptr32:
1505e5dd7070Spatrick   case tok::kw___forceinline:
1506e5dd7070Spatrick   case tok::kw___unaligned:
1507e5dd7070Spatrick   case tok::kw__Nonnull:
1508e5dd7070Spatrick   case tok::kw__Nullable:
1509a9ac8606Spatrick   case tok::kw__Nullable_result:
1510e5dd7070Spatrick   case tok::kw__Null_unspecified:
1511e5dd7070Spatrick   case tok::kw___kindof:
1512e5dd7070Spatrick     return TPResult::True;
1513e5dd7070Spatrick 
1514e5dd7070Spatrick     // Borland
1515e5dd7070Spatrick   case tok::kw___pascal:
1516e5dd7070Spatrick     return TPResult::True;
1517e5dd7070Spatrick 
1518e5dd7070Spatrick     // AltiVec
1519e5dd7070Spatrick   case tok::kw___vector:
1520e5dd7070Spatrick     return TPResult::True;
1521e5dd7070Spatrick 
1522e5dd7070Spatrick   case tok::annot_template_id: {
1523e5dd7070Spatrick     TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
1524e5dd7070Spatrick     // If lookup for the template-name found nothing, don't assume we have a
1525e5dd7070Spatrick     // definitive disambiguation result yet.
1526ec727ea7Spatrick     if ((TemplateId->hasInvalidName() ||
1527ec727ea7Spatrick          TemplateId->Kind == TNK_Undeclared_template) &&
1528ec727ea7Spatrick         InvalidAsDeclSpec) {
1529e5dd7070Spatrick       // 'template-id(' can be a valid expression but not a valid decl spec if
1530e5dd7070Spatrick       // the template-name is not declared, but we don't consider this to be a
1531e5dd7070Spatrick       // definitive disambiguation. In any other context, it's an error either
1532e5dd7070Spatrick       // way.
1533e5dd7070Spatrick       *InvalidAsDeclSpec = NextToken().is(tok::l_paren);
1534e5dd7070Spatrick       return TPResult::Ambiguous;
1535e5dd7070Spatrick     }
1536ec727ea7Spatrick     if (TemplateId->hasInvalidName())
1537ec727ea7Spatrick       return TPResult::Error;
1538e5dd7070Spatrick     if (IsPlaceholderSpecifier(TemplateId, /*Lookahead=*/0))
1539e5dd7070Spatrick       return TPResult::True;
1540e5dd7070Spatrick     if (TemplateId->Kind != TNK_Type_template)
1541e5dd7070Spatrick       return TPResult::False;
1542e5dd7070Spatrick     CXXScopeSpec SS;
1543*12c85518Srobert     AnnotateTemplateIdTokenAsType(SS, AllowImplicitTypename);
1544e5dd7070Spatrick     assert(Tok.is(tok::annot_typename));
1545e5dd7070Spatrick     goto case_typename;
1546e5dd7070Spatrick   }
1547e5dd7070Spatrick 
1548e5dd7070Spatrick   case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
1549e5dd7070Spatrick     // We've already annotated a scope; try to annotate a type.
1550*12c85518Srobert     if (TryAnnotateTypeOrScopeToken(AllowImplicitTypename))
1551e5dd7070Spatrick       return TPResult::Error;
1552e5dd7070Spatrick     if (!Tok.is(tok::annot_typename)) {
1553e5dd7070Spatrick       if (Tok.is(tok::annot_cxxscope) &&
1554e5dd7070Spatrick           NextToken().is(tok::annot_template_id)) {
1555e5dd7070Spatrick         TemplateIdAnnotation *TemplateId =
1556e5dd7070Spatrick             takeTemplateIdAnnotation(NextToken());
1557ec727ea7Spatrick         if (TemplateId->hasInvalidName()) {
1558ec727ea7Spatrick           if (InvalidAsDeclSpec) {
1559ec727ea7Spatrick             *InvalidAsDeclSpec = NextToken().is(tok::l_paren);
1560ec727ea7Spatrick             return TPResult::Ambiguous;
1561ec727ea7Spatrick           }
1562ec727ea7Spatrick           return TPResult::Error;
1563ec727ea7Spatrick         }
1564e5dd7070Spatrick         if (IsPlaceholderSpecifier(TemplateId, /*Lookahead=*/1))
1565e5dd7070Spatrick           return TPResult::True;
1566e5dd7070Spatrick       }
1567e5dd7070Spatrick       // If the next token is an identifier or a type qualifier, then this
1568e5dd7070Spatrick       // can't possibly be a valid expression either.
1569e5dd7070Spatrick       if (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier)) {
1570e5dd7070Spatrick         CXXScopeSpec SS;
1571e5dd7070Spatrick         Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
1572e5dd7070Spatrick                                                      Tok.getAnnotationRange(),
1573e5dd7070Spatrick                                                      SS);
1574e5dd7070Spatrick         if (SS.getScopeRep() && SS.getScopeRep()->isDependent()) {
1575e5dd7070Spatrick           RevertingTentativeParsingAction PA(*this);
1576e5dd7070Spatrick           ConsumeAnnotationToken();
1577e5dd7070Spatrick           ConsumeToken();
1578e5dd7070Spatrick           bool isIdentifier = Tok.is(tok::identifier);
1579e5dd7070Spatrick           TPResult TPR = TPResult::False;
1580e5dd7070Spatrick           if (!isIdentifier)
1581*12c85518Srobert             TPR = isCXXDeclarationSpecifier(
1582*12c85518Srobert                 AllowImplicitTypename, BracedCastResult, InvalidAsDeclSpec);
1583e5dd7070Spatrick 
1584e5dd7070Spatrick           if (isIdentifier ||
1585e5dd7070Spatrick               TPR == TPResult::True || TPR == TPResult::Error)
1586e5dd7070Spatrick             return TPResult::Error;
1587e5dd7070Spatrick 
1588e5dd7070Spatrick           if (InvalidAsDeclSpec) {
1589e5dd7070Spatrick             // We can't tell whether this is a missing 'typename' or a valid
1590e5dd7070Spatrick             // expression.
1591e5dd7070Spatrick             *InvalidAsDeclSpec = true;
1592e5dd7070Spatrick             return TPResult::Ambiguous;
1593e5dd7070Spatrick           } else {
1594e5dd7070Spatrick             // In MS mode, if InvalidAsDeclSpec is not provided, and the tokens
1595e5dd7070Spatrick             // are or the form *) or &) *> or &> &&>, this can't be an expression.
1596e5dd7070Spatrick             // The typename must be missing.
1597e5dd7070Spatrick             if (getLangOpts().MSVCCompat) {
1598e5dd7070Spatrick               if (((Tok.is(tok::amp) || Tok.is(tok::star)) &&
1599e5dd7070Spatrick                    (NextToken().is(tok::r_paren) ||
1600e5dd7070Spatrick                     NextToken().is(tok::greater))) ||
1601e5dd7070Spatrick                   (Tok.is(tok::ampamp) && NextToken().is(tok::greater)))
1602e5dd7070Spatrick                 return TPResult::True;
1603e5dd7070Spatrick             }
1604e5dd7070Spatrick           }
1605e5dd7070Spatrick         } else {
1606e5dd7070Spatrick           // Try to resolve the name. If it doesn't exist, assume it was
1607e5dd7070Spatrick           // intended to name a type and keep disambiguating.
1608*12c85518Srobert           switch (TryAnnotateName(/*CCC=*/nullptr, AllowImplicitTypename)) {
1609e5dd7070Spatrick           case ANK_Error:
1610e5dd7070Spatrick             return TPResult::Error;
1611e5dd7070Spatrick           case ANK_TentativeDecl:
1612e5dd7070Spatrick             return TPResult::False;
1613e5dd7070Spatrick           case ANK_TemplateName:
1614e5dd7070Spatrick             // In C++17, this could be a type template for class template
1615e5dd7070Spatrick             // argument deduction.
1616e5dd7070Spatrick             if (getLangOpts().CPlusPlus17) {
1617e5dd7070Spatrick               if (TryAnnotateTypeOrScopeToken())
1618e5dd7070Spatrick                 return TPResult::Error;
1619e5dd7070Spatrick               if (Tok.isNot(tok::identifier))
1620e5dd7070Spatrick                 break;
1621e5dd7070Spatrick             }
1622e5dd7070Spatrick 
1623e5dd7070Spatrick             // A bare type template-name which can't be a template template
1624e5dd7070Spatrick             // argument is an error, and was probably intended to be a type.
1625e5dd7070Spatrick             // In C++17, this could be class template argument deduction.
1626e5dd7070Spatrick             return (getLangOpts().CPlusPlus17 || GreaterThanIsOperator)
1627e5dd7070Spatrick                        ? TPResult::True
1628e5dd7070Spatrick                        : TPResult::False;
1629e5dd7070Spatrick           case ANK_Unresolved:
1630e5dd7070Spatrick             return InvalidAsDeclSpec ? TPResult::Ambiguous : TPResult::False;
1631e5dd7070Spatrick           case ANK_Success:
1632e5dd7070Spatrick             break;
1633e5dd7070Spatrick           }
1634e5dd7070Spatrick 
1635e5dd7070Spatrick           // Annotated it, check again.
1636e5dd7070Spatrick           assert(Tok.isNot(tok::annot_cxxscope) ||
1637e5dd7070Spatrick                  NextToken().isNot(tok::identifier));
1638*12c85518Srobert           return isCXXDeclarationSpecifier(AllowImplicitTypename,
1639*12c85518Srobert                                            BracedCastResult, InvalidAsDeclSpec);
1640e5dd7070Spatrick         }
1641e5dd7070Spatrick       }
1642e5dd7070Spatrick       return TPResult::False;
1643e5dd7070Spatrick     }
1644e5dd7070Spatrick     // If that succeeded, fallthrough into the generic simple-type-id case.
1645*12c85518Srobert     [[fallthrough]];
1646e5dd7070Spatrick 
1647e5dd7070Spatrick     // The ambiguity resides in a simple-type-specifier/typename-specifier
1648e5dd7070Spatrick     // followed by a '('. The '(' could either be the start of:
1649e5dd7070Spatrick     //
1650e5dd7070Spatrick     //   direct-declarator:
1651e5dd7070Spatrick     //     '(' declarator ')'
1652e5dd7070Spatrick     //
1653e5dd7070Spatrick     //   direct-abstract-declarator:
1654e5dd7070Spatrick     //     '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
1655e5dd7070Spatrick     //              exception-specification[opt]
1656e5dd7070Spatrick     //     '(' abstract-declarator ')'
1657e5dd7070Spatrick     //
1658e5dd7070Spatrick     // or part of a function-style cast expression:
1659e5dd7070Spatrick     //
1660e5dd7070Spatrick     //     simple-type-specifier '(' expression-list[opt] ')'
1661e5dd7070Spatrick     //
1662e5dd7070Spatrick 
1663e5dd7070Spatrick     // simple-type-specifier:
1664e5dd7070Spatrick 
1665e5dd7070Spatrick   case tok::annot_typename:
1666e5dd7070Spatrick   case_typename:
1667e5dd7070Spatrick     // In Objective-C, we might have a protocol-qualified type.
1668e5dd7070Spatrick     if (getLangOpts().ObjC && NextToken().is(tok::less)) {
1669e5dd7070Spatrick       // Tentatively parse the protocol qualifiers.
1670e5dd7070Spatrick       RevertingTentativeParsingAction PA(*this);
1671e5dd7070Spatrick       ConsumeAnyToken(); // The type token
1672e5dd7070Spatrick 
1673e5dd7070Spatrick       TPResult TPR = TryParseProtocolQualifiers();
1674e5dd7070Spatrick       bool isFollowedByParen = Tok.is(tok::l_paren);
1675e5dd7070Spatrick       bool isFollowedByBrace = Tok.is(tok::l_brace);
1676e5dd7070Spatrick 
1677e5dd7070Spatrick       if (TPR == TPResult::Error)
1678e5dd7070Spatrick         return TPResult::Error;
1679e5dd7070Spatrick 
1680e5dd7070Spatrick       if (isFollowedByParen)
1681e5dd7070Spatrick         return TPResult::Ambiguous;
1682e5dd7070Spatrick 
1683e5dd7070Spatrick       if (getLangOpts().CPlusPlus11 && isFollowedByBrace)
1684e5dd7070Spatrick         return BracedCastResult;
1685e5dd7070Spatrick 
1686e5dd7070Spatrick       return TPResult::True;
1687e5dd7070Spatrick     }
1688*12c85518Srobert     [[fallthrough]];
1689e5dd7070Spatrick 
1690e5dd7070Spatrick   case tok::kw_char:
1691e5dd7070Spatrick   case tok::kw_wchar_t:
1692e5dd7070Spatrick   case tok::kw_char8_t:
1693e5dd7070Spatrick   case tok::kw_char16_t:
1694e5dd7070Spatrick   case tok::kw_char32_t:
1695e5dd7070Spatrick   case tok::kw_bool:
1696e5dd7070Spatrick   case tok::kw_short:
1697e5dd7070Spatrick   case tok::kw_int:
1698e5dd7070Spatrick   case tok::kw_long:
1699e5dd7070Spatrick   case tok::kw___int64:
1700e5dd7070Spatrick   case tok::kw___int128:
1701e5dd7070Spatrick   case tok::kw_signed:
1702e5dd7070Spatrick   case tok::kw_unsigned:
1703e5dd7070Spatrick   case tok::kw_half:
1704e5dd7070Spatrick   case tok::kw_float:
1705e5dd7070Spatrick   case tok::kw_double:
1706ec727ea7Spatrick   case tok::kw___bf16:
1707e5dd7070Spatrick   case tok::kw__Float16:
1708e5dd7070Spatrick   case tok::kw___float128:
1709*12c85518Srobert   case tok::kw___ibm128:
1710e5dd7070Spatrick   case tok::kw_void:
1711e5dd7070Spatrick   case tok::annot_decltype:
1712e5dd7070Spatrick #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
1713e5dd7070Spatrick #include "clang/Basic/OpenCLImageTypes.def"
1714e5dd7070Spatrick     if (NextToken().is(tok::l_paren))
1715e5dd7070Spatrick       return TPResult::Ambiguous;
1716e5dd7070Spatrick 
1717e5dd7070Spatrick     // This is a function-style cast in all cases we disambiguate other than
1718e5dd7070Spatrick     // one:
1719e5dd7070Spatrick     //   struct S {
1720e5dd7070Spatrick     //     enum E : int { a = 4 }; // enum
1721e5dd7070Spatrick     //     enum E : int { 4 };     // bit-field
1722e5dd7070Spatrick     //   };
1723e5dd7070Spatrick     if (getLangOpts().CPlusPlus11 && NextToken().is(tok::l_brace))
1724e5dd7070Spatrick       return BracedCastResult;
1725e5dd7070Spatrick 
1726e5dd7070Spatrick     if (isStartOfObjCClassMessageMissingOpenBracket())
1727e5dd7070Spatrick       return TPResult::False;
1728e5dd7070Spatrick 
1729e5dd7070Spatrick     return TPResult::True;
1730e5dd7070Spatrick 
1731e5dd7070Spatrick   // GNU typeof support.
1732e5dd7070Spatrick   case tok::kw_typeof: {
1733e5dd7070Spatrick     if (NextToken().isNot(tok::l_paren))
1734e5dd7070Spatrick       return TPResult::True;
1735e5dd7070Spatrick 
1736e5dd7070Spatrick     RevertingTentativeParsingAction PA(*this);
1737e5dd7070Spatrick 
1738e5dd7070Spatrick     TPResult TPR = TryParseTypeofSpecifier();
1739e5dd7070Spatrick     bool isFollowedByParen = Tok.is(tok::l_paren);
1740e5dd7070Spatrick     bool isFollowedByBrace = Tok.is(tok::l_brace);
1741e5dd7070Spatrick 
1742e5dd7070Spatrick     if (TPR == TPResult::Error)
1743e5dd7070Spatrick       return TPResult::Error;
1744e5dd7070Spatrick 
1745e5dd7070Spatrick     if (isFollowedByParen)
1746e5dd7070Spatrick       return TPResult::Ambiguous;
1747e5dd7070Spatrick 
1748e5dd7070Spatrick     if (getLangOpts().CPlusPlus11 && isFollowedByBrace)
1749e5dd7070Spatrick       return BracedCastResult;
1750e5dd7070Spatrick 
1751e5dd7070Spatrick     return TPResult::True;
1752e5dd7070Spatrick   }
1753e5dd7070Spatrick 
1754*12c85518Srobert #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
1755*12c85518Srobert #include "clang/Basic/TransformTypeTraits.def"
1756e5dd7070Spatrick     return TPResult::True;
1757e5dd7070Spatrick 
1758e5dd7070Spatrick   // C11 _Atomic
1759e5dd7070Spatrick   case tok::kw__Atomic:
1760e5dd7070Spatrick     return TPResult::True;
1761e5dd7070Spatrick 
1762*12c85518Srobert   case tok::kw__BitInt:
1763ec727ea7Spatrick   case tok::kw__ExtInt: {
1764ec727ea7Spatrick     if (NextToken().isNot(tok::l_paren))
1765ec727ea7Spatrick       return TPResult::Error;
1766ec727ea7Spatrick     RevertingTentativeParsingAction PA(*this);
1767ec727ea7Spatrick     ConsumeToken();
1768ec727ea7Spatrick     ConsumeParen();
1769ec727ea7Spatrick 
1770ec727ea7Spatrick     if (!SkipUntil(tok::r_paren, StopAtSemi))
1771ec727ea7Spatrick       return TPResult::Error;
1772ec727ea7Spatrick 
1773ec727ea7Spatrick     if (Tok.is(tok::l_paren))
1774ec727ea7Spatrick       return TPResult::Ambiguous;
1775ec727ea7Spatrick 
1776ec727ea7Spatrick     if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace))
1777ec727ea7Spatrick       return BracedCastResult;
1778ec727ea7Spatrick 
1779ec727ea7Spatrick     return TPResult::True;
1780ec727ea7Spatrick   }
1781e5dd7070Spatrick   default:
1782e5dd7070Spatrick     return TPResult::False;
1783e5dd7070Spatrick   }
1784e5dd7070Spatrick }
1785e5dd7070Spatrick 
isCXXDeclarationSpecifierAType()1786e5dd7070Spatrick bool Parser::isCXXDeclarationSpecifierAType() {
1787e5dd7070Spatrick   switch (Tok.getKind()) {
1788e5dd7070Spatrick     // typename-specifier
1789e5dd7070Spatrick   case tok::annot_decltype:
1790e5dd7070Spatrick   case tok::annot_template_id:
1791e5dd7070Spatrick   case tok::annot_typename:
1792e5dd7070Spatrick   case tok::kw_typeof:
1793*12c85518Srobert #define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait:
1794*12c85518Srobert #include "clang/Basic/TransformTypeTraits.def"
1795e5dd7070Spatrick     return true;
1796e5dd7070Spatrick 
1797e5dd7070Spatrick     // elaborated-type-specifier
1798e5dd7070Spatrick   case tok::kw_class:
1799e5dd7070Spatrick   case tok::kw_struct:
1800e5dd7070Spatrick   case tok::kw_union:
1801e5dd7070Spatrick   case tok::kw___interface:
1802e5dd7070Spatrick   case tok::kw_enum:
1803e5dd7070Spatrick     return true;
1804e5dd7070Spatrick 
1805e5dd7070Spatrick     // simple-type-specifier
1806e5dd7070Spatrick   case tok::kw_char:
1807e5dd7070Spatrick   case tok::kw_wchar_t:
1808e5dd7070Spatrick   case tok::kw_char8_t:
1809e5dd7070Spatrick   case tok::kw_char16_t:
1810e5dd7070Spatrick   case tok::kw_char32_t:
1811e5dd7070Spatrick   case tok::kw_bool:
1812e5dd7070Spatrick   case tok::kw_short:
1813e5dd7070Spatrick   case tok::kw_int:
1814ec727ea7Spatrick   case tok::kw__ExtInt:
1815*12c85518Srobert   case tok::kw__BitInt:
1816e5dd7070Spatrick   case tok::kw_long:
1817e5dd7070Spatrick   case tok::kw___int64:
1818e5dd7070Spatrick   case tok::kw___int128:
1819e5dd7070Spatrick   case tok::kw_signed:
1820e5dd7070Spatrick   case tok::kw_unsigned:
1821e5dd7070Spatrick   case tok::kw_half:
1822e5dd7070Spatrick   case tok::kw_float:
1823e5dd7070Spatrick   case tok::kw_double:
1824ec727ea7Spatrick   case tok::kw___bf16:
1825e5dd7070Spatrick   case tok::kw__Float16:
1826e5dd7070Spatrick   case tok::kw___float128:
1827*12c85518Srobert   case tok::kw___ibm128:
1828e5dd7070Spatrick   case tok::kw_void:
1829e5dd7070Spatrick   case tok::kw___unknown_anytype:
1830e5dd7070Spatrick   case tok::kw___auto_type:
1831e5dd7070Spatrick #define GENERIC_IMAGE_TYPE(ImgType, Id) case tok::kw_##ImgType##_t:
1832e5dd7070Spatrick #include "clang/Basic/OpenCLImageTypes.def"
1833e5dd7070Spatrick     return true;
1834e5dd7070Spatrick 
1835e5dd7070Spatrick   case tok::kw_auto:
1836e5dd7070Spatrick     return getLangOpts().CPlusPlus11;
1837e5dd7070Spatrick 
1838e5dd7070Spatrick   case tok::kw__Atomic:
1839e5dd7070Spatrick     // "_Atomic foo"
1840e5dd7070Spatrick     return NextToken().is(tok::l_paren);
1841e5dd7070Spatrick 
1842e5dd7070Spatrick   default:
1843e5dd7070Spatrick     return false;
1844e5dd7070Spatrick   }
1845e5dd7070Spatrick }
1846e5dd7070Spatrick 
1847e5dd7070Spatrick /// [GNU] typeof-specifier:
1848e5dd7070Spatrick ///         'typeof' '(' expressions ')'
1849e5dd7070Spatrick ///         'typeof' '(' type-name ')'
1850e5dd7070Spatrick ///
TryParseTypeofSpecifier()1851e5dd7070Spatrick Parser::TPResult Parser::TryParseTypeofSpecifier() {
1852e5dd7070Spatrick   assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");
1853e5dd7070Spatrick   ConsumeToken();
1854e5dd7070Spatrick 
1855e5dd7070Spatrick   assert(Tok.is(tok::l_paren) && "Expected '('");
1856e5dd7070Spatrick   // Parse through the parens after 'typeof'.
1857e5dd7070Spatrick   ConsumeParen();
1858e5dd7070Spatrick   if (!SkipUntil(tok::r_paren, StopAtSemi))
1859e5dd7070Spatrick     return TPResult::Error;
1860e5dd7070Spatrick 
1861e5dd7070Spatrick   return TPResult::Ambiguous;
1862e5dd7070Spatrick }
1863e5dd7070Spatrick 
1864e5dd7070Spatrick /// [ObjC] protocol-qualifiers:
1865e5dd7070Spatrick ////         '<' identifier-list '>'
TryParseProtocolQualifiers()1866e5dd7070Spatrick Parser::TPResult Parser::TryParseProtocolQualifiers() {
1867e5dd7070Spatrick   assert(Tok.is(tok::less) && "Expected '<' for qualifier list");
1868e5dd7070Spatrick   ConsumeToken();
1869e5dd7070Spatrick   do {
1870e5dd7070Spatrick     if (Tok.isNot(tok::identifier))
1871e5dd7070Spatrick       return TPResult::Error;
1872e5dd7070Spatrick     ConsumeToken();
1873e5dd7070Spatrick 
1874e5dd7070Spatrick     if (Tok.is(tok::comma)) {
1875e5dd7070Spatrick       ConsumeToken();
1876e5dd7070Spatrick       continue;
1877e5dd7070Spatrick     }
1878e5dd7070Spatrick 
1879e5dd7070Spatrick     if (Tok.is(tok::greater)) {
1880e5dd7070Spatrick       ConsumeToken();
1881e5dd7070Spatrick       return TPResult::Ambiguous;
1882e5dd7070Spatrick     }
1883e5dd7070Spatrick   } while (false);
1884e5dd7070Spatrick 
1885e5dd7070Spatrick   return TPResult::Error;
1886e5dd7070Spatrick }
1887e5dd7070Spatrick 
1888e5dd7070Spatrick /// isCXXFunctionDeclarator - Disambiguates between a function declarator or
1889e5dd7070Spatrick /// a constructor-style initializer, when parsing declaration statements.
1890e5dd7070Spatrick /// Returns true for function declarator and false for constructor-style
1891e5dd7070Spatrick /// initializer.
1892e5dd7070Spatrick /// If during the disambiguation process a parsing error is encountered,
1893e5dd7070Spatrick /// the function returns true to let the declaration parsing code handle it.
1894e5dd7070Spatrick ///
1895e5dd7070Spatrick /// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
1896e5dd7070Spatrick ///         exception-specification[opt]
1897e5dd7070Spatrick ///
isCXXFunctionDeclarator(bool * IsAmbiguous,ImplicitTypenameContext AllowImplicitTypename)1898*12c85518Srobert bool Parser::isCXXFunctionDeclarator(
1899*12c85518Srobert     bool *IsAmbiguous, ImplicitTypenameContext AllowImplicitTypename) {
1900e5dd7070Spatrick 
1901e5dd7070Spatrick   // C++ 8.2p1:
1902e5dd7070Spatrick   // The ambiguity arising from the similarity between a function-style cast and
1903e5dd7070Spatrick   // a declaration mentioned in 6.8 can also occur in the context of a
1904e5dd7070Spatrick   // declaration. In that context, the choice is between a function declaration
1905e5dd7070Spatrick   // with a redundant set of parentheses around a parameter name and an object
1906e5dd7070Spatrick   // declaration with a function-style cast as the initializer. Just as for the
1907e5dd7070Spatrick   // ambiguities mentioned in 6.8, the resolution is to consider any construct
1908e5dd7070Spatrick   // that could possibly be a declaration a declaration.
1909e5dd7070Spatrick 
1910e5dd7070Spatrick   RevertingTentativeParsingAction PA(*this);
1911e5dd7070Spatrick 
1912e5dd7070Spatrick   ConsumeParen();
1913e5dd7070Spatrick   bool InvalidAsDeclaration = false;
1914*12c85518Srobert   TPResult TPR = TryParseParameterDeclarationClause(
1915*12c85518Srobert       &InvalidAsDeclaration, /*VersusTemplateArgument=*/false,
1916*12c85518Srobert       AllowImplicitTypename);
1917e5dd7070Spatrick   if (TPR == TPResult::Ambiguous) {
1918e5dd7070Spatrick     if (Tok.isNot(tok::r_paren))
1919e5dd7070Spatrick       TPR = TPResult::False;
1920e5dd7070Spatrick     else {
1921e5dd7070Spatrick       const Token &Next = NextToken();
1922e5dd7070Spatrick       if (Next.isOneOf(tok::amp, tok::ampamp, tok::kw_const, tok::kw_volatile,
1923e5dd7070Spatrick                        tok::kw_throw, tok::kw_noexcept, tok::l_square,
1924e5dd7070Spatrick                        tok::l_brace, tok::kw_try, tok::equal, tok::arrow) ||
1925e5dd7070Spatrick           isCXX11VirtSpecifier(Next))
1926e5dd7070Spatrick         // The next token cannot appear after a constructor-style initializer,
1927e5dd7070Spatrick         // and can appear next in a function definition. This must be a function
1928e5dd7070Spatrick         // declarator.
1929e5dd7070Spatrick         TPR = TPResult::True;
1930e5dd7070Spatrick       else if (InvalidAsDeclaration)
1931e5dd7070Spatrick         // Use the absence of 'typename' as a tie-breaker.
1932e5dd7070Spatrick         TPR = TPResult::False;
1933e5dd7070Spatrick     }
1934e5dd7070Spatrick   }
1935e5dd7070Spatrick 
1936e5dd7070Spatrick   if (IsAmbiguous && TPR == TPResult::Ambiguous)
1937e5dd7070Spatrick     *IsAmbiguous = true;
1938e5dd7070Spatrick 
1939e5dd7070Spatrick   // In case of an error, let the declaration parsing code handle it.
1940e5dd7070Spatrick   return TPR != TPResult::False;
1941e5dd7070Spatrick }
1942e5dd7070Spatrick 
1943e5dd7070Spatrick /// parameter-declaration-clause:
1944e5dd7070Spatrick ///   parameter-declaration-list[opt] '...'[opt]
1945e5dd7070Spatrick ///   parameter-declaration-list ',' '...'
1946e5dd7070Spatrick ///
1947e5dd7070Spatrick /// parameter-declaration-list:
1948e5dd7070Spatrick ///   parameter-declaration
1949e5dd7070Spatrick ///   parameter-declaration-list ',' parameter-declaration
1950e5dd7070Spatrick ///
1951e5dd7070Spatrick /// parameter-declaration:
1952e5dd7070Spatrick ///   attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
1953e5dd7070Spatrick ///   attribute-specifier-seq[opt] decl-specifier-seq declarator attributes[opt]
1954e5dd7070Spatrick ///     '=' assignment-expression
1955e5dd7070Spatrick ///   attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
1956e5dd7070Spatrick ///     attributes[opt]
1957e5dd7070Spatrick ///   attribute-specifier-seq[opt] decl-specifier-seq abstract-declarator[opt]
1958e5dd7070Spatrick ///     attributes[opt] '=' assignment-expression
1959e5dd7070Spatrick ///
TryParseParameterDeclarationClause(bool * InvalidAsDeclaration,bool VersusTemplateArgument,ImplicitTypenameContext AllowImplicitTypename)1960*12c85518Srobert Parser::TPResult Parser::TryParseParameterDeclarationClause(
1961*12c85518Srobert     bool *InvalidAsDeclaration, bool VersusTemplateArgument,
1962*12c85518Srobert     ImplicitTypenameContext AllowImplicitTypename) {
1963e5dd7070Spatrick 
1964e5dd7070Spatrick   if (Tok.is(tok::r_paren))
1965e5dd7070Spatrick     return TPResult::Ambiguous;
1966e5dd7070Spatrick 
1967e5dd7070Spatrick   //   parameter-declaration-list[opt] '...'[opt]
1968e5dd7070Spatrick   //   parameter-declaration-list ',' '...'
1969e5dd7070Spatrick   //
1970e5dd7070Spatrick   // parameter-declaration-list:
1971e5dd7070Spatrick   //   parameter-declaration
1972e5dd7070Spatrick   //   parameter-declaration-list ',' parameter-declaration
1973e5dd7070Spatrick   //
1974*12c85518Srobert   while (true) {
1975e5dd7070Spatrick     // '...'[opt]
1976e5dd7070Spatrick     if (Tok.is(tok::ellipsis)) {
1977e5dd7070Spatrick       ConsumeToken();
1978e5dd7070Spatrick       if (Tok.is(tok::r_paren))
1979e5dd7070Spatrick         return TPResult::True; // '...)' is a sign of a function declarator.
1980e5dd7070Spatrick       else
1981e5dd7070Spatrick         return TPResult::False;
1982e5dd7070Spatrick     }
1983e5dd7070Spatrick 
1984e5dd7070Spatrick     // An attribute-specifier-seq here is a sign of a function declarator.
1985e5dd7070Spatrick     if (isCXX11AttributeSpecifier(/*Disambiguate*/false,
1986e5dd7070Spatrick                                   /*OuterMightBeMessageSend*/true))
1987e5dd7070Spatrick       return TPResult::True;
1988e5dd7070Spatrick 
1989e5dd7070Spatrick     ParsedAttributes attrs(AttrFactory);
1990e5dd7070Spatrick     MaybeParseMicrosoftAttributes(attrs);
1991e5dd7070Spatrick 
1992e5dd7070Spatrick     // decl-specifier-seq
1993e5dd7070Spatrick     // A parameter-declaration's initializer must be preceded by an '=', so
1994e5dd7070Spatrick     // decl-specifier-seq '{' is not a parameter in C++11.
1995*12c85518Srobert     TPResult TPR = isCXXDeclarationSpecifier(
1996*12c85518Srobert         AllowImplicitTypename, TPResult::False, InvalidAsDeclaration);
1997e5dd7070Spatrick     // A declaration-specifier (not followed by '(' or '{') means this can't be
1998e5dd7070Spatrick     // an expression, but it could still be a template argument.
1999e5dd7070Spatrick     if (TPR != TPResult::Ambiguous &&
2000e5dd7070Spatrick         !(VersusTemplateArgument && TPR == TPResult::True))
2001e5dd7070Spatrick       return TPR;
2002e5dd7070Spatrick 
2003e5dd7070Spatrick     bool SeenType = false;
2004e5dd7070Spatrick     do {
2005e5dd7070Spatrick       SeenType |= isCXXDeclarationSpecifierAType();
2006e5dd7070Spatrick       if (TryConsumeDeclarationSpecifier() == TPResult::Error)
2007e5dd7070Spatrick         return TPResult::Error;
2008e5dd7070Spatrick 
2009e5dd7070Spatrick       // If we see a parameter name, this can't be a template argument.
2010e5dd7070Spatrick       if (SeenType && Tok.is(tok::identifier))
2011e5dd7070Spatrick         return TPResult::True;
2012e5dd7070Spatrick 
2013*12c85518Srobert       TPR = isCXXDeclarationSpecifier(AllowImplicitTypename, TPResult::False,
2014e5dd7070Spatrick                                       InvalidAsDeclaration);
2015e5dd7070Spatrick       if (TPR == TPResult::Error)
2016e5dd7070Spatrick         return TPR;
2017e5dd7070Spatrick 
2018e5dd7070Spatrick       // Two declaration-specifiers means this can't be an expression.
2019e5dd7070Spatrick       if (TPR == TPResult::True && !VersusTemplateArgument)
2020e5dd7070Spatrick         return TPR;
2021e5dd7070Spatrick     } while (TPR != TPResult::False);
2022e5dd7070Spatrick 
2023e5dd7070Spatrick     // declarator
2024e5dd7070Spatrick     // abstract-declarator[opt]
2025e5dd7070Spatrick     TPR = TryParseDeclarator(true/*mayBeAbstract*/);
2026e5dd7070Spatrick     if (TPR != TPResult::Ambiguous)
2027e5dd7070Spatrick       return TPR;
2028e5dd7070Spatrick 
2029e5dd7070Spatrick     // [GNU] attributes[opt]
2030e5dd7070Spatrick     if (Tok.is(tok::kw___attribute))
2031e5dd7070Spatrick       return TPResult::True;
2032e5dd7070Spatrick 
2033e5dd7070Spatrick     // If we're disambiguating a template argument in a default argument in
2034e5dd7070Spatrick     // a class definition versus a parameter declaration, an '=' here
2035e5dd7070Spatrick     // disambiguates the parse one way or the other.
2036e5dd7070Spatrick     // If this is a parameter, it must have a default argument because
2037e5dd7070Spatrick     //   (a) the previous parameter did, and
2038e5dd7070Spatrick     //   (b) this must be the first declaration of the function, so we can't
2039e5dd7070Spatrick     //       inherit any default arguments from elsewhere.
2040ec727ea7Spatrick     // FIXME: If we reach a ')' without consuming any '>'s, then this must
2041ec727ea7Spatrick     // also be a function parameter (that's missing its default argument).
2042e5dd7070Spatrick     if (VersusTemplateArgument)
2043ec727ea7Spatrick       return Tok.is(tok::equal) ? TPResult::True : TPResult::False;
2044e5dd7070Spatrick 
2045e5dd7070Spatrick     if (Tok.is(tok::equal)) {
2046e5dd7070Spatrick       // '=' assignment-expression
2047e5dd7070Spatrick       // Parse through assignment-expression.
2048e5dd7070Spatrick       if (!SkipUntil(tok::comma, tok::r_paren, StopAtSemi | StopBeforeMatch))
2049e5dd7070Spatrick         return TPResult::Error;
2050e5dd7070Spatrick     }
2051e5dd7070Spatrick 
2052e5dd7070Spatrick     if (Tok.is(tok::ellipsis)) {
2053e5dd7070Spatrick       ConsumeToken();
2054e5dd7070Spatrick       if (Tok.is(tok::r_paren))
2055e5dd7070Spatrick         return TPResult::True; // '...)' is a sign of a function declarator.
2056e5dd7070Spatrick       else
2057e5dd7070Spatrick         return TPResult::False;
2058e5dd7070Spatrick     }
2059e5dd7070Spatrick 
2060e5dd7070Spatrick     if (!TryConsumeToken(tok::comma))
2061e5dd7070Spatrick       break;
2062e5dd7070Spatrick   }
2063e5dd7070Spatrick 
2064e5dd7070Spatrick   return TPResult::Ambiguous;
2065e5dd7070Spatrick }
2066e5dd7070Spatrick 
2067e5dd7070Spatrick /// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
2068e5dd7070Spatrick /// parsing as a function declarator.
2069e5dd7070Spatrick /// If TryParseFunctionDeclarator fully parsed the function declarator, it will
2070e5dd7070Spatrick /// return TPResult::Ambiguous, otherwise it will return either False() or
2071e5dd7070Spatrick /// Error().
2072e5dd7070Spatrick ///
2073e5dd7070Spatrick /// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
2074e5dd7070Spatrick ///         exception-specification[opt]
2075e5dd7070Spatrick ///
2076e5dd7070Spatrick /// exception-specification:
2077e5dd7070Spatrick ///   'throw' '(' type-id-list[opt] ')'
2078e5dd7070Spatrick ///
TryParseFunctionDeclarator()2079e5dd7070Spatrick Parser::TPResult Parser::TryParseFunctionDeclarator() {
2080e5dd7070Spatrick   // The '(' is already parsed.
2081e5dd7070Spatrick 
2082e5dd7070Spatrick   TPResult TPR = TryParseParameterDeclarationClause();
2083e5dd7070Spatrick   if (TPR == TPResult::Ambiguous && Tok.isNot(tok::r_paren))
2084e5dd7070Spatrick     TPR = TPResult::False;
2085e5dd7070Spatrick 
2086e5dd7070Spatrick   if (TPR == TPResult::False || TPR == TPResult::Error)
2087e5dd7070Spatrick     return TPR;
2088e5dd7070Spatrick 
2089e5dd7070Spatrick   // Parse through the parens.
2090e5dd7070Spatrick   if (!SkipUntil(tok::r_paren, StopAtSemi))
2091e5dd7070Spatrick     return TPResult::Error;
2092e5dd7070Spatrick 
2093e5dd7070Spatrick   // cv-qualifier-seq
2094e5dd7070Spatrick   while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw___unaligned,
2095e5dd7070Spatrick                      tok::kw_restrict))
2096e5dd7070Spatrick     ConsumeToken();
2097e5dd7070Spatrick 
2098e5dd7070Spatrick   // ref-qualifier[opt]
2099e5dd7070Spatrick   if (Tok.isOneOf(tok::amp, tok::ampamp))
2100e5dd7070Spatrick     ConsumeToken();
2101e5dd7070Spatrick 
2102e5dd7070Spatrick   // exception-specification
2103e5dd7070Spatrick   if (Tok.is(tok::kw_throw)) {
2104e5dd7070Spatrick     ConsumeToken();
2105e5dd7070Spatrick     if (Tok.isNot(tok::l_paren))
2106e5dd7070Spatrick       return TPResult::Error;
2107e5dd7070Spatrick 
2108e5dd7070Spatrick     // Parse through the parens after 'throw'.
2109e5dd7070Spatrick     ConsumeParen();
2110e5dd7070Spatrick     if (!SkipUntil(tok::r_paren, StopAtSemi))
2111e5dd7070Spatrick       return TPResult::Error;
2112e5dd7070Spatrick   }
2113e5dd7070Spatrick   if (Tok.is(tok::kw_noexcept)) {
2114e5dd7070Spatrick     ConsumeToken();
2115e5dd7070Spatrick     // Possibly an expression as well.
2116e5dd7070Spatrick     if (Tok.is(tok::l_paren)) {
2117e5dd7070Spatrick       // Find the matching rparen.
2118e5dd7070Spatrick       ConsumeParen();
2119e5dd7070Spatrick       if (!SkipUntil(tok::r_paren, StopAtSemi))
2120e5dd7070Spatrick         return TPResult::Error;
2121e5dd7070Spatrick     }
2122e5dd7070Spatrick   }
2123e5dd7070Spatrick 
2124e5dd7070Spatrick   return TPResult::Ambiguous;
2125e5dd7070Spatrick }
2126e5dd7070Spatrick 
2127e5dd7070Spatrick /// '[' constant-expression[opt] ']'
2128e5dd7070Spatrick ///
TryParseBracketDeclarator()2129e5dd7070Spatrick Parser::TPResult Parser::TryParseBracketDeclarator() {
2130e5dd7070Spatrick   ConsumeBracket();
2131e5dd7070Spatrick 
2132e5dd7070Spatrick   // A constant-expression cannot begin with a '{', but the
2133e5dd7070Spatrick   // expr-or-braced-init-list of a postfix-expression can.
2134e5dd7070Spatrick   if (Tok.is(tok::l_brace))
2135e5dd7070Spatrick     return TPResult::False;
2136e5dd7070Spatrick 
2137e5dd7070Spatrick   if (!SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch))
2138e5dd7070Spatrick     return TPResult::Error;
2139e5dd7070Spatrick 
2140e5dd7070Spatrick   // If we hit a comma before the ']', this is not a constant-expression,
2141e5dd7070Spatrick   // but might still be the expr-or-braced-init-list of a postfix-expression.
2142e5dd7070Spatrick   if (Tok.isNot(tok::r_square))
2143e5dd7070Spatrick     return TPResult::False;
2144e5dd7070Spatrick 
2145e5dd7070Spatrick   ConsumeBracket();
2146e5dd7070Spatrick   return TPResult::Ambiguous;
2147e5dd7070Spatrick }
2148e5dd7070Spatrick 
2149e5dd7070Spatrick /// Determine whether we might be looking at the '<' template-argument-list '>'
2150e5dd7070Spatrick /// of a template-id or simple-template-id, rather than a less-than comparison.
2151e5dd7070Spatrick /// This will often fail and produce an ambiguity, but should never be wrong
2152e5dd7070Spatrick /// if it returns True or False.
isTemplateArgumentList(unsigned TokensToSkip)2153e5dd7070Spatrick Parser::TPResult Parser::isTemplateArgumentList(unsigned TokensToSkip) {
2154e5dd7070Spatrick   if (!TokensToSkip) {
2155e5dd7070Spatrick     if (Tok.isNot(tok::less))
2156e5dd7070Spatrick       return TPResult::False;
2157e5dd7070Spatrick     if (NextToken().is(tok::greater))
2158e5dd7070Spatrick       return TPResult::True;
2159e5dd7070Spatrick   }
2160e5dd7070Spatrick 
2161e5dd7070Spatrick   RevertingTentativeParsingAction PA(*this);
2162e5dd7070Spatrick 
2163e5dd7070Spatrick   while (TokensToSkip) {
2164e5dd7070Spatrick     ConsumeAnyToken();
2165e5dd7070Spatrick     --TokensToSkip;
2166e5dd7070Spatrick   }
2167e5dd7070Spatrick 
2168e5dd7070Spatrick   if (!TryConsumeToken(tok::less))
2169e5dd7070Spatrick     return TPResult::False;
2170e5dd7070Spatrick 
2171e5dd7070Spatrick   // We can't do much to tell an expression apart from a template-argument,
2172e5dd7070Spatrick   // but one good distinguishing factor is that a "decl-specifier" not
2173e5dd7070Spatrick   // followed by '(' or '{' can't appear in an expression.
2174e5dd7070Spatrick   bool InvalidAsTemplateArgumentList = false;
2175*12c85518Srobert   if (isCXXDeclarationSpecifier(ImplicitTypenameContext::No, TPResult::False,
2176e5dd7070Spatrick                                 &InvalidAsTemplateArgumentList) ==
2177e5dd7070Spatrick       TPResult::True)
2178e5dd7070Spatrick     return TPResult::True;
2179e5dd7070Spatrick   if (InvalidAsTemplateArgumentList)
2180e5dd7070Spatrick     return TPResult::False;
2181e5dd7070Spatrick 
2182e5dd7070Spatrick   // FIXME: In many contexts, X<thing1, Type> can only be a
2183e5dd7070Spatrick   // template-argument-list. But that's not true in general:
2184e5dd7070Spatrick   //
2185e5dd7070Spatrick   // using b = int;
2186e5dd7070Spatrick   // void f() {
2187e5dd7070Spatrick   //   int a = A<B, b, c = C>D; // OK, declares b, not a template-id.
2188e5dd7070Spatrick   //
2189e5dd7070Spatrick   // X<Y<0, int> // ', int>' might be end of X's template argument list
2190e5dd7070Spatrick   //
2191e5dd7070Spatrick   // We might be able to disambiguate a few more cases if we're careful.
2192e5dd7070Spatrick 
2193e5dd7070Spatrick   // A template-argument-list must be terminated by a '>'.
2194e5dd7070Spatrick   if (SkipUntil({tok::greater, tok::greatergreater, tok::greatergreatergreater},
2195e5dd7070Spatrick                 StopAtSemi | StopBeforeMatch))
2196e5dd7070Spatrick     return TPResult::Ambiguous;
2197e5dd7070Spatrick   return TPResult::False;
2198e5dd7070Spatrick }
2199e5dd7070Spatrick 
2200e5dd7070Spatrick /// Determine whether we might be looking at the '(' of a C++20 explicit(bool)
2201e5dd7070Spatrick /// in an earlier language mode.
isExplicitBool()2202e5dd7070Spatrick Parser::TPResult Parser::isExplicitBool() {
2203e5dd7070Spatrick   assert(Tok.is(tok::l_paren) && "expected to be looking at a '(' token");
2204e5dd7070Spatrick 
2205e5dd7070Spatrick   RevertingTentativeParsingAction PA(*this);
2206e5dd7070Spatrick   ConsumeParen();
2207e5dd7070Spatrick 
2208e5dd7070Spatrick   // We can only have 'explicit' on a constructor, conversion function, or
2209e5dd7070Spatrick   // deduction guide. The declarator of a deduction guide cannot be
2210e5dd7070Spatrick   // parenthesized, so we know this isn't a deduction guide. So the only
2211e5dd7070Spatrick   // thing we need to check for is some number of parens followed by either
2212e5dd7070Spatrick   // the current class name or 'operator'.
2213e5dd7070Spatrick   while (Tok.is(tok::l_paren))
2214e5dd7070Spatrick     ConsumeParen();
2215e5dd7070Spatrick 
2216e5dd7070Spatrick   if (TryAnnotateOptionalCXXScopeToken())
2217e5dd7070Spatrick     return TPResult::Error;
2218e5dd7070Spatrick 
2219e5dd7070Spatrick   // Class-scope constructor and conversion function names can't really be
2220e5dd7070Spatrick   // qualified, but we get better diagnostics if we assume they can be.
2221e5dd7070Spatrick   CXXScopeSpec SS;
2222e5dd7070Spatrick   if (Tok.is(tok::annot_cxxscope)) {
2223e5dd7070Spatrick     Actions.RestoreNestedNameSpecifierAnnotation(Tok.getAnnotationValue(),
2224e5dd7070Spatrick                                                  Tok.getAnnotationRange(),
2225e5dd7070Spatrick                                                  SS);
2226e5dd7070Spatrick     ConsumeAnnotationToken();
2227e5dd7070Spatrick   }
2228e5dd7070Spatrick 
2229e5dd7070Spatrick   // 'explicit(operator' might be explicit(bool) or the declaration of a
2230e5dd7070Spatrick   // conversion function, but it's probably a conversion function.
2231e5dd7070Spatrick   if (Tok.is(tok::kw_operator))
2232e5dd7070Spatrick     return TPResult::Ambiguous;
2233e5dd7070Spatrick 
2234e5dd7070Spatrick   // If this can't be a constructor name, it can only be explicit(bool).
2235e5dd7070Spatrick   if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
2236e5dd7070Spatrick     return TPResult::True;
2237e5dd7070Spatrick   if (!Actions.isCurrentClassName(Tok.is(tok::identifier)
2238e5dd7070Spatrick                                       ? *Tok.getIdentifierInfo()
2239e5dd7070Spatrick                                       : *takeTemplateIdAnnotation(Tok)->Name,
2240e5dd7070Spatrick                                   getCurScope(), &SS))
2241e5dd7070Spatrick     return TPResult::True;
2242e5dd7070Spatrick   // Formally, we must have a right-paren after the constructor name to match
2243e5dd7070Spatrick   // the grammar for a constructor. But clang permits a parenthesized
2244e5dd7070Spatrick   // constructor declarator, so also allow a constructor declarator to follow
2245e5dd7070Spatrick   // with no ')' token after the constructor name.
2246e5dd7070Spatrick   if (!NextToken().is(tok::r_paren) &&
2247e5dd7070Spatrick       !isConstructorDeclarator(/*Unqualified=*/SS.isEmpty(),
2248e5dd7070Spatrick                                /*DeductionGuide=*/false))
2249e5dd7070Spatrick     return TPResult::True;
2250e5dd7070Spatrick 
2251e5dd7070Spatrick   // Might be explicit(bool) or a parenthesized constructor name.
2252e5dd7070Spatrick   return TPResult::Ambiguous;
2253e5dd7070Spatrick }
2254