[demangler] Fix undocumented Local encoding

GCC emits [some] static symbols with an 'L' mangling, which we attempt
to demangle.  But the module mangling changes have exposed that we
were doing so at the wrong level.  Such manglings are outside of the
ABI as they are internal-linkage, so a bit of reverse engineering was
needed.  This adjusts the demangler along the same lines as the
existing gcc demangler (which is not yet module-aware).  'L' is part
of an unqualified name.  As before we merely parse the 'L', and then
ignore it.

Reviewed By: iains

Differential Revision: https://reviews.llvm.org/D123138
This commit is contained in:
Nathan Sidwell 2022-04-05 09:25:47 -07:00
parent 1ad36487e9
commit df4522feb7
3 changed files with 40 additions and 32 deletions

View File

@ -2729,8 +2729,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
return make<LocalName>(Encoding, Entity);
}
// <unscoped-name> ::= [L]* <unqualified-name>
// ::= St [L]* <unqualified-name> # ::std::
// <unscoped-name> ::= <unqualified-name>
// ::= St <unqualified-name> # ::std::
// [*] extension
template <typename Derived, typename Alloc>
Node *
@ -2743,7 +2743,6 @@ AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
if (Std == nullptr)
return nullptr;
}
consumeIf('L');
Node *Res = nullptr;
ModuleName *Module = nullptr;
@ -2761,29 +2760,32 @@ AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
}
}
if (Res == nullptr)
if (Res == nullptr || Std != nullptr) {
Res = getDerived().parseUnqualifiedName(State, Std, Module);
}
return Res;
}
// <unqualified-name> ::= [<module-name>] <operator-name> [<abi-tags>]
// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
// ::= [<module-name>] <source-name> [<abi-tags>]
// ::= [<module-name>] <unnamed-type-name> [<abi-tags>]
// ::= [<module-name>] L? <source-name> [<abi-tags>]
// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
// # structured binding declaration
// ::= [<module-name>] DC <source-name>+ E
// ::= [<module-name>] L? DC <source-name>+ E
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
NameState *State, Node *Scope, ModuleName *Module) {
if (getDerived().parseModuleNameOpt(Module))
return nullptr;
consumeIf('L');
Node *Result;
if (look() == 'U') {
Result = getDerived().parseUnnamedTypeName(State);
} else if (look() >= '1' && look() <= '9') {
if (look() >= '1' && look() <= '9') {
Result = getDerived().parseSourceName(State);
} else if (look() == 'U') {
Result = getDerived().parseUnnamedTypeName(State);
} else if (consumeIf("DC")) {
// Structured binding
size_t BindingsBegin = Names.size();
@ -3163,10 +3165,12 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
return nullptr;
}
// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
// <unqualified-name> E
// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
// <template-args> E
//
// <prefix> ::= <prefix> [L]* <unqualified-name>
// <prefix> ::= <prefix> <unqualified-name>
// ::= <template-prefix> <template-args>
// ::= <template-param>
// ::= <decltype>
@ -3230,7 +3234,6 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
SoFar = getDerived().parseDecltype();
} else {
ModuleName *Module = nullptr;
bool IsLocal = consumeIf('L'); // extension
if (look() == 'S') {
// ::= <substitution>
@ -3245,7 +3248,7 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
return nullptr;
if (S->getKind() == Node::KModuleName) {
Module = static_cast<ModuleName *>(S);
} else if (SoFar != nullptr || IsLocal) {
} else if (SoFar != nullptr) {
return nullptr; // Cannot have a prefix.
} else {
SoFar = S;

View File

@ -30078,6 +30078,8 @@ const char* cases[][2] =
{"_ZGIW3Foo", "initializer for module Foo"},
{"_ZGIW3FooW3Bar", "initializer for module Foo.Bar"},
{"_ZGIW3FooWP3BarW3Baz", "initializer for module Foo:Bar.Baz"},
{"_ZW1ML4Oink", "Oink@M"},
{"_ZW1ML1fi", "f@M(int)"},
};
const unsigned N = sizeof(cases) / sizeof(cases[0]);

View File

@ -2729,8 +2729,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {
return make<LocalName>(Encoding, Entity);
}
// <unscoped-name> ::= [L]* <unqualified-name>
// ::= St [L]* <unqualified-name> # ::std::
// <unscoped-name> ::= <unqualified-name>
// ::= St <unqualified-name> # ::std::
// [*] extension
template <typename Derived, typename Alloc>
Node *
@ -2743,7 +2743,6 @@ AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
if (Std == nullptr)
return nullptr;
}
consumeIf('L');
Node *Res = nullptr;
ModuleName *Module = nullptr;
@ -2761,29 +2760,32 @@ AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
}
}
if (Res == nullptr)
if (Res == nullptr || Std != nullptr) {
Res = getDerived().parseUnqualifiedName(State, Std, Module);
}
return Res;
}
// <unqualified-name> ::= [<module-name>] <operator-name> [<abi-tags>]
// <unqualified-name> ::= [<module-name>] L? <operator-name> [<abi-tags>]
// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]
// ::= [<module-name>] <source-name> [<abi-tags>]
// ::= [<module-name>] <unnamed-type-name> [<abi-tags>]
// ::= [<module-name>] L? <source-name> [<abi-tags>]
// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]
// # structured binding declaration
// ::= [<module-name>] DC <source-name>+ E
// ::= [<module-name>] L? DC <source-name>+ E
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(
NameState *State, Node *Scope, ModuleName *Module) {
if (getDerived().parseModuleNameOpt(Module))
return nullptr;
consumeIf('L');
Node *Result;
if (look() == 'U') {
Result = getDerived().parseUnnamedTypeName(State);
} else if (look() >= '1' && look() <= '9') {
if (look() >= '1' && look() <= '9') {
Result = getDerived().parseSourceName(State);
} else if (look() == 'U') {
Result = getDerived().parseUnnamedTypeName(State);
} else if (consumeIf("DC")) {
// Structured binding
size_t BindingsBegin = Names.size();
@ -3163,10 +3165,12 @@ AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,
return nullptr;
}
// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>
// <unqualified-name> E
// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>
// <template-args> E
//
// <prefix> ::= <prefix> [L]* <unqualified-name>
// <prefix> ::= <prefix> <unqualified-name>
// ::= <template-prefix> <template-args>
// ::= <template-param>
// ::= <decltype>
@ -3230,7 +3234,6 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
SoFar = getDerived().parseDecltype();
} else {
ModuleName *Module = nullptr;
bool IsLocal = consumeIf('L'); // extension
if (look() == 'S') {
// ::= <substitution>
@ -3245,7 +3248,7 @@ AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {
return nullptr;
if (S->getKind() == Node::KModuleName) {
Module = static_cast<ModuleName *>(S);
} else if (SoFar != nullptr || IsLocal) {
} else if (SoFar != nullptr) {
return nullptr; // Cannot have a prefix.
} else {
SoFar = S;