[llvm] 9d28363 - [demangler] Fix new/delete demangling
Nathan Sidwell via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 10 04:33:19 PST 2022
Author: Nathan Sidwell
Date: 2022-02-10T04:33:02-08:00
New Revision: 9d283634f7be35f229e1ebe5f908c59352fe88c2
URL: https://github.com/llvm/llvm-project/commit/9d283634f7be35f229e1ebe5f908c59352fe88c2
DIFF: https://github.com/llvm/llvm-project/commit/9d283634f7be35f229e1ebe5f908c59352fe88c2.diff
LOG: [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<new int, new[] int(4)>() // No ::new
void Fn<new (4u)int, new[] (4u)int(4)>() // No ::new, poor whitespace
void Fn<::delete4, delete[] 4>() // missing necessary space
void Fn<delete4u, ::delete[] 4u>() // 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<new(4u) int, ::new[](4u) int(4)>()
void Fn<::delete 4, delete[] 4>()
void Fn<delete 4u, ::delete[] 4u>()
Binutils' behaviour:
c++filt _ZN2FnIXgsnw_iEEXna_ipiLi4EEEEEvv _ZN2FnIXnwLj4E_iEEXgsnaLj4E_ipiLi4EEEEEvv _ZN2FnIXgsdlLi4EEXdaLi4EEEEvv _ZN2FnIXdlLj4EEXgsdaLj4EEEEvv
void Fn<::new int, new int(4)>()
void Fn<new (4u) int, ::new (4u) int(4)>()
void Fn<::delete (4), delete[] (4)>()
void Fn<delete (4u), ::delete[] (4u)>()
The new and binutils demanglings are the same modulo some whitespace and optional parens.
Reviewed By: ChuanqiXu
Differential Revision: https://reviews.llvm.org/D118476
Added:
Modified:
libcxxabi/src/demangle/ItaniumDemangle.h
libcxxabi/test/test_demangle.pass.cpp
llvm/include/llvm/Demangle/ItaniumDemangle.h
Removed:
################################################################################
diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index d79452e42ea29..8d90a10aa446d 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -1926,16 +1926,16 @@ class NewExpr : public Node {
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 @@ class DeleteExpr : public Node {
OB += "::";
OB += "delete";
if (IsArray)
- OB += "[] ";
+ OB += "[]";
+ OB += ' ';
Op->print(OB);
}
};
@@ -2495,7 +2496,6 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Node *parseExprPrimary();
template <class Float> Node *parseFloatingLiteral();
Node *parseFunctionParam();
- Node *parseNewExpr();
Node *parseConversionExpr();
Node *parseBracedExpr();
Node *parseFoldExpr();
@@ -4178,43 +4178,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
return nullptr;
}
-// [gs] nw <expression>* _ <type> E # new (expr-list) type
-// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
-// [gs] na <expression>* _ <type> E # new[] (expr-list) type
-// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
-// <initializer> ::= pi <expression>* E # parenthesized initialization
-template <typename Derived, typename Alloc>
-Node *AbstractManglingParser<Derived, Alloc>::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<NewExpr>(ExprList, Ty, Inits, Global, IsArray);
- } else if (!consumeIf('E'))
- return nullptr;
- return make<NewExpr>(ExprList, Ty, NodeArray(), Global, IsArray);
-}
-
// cv <type> <expression> # conversion with one argument
// cv <type> _ <expression>* E # conversion with a
diff erent number of arguments
template <typename Derived, typename Alloc>
@@ -4817,8 +4780,35 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
case 'n':
switch (First[1]) {
case 'a':
- case 'w':
- return getDerived().parseNewExpr();
+ case 'w': {
+ // [gs] nw <expression>* _ <type> [pi <expression>*] E # new (expr-list) type [(init)]
+ // [gs] na <expression>* _ <type> [pi <expression>*] 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<NewExpr>(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 78289ffcfe2d3..5371f4bfc9915 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<new(4u) int, ::new[](4u) int(4)>()"},
+ {"_ZN2FnIXgsdlLi4EEXdaLi4EEEEvv", "void Fn<::delete 4, delete[] 4>()"},
+ {"_ZN2FnIXdlLj4EEXgsdaLj4EEEEvv", "void Fn<delete 4u, ::delete[] 4u>()"},
+
{"_Z3TPLIiET_S0_", "int TPL<int>(int)"},
};
diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h
index e6a2699b69375..dbd93cda87151 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -1926,16 +1926,16 @@ class NewExpr : public Node {
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 @@ class DeleteExpr : public Node {
OB += "::";
OB += "delete";
if (IsArray)
- OB += "[] ";
+ OB += "[]";
+ OB += ' ';
Op->print(OB);
}
};
@@ -2495,7 +2496,6 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser {
Node *parseExprPrimary();
template <class Float> Node *parseFloatingLiteral();
Node *parseFunctionParam();
- Node *parseNewExpr();
Node *parseConversionExpr();
Node *parseBracedExpr();
Node *parseFoldExpr();
@@ -4178,43 +4178,6 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
return nullptr;
}
-// [gs] nw <expression>* _ <type> E # new (expr-list) type
-// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)
-// [gs] na <expression>* _ <type> E # new[] (expr-list) type
-// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)
-// <initializer> ::= pi <expression>* E # parenthesized initialization
-template <typename Derived, typename Alloc>
-Node *AbstractManglingParser<Derived, Alloc>::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<NewExpr>(ExprList, Ty, Inits, Global, IsArray);
- } else if (!consumeIf('E'))
- return nullptr;
- return make<NewExpr>(ExprList, Ty, NodeArray(), Global, IsArray);
-}
-
// cv <type> <expression> # conversion with one argument
// cv <type> _ <expression>* E # conversion with a
diff erent number of arguments
template <typename Derived, typename Alloc>
@@ -4817,8 +4780,35 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
case 'n':
switch (First[1]) {
case 'a':
- case 'w':
- return getDerived().parseNewExpr();
+ case 'w': {
+ // [gs] nw <expression>* _ <type> [pi <expression>*] E # new (expr-list) type [(init)]
+ // [gs] na <expression>* _ <type> [pi <expression>*] 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<NewExpr>(ExprList, Ty, Inits, Global, IsArray);
+ }
case 'e':
First += 2;
return getDerived().parseBinaryExpr("!=");
More information about the llvm-commits
mailing list