[llvm] r339434 - [MS Demangler] Fix several issues related to templates.

Zachary Turner via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 10 07:31:05 PDT 2018


Author: zturner
Date: Fri Aug 10 07:31:04 2018
New Revision: 339434

URL: http://llvm.org/viewvc/llvm-project?rev=339434&view=rev
Log:
[MS Demangler] Fix several issues related to templates.

These were uncovered when porting the mangling tests in
ms-templates.cpp from clang/CodeGenCXX over to demangling
tests.  The main issues fixed here are surrounding integer
literal signed and unsignedness, empty array dimensions,
and pointer and reference non-type template parameters.

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

Added:
    llvm/trunk/test/Demangle/ms-templates.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=339434&r1=339433&r2=339434&view=diff
==============================================================================
--- llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp (original)
+++ llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp Fri Aug 10 07:31:04 2018
@@ -234,6 +234,15 @@ struct FunctionParams {
 struct TemplateParams {
   bool IsTemplateTemplate = false;
   bool IsAliasTemplate = false;
+  bool IsIntegerLiteral = false;
+  bool IntegerLiteralIsNegative = false;
+  bool IsEmptyParameterPack = false;
+  bool PointerToSymbol = false;
+  bool ReferenceToSymbol = false;
+
+  // If IsIntegerLiteral is true, this is a non-type template parameter
+  // whose value is contained in this field.
+  uint64_t IntegralValue = 0;
 
   // Type can be null if this is a template template parameter.  In that case
   // only Name will be valid.
@@ -340,14 +349,18 @@ struct UdtType : public Type {
   Name *UdtName = nullptr;
 };
 
+struct ArrayDimension {
+  uint64_t Dim = 0;
+  ArrayDimension *Next = nullptr;
+};
+
 struct ArrayType : public Type {
   Type *clone(ArenaAllocator &Arena) const override;
   void outputPre(OutputStream &OS, NameResolver &Resolver) override;
   void outputPost(OutputStream &OS, NameResolver &Resolver) override;
 
   // Either NextDimension or ElementType will be valid.
-  ArrayType *NextDimension = nullptr;
-  uint32_t ArrayDimension = 0;
+  ArrayDimension *Dims = nullptr;
 
   Type *ElementType = nullptr;
 };
@@ -510,7 +523,7 @@ static void outputName(OutputStream &OS,
 
 static void outputParameterList(OutputStream &OS, const TemplateParams &Params,
                                 NameResolver &Resolver) {
-  if (!Params.ParamType && !Params.ParamName) {
+  if (Params.IsEmptyParameterPack) {
     OS << "<>";
     return;
   }
@@ -521,9 +534,13 @@ static void outputParameterList(OutputSt
     // 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 << "&";
+    if (Head->IsIntegerLiteral) {
+      if (Head->IntegerLiteralIsNegative)
+        OS << '-';
+      OS << Head->IntegralValue;
+    } else if (Head->PointerToSymbol || Head->ReferenceToSymbol) {
+      if (Head->PointerToSymbol)
+        OS << "&";
       Type::outputPre(OS, *Head->ParamType, Resolver);
       outputName(OS, Head->ParamName, Resolver);
       Type::outputPost(OS, *Head->ParamType, Resolver);
@@ -867,12 +884,16 @@ void ArrayType::outputPre(OutputStream &
 }
 
 void ArrayType::outputPost(OutputStream &OS, NameResolver &Resolver) {
-  if (ArrayDimension > 0)
-    OS << "[" << ArrayDimension << "]";
-  if (NextDimension)
-    Type::outputPost(OS, *NextDimension, Resolver);
-  else if (ElementType)
-    Type::outputPost(OS, *ElementType, Resolver);
+  ArrayDimension *D = Dims;
+  while (D) {
+    OS << "[";
+    if (D->Dim > 0)
+      OS << D->Dim;
+    OS << "]";
+    D = D->Next;
+  }
+
+  Type::outputPost(OS, *ElementType, Resolver);
 }
 
 struct Symbol {
@@ -938,7 +959,7 @@ private:
   TemplateParams *demangleTemplateParameterList(StringView &MangledName);
   FunctionParams demangleFunctionParameterList(StringView &MangledName);
 
-  int demangleNumber(StringView &MangledName);
+  std::pair<uint64_t, bool> demangleNumber(StringView &MangledName);
 
   void memorizeString(StringView s);
 
@@ -1091,21 +1112,21 @@ Type *Demangler::demangleVariableEncodin
 //                        ::= <hex digit>+ @  # when Numbrer == 0 or >= 10
 //
 // <hex-digit>            ::= [A-P]           # A = 0, B = 1, ...
-int Demangler::demangleNumber(StringView &MangledName) {
-  bool neg = MangledName.consumeFront("?");
+std::pair<uint64_t, bool> Demangler::demangleNumber(StringView &MangledName) {
+  bool IsNegative = MangledName.consumeFront('?');
 
   if (startsWithDigit(MangledName)) {
-    int32_t Ret = MangledName[0] - '0' + 1;
+    uint64_t Ret = MangledName[0] - '0' + 1;
     MangledName = MangledName.dropFront(1);
-    return neg ? -Ret : Ret;
+    return {Ret, IsNegative};
   }
 
-  int Ret = 0;
+  uint64_t Ret = 0;
   for (size_t i = 0; i < MangledName.size(); ++i) {
     char C = MangledName[i];
     if (C == '@') {
       MangledName = MangledName.dropFront(i + 1);
-      return neg ? -Ret : Ret;
+      return {Ret, IsNegative};
     }
     if ('A' <= C && C <= 'P') {
       Ret = (Ret << 4) + (C - 'A');
@@ -1115,7 +1136,7 @@ int Demangler::demangleNumber(StringView
   }
 
   Error = true;
-  return 0;
+  return {0ULL, false};
 }
 
 // First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9.
@@ -1346,7 +1367,8 @@ Name *Demangler::demangleLocallyScopedNa
 
   Name *Node = Arena.alloc<Name>();
   MangledName.consumeFront('?');
-  int ScopeIdentifier = demangleNumber(MangledName);
+  auto Number = demangleNumber(MangledName);
+  assert(!Number.second);
 
   // One ? to terminate the number
   MangledName.consumeFront('?');
@@ -1361,7 +1383,7 @@ Name *Demangler::demangleLocallyScopedNa
   OS << '`';
   output(Scope, OS);
   OS << '\'';
-  OS << "::`" << ScopeIdentifier << "'";
+  OS << "::`" << Number.first << "'";
   OS << '\0';
   char *Result = OS.getBuffer();
   Node->Str = copyString(Result);
@@ -1933,19 +1955,28 @@ ArrayType *Demangler::demangleArrayType(
   assert(MangledName.front() == 'Y');
   MangledName.popFront();
 
-  int Dimension = demangleNumber(MangledName);
-  if (Dimension <= 0) {
+  uint64_t Rank = 0;
+  bool IsNegative = false;
+  std::tie(Rank, IsNegative) = demangleNumber(MangledName);
+  if (IsNegative || Rank == 0) {
     Error = true;
     return nullptr;
   }
 
   ArrayType *ATy = Arena.alloc<ArrayType>();
-  ArrayType *Dim = ATy;
-  for (int I = 0; I < Dimension; ++I) {
-    Dim->Prim = PrimTy::Array;
-    Dim->ArrayDimension = demangleNumber(MangledName);
-    Dim->NextDimension = Arena.alloc<ArrayType>();
-    Dim = Dim->NextDimension;
+  ATy->Prim = PrimTy::Array;
+  ATy->Dims = Arena.alloc<ArrayDimension>();
+  ArrayDimension *Dim = ATy->Dims;
+  for (uint64_t I = 0; I < Rank; ++I) {
+    std::tie(Dim->Dim, IsNegative) = demangleNumber(MangledName);
+    if (IsNegative) {
+      Error = true;
+      return nullptr;
+    }
+    if (I + 1 < Rank) {
+      Dim->Next = Arena.alloc<ArrayDimension>();
+      Dim = Dim->Next;
+    }
   }
 
   if (MangledName.consumeFront("$$C")) {
@@ -1958,7 +1989,6 @@ ArrayType *Demangler::demangleArrayType(
   }
 
   ATy->ElementType = demangleType(MangledName, QualifierMangleMode::Drop);
-  Dim->ElementType = ATy->ElementType;
   return ATy;
 }
 
@@ -2034,16 +2064,42 @@ Demangler::demangleTemplateParameterList
     // Empty parameter pack.
     if (MangledName.consumeFront("$S") || MangledName.consumeFront("$$V") ||
         MangledName.consumeFront("$$$V")) {
+      (*Current)->IsEmptyParameterPack = true;
       break;
     }
 
     if (MangledName.consumeFront("$$Y")) {
+      // Template alias
       (*Current)->IsTemplateTemplate = true;
       (*Current)->IsAliasTemplate = true;
       (*Current)->ParamName = demangleFullyQualifiedTypeName(MangledName);
-    } else if (MangledName.consumeFront("$1?")) {
-      (*Current)->ParamName = demangleFullyQualifiedSymbolName(MangledName);
-      (*Current)->ParamType = demangleFunctionEncoding(MangledName);
+    } else if (MangledName.consumeFront("$$B")) {
+      // Array
+      (*Current)->ParamType =
+          demangleType(MangledName, QualifierMangleMode::Drop);
+    } else if (MangledName.startsWith("$1?")) {
+      MangledName.consumeFront("$1");
+      // Pointer to symbol
+      Symbol *S = parse(MangledName);
+      (*Current)->ParamName = S->SymbolName;
+      (*Current)->ParamType = S->SymbolType;
+      (*Current)->PointerToSymbol = true;
+    } else if (MangledName.startsWith("$E?")) {
+      MangledName.consumeFront("$E");
+      // Reference to symbol
+      Symbol *S = parse(MangledName);
+      (*Current)->ParamName = S->SymbolName;
+      (*Current)->ParamType = S->SymbolType;
+      (*Current)->ReferenceToSymbol = true;
+    } else if (MangledName.consumeFront("$0")) {
+      // Integral non-type template parameter
+      bool IsNegative = false;
+      uint64_t Value = 0;
+      std::tie(Value, IsNegative) = demangleNumber(MangledName);
+
+      (*Current)->IsIntegerLiteral = true;
+      (*Current)->IntegerLiteralIsNegative = IsNegative;
+      (*Current)->IntegralValue = Value;
     } else {
       (*Current)->ParamType =
           demangleType(MangledName, QualifierMangleMode::Drop);

Added: llvm/trunk/test/Demangle/ms-templates.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Demangle/ms-templates.test?rev=339434&view=auto
==============================================================================
--- llvm/trunk/test/Demangle/ms-templates.test (added)
+++ llvm/trunk/test/Demangle/ms-templates.test Fri Aug 10 07:31:04 2018
@@ -0,0 +1,195 @@
+; These tests are based on clang/test/CodeGenCXX/mangle-ms-cxx11.cpp
+
+; RUN: llvm-undname < %s | FileCheck %s
+
+; CHECK-NOT: Invalid mangled name
+
+
+??0?$Class at VTypename@@@@QAE at XZ
+; CHECK: __thiscall Class<class Typename>::Class<class Typename>(void)
+??0?$Class at VTypename@@@@QEAA at XZ
+; CHECK: __cdecl Class<class Typename>::Class<class Typename>(void)
+
+??0?$Class@$$CBVTypename@@@@QAE at XZ
+; FIXME: __thiscall Class<class Typename const>::Class<class Typename const>(void)
+??0?$Class@$$CBVTypename@@@@QEAA at XZ
+; FIXME: __thiscall Class<class Typename const>::Class<class Typename const>(void)
+
+??0?$Class@$$CCVTypename@@@@QAE at XZ
+; FIXME: __thiscall Class<class Typename volatile>::Class<class Typename volatile>(void)
+??0?$Class@$$CCVTypename@@@@QEAA at XZ
+; FIXME: __thiscall Class<class Typename volatile>::Class<class Typename volatile>(void)
+
+??0?$Class@$$CDVTypename@@@@QAE at XZ
+; FIXME: __thiscall Class<class Typename const volatile>::Class<class Typename const volatile>(void)
+??0?$Class@$$CDVTypename@@@@QEAA at XZ
+; FIXME: __thiscall Class<class Typename const volatile>::Class<class Typename const volatile>(void)
+
+??0?$Class at V?$Nested at VTypename@@@@@@QAE at XZ
+; CHECK: __thiscall Class<class Nested<class Typename>>::Class<class Nested<class Typename>>(void)
+??0?$Class at V?$Nested at VTypename@@@@@@QEAA at XZ
+; CHECK: __cdecl Class<class Nested<class Typename>>::Class<class Nested<class Typename>>(void)
+
+??0?$Class at QAH@@QAE at XZ
+; CHECK: __thiscall Class<int *const>::Class<int *const>(void)
+??0?$Class at QEAH@@QEAA at XZ
+; CHECK: __cdecl Class<int *const>::Class<int *const>(void)
+
+??0?$Class@$$A6AHXZ@@QAE at XZ
+; CHECK: __thiscall Class<int __cdecl(void)>::Class<int __cdecl(void)>(void)
+??0?$Class@$$A6AHXZ@@QEAA at XZ
+; CHECK: __cdecl Class<int __cdecl(void)>::Class<int __cdecl(void)>(void)
+
+??0?$Class@$$BY0A at H@@QAE at XZ
+; CHECK: __thiscall Class<int[]>::Class<int[]>(void)
+??0?$Class@$$BY0A at H@@QEAA at XZ
+; CHECK: __cdecl Class<int[]>::Class<int[]>(void)
+
+??0?$Class@$$BY04H@@QAE at XZ
+; CHECK: __thiscall Class<int[5]>::Class<int[5]>(void)
+??0?$Class@$$BY04H@@QEAA at XZ
+; CHECK: __cdecl Class<int[5]>::Class<int[5]>(void)
+
+??0?$Class@$$BY04$$CBH@@QAE at XZ
+; CHECK: __thiscall Class<int const[5]>::Class<int const[5]>(void)
+??0?$Class@$$BY04$$CBH@@QEAA at XZ
+; CHECK: __cdecl Class<int const[5]>::Class<int const[5]>(void)
+
+??0?$Class@$$BY04QAH@@QAE at XZ
+; CHECK: __thiscall Class<int *const[5]>::Class<int *const[5]>(void)
+??0?$Class@$$BY04QEAH@@QEAA at XZ
+; CHECK: __cdecl Class<int *const[5]>::Class<int *const[5]>(void)
+
+??0?$BoolTemplate@$0A@@@QAE at XZ
+; CHECK: __thiscall BoolTemplate<0>::BoolTemplate<0>(void)
+??0?$BoolTemplate@$0A@@@QEAA at XZ
+; CHECK: __cdecl BoolTemplate<0>::BoolTemplate<0>(void)
+
+??0?$BoolTemplate@$00@@QAE at XZ
+; CHECK: __thiscall BoolTemplate<1>::BoolTemplate<1>(void)
+??0?$BoolTemplate@$00@@QEAA at XZ
+; CHECK: __cdecl BoolTemplate<1>::BoolTemplate<1>(void)
+
+??$Foo at H@?$BoolTemplate@$00@@QAEXH at Z
+; CHECK: void __thiscall BoolTemplate<1>::Foo<int>(int)
+??$Foo at H@?$BoolTemplate@$00@@QEAAXH at Z
+; CHECK: void __cdecl BoolTemplate<1>::Foo<int>(int)
+
+??0?$IntTemplate@$0A@@@QAE at XZ
+; CHECK: __thiscall IntTemplate<0>::IntTemplate<0>(void)
+??0?$IntTemplate@$0A@@@QEAA at XZ
+; CHECK: __cdecl IntTemplate<0>::IntTemplate<0>(void)
+
+??0?$IntTemplate@$04@@QAE at XZ
+; CHECK: __thiscall IntTemplate<5>::IntTemplate<5>(void)
+??0?$IntTemplate@$04@@QEAA at XZ
+; CHECK: __cdecl IntTemplate<5>::IntTemplate<5>(void)
+
+??0?$IntTemplate@$0L@@@QAE at XZ
+; CHECK: __thiscall IntTemplate<11>::IntTemplate<11>(void)
+??0?$IntTemplate@$0L@@@QEAA at XZ
+; CHECK: __cdecl IntTemplate<11>::IntTemplate<11>(void)
+
+??0?$IntTemplate@$0BAA@@@QAE at XZ
+; CHECK: __thiscall IntTemplate<256>::IntTemplate<256>(void)
+??0?$IntTemplate@$0BAA@@@QEAA at XZ
+; CHECK: __cdecl IntTemplate<256>::IntTemplate<256>(void)
+
+??0?$IntTemplate@$0CAB@@@QAE at XZ
+; CHECK: __thiscall IntTemplate<513>::IntTemplate<513>(void)
+??0?$IntTemplate@$0CAB@@@QEAA at XZ
+; CHECK: __cdecl IntTemplate<513>::IntTemplate<513>(void)
+
+??0?$IntTemplate@$0EAC@@@QAE at XZ
+; CHECK: __thiscall IntTemplate<1026>::IntTemplate<1026>(void)
+??0?$IntTemplate@$0EAC@@@QEAA at XZ
+; CHECK: __cdecl IntTemplate<1026>::IntTemplate<1026>(void)
+
+??0?$IntTemplate@$0PPPP@@@QAE at XZ
+; CHECK: __thiscall IntTemplate<65535>::IntTemplate<65535>(void)
+??0?$IntTemplate@$0PPPP@@@QEAA at XZ
+; CHECK: __cdecl IntTemplate<65535>::IntTemplate<65535>(void)
+
+??0?$IntTemplate@$0?0@@QAE at XZ
+; CHECK: __thiscall IntTemplate<-1>::IntTemplate<-1>(void)
+??0?$IntTemplate@$0?0@@QEAA at XZ
+; CHECK: __cdecl IntTemplate<-1>::IntTemplate<-1>(void)
+
+??0?$IntTemplate@$0?8@@QAE at XZ
+; CHECK: __thiscall IntTemplate<-9>::IntTemplate<-9>(void)
+??0?$IntTemplate@$0?8@@QEAA at XZ
+; CHECK: __cdecl IntTemplate<-9>::IntTemplate<-9>(void)
+
+??0?$IntTemplate@$0?9@@QAE at XZ
+; CHECK: __thiscall IntTemplate<-10>::IntTemplate<-10>(void)
+??0?$IntTemplate@$0?9@@QEAA at XZ
+; CHECK: __cdecl IntTemplate<-10>::IntTemplate<-10>(void)
+
+??0?$IntTemplate@$0?L@@@QAE at XZ
+; CHECK: __thiscall IntTemplate<-11>::IntTemplate<-11>(void)
+??0?$IntTemplate@$0?L@@@QEAA at XZ
+; CHECK: __cdecl IntTemplate<-11>::IntTemplate<-11>(void)
+
+??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QAE at XZ
+; CHECK: __thiscall UnsignedIntTemplate<4294967295>::UnsignedIntTemplate<4294967295>(void)
+??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QEAA at XZ
+; CHECK: __cdecl UnsignedIntTemplate<4294967295>::UnsignedIntTemplate<4294967295>(void)
+
+??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QAE at XZ
+; CHECK: __thiscall LongLongTemplate<-9223372036854775808>::LongLongTemplate<-9223372036854775808>(void)
+??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QEAA at XZ
+; CHECK: __cdecl LongLongTemplate<-9223372036854775808>::LongLongTemplate<-9223372036854775808>(void)
+
+??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QAE at XZ
+; CHECK: __thiscall LongLongTemplate<9223372036854775807>::LongLongTemplate<9223372036854775807>(void)
+??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QEAA at XZ
+; CHECK: __cdecl LongLongTemplate<9223372036854775807>::LongLongTemplate<9223372036854775807>(void)
+
+; -1 is indistinguishable from uint64_max in this encoding.
+??0?$UnsignedLongLongTemplate@$0?0@@QAE at XZ
+; CHECK: __thiscall UnsignedLongLongTemplate<-1>::UnsignedLongLongTemplate<-1>(void)
+??0?$UnsignedLongLongTemplate@$0?0@@QEAA at XZ
+; CHECK: __cdecl UnsignedLongLongTemplate<-1>::UnsignedLongLongTemplate<-1>(void)
+
+??$foo at H@space@@YAABHABH at Z
+; CHECK: int const & __cdecl space::foo<int>(int const &)
+??$foo at H@space@@YAAEBHAEBH at Z
+; CHECK: int const & __cdecl space::foo<int>(int const &)
+
+??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ
+; CHECK: void __cdecl FunctionPointerTemplate<&void __cdecl spam(void)>(void)
+
+??$variadic_fn_template at HHHH@@YAXABH000 at Z
+; CHECK: void __cdecl variadic_fn_template<int, int, int,   int>(int const &, int const &, int const &, int const &)
+??$variadic_fn_template at HHD$$BY01D@@YAXABH0ABDAAY01$$CBD at Z
+; CHECK: void __cdecl variadic_fn_template<int, int, char, char[2]>(int const &, int const &, char const &, char const (&)[2]
+
+??0?$VariadicClass at HD_N@@QAE at XZ
+; CHECK: __thiscall VariadicClass<int, char, bool>::VariadicClass<int, char, bool>(void)
+
+??0?$VariadicClass at _NDH@@QAE at XZ
+; CHECK: __thiscall VariadicClass<bool, char, int>::VariadicClass<bool, char, int>(void)
+
+
+?template_template_fun@@YAXU?$Type at U?$Thing at USecond@@$00@@USecond@@@@@Z
+; CHECK: void __cdecl template_template_fun(struct Type<struct Thing<struct Second, 1>, struct Second>)
+
+??$template_template_specialization@$$A6AXU?$Type at U?$Thing at USecond@@$00@@USecond@@@@@Z@@YAXXZ
+; CHECK: void __cdecl template_template_specialization<void __cdecl(struct Type<struct Thing<struct Second, 1>, struct Second>)>(void)
+
+?f@@YAXU?$S1@$0A@@@@Z
+; CHECK: void __cdecl f(struct S1<0>)
+
+?recref@@YAXU?$type1@$E?inst@@3Urecord@@B@@@Z
+; CHECK: void __cdecl recref(struct type1<struct record const inst>)
+
+?fun@@YAXU?$UUIDType1 at Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z
+; CHECK: void __cdecl fun(struct UUIDType1<struct uuid, &struct __s_GUID const _GUID_12345678_1234_1234_1234_1234567890ab>)
+?fun@@YAXU?$UUIDType2 at Uuuid@@$E?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z
+; CHECK: void __cdecl fun(struct UUIDType2<struct uuid, struct __s_GUID const _GUID_12345678_1234_1234_1234_1234567890ab>)
+
+?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition at H@@@Z
+; CHECK: void __cdecl FunctionDefinedWithInjectedName(struct TypeWithFriendDefinition<int>)
+
+?bar@?$UUIDType4@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@QAEXXZ
+; CHECK: void __thiscall UUIDType4<&struct __s_GUID const _GUID_12345678_1234_1234_1234_1234567890ab>::bar(void)
\ No newline at end of file




More information about the llvm-commits mailing list