diff options
author | Nathan Sidwell <nathan@acm.org> | 2022-02-04 22:45:23 +0300 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2022-03-28 16:17:57 +0300 |
commit | b3b4113a23756eb5f519ff473295483874d8e164 (patch) | |
tree | 60fb39cf5d20f2e0cc3674cbe9e437aadac8196c /libcxxabi/src/demangle | |
parent | ec6d6210500682e1f5cbf1863b3286304bb5f5bd (diff) |
[demangler] Add operator precedence
The demangler had no concept of operator precendence, and would
parenthesize many more subexpressions than necessary. In particular
it would parenthesize primary-expressions, such as '4', which just
looks strange. It would also parenthesize '>' expressions, just in
case they were inside a template parameter list.
This patch fixes both issues.
* Add operator precedence to the OpInfo structure, and add a
subexpression helper that will parenthesize a lower precedence
subexpression.
* Add a 'greater-than is greater-than' indicator to the output buffer,
so the expression printer knows whether it is immediately inside a
template parameter list (and must therefore parenthesize 'expr >
expr'). This is a counter, so that ...
* Add open and close printers to the output buffer, that increment and
decrement the gt-is-gt indicator.
* Parenthesize comma operators inside comma-separated lists. (probably
a rare case, but still).
This dramatically reduces the extraneous parentheses being printed.
Reviewed By: dblaikie, bruno
Differential Revision: https://reviews.llvm.org/D120905
Diffstat (limited to 'libcxxabi/src/demangle')
-rw-r--r-- | libcxxabi/src/demangle/ItaniumDemangle.h | 554 | ||||
-rw-r--r-- | libcxxabi/src/demangle/Utility.h | 15 |
2 files changed, 329 insertions, 240 deletions
diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h index e084cbfc7b80..85b4923a2101 100644 --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -244,28 +244,60 @@ public: /// has an unexpanded parameter pack below it that may affect this cache. enum class Cache : unsigned char { Yes, No, Unknown, }; + /// Operator precedence for expression nodes. Used to determine required + /// parens in expression emission. + enum class Prec { + Primary, + Postfix, + Unary, + Cast, + PtrMem, + Multiplicative, + Additive, + Shift, + Spaceship, + Relational, + Equality, + And, + Xor, + Ior, + AndIf, + OrIf, + Conditional, + Assign, + Comma, + Default, + }; + private: Kind K; + Prec Precedence : 6; + // FIXME: Make these protected. public: /// Tracks if this node has a component on its right side, in which case we /// need to call printRight. - Cache RHSComponentCache; + Cache RHSComponentCache : 2; /// Track if this node is a (possibly qualified) array type. This can affect /// how we format the output string. - Cache ArrayCache; + Cache ArrayCache : 2; /// Track if this node is a (possibly qualified) function type. This can /// affect how we format the output string. - Cache FunctionCache; + Cache FunctionCache : 2; public: - Node(Kind K_, Cache RHSComponentCache_ = Cache::No, - Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No) - : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_), - FunctionCache(FunctionCache_) {} + Node(Kind K_, Prec Precedence_ = Prec::Primary, + Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No, + Cache FunctionCache_ = Cache::No) + : K(K_), Precedence(Precedence_), RHSComponentCache(RHSComponentCache_), + ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {} + Node(Kind K_, Cache RHSComponentCache_, Cache ArrayCache_ = Cache::No, + Cache FunctionCache_ = Cache::No) + : Node(K_, Prec::Primary, RHSComponentCache_, ArrayCache_, + FunctionCache_) {} /// Visit the most-derived object corresponding to this object. template<typename Fn> void visit(Fn F) const; @@ -296,6 +328,8 @@ public: Kind getKind() const { return K; } + Prec getPrecedence() const { return Precedence; } + virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; } virtual bool hasArraySlow(OutputBuffer &) const { return false; } virtual bool hasFunctionSlow(OutputBuffer &) const { return false; } @@ -304,6 +338,19 @@ public: // get at a node that actually represents some concrete syntax. virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; } + // Print this node as an expression operand, surrounding it in parentheses if + // its precedence is [Strictly] weaker than P. + void printAsOperand(OutputBuffer &OB, Prec P = Prec::Default, + bool StrictlyWorse = false) const { + bool Paren = + unsigned(getPrecedence()) >= unsigned(P) + unsigned(StrictlyWorse); + if (Paren) + OB.printOpen(); + print(OB); + if (Paren) + OB.printClose(); + } + void print(OutputBuffer &OB) const { printLeft(OB); if (RHSComponentCache != Cache::No) @@ -353,7 +400,7 @@ public: if (!FirstElement) OB += ", "; size_t AfterComma = OB.getCurrentPosition(); - Elements[Idx]->print(OB); + Elements[Idx]->printAsOperand(OB, Node::Prec::Comma); // Elements[Idx] is an empty parameter pack expansion, we should erase the // comma we just printed. @@ -812,9 +859,9 @@ public: } void printRight(OutputBuffer &OB) const override { - OB += "("; + OB.printOpen(); Params.printWithComma(OB); - OB += ")"; + OB.printClose(); Ret->printRight(OB); if (CVQuals & QualConst) @@ -844,9 +891,10 @@ public: template<typename Fn> void match(Fn F) const { F(E); } void printLeft(OutputBuffer &OB) const override { - OB += "noexcept("; - E->print(OB); - OB += ")"; + OB += "noexcept"; + OB.printOpen(); + E->printAsOperand(OB); + OB.printClose(); } }; @@ -859,9 +907,10 @@ public: template<typename Fn> void match(Fn F) const { F(Types); } void printLeft(OutputBuffer &OB) const override { - OB += "throw("; + OB += "throw"; + OB.printOpen(); Types.printWithComma(OB); - OB += ')'; + OB.printClose(); } }; @@ -907,9 +956,9 @@ public: } void printRight(OutputBuffer &OB) const override { - OB += "("; + OB.printOpen(); Params.printWithComma(OB); - OB += ")"; + OB.printClose(); if (Ret) Ret->printRight(OB); @@ -1211,6 +1260,7 @@ public: template<typename Fn> void match(Fn F) const { F(Name, Params); } void printLeft(OutputBuffer &OB) const override { + SwapAndRestore<unsigned> LT(OB.GtIsGt, 0); OB += "template<"; Params.printWithComma(OB); OB += "> typename "; @@ -1388,6 +1438,7 @@ public: NodeArray getParams() { return Params; } void printLeft(OutputBuffer &OB) const override { + SwapAndRestore<unsigned> LT(OB.GtIsGt, 0); OB += "<"; Params.printWithComma(OB); if (OB.back() == '>') @@ -1685,13 +1736,14 @@ public: void printDeclarator(OutputBuffer &OB) const { if (!TemplateParams.empty()) { + SwapAndRestore<unsigned> LT(OB.GtIsGt, 0); OB += "<"; TemplateParams.printWithComma(OB); OB += ">"; } - OB += "("; + OB.printOpen(); Params.printWithComma(OB); - OB += ")"; + OB.printClose(); } void printLeft(OutputBuffer &OB) const override { @@ -1711,9 +1763,9 @@ public: template<typename Fn> void match(Fn F) const { F(Bindings); } void printLeft(OutputBuffer &OB) const override { - OB += '['; + OB.printOpen('['); Bindings.printWithComma(OB); - OB += ']'; + OB.printClose(']'); } }; @@ -1725,28 +1777,28 @@ class BinaryExpr : public Node { const Node *RHS; public: - BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_) - : Node(KBinaryExpr), LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) { - } + BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_, + Prec Prec_) + : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_), + RHS(RHS_) {} template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); } void printLeft(OutputBuffer &OB) const override { - // might be a template argument expression, then we need to disambiguate - // with parens. - if (InfixOperator == ">") - OB += "("; - - OB += "("; - LHS->print(OB); - OB += ") "; + bool ParenAll = OB.isGtInsideTemplateArgs() && InfixOperator == ">"; + if (ParenAll) + OB.printOpen(); + // Assignment is right associative, with special LHS precedence. + bool IsAssign = getPrecedence() == Prec::Assign; + LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign); + // No space before comma operator + if (!(InfixOperator == ",")) + OB += " "; OB += InfixOperator; - OB += " ("; - RHS->print(OB); - OB += ")"; - - if (InfixOperator == ">") - OB += ")"; + OB += " "; + RHS->printAsOperand(OB, getPrecedence(), IsAssign); + if (ParenAll) + OB.printClose(); } }; @@ -1755,17 +1807,16 @@ class ArraySubscriptExpr : public Node { const Node *Op2; public: - ArraySubscriptExpr(const Node *Op1_, const Node *Op2_) - : Node(KArraySubscriptExpr), Op1(Op1_), Op2(Op2_) {} + ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_) + : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {} template<typename Fn> void match(Fn F) const { F(Op1, Op2); } void printLeft(OutputBuffer &OB) const override { - OB += "("; - Op1->print(OB); - OB += ")["; - Op2->print(OB); - OB += "]"; + Op1->printAsOperand(OB, getPrecedence()); + OB.printOpen('['); + Op2->printAsOperand(OB); + OB.printClose(']'); } }; @@ -1774,15 +1825,13 @@ class PostfixExpr : public Node { const StringView Operator; public: - PostfixExpr(const Node *Child_, StringView Operator_) - : Node(KPostfixExpr), Child(Child_), Operator(Operator_) {} + PostfixExpr(const Node *Child_, StringView Operator_, Prec Prec_) + : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {} template<typename Fn> void match(Fn F) const { F(Child, Operator); } void printLeft(OutputBuffer &OB) const override { - OB += "("; - Child->print(OB); - OB += ")"; + Child->printAsOperand(OB, getPrecedence(), true); OB += Operator; } }; @@ -1793,19 +1842,18 @@ class ConditionalExpr : public Node { const Node *Else; public: - ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_) - : Node(KConditionalExpr), Cond(Cond_), Then(Then_), Else(Else_) {} + ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_, + Prec Prec_) + : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {} template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); } void printLeft(OutputBuffer &OB) const override { - OB += "("; - Cond->print(OB); - OB += ") ? ("; - Then->print(OB); - OB += ") : ("; - Else->print(OB); - OB += ")"; + Cond->printAsOperand(OB, getPrecedence()); + OB += " ? "; + Then->printAsOperand(OB); + OB += " : "; + Else->printAsOperand(OB, Prec::Assign, true); } }; @@ -1815,21 +1863,15 @@ class MemberExpr : public Node { const Node *RHS; public: - MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_) - : Node(KMemberExpr), LHS(LHS_), Kind(Kind_), RHS(RHS_) {} + MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_, Prec Prec_) + : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {} template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); } void printLeft(OutputBuffer &OB) const override { - LHS->print(OB); + LHS->printAsOperand(OB, getPrecedence(), true); OB += Kind; - // Parenthesize pointer-to-member deference argument. - bool IsPtr = Kind.back() == '*'; - if (IsPtr) - OB += '('; - RHS->print(OB); - if (IsPtr) - OB += ')'; + RHS->printAsOperand(OB, getPrecedence(), false); } }; @@ -1873,15 +1915,16 @@ class EnclosingExpr : public Node { const StringView Postfix; public: - EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_) - : Node(KEnclosingExpr), Prefix(Prefix_), Infix(Infix_), - Postfix(Postfix_) {} + EnclosingExpr(StringView Prefix_, Node *Infix_, Prec Prec_ = Prec::Primary) + : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {} - template<typename Fn> void match(Fn F) const { F(Prefix, Infix, Postfix); } + template <typename Fn> void match(Fn F) const { F(Prefix, Infix); } void printLeft(OutputBuffer &OB) const override { OB += Prefix; + OB.printOpen(); Infix->print(OB); + OB.printClose(); OB += Postfix; } }; @@ -1893,18 +1936,24 @@ class CastExpr : public Node { const Node *From; public: - CastExpr(StringView CastKind_, const Node *To_, const Node *From_) - : Node(KCastExpr), CastKind(CastKind_), To(To_), From(From_) {} + CastExpr(StringView CastKind_, const Node *To_, const Node *From_, Prec Prec_) + : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {} template<typename Fn> void match(Fn F) const { F(CastKind, To, From); } void printLeft(OutputBuffer &OB) const override { OB += CastKind; - OB += "<"; - To->printLeft(OB); - OB += ">("; - From->printLeft(OB); - OB += ")"; + { + SwapAndRestore<unsigned> LT(OB.GtIsGt, 0); + OB += "<"; + To->printLeft(OB); + if (OB.back() == '>') + OB += " "; + OB += ">"; + } + OB.printOpen(); + From->printAsOperand(OB); + OB.printClose(); } }; @@ -1918,10 +1967,11 @@ public: template<typename Fn> void match(Fn F) const { F(Pack); } void printLeft(OutputBuffer &OB) const override { - OB += "sizeof...("; + OB += "sizeof..."; + OB.printOpen(); ParameterPackExpansion PPE(Pack); PPE.printLeft(OB); - OB += ")"; + OB.printClose(); } }; @@ -1930,16 +1980,16 @@ class CallExpr : public Node { NodeArray Args; public: - CallExpr(const Node *Callee_, NodeArray Args_) - : Node(KCallExpr), Callee(Callee_), Args(Args_) {} + CallExpr(const Node *Callee_, NodeArray Args_, Prec Prec_) + : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_) {} template<typename Fn> void match(Fn F) const { F(Callee, Args); } void printLeft(OutputBuffer &OB) const override { Callee->print(OB); - OB += "("; + OB.printOpen(); Args.printWithComma(OB); - OB += ")"; + OB.printClose(); } }; @@ -1952,9 +2002,9 @@ class NewExpr : public Node { bool IsArray; // new[] ? public: NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_, - bool IsArray_) - : Node(KNewExpr), ExprList(ExprList_), Type(Type_), InitList(InitList_), - IsGlobal(IsGlobal_), IsArray(IsArray_) {} + bool IsArray_, Prec Prec_) + : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_), + InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {} template<typename Fn> void match(Fn F) const { F(ExprList, Type, InitList, IsGlobal, IsArray); @@ -1967,16 +2017,16 @@ public: if (IsArray) OB += "[]"; if (!ExprList.empty()) { - OB += "("; + OB.printOpen(); ExprList.printWithComma(OB); - OB += ")"; + OB.printClose(); } - OB += ' '; + OB += " "; Type->print(OB); if (!InitList.empty()) { - OB += "("; + OB.printOpen(); InitList.printWithComma(OB); - OB += ")"; + OB.printClose(); } } }; @@ -1987,8 +2037,9 @@ class DeleteExpr : public Node { bool IsArray; public: - DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_) - : Node(KDeleteExpr), Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {} + DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_) + : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_), + IsArray(IsArray_) {} template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); } @@ -2008,16 +2059,14 @@ class PrefixExpr : public Node { Node *Child; public: - PrefixExpr(StringView Prefix_, Node *Child_) - : Node(KPrefixExpr), Prefix(Prefix_), Child(Child_) {} + PrefixExpr(StringView Prefix_, Node *Child_, Prec Prec_) + : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {} template<typename Fn> void match(Fn F) const { F(Prefix, Child); } void printLeft(OutputBuffer &OB) const override { OB += Prefix; - OB += "("; - Child->print(OB); - OB += ")"; + Child->printAsOperand(OB, getPrecedence()); } }; @@ -2040,17 +2089,18 @@ class ConversionExpr : public Node { NodeArray Expressions; public: - ConversionExpr(const Node *Type_, NodeArray Expressions_) - : Node(KConversionExpr), Type(Type_), Expressions(Expressions_) {} + ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_) + : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {} template<typename Fn> void match(Fn F) const { F(Type, Expressions); } void printLeft(OutputBuffer &OB) const override { - OB += "("; + OB.printOpen(); Type->print(OB); - OB += ")("; + OB.printClose(); + OB.printOpen(); Expressions.printWithComma(OB); - OB += ")"; + OB.printClose(); } }; @@ -2061,18 +2111,19 @@ class PointerToMemberConversionExpr : public Node { public: PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_, - StringView Offset_) - : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_), - Offset(Offset_) {} + StringView Offset_, Prec Prec_) + : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_), + SubExpr(SubExpr_), Offset(Offset_) {} template<typename Fn> void match(Fn F) const { F(Type, SubExpr, Offset); } void printLeft(OutputBuffer &OB) const override { - OB += "("; + OB.printOpen(); Type->print(OB); - OB += ")("; + OB.printClose(); + OB.printOpen(); SubExpr->print(OB); - OB += ")"; + OB.printClose(); } }; @@ -2158,41 +2209,33 @@ public: void printLeft(OutputBuffer &OB) const override { auto PrintPack = [&] { - OB += '('; + OB.printOpen(); ParameterPackExpansion(Pack).print(OB); - OB += ')'; + OB.printClose(); }; - OB += '('; - - if (IsLeftFold) { - // init op ... op pack - if (Init != nullptr) { - Init->print(OB); - OB += ' '; - OB += OperatorName; - OB += ' '; - } - // ... op pack - OB += "... "; - OB += OperatorName; - OB += ' '; - PrintPack(); - } else { // !IsLeftFold - // pack op ... - PrintPack(); - OB += ' '; - OB += OperatorName; - OB += " ..."; - // pack op ... op init - if (Init != nullptr) { - OB += ' '; - OB += OperatorName; - OB += ' '; - Init->print(OB); - } + OB.printOpen(); + // Either '[init op ]... op pack' or 'pack op ...[ op init]' + // Refactored to '[(init|pack) op ]...[ op (pack|init)]' + // Fold expr operands are cast-expressions + if (!IsLeftFold || Init != nullptr) { + // '(init|pack) op ' + if (IsLeftFold) + Init->printAsOperand(OB, Prec::Cast, true); + else + PrintPack(); + OB << " " << OperatorName << " "; } - OB += ')'; + OB << "..."; + if (IsLeftFold || Init != nullptr) { + // ' op (init|pack)' + OB << " " << OperatorName << " "; + if (IsLeftFold) + PrintPack(); + else + Init->printAsOperand(OB, Prec::Cast, true); + } + OB.printClose(); } }; @@ -2266,9 +2309,9 @@ public: template<typename Fn> void match(Fn F) const { F(Ty, Integer); } void printLeft(OutputBuffer &OB) const override { - OB << "("; + OB.printOpen(); Ty->print(OB); - OB << ")"; + OB.printClose(); if (Integer[0] == 'n') OB << "-" << Integer.dropFront(1); @@ -2289,13 +2332,13 @@ public: void printLeft(OutputBuffer &OB) const override { if (Type.size() > 3) { - OB += "("; + OB.printOpen(); OB += Type; - OB += ")"; + OB.printClose(); } if (Value[0] == 'n') { - OB += "-"; + OB += '-'; OB += Value.dropFront(1); } else OB += Value; @@ -2526,8 +2569,8 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser { /// Parse the <expr> production. Node *parseExpr(); - Node *parsePrefixExpr(StringView Kind); - Node *parseBinaryExpr(StringView Kind); + Node *parsePrefixExpr(StringView Kind, Node::Prec Prec); + Node *parseBinaryExpr(StringView Kind, Node::Prec Prec); Node *parseIntegerLiteral(StringView Lit); Node *parseExprPrimary(); template <class Float> Node *parseFloatingLiteral(); @@ -2535,7 +2578,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser { Node *parseConversionExpr(); Node *parseBracedExpr(); Node *parseFoldExpr(); - Node *parsePointerToMemberConversionExpr(); + Node *parsePointerToMemberConversionExpr(Node::Prec Prec); Node *parseSubobjectExpr(); /// Parse the <type> production. @@ -2615,11 +2658,13 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser { char Enc[2]; // Encoding OIKind Kind; // Kind of operator bool Flag : 1; // Entry-specific flag + Node::Prec Prec : 7; // Precedence const char *Name; // Spelling public: - constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, const char *N) - : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Name{N} {} + constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P, + const char *N) + : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {} public: bool operator<(const OperatorInfo &Other) const { @@ -2647,6 +2692,7 @@ template <typename Derived, typename Alloc> struct AbstractManglingParser { StringView getName() const { return Name; } OIKind getKind() const { return Kind; } bool getFlag() const { return Flag; } + Node::Prec getPrecedence() const { return Prec; } }; const OperatorInfo *parseOperatorEncoding(); @@ -2950,68 +2996,89 @@ const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo * AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() { static const OperatorInfo Ops[] = { // Keep ordered by encoding - {"aN", OperatorInfo::Binary, false, "operator&="}, - {"aS", OperatorInfo::Binary, false, "operator="}, - {"aa", OperatorInfo::Binary, false, "operator&&"}, - {"ad", OperatorInfo::Prefix, false, "operator&"}, - {"an", OperatorInfo::Binary, false, "operator&"}, - {"at", OperatorInfo::OfIdOp, /*Type*/ true, "alignof ("}, - {"aw", OperatorInfo::NameOnly, false, "operator co_await"}, - {"az", OperatorInfo::OfIdOp, /*Type*/ false, "alignof ("}, - {"cc", OperatorInfo::NamedCast, false, "const_cast"}, - {"cl", OperatorInfo::Call, false, "operator()"}, - {"cm", OperatorInfo::Binary, false, "operator,"}, - {"co", OperatorInfo::Prefix, false, "operator~"}, - {"cv", OperatorInfo::CCast, false, "operator"}, // C Cast - {"dV", OperatorInfo::Binary, false, "operator/="}, - {"da", OperatorInfo::Del, /*Ary*/ true, "operator delete[]"}, - {"dc", OperatorInfo::NamedCast, false, "dynamic_cast"}, - {"de", OperatorInfo::Prefix, false, "operator*"}, - {"dl", OperatorInfo::Del, /*Ary*/ false, "operator delete"}, - {"ds", OperatorInfo::Member, /*Named*/ false, "operator.*"}, - {"dt", OperatorInfo::Member, /*Named*/ false, "operator."}, - {"dv", OperatorInfo::Binary, false, "operator/"}, - {"eO", OperatorInfo::Binary, false, "operator^="}, - {"eo", OperatorInfo::Binary, false, "operator^"}, - {"eq", OperatorInfo::Binary, false, "operator=="}, - {"ge", OperatorInfo::Binary, false, "operator>="}, - {"gt", OperatorInfo::Binary, false, "operator>"}, - {"ix", OperatorInfo::Array, false, "operator[]"}, - {"lS", OperatorInfo::Binary, false, "operator<<="}, - {"le", OperatorInfo::Binary, false, "operator<="}, - {"ls", OperatorInfo::Binary, false, "operator<<"}, - {"lt", OperatorInfo::Binary, false, "operator<"}, - {"mI", OperatorInfo::Binary, false, "operator-="}, - {"mL", OperatorInfo::Binary, false, "operator*="}, - {"mi", OperatorInfo::Binary, false, "operator-"}, - {"ml", OperatorInfo::Binary, false, "operator*"}, - {"mm", OperatorInfo::Postfix, false, "operator--"}, - {"na", OperatorInfo::New, /*Ary*/ true, "operator new[]"}, - {"ne", OperatorInfo::Binary, false, "operator!="}, - {"ng", OperatorInfo::Prefix, false, "operator-"}, - {"nt", OperatorInfo::Prefix, false, "operator!"}, - {"nw", OperatorInfo::New, /*Ary*/ false, "operator new"}, - {"oR", OperatorInfo::Binary, false, "operator|="}, - {"oo", OperatorInfo::Binary, false, "operator||"}, - {"or", OperatorInfo::Binary, false, "operator|"}, - {"pL", OperatorInfo::Binary, false, "operator+="}, - {"pl", OperatorInfo::Binary, false, "operator+"}, - {"pm", OperatorInfo::Member, /*Named*/ false, "operator->*"}, - {"pp", OperatorInfo::Postfix, false, "operator++"}, - {"ps", OperatorInfo::Prefix, false, "operator+"}, - {"pt", OperatorInfo::Member, /*Named*/ true, "operator->"}, - {"qu", OperatorInfo::Conditional, false, "operator?"}, - {"rM", OperatorInfo::Binary, false, "operator%="}, - {"rS", OperatorInfo::Binary, false, "operator>>="}, - {"rc", OperatorInfo::NamedCast, false, "reinterpret_cast"}, - {"rm", OperatorInfo::Binary, false, "operator%"}, - {"rs", OperatorInfo::Binary, false, "operator>>"}, - {"sc", OperatorInfo::NamedCast, false, "static_cast"}, - {"ss", OperatorInfo::Binary, false, "operator<=>"}, - {"st", OperatorInfo::OfIdOp, /*Type*/ true, "sizeof ("}, - {"sz", OperatorInfo::OfIdOp, /*Type*/ false, "sizeof ("}, - {"te", OperatorInfo::OfIdOp, /*Type*/ false, "typeid ("}, - {"ti", OperatorInfo::OfIdOp, /*Type*/ true, "typeid ("}, + {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="}, + {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="}, + {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"}, + {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"}, + {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"}, + {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, + "alignof "}, + {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary, + "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()"}, + {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"}, + {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "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, + "operator delete[]"}, + {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, + "dynamic_cast"}, + {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"}, + {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary, + "operator delete"}, + {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem, + "operator.*"}, + {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix, + "operator."}, + {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"}, + {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="}, + {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"}, + {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="}, + {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="}, + {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"}, + {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"}, + {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="}, + {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="}, + {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"}, + {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"}, + {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="}, + {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="}, + {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"}, + {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative, + "operator*"}, + {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"}, + {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary, + "operator new[]"}, + {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="}, + {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"}, + {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"}, + {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, + "operator new"}, + {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="}, + {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"}, + {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"}, + {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="}, + {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"}, + {"pm", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem, + "operator->*"}, + {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"}, + {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"}, + {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix, + "operator->"}, + {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional, + "operator?"}, + {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="}, + {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="}, + {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, + "reinterpret_cast"}, + {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative, + "operator%"}, + {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"}, + {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, + "static_cast"}, + {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"}, + {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "}, + {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, + "sizeof "}, + {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix, + "typeid "}, + {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, + "typeid "}, }; const auto NumOps = sizeof(Ops) / sizeof(Ops[0]); @@ -3618,7 +3685,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() { return nullptr; if (!consumeIf('E')) return nullptr; - return make<EnclosingExpr>("decltype(", E, ")"); + return make<EnclosingExpr>("decltype", E); } // <array-type> ::= A <positive dimension number> _ <element type> @@ -4105,22 +4172,24 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() { } template <typename Derived, typename Alloc> -Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind) { +Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind, + Node::Prec Prec) { Node *E = getDerived().parseExpr(); if (E == nullptr) return nullptr; - return make<PrefixExpr>(Kind, E); + return make<PrefixExpr>(Kind, E, Prec); } template <typename Derived, typename Alloc> -Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind) { +Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind, + Node::Prec Prec) { Node *LHS = getDerived().parseExpr(); if (LHS == nullptr) return nullptr; Node *RHS = getDerived().parseExpr(); if (RHS == nullptr) return nullptr; - return make<BinaryExpr>(LHS, Kind, RHS); + return make<BinaryExpr>(LHS, Kind, RHS, Prec); } template <typename Derived, typename Alloc> @@ -4431,7 +4500,9 @@ Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() { // // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47 template <typename Derived, typename Alloc> -Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr() { +Node * +AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr( + Node::Prec Prec) { Node *Ty = getDerived().parseType(); if (!Ty) return nullptr; @@ -4441,7 +4512,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr StringView Offset = getDerived().parseNumber(true); if (!consumeIf('E')) return nullptr; - return make<PointerToMemberConversionExpr>(Ty, Expr, Offset); + return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec); } // <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E @@ -4525,18 +4596,18 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { switch (Op->getKind()) { case OperatorInfo::Binary: // Binary operator: lhs @ rhs - return getDerived().parseBinaryExpr(Sym); + return getDerived().parseBinaryExpr(Sym, Op->getPrecedence()); case OperatorInfo::Prefix: // Prefix unary operator: @ expr - return getDerived().parsePrefixExpr(Sym); + return getDerived().parsePrefixExpr(Sym, Op->getPrecedence()); case OperatorInfo::Postfix: { // Postfix unary operator: expr @ if (consumeIf('_')) - return getDerived().parsePrefixExpr(Sym); + return getDerived().parsePrefixExpr(Sym, Op->getPrecedence()); Node *Ex = getDerived().parseExpr(); if (Ex == nullptr) return nullptr; - return make<PostfixExpr>(Ex, Sym); + return make<PostfixExpr>(Ex, Sym, Op->getPrecedence()); } case OperatorInfo::Array: { // Array Index: lhs [ rhs ] @@ -4546,7 +4617,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { Node *Index = getDerived().parseExpr(); if (Index == nullptr) return nullptr; - return make<ArraySubscriptExpr>(Base, Index); + return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence()); } case OperatorInfo::Member: { // Member access lhs @ rhs @@ -4556,7 +4627,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { Node *RHS = getDerived().parseExpr(); if (RHS == nullptr) return nullptr; - return make<MemberExpr>(LHS, Sym, RHS); + return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence()); } case OperatorInfo::New: { // New @@ -4587,14 +4658,15 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { } NodeArray Inits = popTrailingNodeArray(InitsBegin); return make<NewExpr>(ExprList, Ty, Inits, Global, - /*IsArray=*/Op->getFlag()); + /*IsArray=*/Op->getFlag(), Op->getPrecedence()); } case OperatorInfo::Del: { // Delete Node *Ex = getDerived().parseExpr(); if (Ex == nullptr) return nullptr; - return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag()); + return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(), + Op->getPrecedence()); } case OperatorInfo::Call: { // Function Call @@ -4608,7 +4680,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { return nullptr; Names.push_back(E); } - return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin)); + return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin), + Op->getPrecedence()); } case OperatorInfo::CCast: { // C Cast: (type)expr @@ -4633,7 +4706,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { NodeArray Exprs = popTrailingNodeArray(ExprsBegin); if (!IsMany && Exprs.size() != 1) return nullptr; - return make<ConversionExpr>(Ty, Exprs); + return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence()); } case OperatorInfo::Conditional: { // Conditional operator: expr ? expr : expr @@ -4646,7 +4719,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { Node *RHS = getDerived().parseExpr(); if (RHS == nullptr) return nullptr; - return make<ConditionalExpr>(Cond, LHS, RHS); + return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence()); } case OperatorInfo::NamedCast: { // Named cast operation, @<type>(expr) @@ -4656,7 +4729,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { Node *Ex = getDerived().parseExpr(); if (Ex == nullptr) return nullptr; - return make<CastExpr>(Sym, Ty, Ex); + return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence()); } case OperatorInfo::OfIdOp: { // [sizeof/alignof/typeid] ( <type>|<expr> ) @@ -4664,7 +4737,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr(); if (!Arg) return nullptr; - return make<EnclosingExpr>(Sym, Arg, ")"); + return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence()); } case OperatorInfo::NameOnly: { // Not valid as an expression operand. @@ -4698,12 +4771,12 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin)); } if (consumeIf("mc")) - return parsePointerToMemberConversionExpr(); + return parsePointerToMemberConversionExpr(Node::Prec::Unary); if (consumeIf("nx")) { Node *Ex = getDerived().parseExpr(); if (Ex == nullptr) return Ex; - return make<EnclosingExpr>("noexcept (", Ex, ")"); + return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary); } if (consumeIf("so")) return parseSubobjectExpr(); @@ -4723,7 +4796,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { Node *FP = getDerived().parseFunctionParam(); if (FP == nullptr) return nullptr; - return make<EnclosingExpr>("sizeof... (", FP, ")"); + return make<EnclosingExpr>("sizeof... ", FP); } if (consumeIf("sP")) { size_t ArgsBegin = Names.size(); @@ -4736,7 +4809,7 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin)); if (!Pack) return nullptr; - return make<EnclosingExpr>("sizeof... (", Pack, ")"); + return make<EnclosingExpr>("sizeof... ", Pack); } if (consumeIf("tl")) { Node *Ty = getDerived().parseType(); @@ -4792,7 +4865,8 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { Names.push_back(E); } } - return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin)); + return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin), + Node::Prec::Postfix); } // Only unresolved names remain. diff --git a/libcxxabi/src/demangle/Utility.h b/libcxxabi/src/demangle/Utility.h index 1c4604160749..76330851d21b 100644 --- a/libcxxabi/src/demangle/Utility.h +++ b/libcxxabi/src/demangle/Utility.h @@ -86,6 +86,21 @@ public: unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max(); unsigned CurrentPackMax = std::numeric_limits<unsigned>::max(); + /// When zero, we're printing template args and '>' needs to be parenthesized. + /// Use a counter so we can simply increment inside parentheses. + unsigned GtIsGt = 1; + + bool isGtInsideTemplateArgs() const { return GtIsGt == 0; } + + void printOpen(char Open = '(') { + GtIsGt++; + *this += Open; + } + void printClose(char Close = ')') { + GtIsGt--; + *this += Close; + } + OutputBuffer &operator+=(StringView R) { if (size_t Size = R.size()) { grow(Size); |