summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2018-08-01 18:32:47 +0000
committerZachary Turner <zturner@google.com>2018-08-01 18:32:47 +0000
commit44ebbc216a00dd16ca716e9c0a1871c7badcf85a (patch)
tree8d57fad3aed8111c2620ef82f0c1a2bc70ce0ef8 /llvm
parent54d4ffe554e10a5048f194f48ef252f1978fc515 (diff)
downloadbcm5719-llvm-44ebbc216a00dd16ca716e9c0a1871c7badcf85a.tar.gz
bcm5719-llvm-44ebbc216a00dd16ca716e9c0a1871c7badcf85a.zip
[MS Demangler] Properly demangle templated operators.
After we detected the presence of a template via ?$ we would proceed by only demangling a simple unqualified name. This means we would fail on templated operators (and perhaps other yet-to-be-determined things) This was discovered while doing some refactoring to store richer semantic information about the demangled types to pave the way for overhauling the way we handle backreferences. (Specifically, we need to defer recording or resolving back-references until a symbol has been completely demangled, because we need to use information that only occurs later in the mangled string to decide whether a back-reference should be recorded.) Differential Revision: https://reviews.llvm.org/D50145 llvm-svn: 338608
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Demangle/MicrosoftDemangle.cpp74
-rw-r--r--llvm/test/Demangle/ms-back-references.test4
-rw-r--r--llvm/test/Demangle/ms-mangle.test3
3 files changed, 50 insertions, 31 deletions
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp
index 29f561f22e9..04575818422 100644
--- a/llvm/lib/Demangle/MicrosoftDemangle.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp
@@ -204,6 +204,8 @@ enum FuncClass : uint8_t {
Far = 1 << 6,
};
+enum class SymbolCategory { Function, Variable };
+
namespace {
struct Type;
@@ -265,12 +267,10 @@ struct Name {
// Name read from an MangledName string.
StringView Str;
- // Overloaded operators are represented as special BackReferences in mangled
- // symbols. If this is an operator name, "op" has an operator name (e.g.
- // ">>"). Otherwise, empty.
- StringView Operator;
+ bool IsTemplateInstantiation = false;
+ bool IsOperator = false;
- // Template parameters. Null if not a template.
+ // Template parameters. Only valid if Flags contains NF_TemplateInstantiation.
TemplateParams *TParams = nullptr;
// Nested BackReferences (e.g. "A::B::C") are represented as a linked list.
@@ -541,24 +541,24 @@ static void outputName(OutputStream &OS, const Name *TheName) {
for (; TheName->Next; TheName = TheName->Next) {
Previous = TheName;
OS << TheName->Str;
- if (TheName->TParams)
+ if (TheName->IsTemplateInstantiation)
outputParameterList(OS, *TheName->TParams);
OS << "::";
}
// Print out a regular name.
- if (TheName->Operator.empty()) {
+ if (!TheName->IsOperator) {
OS << TheName->Str;
- if (TheName->TParams)
+ if (TheName->IsTemplateInstantiation)
outputParameterList(OS, *TheName->TParams);
return;
}
// Print out ctor or dtor.
- if (TheName->Operator == "dtor")
+ if (TheName->Str == "dtor")
OS << "~";
- if (TheName->Operator == "ctor" || TheName->Operator == "dtor") {
+ if (TheName->Str == "ctor" || TheName->Str == "dtor") {
OS << Previous->Str;
if (Previous->TParams)
outputParameterList(OS, *Previous->TParams);
@@ -566,9 +566,9 @@ static void outputName(OutputStream &OS, const Name *TheName) {
}
// Print out an overloaded operator.
- if (!TheName->Str.empty())
- OS << TheName->Str << "::";
- OS << "operator" << TheName->Operator;
+ OS << "operator" << TheName->Str;
+ if (TheName->IsTemplateInstantiation)
+ outputParameterList(OS, *TheName->TParams);
}
namespace {
@@ -853,6 +853,8 @@ void ArrayType::outputPost(OutputStream &OS) {
}
struct Symbol {
+ SymbolCategory Category;
+
Name *SymbolName = nullptr;
Type *SymbolType = nullptr;
};
@@ -906,14 +908,14 @@ private:
Name *demangleFullyQualifiedTypeName(StringView &MangledName);
Name *demangleFullyQualifiedSymbolName(StringView &MangledName);
- Name *demangleUnqualifiedTypeName(StringView &MangledName);
- Name *demangleUnqualifiedSymbolName(StringView &MangledName);
+ Name *demangleUnqualifiedTypeName(StringView &MangledName, bool Memorize);
+ Name *demangleUnqualifiedSymbolName(StringView &MangledName, bool Memorize);
Name *demangleNameScopeChain(StringView &MangledName, Name *UnqualifiedName);
Name *demangleNameScopePiece(StringView &MangledName);
Name *demangleBackRefName(StringView &MangledName);
- Name *demangleClassTemplateName(StringView &MangledName);
+ Name *demangleTemplateInstantiationName(StringView &MangledName);
Name *demangleOperatorName(StringView &MangledName);
Name *demangleSimpleName(StringView &MangledName, bool Memorize);
Name *demangleAnonymousNamespaceName(StringView &MangledName);
@@ -981,9 +983,14 @@ Symbol *Demangler::parse(StringView &MangledName) {
if (Error)
return nullptr;
// Read a variable.
- S->SymbolType = startsWithDigit(MangledName)
- ? demangleVariableEncoding(MangledName)
- : demangleFunctionEncoding(MangledName);
+ if (startsWithDigit(MangledName)) {
+ S->Category = SymbolCategory::Variable;
+ S->SymbolType = demangleVariableEncoding(MangledName);
+ } else {
+ S->Category = SymbolCategory::Function;
+ S->SymbolType = demangleFunctionEncoding(MangledName);
+ }
+
if (Error)
return nullptr;
@@ -1101,11 +1108,11 @@ Name *Demangler::demangleBackRefName(StringView &MangledName) {
return Node;
}
-Name *Demangler::demangleClassTemplateName(StringView &MangledName) {
+Name *Demangler::demangleTemplateInstantiationName(StringView &MangledName) {
assert(MangledName.startsWith("?$"));
MangledName.consumeFront("?$");
- Name *Node = demangleSimpleName(MangledName, false);
+ Name *Node = demangleUnqualifiedSymbolName(MangledName, false);
if (Error)
return nullptr;
@@ -1113,6 +1120,8 @@ Name *Demangler::demangleClassTemplateName(StringView &MangledName) {
if (Error)
return nullptr;
+ Node->IsTemplateInstantiation = true;
+
// Render this class template name into a string buffer so that we can
// memorize it for the purpose of back-referencing.
OutputStream OS = OutputStream::create(nullptr, nullptr, 1024);
@@ -1250,7 +1259,8 @@ Name *Demangler::demangleOperatorName(StringView &MangledName) {
};
Name *Node = Arena.alloc<Name>();
- Node->Operator = NameString();
+ Node->Str = NameString();
+ Node->IsOperator = true;
return Node;
}
@@ -1325,7 +1335,7 @@ Name *Demangler::demangleLocallyScopedNamePiece(StringView &MangledName) {
// Parses a type name in the form of A@B@C@@ which represents C::B::A.
Name *Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) {
- Name *TypeName = demangleUnqualifiedTypeName(MangledName);
+ Name *TypeName = demangleUnqualifiedTypeName(MangledName, true);
if (Error)
return nullptr;
assert(TypeName);
@@ -1341,7 +1351,7 @@ Name *Demangler::demangleFullyQualifiedTypeName(StringView &MangledName) {
// Symbol names have slightly different rules regarding what can appear
// so we separate out the implementations for flexibility.
Name *Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) {
- Name *SymbolName = demangleUnqualifiedSymbolName(MangledName);
+ Name *SymbolName = demangleUnqualifiedSymbolName(MangledName, true);
if (Error)
return nullptr;
assert(SymbolName);
@@ -1353,7 +1363,8 @@ Name *Demangler::demangleFullyQualifiedSymbolName(StringView &MangledName) {
return QualName;
}
-Name *Demangler::demangleUnqualifiedTypeName(StringView &MangledName) {
+Name *Demangler::demangleUnqualifiedTypeName(StringView &MangledName,
+ bool Memorize) {
// An inner-most name can be a back-reference, because a fully-qualified name
// (e.g. Scope + Inner) can contain other fully qualified names inside of
// them (for example template parameters), and these nested parameters can
@@ -1362,19 +1373,20 @@ Name *Demangler::demangleUnqualifiedTypeName(StringView &MangledName) {
return demangleBackRefName(MangledName);
if (MangledName.startsWith("?$"))
- return demangleClassTemplateName(MangledName);
+ return demangleTemplateInstantiationName(MangledName);
- return demangleSimpleName(MangledName, true);
+ return demangleSimpleName(MangledName, Memorize);
}
-Name *Demangler::demangleUnqualifiedSymbolName(StringView &MangledName) {
+Name *Demangler::demangleUnqualifiedSymbolName(StringView &MangledName,
+ bool Memorize) {
if (startsWithDigit(MangledName))
return demangleBackRefName(MangledName);
if (MangledName.startsWith("?$"))
- return demangleClassTemplateName(MangledName);
+ return demangleTemplateInstantiationName(MangledName);
if (MangledName.startsWith('?'))
return demangleOperatorName(MangledName);
- return demangleSimpleName(MangledName, true);
+ return demangleSimpleName(MangledName, Memorize);
}
Name *Demangler::demangleNameScopePiece(StringView &MangledName) {
@@ -1382,7 +1394,7 @@ Name *Demangler::demangleNameScopePiece(StringView &MangledName) {
return demangleBackRefName(MangledName);
if (MangledName.startsWith("?$"))
- return demangleClassTemplateName(MangledName);
+ return demangleTemplateInstantiationName(MangledName);
if (MangledName.startsWith("?A"))
return demangleAnonymousNamespaceName(MangledName);
diff --git a/llvm/test/Demangle/ms-back-references.test b/llvm/test/Demangle/ms-back-references.test
index d5ec4736b10..0729a5b8bef 100644
--- a/llvm/test/Demangle/ms-back-references.test
+++ b/llvm/test/Demangle/ms-back-references.test
@@ -51,3 +51,7 @@
?foo@0@YAXXZ
; CHECK: void __cdecl foo::foo(void)
+
+; We have some issues with back-references and class / function templates.
+??$?HH@S@@QEAAAEAU0@H@Z
+; FIXME: struct S &__cdecl S::operator+<int>(int) \ No newline at end of file
diff --git a/llvm/test/Demangle/ms-mangle.test b/llvm/test/Demangle/ms-mangle.test
index 9a2f780f933..981f557a207 100644
--- a/llvm/test/Demangle/ms-mangle.test
+++ b/llvm/test/Demangle/ms-mangle.test
@@ -64,6 +64,9 @@
??Hfoo@@QEAAHH@Z
; CHECK: int __cdecl foo::operator+(int)
+??$?HH@S@@QEAAAEANH@Z
+; CHECK: double & __cdecl S::operator+<int>(int)
+
?static_method@foo@@SAPAV1@XZ
; CHECK: static class foo * __cdecl foo::static_method(void)
OpenPOWER on IntegriCloud