From 9d283634f7be35f229e1ebe5f908c59352fe88c2 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 28 Jan 2022 07:09:38 -0800 Subject: [PATCH] [demangler] Fix new/delete demangling I discovered some demangler problems: a) parsing of new expressions was broken, ignoring any 'gs' prefix b) (when #a is fixed) badly formatted global new expressions c) formatting of new and delete failed to correctly add whitespace (a) happens as parseExpr swallows the 'gs' prefix but doesn't pass it to 'parseNewExpr'. It seems simpler to me to just code the new expression parsing directly in parseExpr, as is done for delete expressions. (b) global new should be rendered something like '::new T' not '::operator new T' (c) is resolved by being a bit more careful with whitespace. Best shown with some examples (don't worry that these symbols are for impossible instantiations, that's not the point): Old behaviour: build/bin/llvm-cxxfilt _ZN2FnIXgsnw_iEEXna_ipiLi4EEEEEvv _ZN2FnIXnwLj4E_iEEXgsnaLj4E_ipiLi4EEEEEvv _ZN2FnIXgsdlLi4EEXdaLi4EEEEvv _ZN2FnIXdlLj4EEXgsdaLj4EEEEvv void Fn() // No ::new void Fn() // No ::new, poor whitespace void Fn<::delete4, delete[] 4>() // missing necessary space void Fn() // missing necessary space New behaviour: build/bin/llvm-cxxfilt _ZN2FnIXgsnw_iEEXna_ipiLi4EEEEEvv _ZN2FnIXnwLj4E_iEEXgsnaLj4E_ipiLi4EEEEEvv _ZN2FnIXgsdlLi4EEXdaLi4EEEEvv _ZN2FnIXdlLj4EEXgsdaLj4EEEEvv void Fn<::new int, new[] int(4)>() void Fn() void Fn<::delete 4, delete[] 4>() void Fn() Binutils' behaviour: c++filt _ZN2FnIXgsnw_iEEXna_ipiLi4EEEEEvv _ZN2FnIXnwLj4E_iEEXgsnaLj4E_ipiLi4EEEEEvv _ZN2FnIXgsdlLi4EEXdaLi4EEEEvv _ZN2FnIXdlLj4EEXgsdaLj4EEEEvv void Fn<::new int, new int(4)>() void Fn() void Fn<::delete (4), delete[] (4)>() void Fn() The new and binutils demanglings are the same modulo some whitespace and optional parens. Reviewed By: ChuanqiXu Differential Revision: https://reviews.llvm.org/D118476 --- libcxxabi/src/demangle/ItaniumDemangle.h | 76 ++++++++++++---------------- libcxxabi/test/test_demangle.pass.cpp | 5 ++ llvm/include/llvm/Demangle/ItaniumDemangle.h | 76 ++++++++++++---------------- 3 files changed, 71 insertions(+), 86 deletions(-) diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h index d79452e..8d90a10 100644 --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -1926,16 +1926,16 @@ public: void printLeft(OutputBuffer &OB) const override { if (IsGlobal) - OB += "::operator "; + OB += "::"; OB += "new"; if (IsArray) OB += "[]"; - OB += ' '; if (!ExprList.empty()) { OB += "("; ExprList.printWithComma(OB); OB += ")"; } + OB += ' '; Type->print(OB); if (!InitList.empty()) { OB += "("; @@ -1961,7 +1961,8 @@ public: OB += "::"; OB += "delete"; if (IsArray) - OB += "[] "; + OB += "[]"; + OB += ' '; Op->print(OB); } }; @@ -2495,7 +2496,6 @@ template struct AbstractManglingParser { Node *parseExprPrimary(); template Node *parseFloatingLiteral(); Node *parseFunctionParam(); - Node *parseNewExpr(); Node *parseConversionExpr(); Node *parseBracedExpr(); Node *parseFoldExpr(); @@ -4178,43 +4178,6 @@ Node *AbstractManglingParser::parseFunctionParam() { return nullptr; } -// [gs] nw * _ E # new (expr-list) type -// [gs] nw * _ # new (expr-list) type (init) -// [gs] na * _ E # new[] (expr-list) type -// [gs] na * _ # new[] (expr-list) type (init) -// ::= pi * E # parenthesized initialization -template -Node *AbstractManglingParser::parseNewExpr() { - bool Global = consumeIf("gs"); - bool IsArray = look(1) == 'a'; - if (!consumeIf("nw") && !consumeIf("na")) - return nullptr; - size_t Exprs = Names.size(); - while (!consumeIf('_')) { - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return nullptr; - Names.push_back(Ex); - } - NodeArray ExprList = popTrailingNodeArray(Exprs); - Node *Ty = getDerived().parseType(); - if (Ty == nullptr) - return Ty; - if (consumeIf("pi")) { - size_t InitsBegin = Names.size(); - while (!consumeIf('E')) { - Node *Init = getDerived().parseExpr(); - if (Init == nullptr) - return Init; - Names.push_back(Init); - } - NodeArray Inits = popTrailingNodeArray(InitsBegin); - return make(ExprList, Ty, Inits, Global, IsArray); - } else if (!consumeIf('E')) - return nullptr; - return make(ExprList, Ty, NodeArray(), Global, IsArray); -} - // cv # conversion with one argument // cv _ * E # conversion with a different number of arguments template @@ -4817,8 +4780,35 @@ Node *AbstractManglingParser::parseExpr() { case 'n': switch (First[1]) { case 'a': - case 'w': - return getDerived().parseNewExpr(); + case 'w': { + // [gs] nw * _ [pi *] E # new (expr-list) type [(init)] + // [gs] na * _ [pi *] E # new[] (expr-list) type [(init)] + bool IsArray = First[1] == 'a'; + First += 2; + size_t Exprs = Names.size(); + while (!consumeIf('_')) { + Node *Ex = getDerived().parseExpr(); + if (Ex == nullptr) + return nullptr; + Names.push_back(Ex); + } + NodeArray ExprList = popTrailingNodeArray(Exprs); + Node *Ty = getDerived().parseType(); + if (Ty == nullptr) + return nullptr; + bool HaveInits = consumeIf("pi"); + size_t InitsBegin = Names.size(); + while (!consumeIf('E')) { + if (!HaveInits) + return nullptr; + Node *Init = getDerived().parseExpr(); + if (Init == nullptr) + return Init; + Names.push_back(Init); + } + NodeArray Inits = popTrailingNodeArray(InitsBegin); + return make(ExprList, Ty, Inits, Global, IsArray); + } case 'e': First += 2; return getDerived().parseBinaryExpr("!="); diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp index 78289ff..5371f4b 100644 --- a/libcxxabi/test/test_demangle.pass.cpp +++ b/libcxxabi/test/test_demangle.pass.cpp @@ -29858,6 +29858,11 @@ const char* cases[][2] = {"_ZN2FnIXgs4BaseEX4BaseEEEvv","void Fn<::Base, Base>()"}, + {"_ZN2FnIXgsnw_iEEXna_ipiLi4EEEEEvv", "void Fn<::new int, new[] int(4)>()"}, + {"_ZN2FnIXnwLj4E_iEEXgsnaLj4E_ipiLi4EEEEEvv", "void Fn()"}, + {"_ZN2FnIXgsdlLi4EEXdaLi4EEEEvv", "void Fn<::delete 4, delete[] 4>()"}, + {"_ZN2FnIXdlLj4EEXgsdaLj4EEEEvv", "void Fn()"}, + {"_Z3TPLIiET_S0_", "int TPL(int)"}, }; diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h index e6a2699..dbd93cd 100644 --- a/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -1926,16 +1926,16 @@ public: void printLeft(OutputBuffer &OB) const override { if (IsGlobal) - OB += "::operator "; + OB += "::"; OB += "new"; if (IsArray) OB += "[]"; - OB += ' '; if (!ExprList.empty()) { OB += "("; ExprList.printWithComma(OB); OB += ")"; } + OB += ' '; Type->print(OB); if (!InitList.empty()) { OB += "("; @@ -1961,7 +1961,8 @@ public: OB += "::"; OB += "delete"; if (IsArray) - OB += "[] "; + OB += "[]"; + OB += ' '; Op->print(OB); } }; @@ -2495,7 +2496,6 @@ template struct AbstractManglingParser { Node *parseExprPrimary(); template Node *parseFloatingLiteral(); Node *parseFunctionParam(); - Node *parseNewExpr(); Node *parseConversionExpr(); Node *parseBracedExpr(); Node *parseFoldExpr(); @@ -4178,43 +4178,6 @@ Node *AbstractManglingParser::parseFunctionParam() { return nullptr; } -// [gs] nw * _ E # new (expr-list) type -// [gs] nw * _ # new (expr-list) type (init) -// [gs] na * _ E # new[] (expr-list) type -// [gs] na * _ # new[] (expr-list) type (init) -// ::= pi * E # parenthesized initialization -template -Node *AbstractManglingParser::parseNewExpr() { - bool Global = consumeIf("gs"); - bool IsArray = look(1) == 'a'; - if (!consumeIf("nw") && !consumeIf("na")) - return nullptr; - size_t Exprs = Names.size(); - while (!consumeIf('_')) { - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return nullptr; - Names.push_back(Ex); - } - NodeArray ExprList = popTrailingNodeArray(Exprs); - Node *Ty = getDerived().parseType(); - if (Ty == nullptr) - return Ty; - if (consumeIf("pi")) { - size_t InitsBegin = Names.size(); - while (!consumeIf('E')) { - Node *Init = getDerived().parseExpr(); - if (Init == nullptr) - return Init; - Names.push_back(Init); - } - NodeArray Inits = popTrailingNodeArray(InitsBegin); - return make(ExprList, Ty, Inits, Global, IsArray); - } else if (!consumeIf('E')) - return nullptr; - return make(ExprList, Ty, NodeArray(), Global, IsArray); -} - // cv # conversion with one argument // cv _ * E # conversion with a different number of arguments template @@ -4817,8 +4780,35 @@ Node *AbstractManglingParser::parseExpr() { case 'n': switch (First[1]) { case 'a': - case 'w': - return getDerived().parseNewExpr(); + case 'w': { + // [gs] nw * _ [pi *] E # new (expr-list) type [(init)] + // [gs] na * _ [pi *] E # new[] (expr-list) type [(init)] + bool IsArray = First[1] == 'a'; + First += 2; + size_t Exprs = Names.size(); + while (!consumeIf('_')) { + Node *Ex = getDerived().parseExpr(); + if (Ex == nullptr) + return nullptr; + Names.push_back(Ex); + } + NodeArray ExprList = popTrailingNodeArray(Exprs); + Node *Ty = getDerived().parseType(); + if (Ty == nullptr) + return nullptr; + bool HaveInits = consumeIf("pi"); + size_t InitsBegin = Names.size(); + while (!consumeIf('E')) { + if (!HaveInits) + return nullptr; + Node *Init = getDerived().parseExpr(); + if (Init == nullptr) + return Init; + Names.push_back(Init); + } + NodeArray Inits = popTrailingNodeArray(InitsBegin); + return make(ExprList, Ty, Inits, Global, IsArray); + } case 'e': First += 2; return getDerived().parseBinaryExpr("!="); -- 2.7.4