diff options
author | Chris Mihelich <cmihelic@google.com> | 2024-05-24 15:33:25 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-05-24 15:34:23 -0700 |
commit | baf07b1f6201e4a6b3f16d87131a558693197c6f (patch) | |
tree | 4587a71cec7a762e1e419ba3452d9d04b802350c /absl | |
parent | 49c1f36ec50b3f812f9031d1cf35f1f514eb2a21 (diff) |
Demangle C++ requires-expressions without parameters (rq ... E).
PiperOrigin-RevId: 637052089
Change-Id: I8e22c2479749c05d8ca5f9e8eeba480a93da2d18
Diffstat (limited to 'absl')
-rw-r--r-- | absl/debugging/internal/demangle.cc | 44 | ||||
-rw-r--r-- | absl/debugging/internal/demangle_test.cc | 91 |
2 files changed, 135 insertions, 0 deletions
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc index 6012a59a..cfcd64b6 100644 --- a/absl/debugging/internal/demangle.cc +++ b/absl/debugging/internal/demangle.cc @@ -602,6 +602,7 @@ static bool ParseExpression(State *state); static bool ParseExprPrimary(State *state); static bool ParseExprCastValueAndTrailingE(State *state); static bool ParseQRequiresClauseExpr(State *state); +static bool ParseRequirement(State *state); static bool ParseLocalName(State *state); static bool ParseLocalNameSuffix(State *state); static bool ParseDiscriminator(State *state); @@ -1852,6 +1853,7 @@ static bool ParseBracedExpression(State *state) { // ::= sr <type> <unqualified-name> <template-args> // ::= sr <type> <unqualified-name> // ::= u <source-name> <template-arg>* E # vendor extension +// ::= rq <requirement>+ E static bool ParseExpression(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; @@ -1982,6 +1984,15 @@ static bool ParseExpression(State *state) { } state->parse_state = copy; + // <expression> ::= rq <requirement>+ E + // + // https://github.com/itanium-cxx-abi/cxx-abi/issues/24 + if (ParseTwoCharToken(state, "rq") && OneOrMore(ParseRequirement, state) && + ParseOneCharToken(state, 'E')) { + return true; + } + state->parse_state = copy; + return ParseUnresolvedName(state); } @@ -2098,6 +2109,39 @@ static bool ParseQRequiresClauseExpr(State *state) { return false; } +// <requirement> ::= X <expression> [N] [R <type-constraint>] +// <requirement> ::= T <type> +// <requirement> ::= Q <constraint-expression> +// +// <type-constraint> ::= <name> +// +// <constraint-expression> ::= <expression> +// +// https://github.com/itanium-cxx-abi/cxx-abi/issues/24 +static bool ParseRequirement(State *state) { + ComplexityGuard guard(state); + if (guard.IsTooComplex()) return false; + + ParseState copy = state->parse_state; + + if (ParseOneCharToken(state, 'X') && ParseExpression(state) && + Optional(ParseOneCharToken(state, 'N')) && + // This logic backtracks cleanly if we eat an R but a valid type doesn't + // follow it. + (!ParseOneCharToken(state, 'R') || ParseName(state))) { + return true; + } + state->parse_state = copy; + + if (ParseOneCharToken(state, 'T') && ParseType(state)) return true; + state->parse_state = copy; + + if (ParseOneCharToken(state, 'Q') && ParseExpression(state)) return true; + state->parse_state = copy; + + return false; +} + // <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 51e36642..23556a86 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -212,6 +212,97 @@ TEST(Demangle, TemplateParamSubstitutionWithGenericLambda) { EXPECT_STREQ(tmp, "Fooer<>::foo<>()"); } +TEST(Demangle, LambdaRequiresTrue) { + char tmp[100]; + + // auto $_0::operator()<int>(int) const requires true + ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QLb1E", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "$_0::operator()<>()"); +} + +TEST(Demangle, LambdaRequiresSimpleExpression) { + char tmp[100]; + + // auto $_0::operator()<int>(int) const requires 2 + 2 == 4 + ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QeqplLi2ELi2ELi4E", + tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "$_0::operator()<>()"); +} + +TEST(Demangle, LambdaRequiresRequiresExpressionContainingTrue) { + char tmp[100]; + + // auto $_0::operator()<int>(int) const requires requires { true; } + ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXLb1EE", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "$_0::operator()<>()"); +} + +TEST(Demangle, LambdaRequiresRequiresExpressionContainingConcept) { + char tmp[100]; + + // auto $_0::operator()<int>(int) const + // requires requires { std::same_as<decltype(fp), int>; } + ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXsr3stdE7same_asIDtfp_EiEE", + tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "$_0::operator()<>()"); +} + +TEST(Demangle, LambdaRequiresRequiresExpressionContainingNoexceptExpression) { + char tmp[100]; + + // auto $_0::operator()<int>(int) const + // requires requires { {fp + fp} noexcept; } + ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXplfp_fp_NE", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "$_0::operator()<>()"); +} + +TEST(Demangle, LambdaRequiresRequiresExpressionContainingReturnTypeConstraint) { + char tmp[100]; + + // auto $_0::operator()<int>(int) const + // requires requires { {fp + fp} -> std::same_as<decltype(fp)>; } + ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXplfp_fp_RNSt7same_asIDtfp_EEEE", + tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "$_0::operator()<>()"); +} + +TEST(Demangle, LambdaRequiresRequiresExpressionWithBothNoexceptAndReturnType) { + char tmp[100]; + + // auto $_0::operator()<int>(int) const + // requires requires { {fp + fp} noexcept -> std::same_as<decltype(fp)>; } + ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXplfp_fp_NRNSt7same_asIDtfp_EEEE", + tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "$_0::operator()<>()"); +} + +TEST(Demangle, LambdaRequiresRequiresExpressionContainingType) { + char tmp[100]; + + // auto $_0::operator()<S>(S) const + // requires requires { typename S::T; } + ASSERT_TRUE(Demangle("_ZNK3$_0clI1SEEDaT_QrqTNS2_1TEE", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "$_0::operator()<>()"); +} + +TEST(Demangle, LambdaRequiresRequiresExpressionNestingAnotherRequires) { + char tmp[100]; + + // auto $_0::operator()<int>(int) const requires requires { requires true; } + ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqQLb1EE", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "$_0::operator()<>()"); +} + +TEST(Demangle, LambdaRequiresRequiresExpressionContainingTwoRequirements) { + char tmp[100]; + + // auto $_0::operator()<int>(int) const + // requires requires { requires true; requires 2 + 2 == 4; } + ASSERT_TRUE(Demangle("_ZNK3$_0clIiEEDaT_QrqXLb1EXeqplLi2ELi2ELi4EE", + tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "$_0::operator()<>()"); +} + // Test corner cases of boundary conditions. TEST(Demangle, CornerCases) { char tmp[10]; |