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