diff options
author | Chris Mihelich <cmihelic@google.com> | 2024-05-30 11:28:11 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-05-30 11:30:17 -0700 |
commit | c8671e7542ebfd928ee3e239315c8784fdd88e1c (patch) | |
tree | 65168844b779fc3c3a5fdee32231d299885a95d8 /absl/debugging | |
parent | 36c2a14c5966d06f4f8c3bd02e3ef9d517ead081 (diff) | |
download | abseil-c8671e7542ebfd928ee3e239315c8784fdd88e1c.tar.gz abseil-c8671e7542ebfd928ee3e239315c8784fdd88e1c.tar.bz2 abseil-c8671e7542ebfd928ee3e239315c8784fdd88e1c.zip |
Demangle lambdas in class member functions' default arguments.
PiperOrigin-RevId: 638723132
Change-Id: I26ef4dbcb1b965a9d8c2f6092ccb51cf3575ba22
Diffstat (limited to 'absl/debugging')
-rw-r--r-- | absl/debugging/internal/demangle.cc | 36 | ||||
-rw-r--r-- | absl/debugging/internal/demangle_test.cc | 28 |
2 files changed, 59 insertions, 5 deletions
diff --git a/absl/debugging/internal/demangle.cc b/absl/debugging/internal/demangle.cc index 2d9cd018..c730f8bf 100644 --- a/absl/debugging/internal/demangle.cc +++ b/absl/debugging/internal/demangle.cc @@ -2323,29 +2323,55 @@ static bool ParseRequirement(State *state) { // <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>] // ::= Z <(function) encoding> E s [<discriminator>] +// ::= Z <(function) encoding> E d [<(parameter) number>] _ <name> // // Parsing a common prefix of these two productions together avoids an // exponential blowup of backtracking. Parse like: // <local-name> := Z <encoding> E <local-name-suffix> // <local-name-suffix> ::= s [<discriminator>] +// ::= d [<(parameter) number>] _ <name> // ::= <name> [<discriminator>] static bool ParseLocalNameSuffix(State *state) { ComplexityGuard guard(state); if (guard.IsTooComplex()) return false; + ParseState copy = state->parse_state; + + // <local-name-suffix> ::= d [<(parameter) number>] _ <name> + if (ParseOneCharToken(state, 'd') && + (IsDigit(RemainingInput(state)[0]) || RemainingInput(state)[0] == '_')) { + int number = -1; + Optional(ParseNumber(state, &number)); + number += 2; + + // The ::{default arg#1}:: infix must be rendered before the lambda itself, + // so print this before parsing the rest of the <local-name-suffix>. + MaybeAppend(state, "::{default arg#"); + MaybeAppendDecimal(state, number); + MaybeAppend(state, "}::"); + if (ParseOneCharToken(state, '_') && ParseName(state)) return true; + + // On late parse failure, roll back not only the input but also the output, + // whose trailing NUL was overwritten. + state->parse_state = copy; + if (state->parse_state.append) { + state->out[state->parse_state.out_cur_idx] = '\0'; + } + return false; + } + state->parse_state = copy; + // <local-name-suffix> ::= <name> [<discriminator>] if (MaybeAppend(state, "::") && ParseName(state) && Optional(ParseDiscriminator(state))) { return true; } - - // Since we're not going to overwrite the above "::" by re-parsing the - // <encoding> (whose trailing '\0' byte was in the byte now holding the - // first ':'), we have to rollback the "::" if the <name> parse failed. + state->parse_state = copy; if (state->parse_state.append) { - state->out[state->parse_state.out_cur_idx - 2] = '\0'; + state->out[state->parse_state.out_cur_idx] = '\0'; } + // <local-name-suffix> ::= s [<discriminator>] return ParseOneCharToken(state, 's') && Optional(ParseDiscriminator(state)); } diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index 7705b0fd..58832e99 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -353,6 +353,34 @@ TEST(Demangle, LambdaWithExplicitPackArgument) { EXPECT_STREQ(tmp, "f<>()::{lambda()#1}::operator()<>()"); } +TEST(Demangle, LambdaInClassMemberDefaultArgument) { + char tmp[100]; + + // Source: + // + // struct S { + // static auto f(void (*g)() = [] {}) { return g; } + // }; + // void (*p)() = S::f(); + // + // Full LLVM demangling of the lambda call operator: + // + // S::f(void (*)())::'lambda'()::operator()() const + // + // Full GNU binutils demangling: + // + // S::f(void (*)())::{default arg#1}::{lambda()#1}::operator()() const + ASSERT_TRUE(Demangle("_ZZN1S1fEPFvvEEd_NKUlvE_clEv", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "S::f()::{default arg#1}::{lambda()#1}::operator()()"); + + // The same but in the second rightmost default argument. + ASSERT_TRUE(Demangle("_ZZN1S1fEPFvvEEd0_NKUlvE_clEv", tmp, sizeof(tmp))); + EXPECT_STREQ(tmp, "S::f()::{default arg#2}::{lambda()#1}::operator()()"); + + // Reject negative <(parameter) number> values. + ASSERT_FALSE(Demangle("_ZZN1S1fEPFvvEEdn1_NKUlvE_clEv", tmp, sizeof(tmp))); +} + TEST(Demangle, SubstpackNotationForTroublesomeTemplatePack) { char tmp[100]; |