Commit a3c25aec by Chris Mihelich Committed by Copybara-Service

Demangle C++ sZ encodings (sizeof...(pack)).

PiperOrigin-RevId: 636615840
Change-Id: I34f584ea0c6603a0781e874d683b516de94c6928
parent 88c1f181
......@@ -100,6 +100,7 @@ static const AbbrevPair kOperatorList[] = {
{"qu", "?", 3},
{"st", "sizeof", 0}, // Special syntax
{"sz", "sizeof", 1}, // Not a real operator name, but used in expressions.
{"sZ", "sizeof...", 0}, // Special syntax
{nullptr, nullptr, 0},
};
......@@ -579,6 +580,7 @@ static bool ParseTemplateArg(State *state);
static bool ParseBaseUnresolvedName(State *state);
static bool ParseUnresolvedName(State *state);
static bool ParseUnionSelector(State* state);
static bool ParseFunctionParam(State* state);
static bool ParseExpression(State *state);
static bool ParseExprPrimary(State *state);
static bool ParseExprCastValue(State *state);
......@@ -1751,6 +1753,34 @@ static bool ParseUnionSelector(State *state) {
return ParseOneCharToken(state, '_') && Optional(ParseNumber(state, nullptr));
}
// <function-param> ::= fp <(top-level) CV-qualifiers> _
// ::= fp <(top-level) CV-qualifiers> <number> _
// ::= fL <number> p <(top-level) CV-qualifiers> _
// ::= fL <number> p <(top-level) CV-qualifiers> <number> _
static bool ParseFunctionParam(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
ParseState copy = state->parse_state;
// Function-param expression (level 0).
if (ParseTwoCharToken(state, "fp") && Optional(ParseCVQualifiers(state)) &&
Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) {
return true;
}
state->parse_state = copy;
// Function-param expression (level 1+).
if (ParseTwoCharToken(state, "fL") && Optional(ParseNumber(state, nullptr)) &&
ParseOneCharToken(state, 'p') && Optional(ParseCVQualifiers(state)) &&
Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) {
return true;
}
state->parse_state = copy;
return false;
}
// <expression> ::= <1-ary operator-name> <expression>
// ::= <2-ary operator-name> <expression> <expression>
// ::= <3-ary operator-name> <expression> <expression> <expression>
......@@ -1762,16 +1792,14 @@ static bool ParseUnionSelector(State *state) {
// ::= st <type>
// ::= <template-param>
// ::= <function-param>
// ::= sZ <template-param>
// ::= sZ <function-param>
// ::= <expr-primary>
// ::= dt <expression> <unresolved-name> # expr.name
// ::= pt <expression> <unresolved-name> # expr->name
// ::= sp <expression> # argument pack expansion
// ::= sr <type> <unqualified-name> <template-args>
// ::= sr <type> <unqualified-name>
// <function-param> ::= fp <(top-level) CV-qualifiers> _
// ::= fp <(top-level) CV-qualifiers> <number> _
// ::= fL <number> p <(top-level) CV-qualifiers> _
// ::= fL <number> p <(top-level) CV-qualifiers> <number> _
static bool ParseExpression(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
......@@ -1808,19 +1836,8 @@ static bool ParseExpression(State *state) {
}
state->parse_state = copy;
// Function-param expression (level 0).
if (ParseTwoCharToken(state, "fp") && Optional(ParseCVQualifiers(state)) &&
Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) {
return true;
}
state->parse_state = copy;
// Function-param expression (level 1+).
if (ParseTwoCharToken(state, "fL") && Optional(ParseNumber(state, nullptr)) &&
ParseOneCharToken(state, 'p') && Optional(ParseCVQualifiers(state)) &&
Optional(ParseNumber(state, nullptr)) && ParseOneCharToken(state, '_')) {
return true;
}
// <expression> ::= <function-param>
if (ParseFunctionParam(state)) return true;
state->parse_state = copy;
// Parse the conversion expressions jointly to avoid re-parsing the <type> in
......@@ -1866,6 +1883,16 @@ static bool ParseExpression(State *state) {
}
state->parse_state = copy;
// sizeof...(pack)
//
// <expression> ::= sZ <template-param>
// ::= sZ <function-param>
if (ParseTwoCharToken(state, "sZ") &&
(ParseFunctionParam(state) || ParseTemplateParam(state))) {
return true;
}
state->parse_state = copy;
// Object and pointer member access expressions.
if ((ParseTwoCharToken(state, "dt") || ParseTwoCharToken(state, "pt")) &&
ParseExpression(state) && ParseType(state)) {
......
......@@ -329,6 +329,26 @@ TEST(Demangle, SubobjectAddresses) {
EXPECT_STREQ("f<>()", tmp);
}
TEST(Demangle, SizeofPacks) {
char tmp[80];
// template <std::size_t i> struct S {};
//
// template <class... T> auto f(T... p) -> S<sizeof...(T)> { return {}; }
// template auto f<int, long>(int, long) -> S<2>;
//
// template <class... T> auto g(T... p) -> S<sizeof...(p)> { return {}; }
// template auto g<int, long>(int, long) -> S<2>;
// S<sizeof...(int, long)> f<int, long>(int, long)
EXPECT_TRUE(Demangle("_Z1fIJilEE1SIXsZT_EEDpT_", tmp, sizeof(tmp)));
EXPECT_STREQ("f<>()", tmp);
// S<sizeof... (fp)> g<int, long>(int, long)
EXPECT_TRUE(Demangle("_Z1gIJilEE1SIXsZfp_EEDpT_", tmp, sizeof(tmp)));
EXPECT_STREQ("g<>()", tmp);
}
// Test one Rust symbol to exercise Demangle's delegation path. Rust demangling
// itself is more thoroughly tested in demangle_rust_test.cc.
TEST(Demangle, DelegatesToDemangleRustSymbolEncoding) {
......
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