Commit 9e095d74 by Chris Mihelich Committed by Copybara-Service

Demangle C++ direct-list-initialization (T{1, 2, 3}, tl ... E).

PiperOrigin-RevId: 636649618
Change-Id: I73a0be3defa438daf0e9db5c34c0e2feb0e52b69
parent cfac0a35
......@@ -582,6 +582,7 @@ static bool ParseBaseUnresolvedName(State *state);
static bool ParseUnresolvedName(State *state);
static bool ParseUnionSelector(State* state);
static bool ParseFunctionParam(State* state);
static bool ParseBracedExpression(State *state);
static bool ParseExpression(State *state);
static bool ParseExprPrimary(State *state);
static bool ParseExprCastValue(State *state);
......@@ -1782,6 +1783,38 @@ static bool ParseFunctionParam(State *state) {
return false;
}
// <braced-expression> ::= <expression>
// ::= di <field source-name> <braced-expression>
// ::= dx <index expression> <braced-expression>
// ::= dX <expression> <expression> <braced-expression>
static bool ParseBracedExpression(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
ParseState copy = state->parse_state;
if (ParseTwoCharToken(state, "di") && ParseSourceName(state) &&
ParseBracedExpression(state)) {
return true;
}
state->parse_state = copy;
if (ParseTwoCharToken(state, "dx") && ParseExpression(state) &&
ParseBracedExpression(state)) {
return true;
}
state->parse_state = copy;
if (ParseTwoCharToken(state, "dX") &&
ParseExpression(state) && ParseExpression(state) &&
ParseBracedExpression(state)) {
return true;
}
state->parse_state = copy;
return ParseExpression(state);
}
// <expression> ::= <1-ary operator-name> <expression>
// ::= <2-ary operator-name> <expression> <expression>
// ::= <3-ary operator-name> <expression> <expression> <expression>
......@@ -1790,6 +1823,7 @@ static bool ParseFunctionParam(State *state) {
// ::= so <type> <expression> [<number>] <union-selector>* [p] E
// ::= cv <type> <expression> # type (expression)
// ::= cv <type> _ <expression>* E # type (expr-list)
// ::= tl <type> <braced-expression>* E
// ::= st <type>
// ::= <template-param>
// ::= <function-param>
......@@ -1841,6 +1875,14 @@ static bool ParseExpression(State *state) {
if (ParseFunctionParam(state)) return true;
state->parse_state = copy;
// <expression> ::= tl <type> <braced-expression>* E
if (ParseTwoCharToken(state, "tl") && ParseType(state) &&
ZeroOrMore(ParseBracedExpression, state) &&
ParseOneCharToken(state, 'E')) {
return true;
}
state->parse_state = copy;
// Parse the conversion expressions jointly to avoid re-parsing the <type> in
// their common prefix. Parsed as:
// <expression> ::= cv <type> <conversion-args>
......
......@@ -371,6 +371,57 @@ TEST(Demangle, Spaceship) {
EXPECT_STREQ("g<>()", tmp);
}
TEST(Demangle, DirectListInitialization) {
char tmp[80];
// template <class T> decltype(T{}) f() { return T{}; }
// template decltype(int{}) f<int>();
//
// struct XYZ { int x, y, z; };
// template <class T> decltype(T{1, 2, 3}) g() { return T{1, 2, 3}; }
// template decltype(XYZ{1, 2, 3}) g<XYZ>();
//
// template <class T> decltype(T{.x = 1, .y = 2, .z = 3}) h() {
// return T{.x = 1, .y = 2, .z = 3};
// }
// template decltype(XYZ{.x = 1, .y = 2, .z = 3}) h<XYZ>();
//
// // The following two cases require full C99 designated initializers,
// // not part of C++ but likely available as an extension if you ask your
// // compiler nicely.
//
// struct A { int a[4]; };
// template <class T> decltype(T{.a[2] = 42}) i() { return T{.a[2] = 42}; }
// template decltype(A{.a[2] = 42}) i<A>();
//
// template <class T> decltype(T{.a[1 ... 3] = 42}) j() {
// return T{.a[1 ... 3] = 42};
// }
// template decltype(A{.a[1 ... 3] = 42}) j<A>();
// decltype(int{}) f<int>()
EXPECT_TRUE(Demangle("_Z1fIiEDTtlT_EEv", tmp, sizeof(tmp)));
EXPECT_STREQ("f<>()", tmp);
// decltype(XYZ{1, 2, 3}) g<XYZ>()
EXPECT_TRUE(Demangle("_Z1gI3XYZEDTtlT_Li1ELi2ELi3EEEv", tmp, sizeof(tmp)));
EXPECT_STREQ("g<>()", tmp);
// decltype(XYZ{.x = 1, .y = 2, .z = 3}) h<XYZ>()
EXPECT_TRUE(Demangle("_Z1hI3XYZEDTtlT_di1xLi1Edi1yLi2Edi1zLi3EEEv",
tmp, sizeof(tmp)));
EXPECT_STREQ("h<>()", tmp);
// decltype(A{.a[2] = 42}) i<A>()
EXPECT_TRUE(Demangle("_Z1iI1AEDTtlT_di1adxLi2ELi42EEEv", tmp, sizeof(tmp)));
EXPECT_STREQ("i<>()", tmp);
// decltype(A{.a[1 ... 3] = 42}) j<A>()
EXPECT_TRUE(Demangle("_Z1jI1AEDTtlT_di1adXLi1ELi3ELi42EEEv",
tmp, sizeof(tmp)));
EXPECT_STREQ("j<>()", 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