Commit d8e17c00 by Chris Mihelich Committed by Copybara-Service

Demangle types nested under vendor extended types.

PiperOrigin-RevId: 640284003
Change-Id: I3ad2d971383513c7eeb5e3179e50c036cf7aa020
parent 36d1644b
...@@ -599,6 +599,7 @@ static bool ParseDecltype(State *state); ...@@ -599,6 +599,7 @@ static bool ParseDecltype(State *state);
static bool ParseType(State *state); static bool ParseType(State *state);
static bool ParseCVQualifiers(State *state); static bool ParseCVQualifiers(State *state);
static bool ParseBuiltinType(State *state); static bool ParseBuiltinType(State *state);
static bool ParseVendorExtendedType(State *state);
static bool ParseFunctionType(State *state); static bool ParseFunctionType(State *state);
static bool ParseBareFunctionType(State *state); static bool ParseBareFunctionType(State *state);
static bool ParseOverloadAttribute(State *state); static bool ParseOverloadAttribute(State *state);
...@@ -785,6 +786,7 @@ static bool ParseNestedName(State *state) { ...@@ -785,6 +786,7 @@ static bool ParseNestedName(State *state) {
// <template-prefix> ::= <prefix> <(template) unqualified-name> // <template-prefix> ::= <prefix> <(template) unqualified-name>
// ::= <template-param> // ::= <template-param>
// ::= <substitution> // ::= <substitution>
// ::= <vendor-extended-type>
static bool ParsePrefix(State *state) { static bool ParsePrefix(State *state) {
ComplexityGuard guard(state); ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false; if (guard.IsTooComplex()) return false;
...@@ -793,6 +795,11 @@ static bool ParsePrefix(State *state) { ...@@ -793,6 +795,11 @@ static bool ParsePrefix(State *state) {
MaybeAppendSeparator(state); MaybeAppendSeparator(state);
if (ParseTemplateParam(state) || ParseDecltype(state) || if (ParseTemplateParam(state) || ParseDecltype(state) ||
ParseSubstitution(state, /*accept_std=*/true) || ParseSubstitution(state, /*accept_std=*/true) ||
// Although the official grammar does not mention it, nested-names
// shaped like Nu14__some_builtinIiE6memberE occur in practice, and it
// is not clear what else a compiler is supposed to do when a
// vendor-extended type has named members.
ParseVendorExtendedType(state) ||
ParseUnscopedName(state) || ParseUnscopedName(state) ||
(ParseOneCharToken(state, 'M') && ParseUnnamedTypeName(state))) { (ParseOneCharToken(state, 'M') && ParseUnnamedTypeName(state))) {
has_something = true; has_something = true;
...@@ -1373,7 +1380,7 @@ static bool ParseCVQualifiers(State *state) { ...@@ -1373,7 +1380,7 @@ static bool ParseCVQualifiers(State *state) {
} }
// <builtin-type> ::= v, etc. # single-character builtin types // <builtin-type> ::= v, etc. # single-character builtin types
// ::= u <source-name> [I <type> E] // ::= <vendor-extended-type>
// ::= Dd, etc. # two-character builtin types // ::= Dd, etc. # two-character builtin types
// //
// Not supported: // Not supported:
...@@ -1397,6 +1404,16 @@ static bool ParseBuiltinType(State *state) { ...@@ -1397,6 +1404,16 @@ static bool ParseBuiltinType(State *state) {
} }
} }
return ParseVendorExtendedType(state);
}
// <vendor-extended-type> ::= u <source-name> [I <type> E]
//
// NOTE: [I <type> E] is a vendor extension (http://shortn/_FrINpH1XC5).
static bool ParseVendorExtendedType(State *state) {
ComplexityGuard guard(state);
if (guard.IsTooComplex()) return false;
ParseState copy = state->parse_state; ParseState copy = state->parse_state;
if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) { if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) {
copy = state->parse_state; copy = state->parse_state;
......
...@@ -192,6 +192,27 @@ TEST(Demangle, FailsOnTwoArgTemplateBuiltinType) { ...@@ -192,6 +192,27 @@ TEST(Demangle, FailsOnTwoArgTemplateBuiltinType) {
Demangle("_Z3fooIicEu17__my_builtin_typeIT_T0_Ev", tmp, sizeof(tmp))); Demangle("_Z3fooIicEu17__my_builtin_typeIT_T0_Ev", tmp, sizeof(tmp)));
} }
TEST(Demangle, TypeNestedUnderTemplatedBuiltinType) {
char tmp[100];
// Source:
//
// template <typename T>
// typename std::remove_reference_t<T>::type f(T t);
//
// struct C { using type = C; };
//
// f<const C&>(C{});
//
// These days std::remove_reference_t is implemented in terms of a vendor
// builtin __remove_reference_t. A full demangling might look like:
//
// __remove_reference_t<C const&>::type f<C const&>(C const&)
ASSERT_TRUE(Demangle("_Z1fIRK1CENu20__remove_reference_tIT_E4typeES3_",
tmp, sizeof(tmp)));
EXPECT_STREQ("f<>()", tmp);
}
TEST(Demangle, TemplateTemplateParamSubstitution) { TEST(Demangle, TemplateTemplateParamSubstitution) {
char tmp[100]; 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