diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index 5aa90395c7d2..fd64edbb9e0d 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -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, const Name *TheName, 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(OutputStream &OS, const TemplateParams &Params, // 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 &OS, NameResolver &Resolver) { } 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 demangleNumber(StringView &MangledName); void memorizeString(StringView s); @@ -1091,21 +1112,21 @@ Type *Demangler::demangleVariableEncoding(StringView &MangledName) { // ::= + @ # when Numbrer == 0 or >= 10 // // ::= [A-P] # A = 0, B = 1, ... -int Demangler::demangleNumber(StringView &MangledName) { - bool neg = MangledName.consumeFront("?"); +std::pair 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 &MangledName) { } 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::demangleLocallyScopedNamePiece(StringView &MangledName) { Name *Node = Arena.alloc(); 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::demangleLocallyScopedNamePiece(StringView &MangledName) { 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(StringView &MangledName) { 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 *Dim = ATy; - for (int I = 0; I < Dimension; ++I) { - Dim->Prim = PrimTy::Array; - Dim->ArrayDimension = demangleNumber(MangledName); - Dim->NextDimension = Arena.alloc(); - Dim = Dim->NextDimension; + ATy->Prim = PrimTy::Array; + ATy->Dims = Arena.alloc(); + 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(); + Dim = Dim->Next; + } } if (MangledName.consumeFront("$$C")) { @@ -1958,7 +1989,6 @@ ArrayType *Demangler::demangleArrayType(StringView &MangledName) { } ATy->ElementType = demangleType(MangledName, QualifierMangleMode::Drop); - Dim->ElementType = ATy->ElementType; return ATy; } @@ -2034,16 +2064,42 @@ Demangler::demangleTemplateParameterList(StringView &MangledName) { // 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); diff --git a/llvm/test/Demangle/ms-templates.test b/llvm/test/Demangle/ms-templates.test new file mode 100644 index 000000000000..ad35953c28e6 --- /dev/null +++ b/llvm/test/Demangle/ms-templates.test @@ -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@VTypename@@@@QAE@XZ +; CHECK: __thiscall Class::Class(void) +??0?$Class@VTypename@@@@QEAA@XZ +; CHECK: __cdecl Class::Class(void) + +??0?$Class@$$CBVTypename@@@@QAE@XZ +; FIXME: __thiscall Class::Class(void) +??0?$Class@$$CBVTypename@@@@QEAA@XZ +; FIXME: __thiscall Class::Class(void) + +??0?$Class@$$CCVTypename@@@@QAE@XZ +; FIXME: __thiscall Class::Class(void) +??0?$Class@$$CCVTypename@@@@QEAA@XZ +; FIXME: __thiscall Class::Class(void) + +??0?$Class@$$CDVTypename@@@@QAE@XZ +; FIXME: __thiscall Class::Class(void) +??0?$Class@$$CDVTypename@@@@QEAA@XZ +; FIXME: __thiscall Class::Class(void) + +??0?$Class@V?$Nested@VTypename@@@@@@QAE@XZ +; CHECK: __thiscall Class>::Class>(void) +??0?$Class@V?$Nested@VTypename@@@@@@QEAA@XZ +; CHECK: __cdecl Class>::Class>(void) + +??0?$Class@QAH@@QAE@XZ +; CHECK: __thiscall Class::Class(void) +??0?$Class@QEAH@@QEAA@XZ +; CHECK: __cdecl Class::Class(void) + +??0?$Class@$$A6AHXZ@@QAE@XZ +; CHECK: __thiscall Class::Class(void) +??0?$Class@$$A6AHXZ@@QEAA@XZ +; CHECK: __cdecl Class::Class(void) + +??0?$Class@$$BY0A@H@@QAE@XZ +; CHECK: __thiscall Class::Class(void) +??0?$Class@$$BY0A@H@@QEAA@XZ +; CHECK: __cdecl Class::Class(void) + +??0?$Class@$$BY04H@@QAE@XZ +; CHECK: __thiscall Class::Class(void) +??0?$Class@$$BY04H@@QEAA@XZ +; CHECK: __cdecl Class::Class(void) + +??0?$Class@$$BY04$$CBH@@QAE@XZ +; CHECK: __thiscall Class::Class(void) +??0?$Class@$$BY04$$CBH@@QEAA@XZ +; CHECK: __cdecl Class::Class(void) + +??0?$Class@$$BY04QAH@@QAE@XZ +; CHECK: __thiscall Class::Class(void) +??0?$Class@$$BY04QEAH@@QEAA@XZ +; CHECK: __cdecl Class::Class(void) + +??0?$BoolTemplate@$0A@@@QAE@XZ +; CHECK: __thiscall BoolTemplate<0>::BoolTemplate<0>(void) +??0?$BoolTemplate@$0A@@@QEAA@XZ +; CHECK: __cdecl BoolTemplate<0>::BoolTemplate<0>(void) + +??0?$BoolTemplate@$00@@QAE@XZ +; CHECK: __thiscall BoolTemplate<1>::BoolTemplate<1>(void) +??0?$BoolTemplate@$00@@QEAA@XZ +; CHECK: __cdecl BoolTemplate<1>::BoolTemplate<1>(void) + +??$Foo@H@?$BoolTemplate@$00@@QAEXH@Z +; CHECK: void __thiscall BoolTemplate<1>::Foo(int) +??$Foo@H@?$BoolTemplate@$00@@QEAAXH@Z +; CHECK: void __cdecl BoolTemplate<1>::Foo(int) + +??0?$IntTemplate@$0A@@@QAE@XZ +; CHECK: __thiscall IntTemplate<0>::IntTemplate<0>(void) +??0?$IntTemplate@$0A@@@QEAA@XZ +; CHECK: __cdecl IntTemplate<0>::IntTemplate<0>(void) + +??0?$IntTemplate@$04@@QAE@XZ +; CHECK: __thiscall IntTemplate<5>::IntTemplate<5>(void) +??0?$IntTemplate@$04@@QEAA@XZ +; CHECK: __cdecl IntTemplate<5>::IntTemplate<5>(void) + +??0?$IntTemplate@$0L@@@QAE@XZ +; CHECK: __thiscall IntTemplate<11>::IntTemplate<11>(void) +??0?$IntTemplate@$0L@@@QEAA@XZ +; CHECK: __cdecl IntTemplate<11>::IntTemplate<11>(void) + +??0?$IntTemplate@$0BAA@@@QAE@XZ +; CHECK: __thiscall IntTemplate<256>::IntTemplate<256>(void) +??0?$IntTemplate@$0BAA@@@QEAA@XZ +; CHECK: __cdecl IntTemplate<256>::IntTemplate<256>(void) + +??0?$IntTemplate@$0CAB@@@QAE@XZ +; CHECK: __thiscall IntTemplate<513>::IntTemplate<513>(void) +??0?$IntTemplate@$0CAB@@@QEAA@XZ +; CHECK: __cdecl IntTemplate<513>::IntTemplate<513>(void) + +??0?$IntTemplate@$0EAC@@@QAE@XZ +; CHECK: __thiscall IntTemplate<1026>::IntTemplate<1026>(void) +??0?$IntTemplate@$0EAC@@@QEAA@XZ +; CHECK: __cdecl IntTemplate<1026>::IntTemplate<1026>(void) + +??0?$IntTemplate@$0PPPP@@@QAE@XZ +; CHECK: __thiscall IntTemplate<65535>::IntTemplate<65535>(void) +??0?$IntTemplate@$0PPPP@@@QEAA@XZ +; CHECK: __cdecl IntTemplate<65535>::IntTemplate<65535>(void) + +??0?$IntTemplate@$0?0@@QAE@XZ +; CHECK: __thiscall IntTemplate<-1>::IntTemplate<-1>(void) +??0?$IntTemplate@$0?0@@QEAA@XZ +; CHECK: __cdecl IntTemplate<-1>::IntTemplate<-1>(void) + +??0?$IntTemplate@$0?8@@QAE@XZ +; CHECK: __thiscall IntTemplate<-9>::IntTemplate<-9>(void) +??0?$IntTemplate@$0?8@@QEAA@XZ +; CHECK: __cdecl IntTemplate<-9>::IntTemplate<-9>(void) + +??0?$IntTemplate@$0?9@@QAE@XZ +; CHECK: __thiscall IntTemplate<-10>::IntTemplate<-10>(void) +??0?$IntTemplate@$0?9@@QEAA@XZ +; CHECK: __cdecl IntTemplate<-10>::IntTemplate<-10>(void) + +??0?$IntTemplate@$0?L@@@QAE@XZ +; CHECK: __thiscall IntTemplate<-11>::IntTemplate<-11>(void) +??0?$IntTemplate@$0?L@@@QEAA@XZ +; CHECK: __cdecl IntTemplate<-11>::IntTemplate<-11>(void) + +??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QAE@XZ +; CHECK: __thiscall UnsignedIntTemplate<4294967295>::UnsignedIntTemplate<4294967295>(void) +??0?$UnsignedIntTemplate@$0PPPPPPPP@@@QEAA@XZ +; CHECK: __cdecl UnsignedIntTemplate<4294967295>::UnsignedIntTemplate<4294967295>(void) + +??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QAE@XZ +; CHECK: __thiscall LongLongTemplate<-9223372036854775808>::LongLongTemplate<-9223372036854775808>(void) +??0?$LongLongTemplate@$0?IAAAAAAAAAAAAAAA@@@QEAA@XZ +; CHECK: __cdecl LongLongTemplate<-9223372036854775808>::LongLongTemplate<-9223372036854775808>(void) + +??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QAE@XZ +; CHECK: __thiscall LongLongTemplate<9223372036854775807>::LongLongTemplate<9223372036854775807>(void) +??0?$LongLongTemplate@$0HPPPPPPPPPPPPPPP@@@QEAA@XZ +; CHECK: __cdecl LongLongTemplate<9223372036854775807>::LongLongTemplate<9223372036854775807>(void) + +; -1 is indistinguishable from uint64_max in this encoding. +??0?$UnsignedLongLongTemplate@$0?0@@QAE@XZ +; CHECK: __thiscall UnsignedLongLongTemplate<-1>::UnsignedLongLongTemplate<-1>(void) +??0?$UnsignedLongLongTemplate@$0?0@@QEAA@XZ +; CHECK: __cdecl UnsignedLongLongTemplate<-1>::UnsignedLongLongTemplate<-1>(void) + +??$foo@H@space@@YAABHABH@Z +; CHECK: int const & __cdecl space::foo(int const &) +??$foo@H@space@@YAAEBHAEBH@Z +; CHECK: int const & __cdecl space::foo(int const &) + +??$FunctionPointerTemplate@$1?spam@@YAXXZ@@YAXXZ +; CHECK: void __cdecl FunctionPointerTemplate<&void __cdecl spam(void)>(void) + +??$variadic_fn_template@HHHH@@YAXABH000@Z +; CHECK: void __cdecl variadic_fn_template(int const &, int const &, int const &, int const &) +??$variadic_fn_template@HHD$$BY01D@@YAXABH0ABDAAY01$$CBD@Z +; CHECK: void __cdecl variadic_fn_template(int const &, int const &, char const &, char const (&)[2] + +??0?$VariadicClass@HD_N@@QAE@XZ +; CHECK: __thiscall VariadicClass::VariadicClass(void) + +??0?$VariadicClass@_NDH@@QAE@XZ +; CHECK: __thiscall VariadicClass::VariadicClass(void) + + +?template_template_fun@@YAXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z +; CHECK: void __cdecl template_template_fun(struct Type, struct Second>) + +??$template_template_specialization@$$A6AXU?$Type@U?$Thing@USecond@@$00@@USecond@@@@@Z@@YAXXZ +; CHECK: void __cdecl template_template_specialization, 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) + +?fun@@YAXU?$UUIDType1@Uuuid@@$1?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z +; CHECK: void __cdecl fun(struct UUIDType1) +?fun@@YAXU?$UUIDType2@Uuuid@@$E?_GUID_12345678_1234_1234_1234_1234567890ab@@3U__s_GUID@@B@@@Z +; CHECK: void __cdecl fun(struct UUIDType2) + +?FunctionDefinedWithInjectedName@@YAXU?$TypeWithFriendDefinition@H@@@Z +; CHECK: void __cdecl FunctionDefinedWithInjectedName(struct TypeWithFriendDefinition) + +?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