[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