diff options
author | Hubert Tong <hubert.reinterpretcast@gmail.com> | 2024-12-10 20:24:15 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-10 20:24:15 -0400 |
commit | 918d4558b0bad366ecadd411ed48cf64728c68d7 (patch) | |
tree | 768b345c871db01d015d0780c8641002591da6c6 | |
parent | 9b6bb8386001a1d308cda42fe273733e58b8e93e (diff) | |
download | llvm-918d4558b0bad366ecadd411ed48cf64728c68d7.zip llvm-918d4558b0bad366ecadd411ed48cf64728c68d7.tar.gz llvm-918d4558b0bad366ecadd411ed48cf64728c68d7.tar.bz2 |
[libc++abi] Enable demangling of `cp` expression production (#114882)
See itanium-cxx-abi/cxx-abi#196
-rw-r--r-- | libcxxabi/src/demangle/ItaniumDemangle.h | 22 | ||||
-rw-r--r-- | libcxxabi/test/test_demangle.pass.cpp | 17 | ||||
-rw-r--r-- | llvm/include/llvm/Demangle/ItaniumDemangle.h | 22 |
3 files changed, 41 insertions, 20 deletions
diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h index 52755e6..e4752be 100644 --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -2077,17 +2077,23 @@ public: class CallExpr : public Node { const Node *Callee; NodeArray Args; + bool IsParen; // (func)(args ...) ? public: - CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_) - : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {} + CallExpr(const Node *Callee_, NodeArray Args_, bool IsParen_, Prec Prec_) + : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_), + IsParen(IsParen_) {} template <typename Fn> void match(Fn F) const { - F(Callee, Args, getPrecedence()); + F(Callee, Args, IsParen, getPrecedence()); } void printLeft(OutputBuffer &OB) const override { + if (IsParen) + OB.printOpen(); Callee->print(OB); + if (IsParen) + OB.printClose(); OB.printOpen(); Args.printWithComma(OB); OB.printClose(); @@ -3354,9 +3360,12 @@ const typename AbstractManglingParser< "operator co_await"}, {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "}, {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"}, - {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"}, + {"cl", OperatorInfo::Call, /*Paren*/ false, Node::Prec::Postfix, + "operator()"}, {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"}, {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"}, + {"cp", OperatorInfo::Call, /*Paren*/ true, Node::Prec::Postfix, + "operator()"}, {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="}, {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary, @@ -5099,6 +5108,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseRequiresExpr() { // ::= <binary operator-name> <expression> <expression> // ::= <ternary operator-name> <expression> <expression> <expression> // ::= cl <expression>+ E # call +// ::= cp <base-unresolved-name> <expression>* E # (name) (expr-list), call that would use argument-dependent lookup but for the parentheses // ::= cv <type> <expression> # conversion with one argument // ::= cv <type> _ <expression>* E # conversion with a different number of arguments // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type @@ -5234,7 +5244,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { Names.push_back(E); } return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin), - Op->getPrecedence()); + /*IsParen=*/Op->getFlag(), Op->getPrecedence()); } case OperatorInfo::CCast: { // C Cast: (type)expr @@ -5421,7 +5431,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { } } return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin), - Node::Prec::Postfix); + /*IsParen=*/false, Node::Prec::Postfix); } // Only unresolved names remain. diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp index 36f9e07..9e8a7c3 100644 --- a/libcxxabi/test/test_demangle.pass.cpp +++ b/libcxxabi/test/test_demangle.pass.cpp @@ -29834,6 +29834,7 @@ const char* cases[][2] = {"_ZN5Casts5auto_IiEEvDTnw_DapicvT__EEE", "void Casts::auto_<int>(decltype(new auto((int)())))"}, {"_ZN5Casts7scalar_IiEEvDTcmcvT__Ecvi_EE", "void Casts::scalar_<int>(decltype((int)(), (int)()))"}, {"_ZN5test11aIsEEDTcl3foocvT__EEES1_", "decltype(foo((short)())) test1::a<short>(short)"}, + {"_ZN5test11bIsEEDTcp3foocvT__EEES1_", "decltype((foo)((short)())) test1::b<short>(short)"}, {"_ZN5test21aIPFfvEEEvT_DTclfL0p_EE", "void test2::a<float (*)()>(float (*)(), decltype(fp()))"}, {"_ZN5test21bIPFfvEEEDTclfp_EET_", "decltype(fp()) test2::b<float (*)()>(float (*)())"}, {"_ZN5test21cIPFfvEEEvT_PFvDTclfL1p_EEE", "void test2::c<float (*)()>(float (*)(), void (*)(decltype(fp())))"}, @@ -30397,24 +30398,24 @@ void test_invalid_cases() assert(!passed && "demangle did not fail"); } -const char *xfail_cases[] = { - // FIXME: Why does clang generate the "cp" expr? - "_ZN5test11bIsEEDTcp3foocvT__EEES1_", +const char *const xfail_cases[] = { + // Sentinel value + nullptr }; -const size_t num_xfails = sizeof(xfail_cases) / sizeof(xfail_cases[0]); - void test_xfail_cases() { std::size_t len = 0; char* buf = nullptr; - for (std::size_t i = 0; i < num_xfails; ++i) + for (const char *c_str : xfail_cases) { + if (!c_str) + break; int status; - char* demang = __cxxabiv1::__cxa_demangle(xfail_cases[i], buf, &len, &status); + char* demang = __cxxabiv1::__cxa_demangle(c_str, buf, &len, &status); if (status != -2) { - std::printf("%s was documented as xfail but passed\n", xfail_cases[i]); + std::printf("%s was documented as xfail but passed\n", c_str); std::printf("Got status = %d\n", status); assert(status == -2); } diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h index 3dfe838..7fba3fd 100644 --- a/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -2077,17 +2077,23 @@ public: class CallExpr : public Node { const Node *Callee; NodeArray Args; + bool IsParen; // (func)(args ...) ? public: - CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_) - : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {} + CallExpr(const Node *Callee_, NodeArray Args_, bool IsParen_, Prec Prec_) + : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_), + IsParen(IsParen_) {} template <typename Fn> void match(Fn F) const { - F(Callee, Args, getPrecedence()); + F(Callee, Args, IsParen, getPrecedence()); } void printLeft(OutputBuffer &OB) const override { + if (IsParen) + OB.printOpen(); Callee->print(OB); + if (IsParen) + OB.printClose(); OB.printOpen(); Args.printWithComma(OB); OB.printClose(); @@ -3354,9 +3360,12 @@ const typename AbstractManglingParser< "operator co_await"}, {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "}, {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"}, - {"cl", OperatorInfo::Call, false, Node::Prec::Postfix, "operator()"}, + {"cl", OperatorInfo::Call, /*Paren*/ false, Node::Prec::Postfix, + "operator()"}, {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"}, {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"}, + {"cp", OperatorInfo::Call, /*Paren*/ true, Node::Prec::Postfix, + "operator()"}, {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="}, {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary, @@ -5099,6 +5108,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseRequiresExpr() { // ::= <binary operator-name> <expression> <expression> // ::= <ternary operator-name> <expression> <expression> <expression> // ::= cl <expression>+ E # call +// ::= cp <base-unresolved-name> <expression>* E # (name) (expr-list), call that would use argument-dependent lookup but for the parentheses // ::= cv <type> <expression> # conversion with one argument // ::= cv <type> _ <expression>* E # conversion with a different number of arguments // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type @@ -5234,7 +5244,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { Names.push_back(E); } return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin), - Op->getPrecedence()); + /*IsParen=*/Op->getFlag(), Op->getPrecedence()); } case OperatorInfo::CCast: { // C Cast: (type)expr @@ -5421,7 +5431,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { } } return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin), - Node::Prec::Postfix); + /*IsParen=*/false, Node::Prec::Postfix); } // Only unresolved names remain. |