diff options
author | Zachary Turner <zturner@google.com> | 2018-08-10 14:31:04 +0000 |
---|---|---|
committer | Zachary Turner <zturner@google.com> | 2018-08-10 14:31:04 +0000 |
commit | dbefc6cd4ee559e2788ed9d1799b8c1b3da812cc (patch) | |
tree | 9b9894b7c74e95a9dc34f8faa424bd69f6712b5f /llvm/lib/Demangle | |
parent | f337f5b7a579cf84a9243b9a96d294228ca63f75 (diff) | |
download | bcm5719-llvm-dbefc6cd4ee559e2788ed9d1799b8c1b3da812cc.tar.gz bcm5719-llvm-dbefc6cd4ee559e2788ed9d1799b8c1b3da812cc.zip |
[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
llvm-svn: 339434
Diffstat (limited to 'llvm/lib/Demangle')
-rw-r--r-- | llvm/lib/Demangle/MicrosoftDemangle.cpp | 124 |
1 files changed, 90 insertions, 34 deletions
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index 5aa90395c7d..fd64edbb9e0 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<uint64_t, bool> demangleNumber(StringView &MangledName); void memorizeString(StringView s); @@ -1091,21 +1112,21 @@ Type *Demangler::demangleVariableEncoding(StringView &MangledName) { // ::= <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 &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<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::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>(); - 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(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); |