Skip to content

Commit

Permalink
[demangler] Fix undocumented Local encoding
Browse files Browse the repository at this point in the history
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
  • Loading branch information
urnathan committed Apr 6, 2022
1 parent 1ad3648 commit df4522f
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 32 deletions.
35 changes: 19 additions & 16 deletions libcxxabi/src/demangle/ItaniumDemangle.h
Expand Up @@ -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 *
Expand All @@ -2743,7 +2743,6 @@ AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
if (Std == nullptr)
return nullptr;
}
consumeIf('L');

Node *Res = nullptr;
ModuleName *Module = nullptr;
Expand All @@ -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();
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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>
Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions libcxxabi/test/test_demangle.pass.cpp
Expand Up @@ -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]);
Expand Down
35 changes: 19 additions & 16 deletions llvm/include/llvm/Demangle/ItaniumDemangle.h
Expand Up @@ -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 *
Expand All @@ -2743,7 +2743,6 @@ AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,
if (Std == nullptr)
return nullptr;
}
consumeIf('L');

Node *Res = nullptr;
ModuleName *Module = nullptr;
Expand All @@ -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();
Expand Down Expand Up @@ -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>
Expand Down Expand Up @@ -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>
Expand All @@ -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;
Expand Down

0 comments on commit df4522f

Please sign in to comment.