@@ -579,7 +579,7 @@ static bool ParseUnresolvedName(State *state);
579579static bool ParseExpression (State *state);
580580static bool ParseExprPrimary (State *state);
581581static bool ParseExprCastValue (State *state);
582- static bool ParseRequiresClauseExpression (State *state);
582+ static bool ParseQRequiresClauseExpr (State *state);
583583static bool ParseLocalName (State *state);
584584static bool ParseLocalNameSuffix (State *state);
585585static bool ParseDiscriminator (State *state);
@@ -646,12 +646,8 @@ static bool ParseEncoding(State *state) {
646646
647647 // Parsed: <(function) name> <bare-function-type>
648648 // Pending: [`Q` <requires-clause expr>]
649- ParseState copy = state->parse_state ;
650- if (ParseOneCharToken (state, ' Q' ) && ParseRequiresClauseExpression (state)) {
651- return true ; // <(function) name> <bare-function-type> `Q` <requires>
652- }
653- state->parse_state = copy;
654- return true ; // <(function) name> <bare-function-type>
649+ ParseQRequiresClauseExpr (state); // restores state on failure
650+ return true ;
655651 }
656652
657653 if (ParseSpecialName (state)) {
@@ -1505,16 +1501,14 @@ static bool ParseTemplateTemplateParam(State *state) {
15051501 ParseSubstitution (state, /* accept_std=*/ false ));
15061502}
15071503
1508- // <template-args> ::= I <template-arg>+ E
1509- //
1510- // TODO(b/324066279): Implement optional [Q <requires-clause expr>] before E.
1511- // See: http://shortn/_Z7yM7PonSD
1504+ // <template-args> ::= I <template-arg>+ [Q <requires-clause expr>] E
15121505static bool ParseTemplateArgs (State *state) {
15131506 ComplexityGuard guard (state);
15141507 if (guard.IsTooComplex ()) return false ;
15151508 ParseState copy = state->parse_state ;
15161509 DisableAppend (state);
15171510 if (ParseOneCharToken (state, ' I' ) && OneOrMore (ParseTemplateArg, state) &&
1511+ Optional (ParseQRequiresClauseExpr (state)) &&
15181512 ParseOneCharToken (state, ' E' )) {
15191513 RestoreAppend (state, copy.append );
15201514 MaybeAppend (state, " <>" );
@@ -1930,7 +1924,12 @@ static bool ParseExprCastValue(State *state) {
19301924 return false ;
19311925}
19321926
1933- // <requires-clause expr> is just an <expression>: http://shortn/_9E1Ul0rIM8
1927+ // Parses `Q <requires-clause expr>`.
1928+ // If parsing fails, applies backtracking to `state`.
1929+ //
1930+ // This function covers two symbols instead of one for convenience,
1931+ // because in LLVM's Itanium ABI mangling grammar, <requires-clause expr>
1932+ // always appears after Q.
19341933//
19351934// Does not emit the parsed `requires` clause to simplify the implementation.
19361935// In other words, these two functions' mangled names will demangle identically:
@@ -1942,12 +1941,19 @@ static bool ParseExprCastValue(State *state) {
19421941//
19431942// template <typename T>
19441943// int foo(T);
1945- static bool ParseRequiresClauseExpression (State *state) {
1946- bool original_append = state->parse_state . append ;
1944+ static bool ParseQRequiresClauseExpr (State *state) {
1945+ ParseState copy = state->parse_state ;
19471946 DisableAppend (state);
1948- bool result = ParseExpression (state);
1949- RestoreAppend (state, original_append);
1950- return result;
1947+
1948+ // <requires-clause expr> is just an <expression>: http://shortn/_9E1Ul0rIM8
1949+ if (ParseOneCharToken (state, ' Q' ) && ParseExpression (state)) {
1950+ RestoreAppend (state, copy.append );
1951+ return true ;
1952+ }
1953+
1954+ // also restores append
1955+ state->parse_state = copy;
1956+ return false ;
19511957}
19521958
19531959// <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>]
0 commit comments