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