Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/llvm/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2022-02-04 22:45:23 +0300
committerNathan Sidwell <nathan@acm.org>2022-03-28 16:17:57 +0300
commitb3b4113a23756eb5f519ff473295483874d8e164 (patch)
tree60fb39cf5d20f2e0cc3674cbe9e437aadac8196c /libcxxabi/src/demangle
parentec6d6210500682e1f5cbf1863b3286304bb5f5bd (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.h554
-rw-r--r--libcxxabi/src/demangle/Utility.h15
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);