aboutsummaryrefslogtreecommitdiff
path: root/absl/debugging
diff options
context:
space:
mode:
authorChris Mihelich <cmihelic@google.com>2024-05-30 11:28:11 -0700
committerCopybara-Service <copybara-worker@google.com>2024-05-30 11:30:17 -0700
commitc8671e7542ebfd928ee3e239315c8784fdd88e1c (patch)
tree65168844b779fc3c3a5fdee32231d299885a95d8 /absl/debugging
parent36c2a14c5966d06f4f8c3bd02e3ef9d517ead081 (diff)
downloadabseil-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.cc36
-rw-r--r--absl/debugging/internal/demangle_test.cc28
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];