@@ -579,6 +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);
582583static bool ParseLocalName (State *state);
583584static bool ParseLocalNameSuffix (State *state);
584585static bool ParseDiscriminator (State *state);
@@ -623,25 +624,38 @@ static bool ParseMangledName(State *state) {
623624}
624625
625626// <encoding> ::= <(function) name> <bare-function-type>
627+ // [`Q` <requires-clause expr>]
626628// ::= <(data) name>
627629// ::= <special-name>
628630//
629631// NOTE: Based on http://shortn/_Hoq9qG83rx
630- // TODO(b/324066279): Add support for [Q <requires-clause expression>].
631632static bool ParseEncoding (State *state) {
632633 ComplexityGuard guard (state);
633634 if (guard.IsTooComplex ()) return false ;
634- // Implementing the first two productions together as <name>
635- // [<bare-function-type>] avoids exponential blowup of backtracking.
635+ // Since the first two productions both start with <name>, attempt
636+ // to parse it only once to avoid exponential blowup of backtracking.
636637 //
637- // Since Optional(...) can't fail, there's no need to copy the state for
638- // backtracking.
639- if (ParseName (state) && Optional (ParseBareFunctionType (state))) {
640- return true ;
638+ // We're careful about exponential blowup because <encoding> recursively
639+ // appears in other productions downstream of its first two productions,
640+ // which means that every call to `ParseName` would possibly indirectly
641+ // result in two calls to `ParseName` etc.
642+ if (ParseName (state)) {
643+ if (!ParseBareFunctionType (state)) {
644+ return true ; // <(data) name>
645+ }
646+
647+ // Parsed: <(function) name> <bare-function-type>
648+ // 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>
641655 }
642656
643657 if (ParseSpecialName (state)) {
644- return true ;
658+ return true ; // <special-name>
645659 }
646660 return false ;
647661}
@@ -1916,6 +1930,26 @@ static bool ParseExprCastValue(State *state) {
19161930 return false ;
19171931}
19181932
1933+ // <requires-clause expr> is just an <expression>: http://shortn/_9E1Ul0rIM8
1934+ //
1935+ // Does not emit the parsed `requires` clause to simplify the implementation.
1936+ // In other words, these two functions' mangled names will demangle identically:
1937+ //
1938+ // template <typename T>
1939+ // int foo(T) requires IsIntegral<T>;
1940+ //
1941+ // vs.
1942+ //
1943+ // template <typename T>
1944+ // int foo(T);
1945+ static bool ParseRequiresClauseExpression (State *state) {
1946+ bool original_append = state->parse_state .append ;
1947+ DisableAppend (state);
1948+ bool result = ParseExpression (state);
1949+ RestoreAppend (state, original_append);
1950+ return result;
1951+ }
1952+
19191953// <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>]
19201954// ::= Z <(function) encoding> E s [<discriminator>]
19211955//
0 commit comments