diff options
author | Dino Radakovic <dinor@google.com> | 2024-02-09 11:58:31 -0800 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-02-09 12:00:20 -0800 |
commit | 1ac7f340105c75e447f5f98b77b71e4df2125153 (patch) | |
tree | 9b4328062098c4e986fe9f6c06d9d193e5df7c0d /absl/debugging | |
parent | 760b21530ffc22ef4859356e543022b18de7d2ce (diff) |
`demangle`: Parse `requires` clauses on functions
These clauses show up in other places that end up mangled as parts of function signatures (e.g. on template struct params). We'll handle those in a follow-up.
PiperOrigin-RevId: 605694497
Change-Id: I1bfe4c0cfaa739fdd24548b1547482410c92b5a7
Diffstat (limited to 'absl/debugging')
-rw-r--r-- | absl/debugging/internal/demangle.cc | 50 | ||||
-rw-r--r-- | absl/debugging/internal/demangle_test.cc | 11 |
2 files changed, 53 insertions, 8 deletions
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc index fd3aef70..c2f19451 100644 --- a/absl/debugging/internal/demangle.cc +++ b/absl/debugging/internal/demangle.cc @@ -579,6 +579,7 @@ static bool ParseUnresolvedName(State *state); static bool ParseExpression(State *state); static bool ParseExprPrimary(State *state); static bool ParseExprCastValue(State *state); +static bool ParseRequiresClauseExpression(State *state); static bool ParseLocalName(State *state); static bool ParseLocalNameSuffix(State *state); static bool ParseDiscriminator(State *state); @@ -623,25 +624,38 @@ static bool ParseMangledName(State *state) { } // <encoding> ::= <(function) name> <bare-function-type> +// [`Q` <requires-clause expr>] // ::= <(data) name> // ::= <special-name> // // NOTE: Based on http://shortn/_Hoq9qG83rx -// TODO(b/324066279): Add support for [Q <requires-clause expression>]. static bool ParseEncoding(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; - // Implementing the first two productions together as <name> - // [<bare-function-type>] avoids exponential blowup of backtracking. + // Since the first two productions both start with <name>, attempt + // to parse it only once to avoid exponential blowup of backtracking. // - // Since Optional(...) can't fail, there's no need to copy the state for - // backtracking. - if (ParseName(state) && Optional(ParseBareFunctionType(state))) { - return true; + // We're careful about exponential blowup because <encoding> recursively + // appears in other productions downstream of its first two productions, + // which means that every call to `ParseName` would possibly indirectly + // result in two calls to `ParseName` etc. + if (ParseName(state)) { + if (!ParseBareFunctionType(state)) { + return true; // <(data) name> + } + + // Parsed: <(function) name> <bare-function-type> + // Pending: [`Q` <requires-clause expr>] + ParseState copy = state->parse_state; + if (ParseOneCharToken(state, 'Q') && ParseRequiresClauseExpression(state)) { + return true; // <(function) name> <bare-function-type> `Q` <requires> + } + state->parse_state = copy; + return true; // <(function) name> <bare-function-type> } if (ParseSpecialName(state)) { - return true; + return true; // <special-name> } return false; } @@ -1916,6 +1930,26 @@ static bool ParseExprCastValue(State *state) { return false; } +// <requires-clause expr> is just an <expression>: http://shortn/_9E1Ul0rIM8 +// +// Does not emit the parsed `requires` clause to simplify the implementation. +// In other words, these two functions' mangled names will demangle identically: +// +// template <typename T> +// int foo(T) requires IsIntegral<T>; +// +// vs. +// +// template <typename T> +// int foo(T); +static bool ParseRequiresClauseExpression(State *state) { + bool original_append = state->parse_state.append; + DisableAppend(state); + bool result = ParseExpression(state); + RestoreAppend(state, original_append); + return result; +} + // <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>] // ::= Z <(function) encoding> E s [<discriminator>] // diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index 4e04210e..4b9d7711 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -64,6 +64,17 @@ TEST(Demangle, FunctionTemplateWithNonTypeParamConstraint) { EXPECT_STREQ(tmp, "foo<>()"); } +TEST(Demangle, FunctionTemplateWithFunctionRequiresClause) { + char tmp[100]; + + // template <typename T> + // int foo() requires std::integral<T>; + // + // foo<int>(); + ASSERT_TRUE(Demangle("_Z3fooIiEivQsr3stdE8integralIT_E", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "foo<>()"); +} + TEST(Demangle, FunctionTemplateWithAutoParam) { char tmp[100]; |