Skip to content

Commit

Permalink
[MS Demangler] Properly handle backreferencing of special names.
Browse files Browse the repository at this point in the history
Function template names are not stored in the backref table,
but non-template function names are.  The general pattern seems
to be that when you are demangling a symbol name, if the name
starts with '?' it does not go into the backreference table,
otherwise it does.  Note that this even handles the general case
of operator names (template or otherwise) not going into the
back-reference table, anonymous namespaces not going into the
backreference table, etc.

It's important that we apply this check *only* for the
unqualified portion of a name, and only for symbol names.
For example, this does not apply to type names (such as class
templates) and we need to make sure that these still do go
into the backref table.

Differential Revision: https://reviews.llvm.org/D50394

llvm-svn: 339211
  • Loading branch information
Zachary Turner committed Aug 8, 2018
1 parent 2e34bbd commit 58d29cf
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 22 deletions.
56 changes: 36 additions & 20 deletions llvm/lib/Demangle/MicrosoftDemangle.cpp
Expand Up @@ -205,6 +205,12 @@ enum FuncClass : uint8_t {
Far = 1 << 6,
};

enum NameBackrefBehavior : uint8_t {
NBB_None = 0, // don't save any names as backrefs.
NBB_Template = 1 << 0, // save template instanations.
NBB_Simple = 1 << 1, // save simple names.
};

enum class SymbolCategory { Function, Variable };

namespace {
Expand Down Expand Up @@ -931,13 +937,15 @@ class Demangler : public NameResolver {
Name *demangleFullyQualifiedSymbolName(StringView &MangledName);

Name *demangleUnqualifiedTypeName(StringView &MangledName, bool Memorize);
Name *demangleUnqualifiedSymbolName(StringView &MangledName, bool Memorize);
Name *demangleUnqualifiedSymbolName(StringView &MangledName,
NameBackrefBehavior NBB);

Name *demangleNameScopeChain(StringView &MangledName, Name *UnqualifiedName);
Name *demangleNameScopePiece(StringView &MangledName);

Name *demangleBackRefName(StringView &MangledName);
Name *demangleTemplateInstantiationName(StringView &MangledName);
Name *demangleTemplateInstantiationName(StringView &MangledName,
NameBackrefBehavior NBB);
Name *demangleOperatorName(StringView &MangledName);
Name *demangleSimpleName(StringView &MangledName, bool Memorize);
Name *demangleAnonymousNamespaceName(StringView &MangledName);
Expand Down Expand Up @@ -1124,11 +1132,12 @@ Name *Demangler::demangleBackRefName(StringView &MangledName) {
return Node;
}

Name *Demangler::demangleTemplateInstantiationName(StringView &MangledName) {
Name *Demangler::demangleTemplateInstantiationName(StringView &MangledName,
NameBackrefBehavior NBB) {
assert(MangledName.startsWith("?$"));
MangledName.consumeFront("?$");

Name *Node = demangleUnqualifiedSymbolName(MangledName, false);
Name *Node = demangleUnqualifiedSymbolName(MangledName, NBB_None);
if (Error)
return nullptr;

Expand All @@ -1138,16 +1147,18 @@ Name *Demangler::demangleTemplateInstantiationName(StringView &MangledName) {

Node->IsTemplateInstantiation = true;

// Render this class template name into a string buffer so that we can
// memorize it for the purpose of back-referencing.
OutputStream OS = OutputStream::create(nullptr, nullptr, 1024);
outputName(OS, Node, *this);
OS << '\0';
char *Name = OS.getBuffer();

StringView Owned = copyString(Name);
memorizeString(Owned);
std::free(Name);
if (NBB & NBB_Template) {
// Render this class template name into a string buffer so that we can
// memorize it for the purpose of back-referencing.
OutputStream OS = OutputStream::create(nullptr, nullptr, 1024);
outputName(OS, Node, *this);
OS << '\0';
char *Name = OS.getBuffer();

StringView Owned = copyString(Name);
memorizeString(Owned);
std::free(Name);
}

return Node;
}
Expand Down Expand Up @@ -1367,7 +1378,12 @@ Name *Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) {
// Symbol names have slightly different rules regarding what can appear
// so we separate out the implementations for flexibility.
Name *Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) {
Name *SymbolName = demangleUnqualifiedSymbolName(MangledName, true);
// This is the final component of a symbol name (i.e. the leftmost component
// of a mangled name. Since the only possible template instantiation that
// can appear in this context is a function template, and since those are
// not saved for the purposes of name backreferences, only backref simple
// names.
Name *SymbolName = demangleUnqualifiedSymbolName(MangledName, NBB_Simple);
if (Error)
return nullptr;
assert(SymbolName);
Expand All @@ -1389,28 +1405,28 @@ Name *Demangler::demangleUnqualifiedTypeName(StringView &MangledName,
return demangleBackRefName(MangledName);

if (MangledName.startsWith("?$"))
return demangleTemplateInstantiationName(MangledName);
return demangleTemplateInstantiationName(MangledName, NBB_Template);

return demangleSimpleName(MangledName, Memorize);
}

Name *Demangler::demangleUnqualifiedSymbolName(StringView &MangledName,
bool Memorize) {
NameBackrefBehavior NBB) {
if (startsWithDigit(MangledName))
return demangleBackRefName(MangledName);
if (MangledName.startsWith("?$"))
return demangleTemplateInstantiationName(MangledName);
return demangleTemplateInstantiationName(MangledName, NBB);
if (MangledName.startsWith('?'))
return demangleOperatorName(MangledName);
return demangleSimpleName(MangledName, Memorize);
return demangleSimpleName(MangledName, (NBB & NBB_Simple) != 0);
}

Name *Demangler::demangleNameScopePiece(StringView &MangledName) {
if (startsWithDigit(MangledName))
return demangleBackRefName(MangledName);

if (MangledName.startsWith("?$"))
return demangleTemplateInstantiationName(MangledName);
return demangleTemplateInstantiationName(MangledName, NBB_Template);

if (MangledName.startsWith("?A"))
return demangleAnonymousNamespaceName(MangledName);
Expand Down
3 changes: 1 addition & 2 deletions llvm/test/Demangle/ms-back-references.test
Expand Up @@ -52,6 +52,5 @@
?foo@0@YAXXZ
; CHECK: void __cdecl foo::foo(void)

; We have some issues with back-references and class / function templates.
??$?HH@S@@QEAAAEAU0@H@Z
; FIXME: struct S &__cdecl S::operator+<int>(int)
struct S & __cdecl S::operator+<int>(int)

0 comments on commit 58d29cf

Please sign in to comment.