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