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