[llvm] r338403 - Resubmit r338340 "[MS Demangler] Better demangling of template arguments."

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 31 10:16:44 PDT 2018


Author: zturner
Date: Tue Jul 31 10:16:44 2018
New Revision: 338403

URL: http://llvm.org/viewvc/llvm-project?rev=338403&view=rev
Log:
Resubmit r338340 "[MS Demangler] Better demangling of template arguments."

This broke the build with GCC, but has since been fixed.

Added:
    llvm/trunk/test/Demangle/ms-template-callback.test
Modified:
    llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp

Modified: llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp?rev=338403&r1=338402&r2=338403&view=diff
==============================================================================
--- llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp (original)
+++ llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp Tue Jul 31 10:16:44 2018
@@ -209,19 +209,28 @@ namespace {
 struct Type;
 struct Name;
 
-// Represents a list of parameters (template params or function arguments.
-// It's represented as a linked list.
-struct ParamList {
+struct FunctionParams {
   bool IsVariadic = false;
 
-  // If this is a type, Current will be valid and AliasName will be null.
   Type *Current = nullptr;
 
-  // If this is an alias (e.g. using X = Y), Current will be null and AliasName
-  // will be valid.
-  Name *AliasName = nullptr;
+  FunctionParams *Next = nullptr;
+};
+
+struct TemplateParams {
+  bool IsTemplateTemplate = false;
+  bool IsAliasTemplate = false;
+
+  // Type can be null if this is a template template parameter.  In that case
+  // only Name will be valid.
+  Type *ParamType = nullptr;
+
+  // Name can be valid if this is a template template parameter (see above) or
+  // this is a function declaration (e.g. foo<&SomeFunc>).  In the latter case
+  // Name contains the name of the function and Type contains the signature.
+  Name *ParamName = nullptr;
 
-  ParamList *Next = nullptr;
+  TemplateParams *Next = nullptr;
 };
 
 // The type class. Mangled symbols are first parsed and converted to
@@ -262,7 +271,7 @@ struct Name {
   StringView Operator;
 
   // Template parameters. Null if not a template.
-  ParamList *TemplateParams = nullptr;
+  TemplateParams *TParams = nullptr;
 
   // Nested BackReferences (e.g. "A::B::C") are represented as a linked list.
   Name *Next = nullptr;
@@ -308,7 +317,7 @@ struct FunctionType : public Type {
   CallingConv CallConvention;
   FuncClass FunctionClass;
 
-  ParamList Params;
+  FunctionParams Params;
 };
 
 struct UdtType : public Type {
@@ -466,22 +475,17 @@ static bool startsWithLocalScopePattern(
 static void outputName(OutputStream &OS, const Name *TheName);
 
 // Write a function or template parameter list.
-static void outputParameterList(OutputStream &OS, const ParamList &Params,
-                                bool EmptyAsVoid) {
-  if (!Params.Current && !Params.AliasName) {
-    if (EmptyAsVoid)
-      OS << "void";
+static void outputParameterList(OutputStream &OS,
+                                const FunctionParams &Params) {
+  if (!Params.Current) {
+    OS << "void";
     return;
   }
 
-  const ParamList *Head = &Params;
+  const FunctionParams *Head = &Params;
   while (Head) {
-    if (Head->Current) {
-      Type::outputPre(OS, *Head->Current);
-      Type::outputPost(OS, *Head->Current);
-    } else if (Head->AliasName) {
-      outputName(OS, Head->AliasName);
-    }
+    Type::outputPre(OS, *Head->Current);
+    Type::outputPost(OS, *Head->Current);
 
     Head = Head->Next;
 
@@ -490,12 +494,39 @@ static void outputParameterList(OutputSt
   }
 }
 
-static void outputTemplateParams(OutputStream &OS, const Name &TheName) {
-  if (!TheName.TemplateParams)
+static void outputParameterList(OutputStream &OS,
+                                const TemplateParams &Params) {
+  if (!Params.ParamType && !Params.ParamName) {
+    OS << "<>";
     return;
+  }
 
   OS << "<";
-  outputParameterList(OS, *TheName.TemplateParams, false);
+  const TemplateParams *Head = &Params;
+  while (Head) {
+    // Type can be null if this is a template template parameter,
+    // and Name can be null if this is a simple type.
+
+    if (Head->ParamType && Head->ParamName) {
+      // Function pointer.
+      OS << "&";
+      Type::outputPre(OS, *Head->ParamType);
+      outputName(OS, Head->ParamName);
+      Type::outputPost(OS, *Head->ParamType);
+    } else if (Head->ParamType) {
+      // simple type.
+      Type::outputPre(OS, *Head->ParamType);
+      Type::outputPost(OS, *Head->ParamType);
+    } else {
+      // Template alias.
+      outputName(OS, Head->ParamName);
+    }
+
+    Head = Head->Next;
+
+    if (Head)
+      OS << ", ";
+  }
   OS << ">";
 }
 
@@ -510,14 +541,16 @@ static void outputName(OutputStream &OS,
   for (; TheName->Next; TheName = TheName->Next) {
     Previous = TheName;
     OS << TheName->Str;
-    outputTemplateParams(OS, *TheName);
+    if (TheName->TParams)
+      outputParameterList(OS, *TheName->TParams);
     OS << "::";
   }
 
   // Print out a regular name.
   if (TheName->Operator.empty()) {
     OS << TheName->Str;
-    outputTemplateParams(OS, *TheName);
+    if (TheName->TParams)
+      outputParameterList(OS, *TheName->TParams);
     return;
   }
 
@@ -527,7 +560,8 @@ static void outputName(OutputStream &OS,
 
   if (TheName->Operator == "ctor" || TheName->Operator == "dtor") {
     OS << Previous->Str;
-    outputTemplateParams(OS, *Previous);
+    if (Previous->TParams)
+      outputParameterList(OS, *Previous->TParams);
     return;
   }
 
@@ -755,7 +789,7 @@ void FunctionType::outputPre(OutputStrea
 
 void FunctionType::outputPost(OutputStream &OS) {
   OS << "(";
-  outputParameterList(OS, Params, true);
+  outputParameterList(OS, Params);
   OS << ")";
   if (Quals & Q_Const)
     OS << " const";
@@ -859,8 +893,8 @@ private:
 
   ArrayType *demangleArrayType(StringView &MangledName);
 
-  ParamList *demangleTemplateParameterList(StringView &MangledName);
-  ParamList demangleFunctionParameterList(StringView &MangledName);
+  TemplateParams *demangleTemplateParameterList(StringView &MangledName);
+  FunctionParams demangleFunctionParameterList(StringView &MangledName);
 
   int demangleNumber(StringView &MangledName);
 
@@ -1069,7 +1103,7 @@ Name *Demangler::demangleClassTemplateNa
   MangledName.consumeFront("?$");
 
   Name *Node = demangleSimpleName(MangledName, false);
-  Node->TemplateParams = demangleTemplateParameterList(MangledName);
+  Node->TParams = demangleTemplateParameterList(MangledName);
 
   // Render this class template name into a string buffer so that we can
   // memorize it for the purpose of back-referencing.
@@ -1860,13 +1894,14 @@ ArrayType *Demangler::demangleArrayType(
 }
 
 // Reads a function or a template parameters.
-ParamList Demangler::demangleFunctionParameterList(StringView &MangledName) {
+FunctionParams
+Demangler::demangleFunctionParameterList(StringView &MangledName) {
   // Empty parameter list.
   if (MangledName.consumeFront('X'))
     return {};
 
-  ParamList *Head;
-  ParamList **Current = &Head;
+  FunctionParams *Head;
+  FunctionParams **Current = &Head;
   while (!Error && !MangledName.startsWith('@') &&
          !MangledName.startsWith('Z')) {
 
@@ -1878,7 +1913,7 @@ ParamList Demangler::demangleFunctionPar
       }
       MangledName = MangledName.dropFront();
 
-      *Current = Arena.alloc<ParamList>();
+      *Current = Arena.alloc<FunctionParams>();
       (*Current)->Current = FunctionParamBackRefs[N]->clone(Arena);
       Current = &(*Current)->Next;
       continue;
@@ -1886,7 +1921,7 @@ ParamList Demangler::demangleFunctionPar
 
     size_t OldSize = MangledName.size();
 
-    *Current = Arena.alloc<ParamList>();
+    *Current = Arena.alloc<FunctionParams>();
     (*Current)->Current = demangleType(MangledName, QualifierMangleMode::Drop);
 
     size_t CharsConsumed = OldSize - MangledName.size();
@@ -1918,12 +1953,13 @@ ParamList Demangler::demangleFunctionPar
   return {};
 }
 
-ParamList *Demangler::demangleTemplateParameterList(StringView &MangledName) {
-  ParamList *Head;
-  ParamList **Current = &Head;
+TemplateParams *
+Demangler::demangleTemplateParameterList(StringView &MangledName) {
+  TemplateParams *Head;
+  TemplateParams **Current = &Head;
   while (!Error && !MangledName.startsWith('@')) {
     // Template parameter lists don't participate in back-referencing.
-    *Current = Arena.alloc<ParamList>();
+    *Current = Arena.alloc<TemplateParams>();
 
     // Empty parameter pack.
     if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") ||
@@ -1933,11 +1969,17 @@ ParamList *Demangler::demangleTemplatePa
       continue;
     }
 
-    if (MangledName.consumeFront("$$Y"))
-      (*Current)->AliasName = demangleFullyQualifiedTypeName(MangledName);
-    else
-      (*Current)->Current =
+    if (MangledName.consumeFront("$$Y")) {
+      (*Current)->IsTemplateTemplate = true;
+      (*Current)->IsAliasTemplate = true;
+      (*Current)->ParamName = demangleFullyQualifiedTypeName(MangledName);
+    } else if (MangledName.consumeFront("$1?")) {
+      (*Current)->ParamName = demangleFullyQualifiedSymbolName(MangledName);
+      (*Current)->ParamType = demangleFunctionEncoding(MangledName);
+    } else {
+      (*Current)->ParamType =
           demangleType(MangledName, QualifierMangleMode::Drop);
+    }
 
     Current = &(*Current)->Next;
   }

Added: llvm/trunk/test/Demangle/ms-template-callback.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Demangle/ms-template-callback.test?rev=338403&view=auto
==============================================================================
--- llvm/trunk/test/Demangle/ms-template-callback.test (added)
+++ llvm/trunk/test/Demangle/ms-template-callback.test Tue Jul 31 10:16:44 2018
@@ -0,0 +1,53 @@
+; These tests are based on clang/test/CodeGenCXX/mangle-ms-template-callback.cpp
+
+; RUN: llvm-undname < %s | FileCheck %s
+
+; CHECK-NOT: Invalid mangled name
+
+?callback_void@@3V?$C@$$A6AXXZ@@A
+; CHECK: class C<void __cdecl(void)> callback_void
+
+?callback_void_volatile@@3V?$C@$$A6AXXZ@@C
+; CHECK: class C<void __cdecl(void)> volatile callback_void_volatile
+
+?callback_int@@3V?$C@$$A6AHXZ@@A
+; CHECK: C<int __cdecl(void)> callback_int
+
+?callback_Type@@3V?$C@$$A6A?AVType@@XZ@@A
+; CHECK: C<class Type __cdecl(void)> callback_Type
+
+?callback_void_int@@3V?$C@$$A6AXH at Z@@A
+; CHECK: C<void __cdecl(int)> callback_void_int
+
+?callback_int_int@@3V?$C@$$A6AHH at Z@@A
+; CHECK: C<int __cdecl(int)> callback_int_int
+
+?callback_void_Type@@3V?$C@$$A6AXVType@@@Z@@A
+; CHECK: C<void __cdecl(class Type)> callback_void_Type
+
+?foo@@YAXV?$C@$$A6AXXZ@@@Z
+; CHECK: void __cdecl foo(class C<void __cdecl(void)>)
+
+?function@@YAXV?$C@$$A6AXXZ@@@Z
+; CHECK: void __cdecl function(class C<void __cdecl(void)>)
+
+?function_pointer@@YAXV?$C at P6AXXZ@@@Z
+; CHECK: void __cdecl function_pointer(class C<void (__cdecl *)(void)>)
+
+?member_pointer@@YAXV?$C at P8Z@@AEXXZ@@@Z
+; CHECK: void __cdecl member_pointer(class C<void (__thiscall Z::*)(void)>)
+
+??$bar at P6AHH@Z@@YAXP6AHH at Z@Z
+; CHECK: void __cdecl bar<int (__cdecl *)(int)>(int (__cdecl *)(int))
+
+??$WrapFnPtr@$1?VoidFn@@YAXXZ@@YAXXZ
+; CHECK: void __cdecl WrapFnPtr<&void __cdecl VoidFn(void)>(void)
+
+??$WrapFnRef@$1?VoidFn@@YAXXZ@@YAXXZ
+; CHECK: void __cdecl WrapFnRef<&void __cdecl VoidFn(void)>(void)
+
+??$WrapFnPtr@$1?VoidStaticMethod at Thing@@SAXXZ@@YAXXZ
+; CHECK: void __cdecl WrapFnPtr<&static void __cdecl Thing::VoidStaticMethod(void)>(void)
+
+??$WrapFnRef@$1?VoidStaticMethod at Thing@@SAXXZ@@YAXXZ
+; CHECK: void __cdecl WrapFnRef<&static void __cdecl Thing::VoidStaticMethod(void)>(void)




More information about the llvm-commits mailing list