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