[llvm] r339211 - [MS Demangler] Properly handle backreferencing of special names.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 7 17:43:31 PDT 2018


Author: zturner
Date: Tue Aug  7 17:43:31 2018
New Revision: 339211

URL: http://llvm.org/viewvc/llvm-project?rev=339211&view=rev
Log:
[MS Demangler] Properly handle backreferencing of special names.

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

Modified:
    llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
    llvm/trunk/test/Demangle/ms-back-references.test

Modified: llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp?rev=339211&r1=339210&r2=339211&view=diff
==============================================================================
--- llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp (original)
+++ llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp Tue Aug  7 17:43:31 2018
@@ -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 {
@@ -931,13 +937,15 @@ private:
   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);
@@ -1124,11 +1132,12 @@ Name *Demangler::demangleBackRefName(Str
   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;
 
@@ -1138,16 +1147,18 @@ Name *Demangler::demangleTemplateInstant
 
   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;
 }
@@ -1367,7 +1378,12 @@ Name *Demangler::demangleFullyQualifiedT
 // 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);
@@ -1389,20 +1405,20 @@ Name *Demangler::demangleUnqualifiedType
     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) {
@@ -1410,7 +1426,7 @@ Name *Demangler::demangleNameScopePiece(
     return demangleBackRefName(MangledName);
 
   if (MangledName.startsWith("?$"))
-    return demangleTemplateInstantiationName(MangledName);
+    return demangleTemplateInstantiationName(MangledName, NBB_Template);
 
   if (MangledName.startsWith("?A"))
     return demangleAnonymousNamespaceName(MangledName);

Modified: llvm/trunk/test/Demangle/ms-back-references.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Demangle/ms-back-references.test?rev=339211&r1=339210&r2=339211&view=diff
==============================================================================
--- llvm/trunk/test/Demangle/ms-back-references.test (original)
+++ llvm/trunk/test/Demangle/ms-back-references.test Tue Aug  7 17:43:31 2018
@@ -52,6 +52,5 @@
 ?foo at 0@YAXXZ
 ; CHECK: void __cdecl foo::foo(void)
 
-; We have some issues with back-references and class / function templates.
 ??$?HH at S@@QEAAAEAU0 at H@Z
-; FIXME: struct S &__cdecl S::operator+<int>(int)
\ No newline at end of file
+struct S & __cdecl S::operator+<int>(int)
\ No newline at end of file




More information about the llvm-commits mailing list