Commit c8671e75 by Chris Mihelich Committed by Copybara-Service

Demangle lambdas in class member functions' default arguments.

PiperOrigin-RevId: 638723132
Change-Id: I26ef4dbcb1b965a9d8c2f6092ccb51cf3575ba22
parent 36c2a14c
......@@ -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));
}
......
......@@ -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];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment