summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Demangle/MicrosoftDemangle.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Demangle/MicrosoftDemangle.cpp')
-rw-r--r--llvm/lib/Demangle/MicrosoftDemangle.cpp73
1 files changed, 56 insertions, 17 deletions
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp
index 7d95dedafaa..1e4f85303c9 100644
--- a/llvm/lib/Demangle/MicrosoftDemangle.cpp
+++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp
@@ -751,7 +751,8 @@ private:
ArrayType *demangleArrayType();
- ParamList demangleParameterList();
+ ParamList demangleTemplateParameterList();
+ ParamList demangleFunctionParameterList();
int demangleNumber();
void demangleNamePiece(Name &Node, bool IsHead);
@@ -785,6 +786,22 @@ private:
// Memory allocator.
ArenaAllocator Arena;
+ // A single type uses one global back-ref table for all function params.
+ // This means back-refs can even go "into" other types. Examples:
+ //
+ // // Second int* is a back-ref to first.
+ // void foo(int *, int*);
+ //
+ // // Second int* is not a back-ref to first (first is not a function param).
+ // int* foo(int*);
+ //
+ // // Second int* is a back-ref to first (ALL function types share the same
+ // // back-ref map.
+ // using F = void(*)(int*);
+ // F G(int *);
+ Type *FunctionParamBackRefs[10];
+ size_t FunctionParamBackRefCount = 0;
+
// The first 10 BackReferences in a mangled name can be back-referenced by
// special name @[0-9]. This is a storage for the first 10 BackReferences.
StringView BackReferences[10];
@@ -941,7 +958,7 @@ void Demangler::demangleNamePiece(Name &Node, bool IsHead) {
} else if (MangledName.consumeFront("?$")) {
// Class template.
Node.Str = demangleString(false);
- Node.TemplateParams = demangleParameterList();
+ Node.TemplateParams = demangleTemplateParameterList();
} 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
@@ -1311,7 +1328,7 @@ FunctionType *Demangler::demangleFunctionType(bool HasThisQuals,
if (!IsStructor)
FTy->ReturnType = demangleType(QualifierMangleMode::Result);
- FTy->Params = demangleParameterList();
+ FTy->Params = demangleFunctionParameterList();
demangleThrowSpecification();
@@ -1543,14 +1560,8 @@ ArrayType *Demangler::demangleArrayType() {
}
// Reads a function or a template parameters.
-ParamList Demangler::demangleParameterList() {
- // Within the same parameter list, you can backreference the first 10 types.
- Type *BackRef[10];
- int Idx = 0;
-
+ParamList Demangler::demangleFunctionParameterList() {
// 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 {};
@@ -1558,29 +1569,34 @@ ParamList Demangler::demangleParameterList() {
ParamList **Current = &Head;
while (!Error && !MangledName.startsWith('@') &&
!MangledName.startsWith('Z')) {
+
if (startsWithDigit(MangledName)) {
int N = MangledName[0] - '0';
- if (N >= Idx) {
+ if (N >= FunctionParamBackRefCount) {
Error = true;
return {};
}
MangledName = MangledName.dropFront();
*Current = Arena.alloc<ParamList>();
- (*Current)->Current = BackRef[N]->clone(Arena);
+ (*Current)->Current = FunctionParamBackRefs[N]->clone(Arena);
Current = &(*Current)->Next;
continue;
}
- size_t ArrayDimension = MangledName.size();
+ size_t OldSize = MangledName.size();
*Current = Arena.alloc<ParamList>();
(*Current)->Current = demangleType(QualifierMangleMode::Drop);
- // Single-letter types are ignored for backreferences because
- // memorizing them doesn't save anything.
- if (Idx <= 9 && ArrayDimension - MangledName.size() > 1)
- BackRef[Idx++] = (*Current)->Current;
+ size_t CharsConsumed = OldSize - MangledName.size();
+ assert(CharsConsumed != 0);
+
+ // Single-letter types are ignored for backreferences because memorizing
+ // them doesn't save anything.
+ if (FunctionParamBackRefCount <= 9 && CharsConsumed > 1)
+ FunctionParamBackRefs[FunctionParamBackRefCount++] = (*Current)->Current;
+
Current = &(*Current)->Next;
}
@@ -1602,6 +1618,29 @@ ParamList Demangler::demangleParameterList() {
return {};
}
+ParamList Demangler::demangleTemplateParameterList() {
+ ParamList *Head;
+ ParamList **Current = &Head;
+ while (!Error && !MangledName.startsWith('@')) {
+
+ // Template parameter lists don't participate in back-referencing.
+ *Current = Arena.alloc<ParamList>();
+ (*Current)->Current = demangleType(QualifierMangleMode::Drop);
+
+ Current = &(*Current)->Next;
+ }
+
+ if (Error)
+ return {};
+
+ // Template parameter lists cannot be variadic, so it can only be terminated
+ // by @.
+ if (MangledName.consumeFront('@'))
+ return *Head;
+ Error = true;
+ return {};
+}
+
void Demangler::output() {
// Converts an AST to a string.
//
OpenPOWER on IntegriCloud