summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorZachary Turner <zturner@google.com>2018-07-26 22:13:39 +0000
committerZachary Turner <zturner@google.com>2018-07-26 22:13:39 +0000
commit23df1319ca76f867a83634d74ba78377569e29b1 (patch)
tree75441b96905f6734a47649d0f5545865dcacc4e3 /llvm/lib
parent60bdd09d10c6f758603907cbf0dfbf866dd12325 (diff)
downloadbcm5719-llvm-23df1319ca76f867a83634d74ba78377569e29b1.tar.gz
bcm5719-llvm-23df1319ca76f867a83634d74ba78377569e29b1.zip
[MS Demangler] Properly handle function parameter back-refs.
Properly demangle function parameter back-references. Previously we treated lists of function parameters and template parameters the same. There are some important differences with regards to back-references, and some less important differences regarding which characters can appear before or after the name. The important differences are that with a given type T, all instances of a function parameter list share the same global back-ref table. Specifically, if X and Y are function pointers, then there are 3 entities in the declaration X func(Y) which all affect and are affected by the master parameter back-ref table: 1) The parameter list of X's function type 2) the parameter list of func itself 3) The parameter list of Y's function type. The previous code would create a back-reference table that was local to a single parameter list, so it would not be shared across parameter lists. This was discovered when porting ms-back-references.test from clang's mangling tests. All of these tests should now pass with the new changes. In doing so, I split the function for parsing template and function parameters into two separate functions. This makes the template parameter list parsing code in particular very small and easy to understand now. Differential Revision: https://reviews.llvm.org/D49875 llvm-svn: 338075
Diffstat (limited to 'llvm/lib')
-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