[llvm] r340083 - [MS Demangler] Demangle all remaining types of operators.
Zachary Turner via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 17 14:18:05 PDT 2018
Author: zturner
Date: Fri Aug 17 14:18:05 2018
New Revision: 340083
URL: http://llvm.org/viewvc/llvm-project?rev=340083&view=rev
Log:
[MS Demangler] Demangle all remaining types of operators.
This demangles all remaining special operators including thunks,
RTTI Descriptors, and local static guard variables.
Modified:
llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
llvm/trunk/test/Demangle/ms-operators.test
Modified: llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp?rev=340083&r1=340082&r2=340083&view=diff
==============================================================================
--- llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp (original)
+++ llvm/trunk/lib/Demangle/MicrosoftDemangle.cpp Fri Aug 17 14:18:05 2018
@@ -282,6 +282,8 @@ struct OperatorMapEntry {
OperatorTy Operator;
};
+// The entries here must be in the same order as the enumeration so that it can
+// be indexed by enum value.
OperatorMapEntry OperatorMap[] = {
{"0", " <ctor>", OperatorTy::Ctor},
{"1", " <dtor>", OperatorTy::Dtor},
@@ -347,8 +349,7 @@ OperatorMapEntry OperatorMap[] = {
{"_P", "`udt returning'", OperatorTy::UdtReturning},
{"_Q", "`unknown'", OperatorTy::Unknown},
{"_R0", "`RTTI Type Descriptor'", OperatorTy::RttiTypeDescriptor},
- {"_R1", "`RTTI Base Class Descriptor'",
- OperatorTy::RttiBaseClassDescriptor},
+ {"_R1", "RTTI Base Class Descriptor", OperatorTy::RttiBaseClassDescriptor},
{"_R2", "`RTTI Base Class Array'", OperatorTy::RttiBaseClassArray},
{"_R3", "`RTTI Class Hierarchy Descriptor'",
OperatorTy::RttiClassHierarchyDescriptor},
@@ -364,6 +365,7 @@ OperatorMapEntry OperatorMap[] = {
// Function classes
enum FuncClass : uint16_t {
+ None = 0,
Public = 1 << 0,
Protected = 1 << 1,
Private = 1 << 2,
@@ -373,6 +375,9 @@ enum FuncClass : uint16_t {
Far = 1 << 6,
ExternC = 1 << 7,
NoPrototype = 1 << 8,
+ VirtualThisAdjust = 1 << 9,
+ VirtualThisAdjustEx = 1 << 10,
+ StaticThisAdjust = 1 << 11
};
enum NameBackrefBehavior : uint8_t {
@@ -381,7 +386,14 @@ enum NameBackrefBehavior : uint8_t {
NBB_Simple = 1 << 1, // save simple names.
};
-enum class SymbolCategory { Unknown, Function, Variable };
+enum class SymbolCategory {
+ Unknown,
+ NamedFunction,
+ NamedVariable,
+ UnnamedFunction,
+ UnnamedVariable,
+ SpecialOperator
+};
namespace {
@@ -474,14 +486,46 @@ struct Name {
};
struct OperatorInfo : public Name {
+ explicit OperatorInfo(const OperatorMapEntry &Info) : Info(&Info) {
+ this->IsOperator = true;
+ }
+ explicit OperatorInfo(OperatorTy OpType)
+ : OperatorInfo(OperatorMap[(int)OpType]) {}
+
const OperatorMapEntry *Info = nullptr;
};
struct StringLiteral : public OperatorInfo {
+ StringLiteral() : OperatorInfo(OperatorTy::StringLiteral) {}
+
PrimTy CharType;
bool IsTruncated = false;
};
+struct RttiBaseClassDescriptor : public OperatorInfo {
+ RttiBaseClassDescriptor()
+ : OperatorInfo(OperatorTy::RttiBaseClassDescriptor) {}
+
+ uint32_t NVOffset = 0;
+ int32_t VBPtrOffset = 0;
+ uint32_t VBTableOffset = 0;
+ uint32_t Flags = 0;
+};
+
+struct LocalStaticGuardVariable : public OperatorInfo {
+ LocalStaticGuardVariable() : OperatorInfo(OperatorTy::LocalStaticGuard) {}
+
+ uint32_t ScopeIndex = 0;
+ bool IsVisible = false;
+};
+
+struct VirtualMemberPtrThunk : public OperatorInfo {
+ VirtualMemberPtrThunk() : OperatorInfo(OperatorTy::Vcall) {}
+
+ uint64_t OffsetInVTable = 0;
+ CallingConv CC = CallingConv::Cdecl;
+};
+
struct PointerType : public Type {
Type *clone(ArenaAllocator &Arena) const override;
void outputPre(OutputStream &OS, NameResolver &Resolver) override;
@@ -507,6 +551,13 @@ struct MemberPointerType : public Type {
};
struct FunctionType : public Type {
+ struct ThisAdjustor {
+ uint32_t StaticOffset = 0;
+ int32_t VBPtrOffset = 0;
+ int32_t VBOffsetOffset = 0;
+ int32_t VtordispOffset = 0;
+ };
+
Type *clone(ArenaAllocator &Arena) const override;
void outputPre(OutputStream &OS, NameResolver &Resolver) override;
void outputPost(OutputStream &OS, NameResolver &Resolver) override;
@@ -514,6 +565,7 @@ struct FunctionType : public Type {
// True if this FunctionType instance is the Pointee of a PointerType or
// MemberPointerType.
bool IsFunctionPointer = false;
+ bool IsThunk = false;
Type *ReturnType = nullptr;
// If this is a reference, the type of reference.
@@ -522,6 +574,9 @@ struct FunctionType : public Type {
CallingConv CallConvention;
FuncClass FunctionClass;
+ // Valid if IsThunk is true.
+ ThisAdjustor *ThisAdjust = nullptr;
+
FunctionParams Params;
};
@@ -767,6 +822,23 @@ static void outputParameterList(OutputSt
OS << ">";
}
+static void outputQualifiers(OutputStream &OS, Qualifiers Q) {
+ if (Q & Q_Const) {
+ outputSpaceIfNecessary(OS);
+ OS << "const";
+ }
+
+ if (Q & Q_Volatile) {
+ outputSpaceIfNecessary(OS);
+ OS << "volatile";
+ }
+
+ if (Q & Q_Restrict) {
+ outputSpaceIfNecessary(OS);
+ OS << "__restrict";
+ }
+}
+
static void outputNameComponent(OutputStream &OS, bool IsBackReference,
const TemplateParams *TParams, StringView Str,
NameResolver &Resolver) {
@@ -827,15 +899,27 @@ static void outputName(OutputStream &OS,
OS << "<conversion>";
}
break;
- case OperatorTy::StringLiteral: {
- const StringLiteral &SL = static_cast<const StringLiteral &>(Operator);
- outputStringLiteral(OS, SL);
- break;
- }
case OperatorTy::LiteralOperator:
OS << Operator.Info->Name;
outputNameComponent(OS, *TheName, Resolver);
break;
+ case OperatorTy::RttiBaseClassDescriptor: {
+ const RttiBaseClassDescriptor &BCD =
+ static_cast<const RttiBaseClassDescriptor &>(Operator);
+ OS << "`" << Operator.Info->Name << " at (";
+ OS << BCD.NVOffset << ", " << BCD.VBPtrOffset << ", " << BCD.VBTableOffset
+ << ", " << BCD.Flags;
+ OS << ")'";
+ break;
+ }
+ case OperatorTy::LocalStaticGuard: {
+ const LocalStaticGuardVariable &LSG =
+ static_cast<const LocalStaticGuardVariable &>(Operator);
+ OS << Operator.Info->Name;
+ if (LSG.ScopeIndex > 0)
+ OS << "{" << LSG.ScopeIndex << "}";
+ break;
+ }
default:
OS << Operator.Info->Name;
if (Operator.IsTemplateInstantiation)
@@ -844,6 +928,45 @@ static void outputName(OutputStream &OS,
}
}
+static void outputSpecialOperator(OutputStream &OS, const Name *OuterName,
+ NameResolver &Resolver) {
+ assert(OuterName);
+ // The last component should be an operator.
+ const Name *LastComponent = OuterName;
+ while (LastComponent->Next)
+ LastComponent = LastComponent->Next;
+
+ assert(LastComponent->IsOperator);
+ const OperatorInfo &Oper = static_cast<const OperatorInfo &>(*LastComponent);
+ switch (Oper.Info->Operator) {
+ case OperatorTy::StringLiteral: {
+ const StringLiteral &SL = static_cast<const StringLiteral &>(Oper);
+ outputStringLiteral(OS, SL);
+ break;
+ }
+ case OperatorTy::Vcall: {
+ // [thunk]: __cdecl Base::`vcall'{8, {flat}}' }'
+ const VirtualMemberPtrThunk &Thunk =
+ static_cast<const VirtualMemberPtrThunk &>(Oper);
+ OS << "[thunk]: ";
+ outputCallingConvention(OS, Thunk.CC);
+ OS << " ";
+ // Print out namespaces or outer class BackReferences.
+ const Name *N = OuterName;
+ for (; N->Next; N = N->Next) {
+ outputNameComponent(OS, *N, Resolver);
+ OS << "::";
+ }
+ OS << "`vcall'{";
+ OS << Thunk.OffsetInVTable << ", {flat}}";
+ break;
+ }
+ default:
+ // There are no other special operator categories.
+ LLVM_BUILTIN_UNREACHABLE;
+ }
+}
+
namespace {
bool Name::isStringLiteralOperatorInfo() const {
@@ -877,20 +1000,7 @@ void Type::outputPre(OutputStream &OS, T
}
Ty.outputPre(OS, Resolver);
- if (Ty.Quals & Q_Const) {
- outputSpaceIfNecessary(OS);
- OS << "const";
- }
-
- if (Ty.Quals & Q_Volatile) {
- outputSpaceIfNecessary(OS);
- OS << "volatile";
- }
-
- if (Ty.Quals & Q_Restrict) {
- outputSpaceIfNecessary(OS);
- OS << "__restrict";
- }
+ outputQualifiers(OS, Ty.Quals);
}
// Write the "second half" of a given type.
@@ -1054,6 +1164,9 @@ Type *FunctionType::clone(ArenaAllocator
}
void FunctionType::outputPre(OutputStream &OS, NameResolver &Resolver) {
+ if ((FunctionClass & StaticThisAdjust) || (FunctionClass & VirtualThisAdjust))
+ OS << "[thunk]: ";
+
if (!(FunctionClass & Global)) {
if (FunctionClass & Static)
OS << "static ";
@@ -1081,6 +1194,11 @@ void FunctionType::outputPost(OutputStre
if (FunctionClass & NoPrototype)
return;
+ if (FunctionClass & VirtualThisAdjust) {
+ OS << "`vtordisp{" << ThisAdjust->VtordispOffset << ", "
+ << ThisAdjust->StaticOffset << "}'";
+ }
+
OS << "(";
outputParameterList(OS, Params, Resolver);
OS << ")";
@@ -1152,6 +1270,7 @@ void ArrayType::outputPost(OutputStream
struct Symbol {
SymbolCategory Category;
+ Qualifiers SymbolQuals = Q_None;
Name *SymbolName = nullptr;
Type *SymbolType = nullptr;
};
@@ -1183,6 +1302,8 @@ public:
// You are supposed to call parse() first and then check if error is true. If
// it is false, call output() to write the formatted name to the given stream.
Symbol *parse(StringView &MangledName);
+ Symbol *parseOperator(StringView &MangledName);
+
void output(const Symbol *S, OutputStream &OS);
StringView resolve(StringView N) override;
@@ -1193,9 +1314,12 @@ public:
void dumpBackReferences();
private:
- Type *demangleVariableEncoding(StringView &MangledName);
+ std::pair<SymbolCategory, Type *>
+ demangleSymbolCategoryAndType(StringView &MangledName);
+
+ Type *demangleVariableEncoding(StringView &MangledName, StorageClass SC);
Type *demangleFunctionEncoding(StringView &MangledName);
- Type *demangleVtableEncoding(StringView &MangledName);
+ uint64_t demangleThunkThisAdjust(StringView &MangledName);
Qualifiers demanglePointerExtQualifiers(StringView &MangledName);
@@ -1214,6 +1338,8 @@ private:
FunctionParams demangleFunctionParameterList(StringView &MangledName);
std::pair<uint64_t, bool> demangleNumber(StringView &MangledName);
+ uint64_t demangleUnsigned(StringView &MangledName);
+ int64_t demangleSigned(StringView &MangledName);
void memorizeString(StringView s);
@@ -1233,7 +1359,8 @@ private:
Name *demangleBackRefName(StringView &MangledName);
Name *demangleTemplateInstantiationName(StringView &MangledName,
NameBackrefBehavior NBB);
- OperatorInfo *demangleOperatorName(StringView &MangledName);
+ std::pair<OperatorTy, Name *> demangleOperatorName(StringView &MangledName,
+ bool FullyQualified);
Name *demangleSimpleName(StringView &MangledName, bool Memorize);
Name *demangleAnonymousNamespaceName(StringView &MangledName);
Name *demangleLocallyScopedNamePiece(StringView &MangledName);
@@ -1278,12 +1405,86 @@ StringView Demangler::copyString(StringV
return {Stable, Borrowed.size()};
}
-// Parser entry point.
-Symbol *Demangler::parse(StringView &MangledName) {
+Symbol *Demangler::parseOperator(StringView &MangledName) {
Symbol *S = Arena.alloc<Symbol>();
+ bool IsMember = false;
+ OperatorTy OTy;
+ std::tie(OTy, S->SymbolName) = demangleOperatorName(MangledName, true);
+ switch (OTy) {
+ case OperatorTy::StringLiteral:
+ case OperatorTy::Vcall:
+ S->Category = SymbolCategory::SpecialOperator;
+ break;
+ case OperatorTy::Vftable: // Foo@@6B@
+ case OperatorTy::LocalVftable: // Foo@@6B@
+ case OperatorTy::RttiCompleteObjLocator: // Foo@@6B@
+ case OperatorTy::Vbtable: // Foo@@7B@
+ S->Category = SymbolCategory::UnnamedVariable;
+ switch (MangledName.popFront()) {
+ case '6':
+ case '7':
+ std::tie(S->SymbolQuals, IsMember) = demangleQualifiers(MangledName);
+ if (!MangledName.consumeFront('@'))
+ Error = true;
+ break;
+ default:
+ Error = true;
+ break;
+ }
+ break;
+ case OperatorTy::RttiTypeDescriptor: // <type>@@8
+ S->Category = SymbolCategory::UnnamedVariable;
+ S->SymbolType = demangleType(MangledName, QualifierMangleMode::Result);
+ if (Error)
+ break;
+ if (!MangledName.consumeFront("@8"))
+ Error = true;
+ if (!MangledName.empty())
+ Error = true;
+ break;
+ case OperatorTy::LocalStaticGuard: {
+ S->Category = SymbolCategory::UnnamedVariable;
+ break;
+ }
+ default:
+ if (!Error)
+ std::tie(S->Category, S->SymbolType) =
+ demangleSymbolCategoryAndType(MangledName);
+ break;
+ }
+
+ return (Error) ? nullptr : S;
+}
+
+std::pair<SymbolCategory, Type *>
+Demangler::demangleSymbolCategoryAndType(StringView &MangledName) {
+ // Read a variable.
+ switch (MangledName.front()) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ return std::make_pair(
+ SymbolCategory::NamedVariable,
+ demangleVariableEncoding(MangledName,
+ demangleVariableStorageClass(MangledName)));
+ case '8':
+ MangledName.consumeFront('8');
+ return std::pair<SymbolCategory, Type *>(SymbolCategory::UnnamedVariable,
+ nullptr);
+ }
+ return std::make_pair(SymbolCategory::NamedFunction,
+ demangleFunctionEncoding(MangledName));
+}
+
+// Parser entry point.
+Symbol *Demangler::parse(StringView &MangledName) {
// We can't demangle MD5 names, just output them as-is.
- if (MangledName.startsWith("??@")) {
+ // Also, MSVC-style mangled symbols must start with '?'.
+ if (MangledName.startsWith("??@") || !MangledName.startsWith('?')) {
+ Symbol *S = Arena.alloc<Symbol>();
S->Category = SymbolCategory::Unknown;
S->SymbolName = Arena.alloc<Name>();
S->SymbolName->Str = MangledName;
@@ -1292,43 +1493,22 @@ Symbol *Demangler::parse(StringView &Man
return S;
}
- // MSVC-style mangled symbols must start with '?'.
- if (!MangledName.consumeFront("?")) {
- S->Category = SymbolCategory::Unknown;
- S->SymbolName = Arena.alloc<Name>();
- S->SymbolName->Str = MangledName;
- S->SymbolType = nullptr;
- return S;
- }
+ MangledName.consumeFront('?');
+
+ // ?$ is a template instantiation, but all other names that start with ? are
+ // operators / special names.
+ if (MangledName.startsWith('?') && !MangledName.startsWith("?$"))
+ return parseOperator(MangledName);
- // What follows is a main symbol name. This may include
- // namespaces or class BackReferences.
+ Symbol *S = Arena.alloc<Symbol>();
+ // What follows is a main symbol name. This may include namespaces or class
+ // back references.
S->SymbolName = demangleFullyQualifiedSymbolName(MangledName);
if (Error)
return nullptr;
- if (S->SymbolName->isStringLiteralOperatorInfo())
- return S;
-
- // Read a variable.
- switch (MangledName.front()) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- S->Category = SymbolCategory::Variable;
- S->SymbolType = demangleVariableEncoding(MangledName);
- break;
- case '6':
- case '7':
- S->Category = SymbolCategory::Variable;
- S->SymbolType = demangleVtableEncoding(MangledName);
- break;
- default:
- S->Category = SymbolCategory::Function;
- S->SymbolType = demangleFunctionEncoding(MangledName);
- }
+ std::tie(S->Category, S->SymbolType) =
+ demangleSymbolCategoryAndType(MangledName);
if (Error)
return nullptr;
@@ -1336,23 +1516,6 @@ Symbol *Demangler::parse(StringView &Man
return S;
}
-Type *Demangler::demangleVtableEncoding(StringView &MangledName) {
- Type *Ty = Arena.alloc<Type>();
- switch (MangledName.popFront()) {
- case '6':
- Ty->Prim = PrimTy::Vftable;
- break;
- case '7':
- Ty->Prim = PrimTy::Vbtable;
- break;
- }
- bool IsMember = false;
- std::tie(Ty->Quals, IsMember) = demangleQualifiers(MangledName);
- Ty->Storage = StorageClass::None;
- MangledName.consumeFront('@');
- return Ty;
-}
-
// <type-encoding> ::= <storage-class> <variable-type>
// <storage-class> ::= 0 # private static member
// ::= 1 # protected static member
@@ -1360,9 +1523,8 @@ Type *Demangler::demangleVtableEncoding(
// ::= 3 # global
// ::= 4 # static local
-Type *Demangler::demangleVariableEncoding(StringView &MangledName) {
- StorageClass SC = demangleVariableStorageClass(MangledName);
-
+Type *Demangler::demangleVariableEncoding(StringView &MangledName,
+ StorageClass SC) {
Type *Ty = demangleType(MangledName, QualifierMangleMode::Drop);
Ty->Storage = SC;
@@ -1438,6 +1600,25 @@ std::pair<uint64_t, bool> Demangler::dem
return {0ULL, false};
}
+uint64_t Demangler::demangleUnsigned(StringView &MangledName) {
+ bool IsNegative = false;
+ uint64_t Number = 0;
+ std::tie(Number, IsNegative) = demangleNumber(MangledName);
+ if (IsNegative)
+ Error = true;
+ return Number;
+}
+
+int64_t Demangler::demangleSigned(StringView &MangledName) {
+ bool IsNegative = false;
+ uint64_t Number = 0;
+ std::tie(Number, IsNegative) = demangleNumber(MangledName);
+ if (Number > INT64_MAX)
+ Error = true;
+ int64_t I = static_cast<int64_t>(Number);
+ return IsNegative ? -I : I;
+}
+
// First 10 strings can be referenced by special BackReferences ?0, ?1, ..., ?9.
// Memorize it.
void Demangler::memorizeString(StringView S) {
@@ -1492,7 +1673,8 @@ Name *Demangler::demangleTemplateInstant
return Node;
}
-OperatorInfo *Demangler::demangleOperatorName(StringView &MangledName) {
+std::pair<OperatorTy, Name *>
+Demangler::demangleOperatorName(StringView &MangledName, bool FullyQualified) {
assert(MangledName.startsWith('?'));
MangledName.consumeFront('?');
@@ -1505,28 +1687,77 @@ OperatorInfo *Demangler::demangleOperato
}
if (!Entry) {
Error = true;
- return nullptr;
+ return std::make_pair(OperatorTy::Unknown, nullptr);
}
- OperatorInfo *Oper = nullptr;
+ Name *N = nullptr;
switch (Entry->Operator) {
+ case OperatorTy::Vftable: // Foo@@6B@
+ case OperatorTy::LocalVftable: // Foo@@6B@
+ case OperatorTy::RttiCompleteObjLocator: // Foo@@6B@
+ case OperatorTy::Vbtable: { // Foo@@7B@
+ OperatorInfo *Oper = Arena.alloc<OperatorInfo>(*Entry);
+ N = (FullyQualified) ? demangleNameScopeChain(MangledName, Oper) : Oper;
+ break;
+ }
+
case OperatorTy::StringLiteral:
- Oper = demangleStringLiteral(MangledName);
+ N = demangleStringLiteral(MangledName);
break;
case OperatorTy::LiteralOperator:
- Oper = Arena.alloc<OperatorInfo>();
- Oper->Str = demangleSimpleString(MangledName, false);
+ N = Arena.alloc<OperatorInfo>(*Entry);
+ N->Str = demangleSimpleString(MangledName, false);
+ if (!MangledName.consumeFront('@'))
+ Error = true;
break;
+ case OperatorTy::RttiBaseClassDescriptor: {
+ RttiBaseClassDescriptor *Temp = Arena.alloc<RttiBaseClassDescriptor>();
+ Temp->NVOffset = demangleUnsigned(MangledName);
+ Temp->VBPtrOffset = demangleSigned(MangledName);
+ Temp->VBTableOffset = demangleUnsigned(MangledName);
+ Temp->Flags = demangleUnsigned(MangledName);
+ N = (FullyQualified) ? demangleNameScopeChain(MangledName, Temp) : Temp;
+ break;
+ }
+ case OperatorTy::Vcall: {
+ VirtualMemberPtrThunk *Temp = Arena.alloc<VirtualMemberPtrThunk>();
+ N = demangleNameScopeChain(MangledName, Temp);
+ if (Error)
+ break;
+ if (!MangledName.consumeFront("$B"))
+ Error = true;
+ Temp->OffsetInVTable = demangleUnsigned(MangledName);
+ if (!MangledName.consumeFront('A'))
+ Error = true;
+ Temp->CC = demangleCallingConvention(MangledName);
+ break;
+ }
+ case OperatorTy::RttiTypeDescriptor:
+ // This one is just followed by a type, not a name scope.
+ N = Arena.alloc<OperatorInfo>(*Entry);
+ break;
+ case OperatorTy::LocalStaticGuard: {
+ LocalStaticGuardVariable *Temp = Arena.alloc<LocalStaticGuardVariable>();
+ N = (FullyQualified) ? demangleNameScopeChain(MangledName, Temp) : Temp;
+ if (MangledName.consumeFront("4IA"))
+ Temp->IsVisible = false;
+ else if (MangledName.consumeFront("5"))
+ Temp->IsVisible = true;
+ else
+ Error = true;
+ if (!MangledName.empty())
+ Temp->ScopeIndex = demangleUnsigned(MangledName);
+ break;
+ }
default:
- Oper = Arena.alloc<OperatorInfo>();
+ N = Arena.alloc<OperatorInfo>(*Entry);
+ N = (FullyQualified) ? demangleNameScopeChain(MangledName, N) : N;
+ break;
}
-
- Oper->Info = Entry;
- Oper->IsOperator = true;
if (Error)
- return nullptr;
+ return std::make_pair(OperatorTy::Unknown, nullptr);
- return Oper;
+ return std::make_pair(Entry->Operator, N);
}
Name *Demangler::demangleSimpleName(StringView &MangledName, bool Memorize) {
@@ -1956,11 +2187,6 @@ Name *Demangler::demangleFullyQualifiedS
if (Error)
return nullptr;
- // This is a special case that isn't followed by a scope.
- assert(SymbolName);
- if (SymbolName->isStringLiteralOperatorInfo())
- return SymbolName;
-
Name *QualName = demangleNameScopeChain(MangledName, SymbolName);
if (Error)
return nullptr;
@@ -1990,7 +2216,7 @@ Name *Demangler::demangleUnqualifiedSymb
if (MangledName.startsWith("?$"))
return demangleTemplateInstantiationName(MangledName, NBB);
if (MangledName.startsWith('?'))
- return demangleOperatorName(MangledName);
+ return demangleOperatorName(MangledName, false).second;
return demangleSimpleName(MangledName, (NBB & NBB_Simple) != 0);
}
@@ -2035,53 +2261,77 @@ FuncClass Demangler::demangleFunctionCla
SwapAndRestore<StringView> RestoreOnError(MangledName, MangledName);
RestoreOnError.shouldRestore(false);
- FuncClass TempFlags = FuncClass(0);
- if (MangledName.consumeFront("$$J0"))
- TempFlags = ExternC;
-
switch (MangledName.popFront()) {
case '9':
- return FuncClass(TempFlags | ExternC | NoPrototype);
+ return FuncClass(ExternC | NoPrototype);
case 'A':
return Private;
case 'B':
- return FuncClass(TempFlags | Private | Far);
+ return FuncClass(Private | Far);
case 'C':
- return FuncClass(TempFlags | Private | Static);
+ return FuncClass(Private | Static);
case 'D':
- return FuncClass(TempFlags | Private | Static);
+ return FuncClass(Private | Static);
case 'E':
- return FuncClass(TempFlags | Private | Virtual);
+ return FuncClass(Private | Virtual);
case 'F':
- return FuncClass(TempFlags | Private | Virtual);
+ return FuncClass(Private | Virtual);
case 'I':
- return FuncClass(TempFlags | Protected);
+ return FuncClass(Protected);
case 'J':
- return FuncClass(TempFlags | Protected | Far);
+ return FuncClass(Protected | Far);
case 'K':
- return FuncClass(TempFlags | Protected | Static);
+ return FuncClass(Protected | Static);
case 'L':
- return FuncClass(TempFlags | Protected | Static | Far);
+ return FuncClass(Protected | Static | Far);
case 'M':
- return FuncClass(TempFlags | Protected | Virtual);
+ return FuncClass(Protected | Virtual);
case 'N':
- return FuncClass(TempFlags | Protected | Virtual | Far);
+ return FuncClass(Protected | Virtual | Far);
+ case 'O':
+ return FuncClass(Protected | Virtual | StaticThisAdjust);
+ case 'P':
+ return FuncClass(Protected | Virtual | StaticThisAdjust | Far);
case 'Q':
- return FuncClass(TempFlags | Public);
+ return FuncClass(Public);
case 'R':
- return FuncClass(TempFlags | Public | Far);
+ return FuncClass(Public | Far);
case 'S':
- return FuncClass(TempFlags | Public | Static);
+ return FuncClass(Public | Static);
case 'T':
- return FuncClass(TempFlags | Public | Static | Far);
+ return FuncClass(Public | Static | Far);
case 'U':
- return FuncClass(TempFlags | Public | Virtual);
+ return FuncClass(Public | Virtual);
case 'V':
- return FuncClass(TempFlags | Public | Virtual | Far);
+ return FuncClass(Public | Virtual | Far);
+ case 'W':
+ return FuncClass(Public | Virtual | StaticThisAdjust);
+ case 'X':
+ return FuncClass(Public | Virtual | StaticThisAdjust | Far);
case 'Y':
- return FuncClass(TempFlags | Global);
+ return FuncClass(Global);
case 'Z':
- return FuncClass(TempFlags | Global | Far);
+ return FuncClass(Global | Far);
+ case '$': {
+ FuncClass VFlag = VirtualThisAdjust;
+ if (MangledName.consumeFront('R'))
+ VFlag = FuncClass(VFlag | VirtualThisAdjustEx);
+
+ switch (MangledName.popFront()) {
+ case '0':
+ return FuncClass(Private | Virtual | VFlag);
+ case '1':
+ return FuncClass(Private | Virtual | VFlag | Far);
+ case '2':
+ return FuncClass(Protected | Virtual | VFlag);
+ case '3':
+ return FuncClass(Protected | Virtual | VFlag | Far);
+ case '4':
+ return FuncClass(Public | Virtual | VFlag);
+ case '5':
+ return FuncClass(Public | Virtual | VFlag | Far);
+ }
+ }
}
Error = true;
@@ -2291,7 +2541,27 @@ FunctionType *Demangler::demangleFunctio
}
Type *Demangler::demangleFunctionEncoding(StringView &MangledName) {
+ FuncClass ExtraFlags = FuncClass::None;
+ if (MangledName.consumeFront("$$J0"))
+ ExtraFlags = FuncClass::ExternC;
+
FuncClass FC = demangleFunctionClass(MangledName);
+ FC = FuncClass(ExtraFlags | FC);
+
+ FunctionType::ThisAdjustor *Adjustor = nullptr;
+ if (FC & FuncClass::StaticThisAdjust) {
+ Adjustor = Arena.alloc<FunctionType::ThisAdjustor>();
+ Adjustor->StaticOffset = demangleSigned(MangledName);
+ } else if (FC & FuncClass::VirtualThisAdjust) {
+ Adjustor = Arena.alloc<FunctionType::ThisAdjustor>();
+ if (FC & FuncClass::VirtualThisAdjustEx) {
+ Adjustor->VBPtrOffset = demangleSigned(MangledName);
+ Adjustor->VBOffsetOffset = demangleSigned(MangledName);
+ }
+ Adjustor->VtordispOffset = demangleSigned(MangledName);
+ Adjustor->StaticOffset = demangleSigned(MangledName);
+ }
+
FunctionType *FTy = nullptr;
if (FC & NoPrototype) {
// This is an extern "C" function whose full signature hasn't been mangled.
@@ -2302,6 +2572,7 @@ Type *Demangler::demangleFunctionEncodin
bool HasThisQuals = !(FC & (Global | Static));
FTy = demangleFunctionType(MangledName, HasThisQuals, false);
}
+ FTy->ThisAdjust = Adjustor;
FTy->FunctionClass = FC;
return FTy;
@@ -2694,6 +2965,11 @@ void Demangler::output(const Symbol *S,
return;
}
+ if (S->Category == SymbolCategory::SpecialOperator) {
+ outputSpecialOperator(OS, S->SymbolName, *this);
+ return;
+ }
+
// Converts an AST to a string.
//
// Converting an AST representing a C++ type to a string is tricky due
@@ -2715,8 +2991,10 @@ void Demangler::output(const Symbol *S,
Type::outputPre(OS, *S->SymbolType, *this);
outputName(OS, S->SymbolName, S->SymbolType, *this);
Type::outputPost(OS, *S->SymbolType, *this);
- } else
+ } else {
+ outputQualifiers(OS, S->SymbolQuals);
outputName(OS, S->SymbolName, nullptr, *this);
+ }
}
void Demangler::dumpBackReferences() {
Modified: llvm/trunk/test/Demangle/ms-operators.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Demangle/ms-operators.test?rev=340083&r1=340082&r2=340083&view=diff
==============================================================================
--- llvm/trunk/test/Demangle/ms-operators.test (original)
+++ llvm/trunk/test/Demangle/ms-operators.test Fri Aug 17 14:18:05 2018
@@ -143,11 +143,11 @@
??_8Middle2@@7B@
; CHECK: const Middle2::`vbtable'
-; ??_9Base@@$B7AA
-; FIXME: [thunk]: __cdecl Base::`vcall'{8, {flat}}' }'
+??_9Base@@$B7AA
+; CHECK: [thunk]: __cdecl Base::`vcall'{8, {flat}}
-; ??_B?1??getS@@YAAAUS@@XZ at 51
-; FIXME: `struct S & __cdecl getS(void)'::`2'::`local static guard'{2}'
+??_B?1??getS@@YAAAUS@@XZ at 51
+; CHECK: `struct S & __cdecl getS(void)'::`2'::`local static guard'{2}
??_C at _02PCEFGMJL@hi?$AA@
; CHECK: const char * {"hi"}
@@ -158,8 +158,8 @@
??_EBase@@UEAAPEAXI at Z
; CHECK: virtual void * __cdecl Base::`vector deleting dtor'(unsigned int)
-; ??_EDerived@@$4PPPPPPPM at A@EAAPEAXI at Z
-; FIXME: [thunk]:virtual void * __cdecl Derived::`vector deleting dtor'`vtordisp{4294967292, 0}' (unsigned int)
+??_EDerived@@$4PPPPPPPM at A@EAAPEAXI at Z
+; CHECK: [thunk]: virtual void * __cdecl Derived::`vector deleting dtor'`vtordisp{-4, 0}'(unsigned int)
??_F?$SomeTemplate at H@@QAEXXZ
; CHECK: void __thiscall SomeTemplate<int>::`default ctor closure'(void)
@@ -203,17 +203,17 @@
??_V at YAXPEAXAEAVklass@@@Z
; CHECK: void __cdecl operator delete[](void *, class klass &)
-; ??_R0?AUBase@@@8
-; FIXME: struct Base `RTTI Type Descriptor'
+??_R0?AUBase@@@8
+; CHECK: struct Base `RTTI Type Descriptor'
-; ??_R1A@?0A at EA@Base@@8
-; FIXME: Base::`RTTI Base Class Descriptor at (0, -1, 0, 64)'
+??_R1A@?0A at EA@Base@@8
+; CHECK: Base::`RTTI Base Class Descriptor at (0, -1, 0, 64)'
-; ??_R2Base@@8
-; FIXME: Base::`RTTI Base Class Array'
+??_R2Base@@8
+; CHECK: Base::`RTTI Base Class Array'
-; ??_R3Base@@8
-; FIXME: Base::`RTTI Class Hierarchy Descriptor'
+??_R3Base@@8
+; CHECK: Base::`RTTI Class Hierarchy Descriptor'
??_R4Base@@6B@
; CHECK: const Base::`RTTI Complete Object Locator'
More information about the llvm-commits
mailing list