[llvm] r338608 - [MS Demangler] Properly demangle templated operators.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 1 11:32:47 PDT 2018


Author: zturner
Date: Wed Aug  1 11:32:47 2018
New Revision: 338608

URL: http://llvm.org/viewvc/llvm-project?rev=338608&view=rev
Log:
[MS Demangler] Properly demangle templated operators.

After we detected the presence of a template via ?$ we would proceed by
only demangling a simple unqualified name. This means we would fail on
templated operators (and perhaps other yet-to-be-determined things)

This was discovered while doing some refactoring to store richer
semantic information about the demangled types to pave the way for
overhauling the way we handle backreferences. (Specifically, we need to
defer recording or resolving back-references until a symbol has been
completely demangled, because we need to use information that only
occurs later in the mangled string to decide whether a back-reference
should be recorded.)

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

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

Modified: llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp?rev=338608&r1=338607&r2=338608&view=diff
==============================================================================
--- llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp (original)
+++ llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp Wed Aug  1 11:32:47 2018
@@ -204,6 +204,8 @@ enum FuncClass : uint8_t {
   Far = 1 << 6,
 };
 
+enum class SymbolCategory { Function, Variable };
+
 namespace {
 
 struct Type;
@@ -265,12 +267,10 @@ struct Name {
   // Name read from an MangledName string.
   StringView Str;
 
-  // Overloaded operators are represented as special BackReferences in mangled
-  // symbols. If this is an operator name, "op" has an operator name (e.g.
-  // ">>"). Otherwise, empty.
-  StringView Operator;
+  bool IsTemplateInstantiation = false;
+  bool IsOperator = false;
 
-  // Template parameters. Null if not a template.
+  // Template parameters. Only valid if Flags contains NF_TemplateInstantiation.
   TemplateParams *TParams = nullptr;
 
   // Nested BackReferences (e.g. "A::B::C") are represented as a linked list.
@@ -541,24 +541,24 @@ static void outputName(OutputStream &OS,
   for (; TheName->Next; TheName = TheName->Next) {
     Previous = TheName;
     OS << TheName->Str;
-    if (TheName->TParams)
+    if (TheName->IsTemplateInstantiation)
       outputParameterList(OS, *TheName->TParams);
     OS << "::";
   }
 
   // Print out a regular name.
-  if (TheName->Operator.empty()) {
+  if (!TheName->IsOperator) {
     OS << TheName->Str;
-    if (TheName->TParams)
+    if (TheName->IsTemplateInstantiation)
       outputParameterList(OS, *TheName->TParams);
     return;
   }
 
   // Print out ctor or dtor.
-  if (TheName->Operator == "dtor")
+  if (TheName->Str == "dtor")
     OS << "~";
 
-  if (TheName->Operator == "ctor" || TheName->Operator == "dtor") {
+  if (TheName->Str == "ctor" || TheName->Str == "dtor") {
     OS << Previous->Str;
     if (Previous->TParams)
       outputParameterList(OS, *Previous->TParams);
@@ -566,9 +566,9 @@ static void outputName(OutputStream &OS,
   }
 
   // Print out an overloaded operator.
-  if (!TheName->Str.empty())
-    OS << TheName->Str << "::";
-  OS << "operator" << TheName->Operator;
+  OS << "operator" << TheName->Str;
+  if (TheName->IsTemplateInstantiation)
+    outputParameterList(OS, *TheName->TParams);
 }
 
 namespace {
@@ -853,6 +853,8 @@ void ArrayType::outputPost(OutputStream
 }
 
 struct Symbol {
+  SymbolCategory Category;
+
   Name *SymbolName = nullptr;
   Type *SymbolType = nullptr;
 };
@@ -906,14 +908,14 @@ private:
   Name *demangleFullyQualifiedTypeName(StringView &MangledName);
   Name *demangleFullyQualifiedSymbolName(StringView &MangledName);
 
-  Name *demangleUnqualifiedTypeName(StringView &MangledName);
-  Name *demangleUnqualifiedSymbolName(StringView &MangledName);
+  Name *demangleUnqualifiedTypeName(StringView &MangledName, bool Memorize);
+  Name *demangleUnqualifiedSymbolName(StringView &MangledName, bool Memorize);
 
   Name *demangleNameScopeChain(StringView &MangledName, Name *UnqualifiedName);
   Name *demangleNameScopePiece(StringView &MangledName);
 
   Name *demangleBackRefName(StringView &MangledName);
-  Name *demangleClassTemplateName(StringView &MangledName);
+  Name *demangleTemplateInstantiationName(StringView &MangledName);
   Name *demangleOperatorName(StringView &MangledName);
   Name *demangleSimpleName(StringView &MangledName, bool Memorize);
   Name *demangleAnonymousNamespaceName(StringView &MangledName);
@@ -981,9 +983,14 @@ Symbol *Demangler::parse(StringView &Man
   if (Error)
     return nullptr;
   // Read a variable.
-  S->SymbolType = startsWithDigit(MangledName)
-                      ? demangleVariableEncoding(MangledName)
-                      : demangleFunctionEncoding(MangledName);
+  if (startsWithDigit(MangledName)) {
+    S->Category = SymbolCategory::Variable;
+    S->SymbolType = demangleVariableEncoding(MangledName);
+  } else {
+    S->Category = SymbolCategory::Function;
+    S->SymbolType = demangleFunctionEncoding(MangledName);
+  }
+
   if (Error)
     return nullptr;
 
@@ -1101,11 +1108,11 @@ Name *Demangler::demangleBackRefName(Str
   return Node;
 }
 
-Name *Demangler::demangleClassTemplateName(StringView &MangledName) {
+Name *Demangler::demangleTemplateInstantiationName(StringView &MangledName) {
   assert(MangledName.startsWith("?$"));
   MangledName.consumeFront("?$");
 
-  Name *Node = demangleSimpleName(MangledName, false);
+  Name *Node = demangleUnqualifiedSymbolName(MangledName, false);
   if (Error)
     return nullptr;
 
@@ -1113,6 +1120,8 @@ Name *Demangler::demangleClassTemplateNa
   if (Error)
     return nullptr;
 
+  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);
@@ -1250,7 +1259,8 @@ Name *Demangler::demangleOperatorName(St
   };
 
   Name *Node = Arena.alloc<Name>();
-  Node->Operator = NameString();
+  Node->Str = NameString();
+  Node->IsOperator = true;
   return Node;
 }
 
@@ -1325,7 +1335,7 @@ Name *Demangler::demangleLocallyScopedNa
 
 // Parses a type name in the form of A at B@C@@ which represents C::B::A.
 Name *Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) {
-  Name *TypeName = demangleUnqualifiedTypeName(MangledName);
+  Name *TypeName = demangleUnqualifiedTypeName(MangledName, true);
   if (Error)
     return nullptr;
   assert(TypeName);
@@ -1341,7 +1351,7 @@ 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);
+  Name *SymbolName = demangleUnqualifiedSymbolName(MangledName, true);
   if (Error)
     return nullptr;
   assert(SymbolName);
@@ -1353,7 +1363,8 @@ Name *Demangler::demangleFullyQualifiedS
   return QualName;
 }
 
-Name *Demangler::demangleUnqualifiedTypeName(StringView &MangledName) {
+Name *Demangler::demangleUnqualifiedTypeName(StringView &MangledName,
+                                             bool Memorize) {
   // An inner-most name can be a back-reference, because a fully-qualified name
   // (e.g. Scope + Inner) can contain other fully qualified names inside of
   // them (for example template parameters), and these nested parameters can
@@ -1362,19 +1373,20 @@ Name *Demangler::demangleUnqualifiedType
     return demangleBackRefName(MangledName);
 
   if (MangledName.startsWith("?$"))
-    return demangleClassTemplateName(MangledName);
+    return demangleTemplateInstantiationName(MangledName);
 
-  return demangleSimpleName(MangledName, true);
+  return demangleSimpleName(MangledName, Memorize);
 }
 
-Name *Demangler::demangleUnqualifiedSymbolName(StringView &MangledName) {
+Name *Demangler::demangleUnqualifiedSymbolName(StringView &MangledName,
+                                               bool Memorize) {
   if (startsWithDigit(MangledName))
     return demangleBackRefName(MangledName);
   if (MangledName.startsWith("?$"))
-    return demangleClassTemplateName(MangledName);
+    return demangleTemplateInstantiationName(MangledName);
   if (MangledName.startsWith('?'))
     return demangleOperatorName(MangledName);
-  return demangleSimpleName(MangledName, true);
+  return demangleSimpleName(MangledName, Memorize);
 }
 
 Name *Demangler::demangleNameScopePiece(StringView &MangledName) {
@@ -1382,7 +1394,7 @@ Name *Demangler::demangleNameScopePiece(
     return demangleBackRefName(MangledName);
 
   if (MangledName.startsWith("?$"))
-    return demangleClassTemplateName(MangledName);
+    return demangleTemplateInstantiationName(MangledName);
 
   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=338608&r1=338607&r2=338608&view=diff
==============================================================================
--- llvm/trunk/test/Demangle/ms-back-references.test (original)
+++ llvm/trunk/test/Demangle/ms-back-references.test Wed Aug  1 11:32:47 2018
@@ -51,3 +51,7 @@
 
 ?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

Modified: llvm/trunk/test/Demangle/ms-mangle.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Demangle/ms-mangle.test?rev=338608&r1=338607&r2=338608&view=diff
==============================================================================
--- llvm/trunk/test/Demangle/ms-mangle.test (original)
+++ llvm/trunk/test/Demangle/ms-mangle.test Wed Aug  1 11:32:47 2018
@@ -64,6 +64,9 @@
 ??Hfoo@@QEAAHH at Z
 ; CHECK: int __cdecl foo::operator+(int)
 
+??$?HH at S@@QEAAAEANH at Z
+; CHECK: double & __cdecl S::operator+<int>(int)
+
 ?static_method at foo@@SAPAV1 at XZ
 ; CHECK: static class foo * __cdecl foo::static_method(void)
 




More information about the llvm-commits mailing list