Skip to content

Commit 2f275f8

Browse files
committed
[FOLD] further improvements to skipping template argument lists
1 parent a8729dd commit 2f275f8

File tree

3 files changed

+148
-15
lines changed

3 files changed

+148
-15
lines changed

clang/include/clang/Parse/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2766,6 +2766,7 @@ class Parser : public CodeCompletionHandler {
27662766
TPResult TryParseTypeofSpecifier();
27672767
TPResult TryParseProtocolQualifiers();
27682768
TPResult TryParsePtrOperatorSeq();
2769+
TPResult TryParseNonConversionOperatorId();
27692770
TPResult TryParseOperatorId();
27702771
TPResult TryParseInitDeclaratorList(bool MayHaveTrailingReturnType = false);
27712772
TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier = true,

clang/lib/Parse/ParseTemplate.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,9 +1783,6 @@ bool Parser::isMissingTemplateKeywordBeforeScope(bool AnnotateInvalid) {
17831783
assert(Tok.is(tok::coloncolon));
17841784
Sema::DisableTypoCorrectionRAII DTC(Actions);
17851785
ColonProtectionRAIIObject ColonProtection(*this);
1786-
std::optional<Sema::TentativeAnalysisScope> TAS;
1787-
if (!AnnotateInvalid)
1788-
TAS.emplace(Actions);
17891786

17901787
SourceLocation StartLoc = Tok.getLocation();
17911788
if (TryAnnotateTypeOrScopeToken())

clang/lib/Parse/ParseTentative.cpp

Lines changed: 147 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,7 @@ Parser::TPResult Parser::TryParsePtrOperatorSeq() {
955955
/// literal-operator-id:
956956
/// 'operator' string-literal identifier
957957
/// 'operator' user-defined-string-literal
958-
Parser::TPResult Parser::TryParseOperatorId() {
958+
Parser::TPResult Parser::TryParseNonConversionOperatorId() {
959959
assert(Tok.is(tok::kw_operator));
960960
ConsumeToken();
961961

@@ -1013,6 +1013,13 @@ Parser::TPResult Parser::TryParseOperatorId() {
10131013
return TPResult::True;
10141014
}
10151015

1016+
return TPResult::False;
1017+
}
1018+
Parser::TPResult Parser::TryParseOperatorId() {
1019+
if (TPResult TPR = TryParseNonConversionOperatorId();
1020+
TPR != TPResult::False)
1021+
return TPR;
1022+
10161023
// Maybe this is a conversion-function-id.
10171024
bool AnyDeclSpecifiers = false;
10181025
while (true) {
@@ -2324,37 +2331,166 @@ Parser::TPResult Parser::isTemplateArgumentList(unsigned TokensToSkip, TemplateN
23242331
bool IsNestedTemplateArgumentList = !GreaterThanIsOperator;
23252332
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
23262333

2334+
auto TrySkipTemplateArgument = [&]() {
2335+
bool NextIsTemplateId = false;
2336+
unsigned TemplateDepth = 0;
2337+
while (true) {
2338+
switch (Tok.getKind()) {
2339+
case tok::eof:
2340+
case tok::annot_module_begin:
2341+
case tok::annot_module_end:
2342+
case tok::annot_module_include:
2343+
case tok::annot_repl_input_end:
2344+
case tok::semi:
2345+
return TPResult::False;
2346+
2347+
case tok::comma:
2348+
case tok::greater:
2349+
case tok::greatergreater:
2350+
case tok::greatergreatergreater:
2351+
return TPResult::True;
2352+
2353+
case tok::l_paren:
2354+
ConsumeParen();
2355+
if (!SkipUntil(tok::r_paren, StopAtSemi))
2356+
return TPResult::Error;
2357+
break;
2358+
case tok::l_brace:
2359+
ConsumeBrace();
2360+
if (!SkipUntil(tok::r_brace, StopAtSemi))
2361+
return TPResult::Error;
2362+
break;
2363+
case tok::l_square:
2364+
ConsumeBracket();
2365+
if (!SkipUntil(tok::r_square, StopAtSemi))
2366+
return TPResult::Error;
2367+
break;
2368+
case tok::question:
2369+
ConsumeToken();
2370+
if (!SkipUntil(tok::colon, StopAtSemi))
2371+
return TPResult::Error;
2372+
break;
2373+
2374+
#if 0
2375+
case tok::kw_template:
2376+
ConsumeToken();
2377+
NextIsTemplateId = true;
2378+
continue;
2379+
#endif
2380+
case tok::identifier:
2381+
ConsumeToken();
2382+
#if 0
2383+
if (Tok.is(tok::less)) {
2384+
if (!NextIsTemplateId)
2385+
return TPResult::Ambiguous;
2386+
ConsumeToken();
2387+
if (!SkipUntil({tok::greater, tok::greatergreater, tok::greatergreatergreater}, StopAtSemi))
2388+
return TPResult::Error;
2389+
break;
2390+
}
2391+
#else
2392+
if (Tok.is(tok::less))
2393+
return TPResult::Ambiguous;
2394+
break;
2395+
#endif
2396+
2397+
case tok::kw_operator:
2398+
if (TPResult TPR = TryParseNonConversionOperatorId();
2399+
TPR == TPResult::Error) {
2400+
return TPResult::Error;
2401+
} else if (TPR == TPResult::True) {
2402+
if (Tok.is(tok::less))
2403+
return TPResult::Ambiguous;
2404+
}
2405+
break;
2406+
2407+
#if 0
2408+
if (Tok.is(tok::less)) {
2409+
if (!NextIsTemplateId)
2410+
return TPResult::Ambiguous;
2411+
ConsumeToken();
2412+
if (!SkipUntil({tok::greater, tok::greatergreater, tok::greatergreatergreater}, StopAtSemi))
2413+
return TPResult::Error;
2414+
}
2415+
break;
2416+
#endif
2417+
2418+
case tok::kw_const_cast:
2419+
case tok::kw_dynamic_cast:
2420+
case tok::kw_reinterpret_cast:
2421+
case tok::kw_static_cast: {
2422+
ConsumeToken();
2423+
if (!TryConsumeToken(tok::less))
2424+
return TPResult::Error;
2425+
bool MayHaveTrailingReturnType = Tok.is(tok::kw_auto);
2426+
2427+
while (true) {
2428+
TPResult TPR = isCXXDeclarationSpecifier(ImplicitTypenameContext::Yes);
2429+
if (TPR == TPResult::False)
2430+
break;
2431+
if (TPR == TPResult::Error ||
2432+
TryConsumeDeclarationSpecifier() == TPResult::Error)
2433+
return TPResult::Error;
2434+
}
2435+
2436+
if (TryParseDeclarator(
2437+
/*mayBeAbstract=*/true,
2438+
/*mayHaveIdentifier=*/false,
2439+
/*mayHaveDirectInit=*/false,
2440+
/*mayHaveTrailingReturnType=*/MayHaveTrailingReturnType) == TPResult::Error)
2441+
return TPResult::Error;
2442+
2443+
if (!TryConsumeToken(tok::greater))
2444+
return TPResult::Error;
2445+
break;
2446+
}
2447+
default:
2448+
ConsumeAnyToken();
2449+
break;
2450+
}
2451+
NextIsTemplateId = false;
2452+
}
2453+
};
2454+
23272455
while (true) {
23282456
// An expression cannot be followed by a braced-init-list unless
23292457
// its the right operand of an assignment operator.
23302458
if (Tok.is(tok::l_brace))
23312459
return TPResult::True;
23322460

2461+
if (TryAnnotateOptionalCXXScopeToken())
2462+
return TPResult::Error;
2463+
23332464
bool InvalidAsTemplateArgumentList = false;
2334-
if (isCXXDeclarationSpecifier(ImplicitTypenameContext::No, TPResult::False,
2335-
&InvalidAsTemplateArgumentList) ==
2336-
TPResult::True)
2337-
return TPResult::True;
2465+
TPResult TPR = isCXXDeclarationSpecifier(ImplicitTypenameContext::No,
2466+
/*BracedCastResult=*/TPResult::Ambiguous,
2467+
&InvalidAsTemplateArgumentList);
23382468
if (InvalidAsTemplateArgumentList)
23392469
return TPResult::False;
23402470

2471+
if (TPR == TPResult::True)
2472+
return TPResult::True;
2473+
23412474
if (IsNestedTemplateArgumentList || TNK != TNK_Non_template)
23422475
break;
23432476

2344-
if (TryAnnotateOptionalCXXScopeToken())
2345-
return TPResult::Error;
2477+
if (TPR == TPResult::Ambiguous)
2478+
TryConsumeDeclarationSpecifier();
2479+
2480+
TPR = TrySkipTemplateArgument();
23462481

2347-
if (!SkipUntil({tok::comma, tok::less,
2348-
tok::greater, tok::greatergreater, tok::greatergreatergreater},
2349-
StopAtSemi | StopBeforeMatch))
2482+
if (TPR == TPResult::Error)
2483+
return TPResult::Error;
2484+
else if (TPR == TPResult::False)
23502485
return TPResult::False;
23512486

2352-
if (Tok.isNot(tok::comma)) {
2487+
if (!TryConsumeToken(tok::comma)) {
23532488
if (Tok.is(tok::less))
23542489
break;
23552490
if (TryConsumeToken(tok::greater) && Tok.is(tok::coloncolon) &&
23562491
!NextToken().isOneOf(tok::kw_new, tok::kw_delete)) {
23572492
TentativeParsingAction TPA(*this, /*Unannotated=*/true);
2493+
Sema::TentativeAnalysisScope TAS(Actions);
23582494
if (isMissingTemplateKeywordBeforeScope(/*AnnotateInvalid=*/false)) {
23592495
TPA.Revert();
23602496
return TPResult::True;
@@ -2363,7 +2499,6 @@ Parser::TPResult Parser::isTemplateArgumentList(unsigned TokensToSkip, TemplateN
23632499
}
23642500
return TPResult::Ambiguous;
23652501
}
2366-
ConsumeToken();
23672502
}
23682503

23692504
#if 0

0 commit comments

Comments
 (0)