summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Demangle/MicrosoftDemangle.cpp136
-rw-r--r--llvm/lib/Demangle/StringView.h2
2 files changed, 92 insertions, 46 deletions
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp
index b6eaa4b7fe7..1bf94ff8469 100644
--- a/llvm/lib/Demangle/MicrosoftDemangle.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp
@@ -187,6 +187,8 @@ struct Type;
// Represents a list of parameters (template params or function arguments.
// It's represented as a linked list.
struct ParamList {
+ bool IsVariadic = false;
+
Type *Current = nullptr;
ParamList *Next = nullptr;
@@ -382,6 +384,11 @@ static void outputCallingConvention(OutputStream &OS, CallingConv CC) {
// Write a function or template parameter list.
static void outputParameterList(OutputStream &OS, const ParamList &Params) {
+ if (!Params.Current) {
+ OS << "void";
+ return;
+ }
+
const ParamList *Head = &Params;
while (Head) {
Type::outputPre(OS, *Head->Current);
@@ -621,8 +628,10 @@ void FunctionType::outputPre(OutputStream &OS) {
OS << "static ";
}
- if (ReturnType)
+ if (ReturnType) {
Type::outputPre(OS, *ReturnType);
+ OS << " ";
+ }
outputCallingConvention(OS, CallConvention);
}
@@ -635,6 +644,9 @@ void FunctionType::outputPost(OutputStream &OS) {
OS << " const";
if (Quals & Q_Volatile)
OS << " volatile";
+
+ if (ReturnType)
+ Type::outputPost(OS, *ReturnType);
return;
}
@@ -711,6 +723,7 @@ private:
UdtType *demangleClassType();
PointerType *demanglePointerType();
MemberPointerType *demangleMemberPointerType();
+ FunctionType *demangleFunctionType(bool HasThisQuals);
ArrayType *demangleArrayType();
@@ -724,10 +737,11 @@ private:
Name *demangleName();
void demangleOperator(Name *);
StringView demangleOperatorName();
- int demangleFunctionClass();
+ FuncClass demangleFunctionClass();
CallingConv demangleCallingConvention();
StorageClass demangleVariableStorageClass();
ReferenceKind demangleReferenceKind();
+ void demangleThrowSpecification();
std::pair<Qualifiers, bool> demangleQualifiers();
@@ -904,10 +918,6 @@ void Demangler::demangleNamePiece(Name &Node, bool IsHead) {
// Class template.
Node.Str = demangleString(false);
Node.TemplateParams = demangleParameterList();
- if (!MangledName.consumeFront('@')) {
- Error = true;
- return;
- }
} else if (!IsHead && MangledName.consumeFront("?A")) {
// Anonymous namespace starts with ?A. So does overloaded operator[],
// but the distinguishing factor is that namespace themselves are not
@@ -1067,7 +1077,7 @@ StringView Demangler::demangleOperatorName() {
return "";
}
-int Demangler::demangleFunctionClass() {
+FuncClass Demangler::demangleFunctionClass() {
SwapAndRestore<StringView> RestoreOnError(MangledName, MangledName);
RestoreOnError.shouldRestore(false);
@@ -1075,48 +1085,48 @@ int Demangler::demangleFunctionClass() {
case 'A':
return Private;
case 'B':
- return Private | Far;
+ return FuncClass(Private | Far);
case 'C':
- return Private | Static;
+ return FuncClass(Private | Static);
case 'D':
- return Private | Static;
+ return FuncClass(Private | Static);
case 'E':
- return Private | Virtual;
+ return FuncClass(Private | Virtual);
case 'F':
- return Private | Virtual;
+ return FuncClass(Private | Virtual);
case 'I':
return Protected;
case 'J':
- return Protected | Far;
+ return FuncClass(Protected | Far);
case 'K':
- return Protected | Static;
+ return FuncClass(Protected | Static);
case 'L':
- return Protected | Static | Far;
+ return FuncClass(Protected | Static | Far);
case 'M':
- return Protected | Virtual;
+ return FuncClass(Protected | Virtual);
case 'N':
- return Protected | Virtual | Far;
+ return FuncClass(Protected | Virtual | Far);
case 'Q':
return Public;
case 'R':
- return Public | Far;
+ return FuncClass(Public | Far);
case 'S':
- return Public | Static;
+ return FuncClass(Public | Static);
case 'T':
- return Public | Static | Far;
+ return FuncClass(Public | Static | Far);
case 'U':
- return Public | Virtual;
+ return FuncClass(Public | Virtual);
case 'V':
- return Public | Virtual | Far;
+ return FuncClass(Public | Virtual | Far);
case 'Y':
return Global;
case 'Z':
- return Global | Far;
+ return FuncClass(Global | Far);
}
Error = true;
RestoreOnError.shouldRestore(true);
- return 0;
+ return Public;
}
CallingConv Demangler::demangleCallingConvention() {
@@ -1241,15 +1251,6 @@ Type *Demangler::demangleType(QualifierMangleMode QMM) {
return Ty;
}
-static bool functionHasThisPtr(const FunctionType &Ty) {
- assert(Ty.Prim == PrimTy::Function);
- if (Ty.FunctionClass & Global)
- return false;
- if (Ty.FunctionClass & Static)
- return false;
- return true;
-}
-
ReferenceKind Demangler::demangleReferenceKind() {
if (MangledName.consumeFront('G'))
return ReferenceKind::LValueRef;
@@ -1258,12 +1259,18 @@ ReferenceKind Demangler::demangleReferenceKind() {
return ReferenceKind::None;
}
-Type *Demangler::demangleFunctionEncoding() {
- FunctionType *FTy = Arena.alloc<FunctionType>();
+void Demangler::demangleThrowSpecification() {
+ if (MangledName.consumeFront('Z'))
+ return;
+ Error = true;
+}
+
+FunctionType *Demangler::demangleFunctionType(bool HasThisQuals) {
+ FunctionType *FTy = Arena.alloc<FunctionType>();
FTy->Prim = PrimTy::Function;
- FTy->FunctionClass = (FuncClass)demangleFunctionClass();
- if (functionHasThisPtr(*FTy)) {
+
+ if (HasThisQuals) {
FTy->Quals = demanglePointerExtQualifiers();
FTy->RefKind = demangleReferenceKind();
FTy->Quals = Qualifiers(FTy->Quals | demangleQualifiers().first);
@@ -1280,6 +1287,18 @@ Type *Demangler::demangleFunctionEncoding() {
FTy->Params = demangleParameterList();
+ demangleThrowSpecification();
+
+ return FTy;
+}
+
+Type *Demangler::demangleFunctionEncoding() {
+ FuncClass FC = demangleFunctionClass();
+
+ bool HasThisQuals = !(FC & (Global | Static));
+ FunctionType *FTy = demangleFunctionType(HasThisQuals);
+ FTy->FunctionClass = FC;
+
return FTy;
}
@@ -1445,14 +1464,20 @@ MemberPointerType *Demangler::demangleMemberPointerType() {
Qualifiers ExtQuals = demanglePointerExtQualifiers();
Pointer->Quals = Qualifiers(Pointer->Quals | ExtQuals);
- Qualifiers PointeeQuals = Q_None;
- bool IsMember = false;
- std::tie(PointeeQuals, IsMember) = demangleQualifiers();
- assert(IsMember);
- Pointer->MemberName = demangleName();
+ if (MangledName.consumeFront("8")) {
+ Pointer->MemberName = demangleName();
+ Pointer->Pointee = demangleFunctionType(true);
+ } else {
+ Qualifiers PointeeQuals = Q_None;
+ bool IsMember = false;
+ std::tie(PointeeQuals, IsMember) = demangleQualifiers();
+ assert(IsMember);
+ Pointer->MemberName = demangleName();
+
+ Pointer->Pointee = demangleType(QualifierMangleMode::Drop);
+ Pointer->Pointee->Quals = PointeeQuals;
+ }
- Pointer->Pointee = demangleType(QualifierMangleMode::Drop);
- Pointer->Pointee->Quals = PointeeQuals;
return Pointer;
}
@@ -1507,6 +1532,12 @@ ParamList Demangler::demangleParameterList() {
Type *BackRef[10];
int Idx = 0;
+ // Empty parameter list.
+ // FIXME: Will this cause problems if demangleParameterList() is called in the
+ // context of a template parameter list?
+ if (MangledName.consumeFront('X'))
+ return {};
+
ParamList *Head;
ParamList **Current = &Head;
while (!Error && !MangledName.startsWith('@') &&
@@ -1537,7 +1568,22 @@ ParamList Demangler::demangleParameterList() {
Current = &(*Current)->Next;
}
- return *Head;
+ if (Error)
+ return {};
+
+ // A non-empty parameter list is terminated by either 'Z' (variadic) parameter
+ // list or '@' (non variadic). Careful not to consume "@Z", as in that case
+ // the following Z could be a throw specifier.
+ if (MangledName.consumeFront('@'))
+ return *Head;
+
+ if (MangledName.consumeFront('Z')) {
+ Head->IsVariadic = true;
+ return *Head;
+ }
+
+ Error = true;
+ return {};
}
void Demangler::output() {
diff --git a/llvm/lib/Demangle/StringView.h b/llvm/lib/Demangle/StringView.h
index 55cab48d969..3416db2c286 100644
--- a/llvm/lib/Demangle/StringView.h
+++ b/llvm/lib/Demangle/StringView.h
@@ -45,7 +45,7 @@ public:
StringView dropFront(size_t N = 1) const {
if (N >= size())
- N = size() - 1;
+ N = size();
return StringView(First + N, Last);
}
OpenPOWER on IntegriCloud