mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-10-10 12:55:00 +00:00
[demangler] Use a back-patching scheme to resolve forward references.
Strictly in a conversion operator's type, a <template-param> refers to a <template-arg> that is further ahead in the mangled name. Instead of doing a second parse to resolve these, introduce a ForwardTemplateReference Node and back-patch the referenced <template-arg> when we're in the right context. This is also a correctness fix, previously we would only do a second parse if the <template-param> was out of bounds in the current set of <template-args>. This lead to misdemangles (gasp!) when the conversion operator was a member of a templated struct, for instance. llvm-svn: 328464
This commit is contained in:
parent
8c7013d4ca
commit
8a1cb33ba5
@ -190,6 +190,7 @@ public:
|
||||
KTemplateArgumentPack,
|
||||
KParameterPackExpansion,
|
||||
KTemplateArgs,
|
||||
KForwardTemplateReference,
|
||||
KNameWithTemplateArgs,
|
||||
KGlobalQualifiedName,
|
||||
KStdQualifiedName,
|
||||
@ -1091,6 +1092,29 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct ForwardTemplateReference : Node {
|
||||
size_t Index;
|
||||
Node *Ref = nullptr;
|
||||
|
||||
ForwardTemplateReference(size_t Index_)
|
||||
: Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
|
||||
Cache::Unknown),
|
||||
Index(Index_) {}
|
||||
|
||||
bool hasRHSComponentSlow(OutputStream &S) const override {
|
||||
return Ref->hasRHSComponent(S);
|
||||
}
|
||||
bool hasArraySlow(OutputStream &S) const override {
|
||||
return Ref->hasArray(S);
|
||||
}
|
||||
bool hasFunctionSlow(OutputStream &S) const override {
|
||||
return Ref->hasFunction(S);
|
||||
}
|
||||
|
||||
void printLeft(OutputStream &S) const override { Ref->printLeft(S); }
|
||||
void printRight(OutputStream &S) const override { Ref->printRight(S); }
|
||||
};
|
||||
|
||||
class NameWithTemplateArgs final : public Node {
|
||||
// name<template_args>
|
||||
Node *Name;
|
||||
@ -1924,10 +1948,12 @@ struct Db {
|
||||
// stored on the stack.
|
||||
PODSmallVector<Node *, 8> TemplateParams;
|
||||
|
||||
unsigned EncodingDepth = 0;
|
||||
bool TagTemplates = true;
|
||||
bool FixForwardReferences = false;
|
||||
// Set of unresolved forward <template-param> references. These can occur in a
|
||||
// conversion operator's type, and are resolved in the enclosing <encoding>.
|
||||
PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
|
||||
|
||||
bool TryToParseTemplateArgs = true;
|
||||
bool PermitForwardTemplateReferences = false;
|
||||
bool ParsingLambdaParams = false;
|
||||
|
||||
BumpPointerAllocator ASTAllocator;
|
||||
@ -1989,7 +2015,7 @@ struct Db {
|
||||
bool parseSeqId(size_t *Out);
|
||||
Node *parseSubstitution();
|
||||
Node *parseTemplateParam();
|
||||
Node *parseTemplateArgs();
|
||||
Node *parseTemplateArgs(bool TagTemplates = false);
|
||||
Node *parseTemplateArg();
|
||||
|
||||
/// Parse the <expr> production.
|
||||
@ -2025,8 +2051,25 @@ struct Db {
|
||||
bool EndsWithTemplateArgs = false;
|
||||
Qualifiers CVQualifiers = QualNone;
|
||||
FunctionRefQual ReferenceQualifier = FrefQualNone;
|
||||
size_t ForwardTemplateRefsBegin;
|
||||
|
||||
NameState(Db *Enclosing)
|
||||
: ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
|
||||
};
|
||||
|
||||
bool resolveForwardTemplateRefs(NameState &State) {
|
||||
size_t I = State.ForwardTemplateRefsBegin;
|
||||
size_t E = ForwardTemplateRefs.size();
|
||||
for (; I < E; ++I) {
|
||||
size_t Idx = ForwardTemplateRefs[I]->Index;
|
||||
if (Idx >= TemplateParams.size())
|
||||
return true;
|
||||
ForwardTemplateRefs[I]->Ref = TemplateParams[Idx];
|
||||
}
|
||||
ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Parse the <name> production>
|
||||
Node *parseName(NameState *State = nullptr);
|
||||
Node *parseLocalName(NameState *State);
|
||||
@ -2075,7 +2118,7 @@ Node *Db::parseName(NameState *State) {
|
||||
return nullptr;
|
||||
if (look() != 'I')
|
||||
return nullptr;
|
||||
Node *TA = parseTemplateArgs();
|
||||
Node *TA = parseTemplateArgs(State != nullptr);
|
||||
if (TA == nullptr)
|
||||
return nullptr;
|
||||
if (State) State->EndsWithTemplateArgs = true;
|
||||
@ -2088,7 +2131,7 @@ Node *Db::parseName(NameState *State) {
|
||||
// ::= <unscoped-template-name> <template-args>
|
||||
if (look() == 'I') {
|
||||
Subs.push_back(N);
|
||||
Node *TA = parseTemplateArgs();
|
||||
Node *TA = parseTemplateArgs(State != nullptr);
|
||||
if (TA == nullptr)
|
||||
return nullptr;
|
||||
if (State) State->EndsWithTemplateArgs = true;
|
||||
@ -2302,9 +2345,15 @@ Node *Db::parseOperatorName(NameState *State) {
|
||||
return make<NameType>("operator~");
|
||||
// ::= cv <type> # (cast)
|
||||
case 'v': {
|
||||
SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
|
||||
First += 2;
|
||||
Node *Ty = parseType();
|
||||
SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
|
||||
// If we're parsing an encoding, State != nullptr and the conversion
|
||||
// operators' <type> could have a <template-param> that refers to some
|
||||
// <template-arg>s further ahead in the mangled name.
|
||||
SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
|
||||
PermitForwardTemplateReferences ||
|
||||
State != nullptr);
|
||||
Node* Ty = parseType();
|
||||
if (Ty == nullptr)
|
||||
return nullptr;
|
||||
if (State) State->CtorDtorConversion = true;
|
||||
@ -2528,7 +2577,7 @@ Node *Db::parseCtorDtorName(Node *&SoFar, NameState *State) {
|
||||
++First;
|
||||
if (State) State->CtorDtorConversion = true;
|
||||
if (IsInherited) {
|
||||
if (parseName() == nullptr)
|
||||
if (parseName(State) == nullptr)
|
||||
return nullptr;
|
||||
}
|
||||
return make<CtorDtorName>(SoFar, false);
|
||||
@ -2598,7 +2647,7 @@ Node *Db::parseNestedName(NameState *State) {
|
||||
|
||||
// ::= <template-prefix> <template-args>
|
||||
if (look() == 'I') {
|
||||
Node *TA = parseTemplateArgs();
|
||||
Node *TA = parseTemplateArgs(State != nullptr);
|
||||
if (TA == nullptr || SoFar == nullptr)
|
||||
return nullptr;
|
||||
SoFar = make<NameWithTemplateArgs>(SoFar, TA);
|
||||
@ -4369,15 +4418,6 @@ Node *Db::parseSpecialName() {
|
||||
// ::= <data name>
|
||||
// ::= <special-name>
|
||||
Node *Db::parseEncoding() {
|
||||
// Always "tag" templates (insert them into Db::TemplateParams) unless we're
|
||||
// doing a second parse to resolve a forward template reference, in which case
|
||||
// we only tag templates if EncodingDepth > 1.
|
||||
// FIXME: This is kinda broken; it would be better to make a forward reference
|
||||
// and patch it all in one pass.
|
||||
SwapAndRestore<bool> SaveTagTemplates(TagTemplates,
|
||||
TagTemplates || EncodingDepth);
|
||||
SwapAndRestore<unsigned> SaveEncodingDepth(EncodingDepth, EncodingDepth + 1);
|
||||
|
||||
if (look() == 'G' || look() == 'T')
|
||||
return parseSpecialName();
|
||||
|
||||
@ -4388,12 +4428,16 @@ Node *Db::parseEncoding() {
|
||||
return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
|
||||
};
|
||||
|
||||
NameState NameInfo;
|
||||
NameState NameInfo(this);
|
||||
Node *Name = parseName(&NameInfo);
|
||||
if (Name == nullptr || IsEndOfEncoding())
|
||||
return Name;
|
||||
if (Name == nullptr)
|
||||
return nullptr;
|
||||
|
||||
TagTemplates = false;
|
||||
if (resolveForwardTemplateRefs(NameInfo))
|
||||
return nullptr;
|
||||
|
||||
if (IsEndOfEncoding())
|
||||
return Name;
|
||||
|
||||
Node *Attrs = nullptr;
|
||||
if (consumeIf("Ua9enable_ifI")) {
|
||||
@ -4601,10 +4645,16 @@ Node *Db::parseTemplateParam() {
|
||||
if (ParsingLambdaParams)
|
||||
return make<NameType>("auto");
|
||||
|
||||
if (Index >= TemplateParams.size()) {
|
||||
FixForwardReferences = true;
|
||||
return make<NameType>("FORWARD_REFERENCE");
|
||||
// If we're in a context where this <template-param> refers to a
|
||||
// <template-arg> further ahead in the mangled name (currently just conversion
|
||||
// operator types), then we should only look it up in the right context.
|
||||
if (PermitForwardTemplateReferences) {
|
||||
ForwardTemplateRefs.push_back(make<ForwardTemplateReference>(Index));
|
||||
return ForwardTemplateRefs.back();
|
||||
}
|
||||
|
||||
if (Index >= TemplateParams.size())
|
||||
return nullptr;
|
||||
return TemplateParams[Index];
|
||||
}
|
||||
|
||||
@ -4653,7 +4703,7 @@ Node *Db::parseTemplateArg() {
|
||||
|
||||
// <template-args> ::= I <template-arg>* E
|
||||
// extension, the abi says <template-arg>+
|
||||
Node *Db::parseTemplateArgs() {
|
||||
Node *Db::parseTemplateArgs(bool TagTemplates) {
|
||||
if (!consumeIf('I'))
|
||||
return nullptr;
|
||||
|
||||
@ -4790,20 +4840,9 @@ __cxa_demangle(const char *MangledName, char *Buf, size_t *N, int *Status) {
|
||||
if (AST == nullptr)
|
||||
InternalStatus = invalid_mangled_name;
|
||||
|
||||
if (InternalStatus == success && Parser.FixForwardReferences &&
|
||||
!Parser.TemplateParams.empty()) {
|
||||
Parser.FixForwardReferences = false;
|
||||
Parser.TagTemplates = false;
|
||||
Parser.Names.clear();
|
||||
Parser.Subs.clear();
|
||||
Parser.First = MangledName;
|
||||
Parser.Last = MangledName + MangledNameLength;
|
||||
AST = Parser.parse();
|
||||
if (AST == nullptr || Parser.FixForwardReferences)
|
||||
InternalStatus = invalid_mangled_name;
|
||||
}
|
||||
|
||||
if (InternalStatus == success) {
|
||||
assert(Parser.ForwardTemplateRefs.empty());
|
||||
|
||||
if (Buf == nullptr) {
|
||||
BufSize = 1024;
|
||||
Buf = static_cast<char*>(std::malloc(BufSize));
|
||||
|
@ -29732,6 +29732,12 @@ const char* cases[][2] =
|
||||
{"_Z1fUa9enable_ifIXLi1EEEv", "f() [enable_if:1]"},
|
||||
{"_ZN5test4IdE1fEUa9enable_ifIXeqfL0p_Li1EEXeqfL0p0_Li2EEEi", "test4<double>::f(int) [enable_if:(fp) == (1), (fp0) == (2)]"},
|
||||
{"_Z3quxUa9enable_ifIXLi1EEXL_Z9TRUEFACTSEEEi", "qux(int) [enable_if:1, TRUEFACTS]"},
|
||||
|
||||
// Conversion operators:
|
||||
{"_ZN5OuterI4MarpEcv7MuncherIJT_T0_DpT1_EEI4MerpS0_JicfEEEv", "Outer<Marp>::operator Muncher<Merp, Marp, int, char, float><Merp, Marp, int, char, float>()"},
|
||||
{"_ZN5OuterI4MarpEcvT_I4MerpEEv", "Outer<Marp>::operator Merp<Merp>()"},
|
||||
{"_ZZN5OuterI4MarpEcv7MuncherIJT_T0_DpT1_EEI4MerpS0_JicfEEEvEN1ScvS9_Ev", "Outer<Marp>::operator Muncher<Merp, Marp, int, char, float><Merp, Marp, int, char, float>()::S::operator Merp()"},
|
||||
{"_ZN1Scv7MuncherIJDpPT_EEIJFivEA_iEEEv", "S::operator Muncher<int (*)(), int (*) []><int (), int []>()"},
|
||||
};
|
||||
|
||||
const unsigned N = sizeof(cases) / sizeof(cases[0]);
|
||||
@ -29799,11 +29805,11 @@ const char* invalid_cases[] =
|
||||
"Z1 Z1 IJEEAcvZcvT_EcvT_T_",
|
||||
"T_IZaaIJEEAnaaaT_T__",
|
||||
"PT_IJPNT_IJEET_T_T_T_)J)JKE",
|
||||
// "1 IJEVNT_T_T_EE",
|
||||
"1 IJEVNT_T_T_EE",
|
||||
"AT__ZSiIJEEAnwscT_T__",
|
||||
"FSiIJEENT_IoE ",
|
||||
"ZTVSiIZTVSiIZTVSiIZTVSiINIJEET_T_T_T_T_ ",
|
||||
// "Ana_T_E_T_IJEffffffffffffffersfffffrsrsffffffbgE",
|
||||
"Ana_T_E_T_IJEffffffffffffffersfffffrsrsffffffbgE",
|
||||
};
|
||||
|
||||
const unsigned NI = sizeof(invalid_cases) / sizeof(invalid_cases[0]);
|
||||
|
@ -182,6 +182,7 @@ public:
|
||||
KTemplateArgumentPack,
|
||||
KParameterPackExpansion,
|
||||
KTemplateArgs,
|
||||
KForwardTemplateReference,
|
||||
KNameWithTemplateArgs,
|
||||
KGlobalQualifiedName,
|
||||
KStdQualifiedName,
|
||||
@ -1083,6 +1084,29 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct ForwardTemplateReference : Node {
|
||||
size_t Index;
|
||||
Node *Ref = nullptr;
|
||||
|
||||
ForwardTemplateReference(size_t Index_)
|
||||
: Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,
|
||||
Cache::Unknown),
|
||||
Index(Index_) {}
|
||||
|
||||
bool hasRHSComponentSlow(OutputStream &S) const override {
|
||||
return Ref->hasRHSComponent(S);
|
||||
}
|
||||
bool hasArraySlow(OutputStream &S) const override {
|
||||
return Ref->hasArray(S);
|
||||
}
|
||||
bool hasFunctionSlow(OutputStream &S) const override {
|
||||
return Ref->hasFunction(S);
|
||||
}
|
||||
|
||||
void printLeft(OutputStream &S) const override { Ref->printLeft(S); }
|
||||
void printRight(OutputStream &S) const override { Ref->printRight(S); }
|
||||
};
|
||||
|
||||
class NameWithTemplateArgs final : public Node {
|
||||
// name<template_args>
|
||||
Node *Name;
|
||||
@ -1916,10 +1940,12 @@ struct Db {
|
||||
// stored on the stack.
|
||||
PODSmallVector<Node *, 8> TemplateParams;
|
||||
|
||||
unsigned EncodingDepth = 0;
|
||||
bool TagTemplates = true;
|
||||
bool FixForwardReferences = false;
|
||||
// Set of unresolved forward <template-param> references. These can occur in a
|
||||
// conversion operator's type, and are resolved in the enclosing <encoding>.
|
||||
PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;
|
||||
|
||||
bool TryToParseTemplateArgs = true;
|
||||
bool PermitForwardTemplateReferences = false;
|
||||
bool ParsingLambdaParams = false;
|
||||
|
||||
BumpPointerAllocator ASTAllocator;
|
||||
@ -1981,7 +2007,7 @@ struct Db {
|
||||
bool parseSeqId(size_t *Out);
|
||||
Node *parseSubstitution();
|
||||
Node *parseTemplateParam();
|
||||
Node *parseTemplateArgs();
|
||||
Node *parseTemplateArgs(bool TagTemplates = false);
|
||||
Node *parseTemplateArg();
|
||||
|
||||
/// Parse the <expr> production.
|
||||
@ -2017,8 +2043,25 @@ struct Db {
|
||||
bool EndsWithTemplateArgs = false;
|
||||
Qualifiers CVQualifiers = QualNone;
|
||||
FunctionRefQual ReferenceQualifier = FrefQualNone;
|
||||
size_t ForwardTemplateRefsBegin;
|
||||
|
||||
NameState(Db *Enclosing)
|
||||
: ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}
|
||||
};
|
||||
|
||||
bool resolveForwardTemplateRefs(NameState &State) {
|
||||
size_t I = State.ForwardTemplateRefsBegin;
|
||||
size_t E = ForwardTemplateRefs.size();
|
||||
for (; I < E; ++I) {
|
||||
size_t Idx = ForwardTemplateRefs[I]->Index;
|
||||
if (Idx >= TemplateParams.size())
|
||||
return true;
|
||||
ForwardTemplateRefs[I]->Ref = TemplateParams[Idx];
|
||||
}
|
||||
ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Parse the <name> production>
|
||||
Node *parseName(NameState *State = nullptr);
|
||||
Node *parseLocalName(NameState *State);
|
||||
@ -2067,7 +2110,7 @@ Node *Db::parseName(NameState *State) {
|
||||
return nullptr;
|
||||
if (look() != 'I')
|
||||
return nullptr;
|
||||
Node *TA = parseTemplateArgs();
|
||||
Node *TA = parseTemplateArgs(State != nullptr);
|
||||
if (TA == nullptr)
|
||||
return nullptr;
|
||||
if (State) State->EndsWithTemplateArgs = true;
|
||||
@ -2080,7 +2123,7 @@ Node *Db::parseName(NameState *State) {
|
||||
// ::= <unscoped-template-name> <template-args>
|
||||
if (look() == 'I') {
|
||||
Subs.push_back(N);
|
||||
Node *TA = parseTemplateArgs();
|
||||
Node *TA = parseTemplateArgs(State != nullptr);
|
||||
if (TA == nullptr)
|
||||
return nullptr;
|
||||
if (State) State->EndsWithTemplateArgs = true;
|
||||
@ -2294,9 +2337,15 @@ Node *Db::parseOperatorName(NameState *State) {
|
||||
return make<NameType>("operator~");
|
||||
// ::= cv <type> # (cast)
|
||||
case 'v': {
|
||||
SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
|
||||
First += 2;
|
||||
Node *Ty = parseType();
|
||||
SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);
|
||||
// If we're parsing an encoding, State != nullptr and the conversion
|
||||
// operators' <type> could have a <template-param> that refers to some
|
||||
// <template-arg>s further ahead in the mangled name.
|
||||
SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,
|
||||
PermitForwardTemplateReferences ||
|
||||
State != nullptr);
|
||||
Node* Ty = parseType();
|
||||
if (Ty == nullptr)
|
||||
return nullptr;
|
||||
if (State) State->CtorDtorConversion = true;
|
||||
@ -2520,7 +2569,7 @@ Node *Db::parseCtorDtorName(Node *&SoFar, NameState *State) {
|
||||
++First;
|
||||
if (State) State->CtorDtorConversion = true;
|
||||
if (IsInherited) {
|
||||
if (parseName() == nullptr)
|
||||
if (parseName(State) == nullptr)
|
||||
return nullptr;
|
||||
}
|
||||
return make<CtorDtorName>(SoFar, false);
|
||||
@ -2590,7 +2639,7 @@ Node *Db::parseNestedName(NameState *State) {
|
||||
|
||||
// ::= <template-prefix> <template-args>
|
||||
if (look() == 'I') {
|
||||
Node *TA = parseTemplateArgs();
|
||||
Node *TA = parseTemplateArgs(State != nullptr);
|
||||
if (TA == nullptr || SoFar == nullptr)
|
||||
return nullptr;
|
||||
SoFar = make<NameWithTemplateArgs>(SoFar, TA);
|
||||
@ -4361,15 +4410,6 @@ Node *Db::parseSpecialName() {
|
||||
// ::= <data name>
|
||||
// ::= <special-name>
|
||||
Node *Db::parseEncoding() {
|
||||
// Always "tag" templates (insert them into Db::TemplateParams) unless we're
|
||||
// doing a second parse to resolve a forward template reference, in which case
|
||||
// we only tag templates if EncodingDepth > 1.
|
||||
// FIXME: This is kinda broken; it would be better to make a forward reference
|
||||
// and patch it all in one pass.
|
||||
SwapAndRestore<bool> SaveTagTemplates(TagTemplates,
|
||||
TagTemplates || EncodingDepth);
|
||||
SwapAndRestore<unsigned> SaveEncodingDepth(EncodingDepth, EncodingDepth + 1);
|
||||
|
||||
if (look() == 'G' || look() == 'T')
|
||||
return parseSpecialName();
|
||||
|
||||
@ -4380,12 +4420,16 @@ Node *Db::parseEncoding() {
|
||||
return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';
|
||||
};
|
||||
|
||||
NameState NameInfo;
|
||||
NameState NameInfo(this);
|
||||
Node *Name = parseName(&NameInfo);
|
||||
if (Name == nullptr || IsEndOfEncoding())
|
||||
return Name;
|
||||
if (Name == nullptr)
|
||||
return nullptr;
|
||||
|
||||
TagTemplates = false;
|
||||
if (resolveForwardTemplateRefs(NameInfo))
|
||||
return nullptr;
|
||||
|
||||
if (IsEndOfEncoding())
|
||||
return Name;
|
||||
|
||||
Node *Attrs = nullptr;
|
||||
if (consumeIf("Ua9enable_ifI")) {
|
||||
@ -4593,10 +4637,16 @@ Node *Db::parseTemplateParam() {
|
||||
if (ParsingLambdaParams)
|
||||
return make<NameType>("auto");
|
||||
|
||||
if (Index >= TemplateParams.size()) {
|
||||
FixForwardReferences = true;
|
||||
return make<NameType>("FORWARD_REFERENCE");
|
||||
// If we're in a context where this <template-param> refers to a
|
||||
// <template-arg> further ahead in the mangled name (currently just conversion
|
||||
// operator types), then we should only look it up in the right context.
|
||||
if (PermitForwardTemplateReferences) {
|
||||
ForwardTemplateRefs.push_back(make<ForwardTemplateReference>(Index));
|
||||
return ForwardTemplateRefs.back();
|
||||
}
|
||||
|
||||
if (Index >= TemplateParams.size())
|
||||
return nullptr;
|
||||
return TemplateParams[Index];
|
||||
}
|
||||
|
||||
@ -4645,7 +4695,7 @@ Node *Db::parseTemplateArg() {
|
||||
|
||||
// <template-args> ::= I <template-arg>* E
|
||||
// extension, the abi says <template-arg>+
|
||||
Node *Db::parseTemplateArgs() {
|
||||
Node *Db::parseTemplateArgs(bool TagTemplates) {
|
||||
if (!consumeIf('I'))
|
||||
return nullptr;
|
||||
|
||||
@ -4781,20 +4831,9 @@ char *llvm::itaniumDemangle(const char *MangledName, char *Buf,
|
||||
if (AST == nullptr)
|
||||
InternalStatus = invalid_mangled_name;
|
||||
|
||||
if (InternalStatus == success && Parser.FixForwardReferences &&
|
||||
!Parser.TemplateParams.empty()) {
|
||||
Parser.FixForwardReferences = false;
|
||||
Parser.TagTemplates = false;
|
||||
Parser.Names.clear();
|
||||
Parser.Subs.clear();
|
||||
Parser.First = MangledName;
|
||||
Parser.Last = MangledName + MangledNameLength;
|
||||
AST = Parser.parse();
|
||||
if (AST == nullptr || Parser.FixForwardReferences)
|
||||
InternalStatus = invalid_mangled_name;
|
||||
}
|
||||
|
||||
if (InternalStatus == success) {
|
||||
assert(Parser.ForwardTemplateRefs.empty());
|
||||
|
||||
if (Buf == nullptr) {
|
||||
BufSize = 1024;
|
||||
Buf = static_cast<char*>(std::malloc(BufSize));
|
||||
|
Loading…
Reference in New Issue
Block a user