Skip to content

Commit 7fdf021

Browse files
committed
[FOLD] further improvements to skipping template argument lists
1 parent 4f9d734 commit 7fdf021

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
@@ -2769,6 +2769,7 @@ class Parser : public CodeCompletionHandler {
27692769
TPResult TryParseTypeofSpecifier();
27702770
TPResult TryParseProtocolQualifiers();
27712771
TPResult TryParsePtrOperatorSeq();
2772+
TPResult TryParseNonConversionOperatorId();
27722773
TPResult TryParseOperatorId();
27732774
TPResult TryParseInitDeclaratorList(bool MayHaveTrailingReturnType = false);
27742775
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
@@ -1795,9 +1795,6 @@ bool Parser::isMissingTemplateKeywordBeforeScope(bool AnnotateInvalid) {
17951795
assert(Tok.is(tok::coloncolon));
17961796
Sema::DisableTypoCorrectionRAII DTC(Actions);
17971797
ColonProtectionRAIIObject ColonProtection(*this);
1798-
std::optional<Sema::TentativeAnalysisScope> TAS;
1799-
if (!AnnotateInvalid)
1800-
TAS.emplace(Actions);
18011798

18021799
SourceLocation StartLoc = Tok.getLocation();
18031800
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) {
@@ -2328,37 +2335,166 @@ Parser::TPResult Parser::isTemplateArgumentList(unsigned TokensToSkip, TemplateN
23282335
bool IsNestedTemplateArgumentList = !GreaterThanIsOperator;
23292336
GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);
23302337

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

2465+
if (TryAnnotateOptionalCXXScopeToken())
2466+
return TPResult::Error;
2467+
23372468
bool InvalidAsTemplateArgumentList = false;
2338-
if (isCXXDeclarationSpecifier(ImplicitTypenameContext::No, TPResult::False,
2339-
&InvalidAsTemplateArgumentList) ==
2340-
TPResult::True)
2341-
return TPResult::True;
2469+
TPResult TPR = isCXXDeclarationSpecifier(ImplicitTypenameContext::No,
2470+
/*BracedCastResult=*/TPResult::Ambiguous,
2471+
&InvalidAsTemplateArgumentList);
23422472
if (InvalidAsTemplateArgumentList)
23432473
return TPResult::False;
23442474

2475+
if (TPR == TPResult::True)
2476+
return TPResult::True;
2477+
23452478
if (IsNestedTemplateArgumentList || TNK != TNK_Non_template)
23462479
break;
23472480

2348-
if (TryAnnotateOptionalCXXScopeToken())
2349-
return TPResult::Error;
2481+
if (TPR == TPResult::Ambiguous)
2482+
TryConsumeDeclarationSpecifier();
2483+
2484+
TPR = TrySkipTemplateArgument();
23502485

2351-
if (!SkipUntil({tok::comma, tok::less,
2352-
tok::greater, tok::greatergreater, tok::greatergreatergreater},
2353-
StopAtSemi | StopBeforeMatch))
2486+
if (TPR == TPResult::Error)
2487+
return TPResult::Error;
2488+
else if (TPR == TPResult::False)
23542489
return TPResult::False;
23552490

2356-
if (Tok.isNot(tok::comma)) {
2491+
if (!TryConsumeToken(tok::comma)) {
23572492
if (Tok.is(tok::less))
23582493
break;
23592494
if (TryConsumeToken(tok::greater) && Tok.is(tok::coloncolon) &&
23602495
!NextToken().isOneOf(tok::kw_new, tok::kw_delete)) {
23612496
TentativeParsingAction TPA(*this, /*Unannotated=*/true);
2497+
Sema::TentativeAnalysisScope TAS(Actions);
23622498
if (isMissingTemplateKeywordBeforeScope(/*AnnotateInvalid=*/false)) {
23632499
TPA.Revert();
23642500
return TPResult::True;
@@ -2367,7 +2503,6 @@ Parser::TPResult Parser::isTemplateArgumentList(unsigned TokensToSkip, TemplateN
23672503
}
23682504
return TPResult::Ambiguous;
23692505
}
2370-
ConsumeToken();
23712506
}
23722507

23732508
#if 0

0 commit comments

Comments
 (0)