diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -2556,6 +2556,62 @@ Node *parseAbiTags(Node *N); + struct OperatorInfo { + enum OIKind : unsigned char { + Prefix, // Prefix unary: @ expr + Postfix, // Postfix unary: expr @ + Binary, // Binary: lhs @ rhs + Array, // Array index: lhs [ rhs ] + Member, // Member access: lhs @ rhs + New, // New + Del, // Delete + Call, // Function call: expr (expr*) + CCast, // C cast: (type)expr + Conditional, // Conditional: expr ? expr : expr + // Below do not have operator names + NamedCast, // Named cast, @(expr) + OfIdOp, // alignof, sizeof, typeid + + Unnameable = NamedCast, + }; + char Enc[2]; // Encoding + OIKind Kind; // Kind of operator + bool Flag : 1; // Entry-specific flag + 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} {} + + public: + bool operator<(const OperatorInfo &Other) const { + return *this < Other.Enc; + } + bool operator<(const char *Peek) const { + return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]); + } + bool operator==(const char *Peek) const { + return Enc[0] == Peek[0] && Enc[1] == Peek[1]; + } + bool operator!=(const char *Peek) const { return !this->operator==(Peek); } + + public: + StringView getSymbol() const { + StringView Res = Name; + if (Kind < Unnameable) { + assert(Res.startsWith("operator") && + "operator name does not start with 'operator'"); + Res = Res.dropFront(sizeof("operator") - 1); + Res.consumeFront(' '); + } + return Res; + } + StringView getName() const { return Name; } + OIKind getKind() const { return Kind; } + bool getFlag() const { return Flag; } + }; + const OperatorInfo *parseOperatorEncoding(); + /// Parse the production. Node *parseUnresolvedName(bool Global); Node *parseSimpleId(); @@ -2808,92 +2864,111 @@ return make(Name); } -// ::= aa # && -// ::= ad # & (unary) -// ::= an # & -// ::= aN # &= -// ::= aS # = -// ::= cl # () -// ::= cm # , -// ::= co # ~ -// ::= cv # (cast) -// ::= da # delete[] -// ::= de # * (unary) -// ::= dl # delete -// ::= dv # / -// ::= dV # /= -// ::= eo # ^ -// ::= eO # ^= -// ::= eq # == -// ::= ge # >= -// ::= gt # > -// ::= ix # [] -// ::= le # <= +// If the next 2 chars are an operator encoding, consume them and return their +// OperatorInfo. Otherwise return nullptr. +template +const typename AbstractManglingParser::OperatorInfo * +AbstractManglingParser::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 ("}, + {"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 ("}, + }; + const auto NumOps = sizeof(Ops) / sizeof(Ops[0]); + +#ifndef NDEBUG + { + // Verify table order. + static bool Done; + if (!Done) { + Done = true; + for (const auto *Op = &Ops[0]; Op != &Ops[NumOps - 1]; Op++) + assert(Op[0] < Op[1] && "Operator table is not ordered"); + } + } +#endif + + if (numLeft() < 2) + return nullptr; + + auto Op = std::lower_bound( + &Ops[0], &Ops[NumOps], First, + [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; }); + if (Op == &Ops[NumOps] || *Op != First) + return nullptr; + + First += 2; + return Op; +} + +// ::= See parseOperatorEncoding() // ::= li # operator "" -// ::= ls # << -// ::= lS # <<= -// ::= lt # < -// ::= mi # - -// ::= mI # -= -// ::= ml # * -// ::= mL # *= -// ::= mm # -- (postfix in context) -// ::= na # new[] -// ::= ne # != -// ::= ng # - (unary) -// ::= nt # ! -// ::= nw # new -// ::= oo # || -// ::= or # | -// ::= oR # |= -// ::= pm # ->* -// ::= pl # + -// ::= pL # += -// ::= pp # ++ (postfix in context) -// ::= ps # + (unary) -// ::= pt # -> -// ::= qu # ? -// ::= rm # % -// ::= rM # %= -// ::= rs # >> -// ::= rS # >>= -// ::= ss # <=> C++2a -// ::= v # vendor extended operator +// ::= v # vendor extended operator template Node * AbstractManglingParser::parseOperatorName(NameState *State) { - switch (look()) { - case 'a': - switch (look(1)) { - case 'a': - First += 2; - return make("operator&&"); - case 'd': - case 'n': - First += 2; - return make("operator&"); - case 'N': - First += 2; - return make("operator&="); - case 'S': - First += 2; - return make("operator="); - } - return nullptr; - case 'c': - switch (look(1)) { - case 'l': - First += 2; - return make("operator()"); - case 'm': - First += 2; - return make("operator,"); - case 'o': - First += 2; - return make("operator~"); - // ::= cv # (cast) - case 'v': { - First += 2; + if (const auto *Op = parseOperatorEncoding()) { + if (Op->getKind() == OperatorInfo::CCast) { + // ::= cv # (cast) SwapAndRestore SaveTemplate(TryToParseTemplateArgs, false); // If we're parsing an encoding, State != nullptr and the conversion // operators' could have a that refers to some @@ -2907,185 +2982,29 @@ if (State) State->CtorDtorConversion = true; return make(Ty); } - } - return nullptr; - case 'd': - switch (look(1)) { - case 'a': - First += 2; - return make("operator delete[]"); - case 'e': - First += 2; - return make("operator*"); - case 'l': - First += 2; - return make("operator delete"); - case 'v': - First += 2; - return make("operator/"); - case 'V': - First += 2; - return make("operator/="); - } - return nullptr; - case 'e': - switch (look(1)) { - case 'o': - First += 2; - return make("operator^"); - case 'O': - First += 2; - return make("operator^="); - case 'q': - First += 2; - return make("operator=="); - } - return nullptr; - case 'g': - switch (look(1)) { - case 'e': - First += 2; - return make("operator>="); - case 't': - First += 2; - return make("operator>"); - } - return nullptr; - case 'i': - if (look(1) == 'x') { - First += 2; - return make("operator[]"); - } - return nullptr; - case 'l': - switch (look(1)) { - case 'e': - First += 2; - return make("operator<="); + + if (Op->getKind() >= OperatorInfo::Unnameable) + /* Not a nameable operator. */ + return nullptr; + if (Op->getKind() == OperatorInfo::Member && !Op->getFlag()) + /* Not a nameable MemberExpr */ + return nullptr; + + return make(Op->getName()); + } + + if (consumeIf("li")) { // ::= li # operator "" - case 'i': { - First += 2; - Node *SN = getDerived().parseSourceName(State); - if (SN == nullptr) - return nullptr; - return make(SN); - } - case 's': - First += 2; - return make("operator<<"); - case 'S': - First += 2; - return make("operator<<="); - case 't': - First += 2; - return make("operator<"); - } - return nullptr; - case 'm': - switch (look(1)) { - case 'i': - First += 2; - return make("operator-"); - case 'I': - First += 2; - return make("operator-="); - case 'l': - First += 2; - return make("operator*"); - case 'L': - First += 2; - return make("operator*="); - case 'm': - First += 2; - return make("operator--"); - } - return nullptr; - case 'n': - switch (look(1)) { - case 'a': - First += 2; - return make("operator new[]"); - case 'e': - First += 2; - return make("operator!="); - case 'g': - First += 2; - return make("operator-"); - case 't': - First += 2; - return make("operator!"); - case 'w': - First += 2; - return make("operator new"); - } - return nullptr; - case 'o': - switch (look(1)) { - case 'o': - First += 2; - return make("operator||"); - case 'r': - First += 2; - return make("operator|"); - case 'R': - First += 2; - return make("operator|="); - } - return nullptr; - case 'p': - switch (look(1)) { - case 'm': - First += 2; - return make("operator->*"); - case 'l': - First += 2; - return make("operator+"); - case 'L': - First += 2; - return make("operator+="); - case 'p': - First += 2; - return make("operator++"); - case 's': - First += 2; - return make("operator+"); - case 't': - First += 2; - return make("operator->"); - } - return nullptr; - case 'q': - if (look(1) == 'u') { - First += 2; - return make("operator?"); - } - return nullptr; - case 'r': - switch (look(1)) { - case 'm': - First += 2; - return make("operator%"); - case 'M': - First += 2; - return make("operator%="); - case 's': - First += 2; - return make("operator>>"); - case 'S': - First += 2; - return make("operator>>="); - } - return nullptr; - case 's': - if (look(1) == 's') { - First += 2; - return make("operator<=>"); - } - return nullptr; - // ::= v # vendor extended operator - case 'v': - if (std::isdigit(look(1))) { - First += 2; + Node *SN = getDerived().parseSourceName(State); + if (SN == nullptr) + return nullptr; + return make(SN); + } + + if (consumeIf('v')) { + // ::= v # vendor extended operator + if (look() >= '0' && look() <= '9') { + First++; Node *SN = getDerived().parseSourceName(State); if (SN == nullptr) return nullptr; @@ -3093,6 +3012,7 @@ } return nullptr; } + return nullptr; } @@ -4374,55 +4294,34 @@ if (!consumeIf('f')) return nullptr; - char FoldKind = look(); - bool IsLeftFold, HasInitializer; - HasInitializer = FoldKind == 'L' || FoldKind == 'R'; - if (FoldKind == 'l' || FoldKind == 'L') - IsLeftFold = true; - else if (FoldKind == 'r' || FoldKind == 'R') - IsLeftFold = false; - else + bool IsLeftFold = false, HasInitializer = false; + switch (look()) { + default: return nullptr; + case 'L': + IsLeftFold = true; + HasInitializer = true; + break; + case 'R': + HasInitializer = true; + break; + case 'l': + IsLeftFold = true; + break; + case 'r': + break; + } ++First; - // FIXME: This map is duplicated in parseOperatorName and parseExpr. - StringView OperatorName; - if (consumeIf("aa")) OperatorName = "&&"; - else if (consumeIf("an")) OperatorName = "&"; - else if (consumeIf("aN")) OperatorName = "&="; - else if (consumeIf("aS")) OperatorName = "="; - else if (consumeIf("cm")) OperatorName = ","; - else if (consumeIf("ds")) OperatorName = ".*"; - else if (consumeIf("dv")) OperatorName = "/"; - else if (consumeIf("dV")) OperatorName = "/="; - else if (consumeIf("eo")) OperatorName = "^"; - else if (consumeIf("eO")) OperatorName = "^="; - else if (consumeIf("eq")) OperatorName = "=="; - else if (consumeIf("ge")) OperatorName = ">="; - else if (consumeIf("gt")) OperatorName = ">"; - else if (consumeIf("le")) OperatorName = "<="; - else if (consumeIf("ls")) OperatorName = "<<"; - else if (consumeIf("lS")) OperatorName = "<<="; - else if (consumeIf("lt")) OperatorName = "<"; - else if (consumeIf("mi")) OperatorName = "-"; - else if (consumeIf("mI")) OperatorName = "-="; - else if (consumeIf("ml")) OperatorName = "*"; - else if (consumeIf("mL")) OperatorName = "*="; - else if (consumeIf("ne")) OperatorName = "!="; - else if (consumeIf("oo")) OperatorName = "||"; - else if (consumeIf("or")) OperatorName = "|"; - else if (consumeIf("oR")) OperatorName = "|="; - else if (consumeIf("pl")) OperatorName = "+"; - else if (consumeIf("pL")) OperatorName = "+="; - else if (consumeIf("rm")) OperatorName = "%"; - else if (consumeIf("rM")) OperatorName = "%="; - else if (consumeIf("rs")) OperatorName = ">>"; - else if (consumeIf("rS")) OperatorName = ">>="; - else return nullptr; - - Node *Pack = getDerived().parseExpr(), *Init = nullptr; + const auto *Op = parseOperatorEncoding(); + if (!Op || Op->getKind() != OperatorInfo::Binary) + return nullptr; + + Node *Pack = getDerived().parseExpr(); if (Pack == nullptr) return nullptr; + + Node *Init = nullptr; if (HasInitializer) { Init = getDerived().parseExpr(); if (Init == nullptr) @@ -4432,7 +4331,7 @@ if (IsLeftFold && Init) std::swap(Pack, Init); - return make(IsLeftFold, OperatorName, Pack, Init); + return make(IsLeftFold, Op->getSymbol(), Pack, Init); } // ::= mc [] E @@ -4526,350 +4425,125 @@ template Node *AbstractManglingParser::parseExpr() { bool Global = consumeIf("gs"); - if (numLeft() < 2) - return nullptr; - switch (*First) { - case 'L': - return getDerived().parseExprPrimary(); - case 'T': - return getDerived().parseTemplateParam(); - case 'f': { - // Disambiguate a fold expression from a . - if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2)))) - return getDerived().parseFunctionParam(); - return getDerived().parseFoldExpr(); - } - case 'a': - switch (First[1]) { - case 'a': - First += 2; - return getDerived().parseBinaryExpr("&&"); - case 'd': - First += 2; - return getDerived().parsePrefixExpr("&"); - case 'n': - First += 2; - return getDerived().parseBinaryExpr("&"); - case 'N': - First += 2; - return getDerived().parseBinaryExpr("&="); - case 'S': - First += 2; - return getDerived().parseBinaryExpr("="); - case 't': { - First += 2; - Node *Ty = getDerived().parseType(); - if (Ty == nullptr) + const auto *Op = parseOperatorEncoding(); + if (Op) { + auto Sym = Op->getSymbol(); + switch (Op->getKind()) { + case OperatorInfo::Binary: + // Binary operator: lhs @ rhs + return getDerived().parseBinaryExpr(Sym); + case OperatorInfo::Prefix: + // Prefix unary operator: @ expr + return getDerived().parsePrefixExpr(Sym); + case OperatorInfo::Postfix: { + // Postfix unary operator: expr @ + if (consumeIf('_')) + return getDerived().parsePrefixExpr(Sym); + Node *Ex = getDerived().parseExpr(); + if (Ex == nullptr) return nullptr; - return make("alignof (", Ty, ")"); + return make(Ex, Sym); } - case 'z': { - First += 2; - Node *Ty = getDerived().parseExpr(); - if (Ty == nullptr) + case OperatorInfo::Array: { + // Array Index: lhs [ rhs ] + Node *Base = getDerived().parseExpr(); + if (Base == nullptr) return nullptr; - return make("alignof (", Ty, ")"); - } + Node *Index = getDerived().parseExpr(); + if (Index == nullptr) + return nullptr; + return make(Base, Index); } - return nullptr; - case 'c': - switch (First[1]) { - // cc # const_cast(expression) - case 'c': { - First += 2; + case OperatorInfo::Member: { + // Member access lhs @ rhs + Node *LHS = getDerived().parseExpr(); + if (LHS == nullptr) + return nullptr; + Node *RHS = getDerived().parseExpr(); + if (RHS == nullptr) + return nullptr; + return make(LHS, Sym, RHS); + } + case OperatorInfo::New: { + // New + // # new (expr-list) type [(init)] + // [gs] nw * _ [pi *] E + // # new[] (expr-list) type [(init)] + // [gs] na * _ [pi *] E + 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; + return nullptr; + bool HaveInits = consumeIf("pi"); + size_t InitsBegin = Names.size(); + while (!consumeIf('E')) { + if (!HaveInits) + return nullptr; + Node *Init = getDerived().parseExpr(); + if (Init == nullptr) + return Init; + Names.push_back(Init); + } + NodeArray Inits = popTrailingNodeArray(InitsBegin); + return make(ExprList, Ty, Inits, Global, + /*IsArray=*/Op->getFlag()); + } + case OperatorInfo::Del: { + // Delete Node *Ex = getDerived().parseExpr(); if (Ex == nullptr) - return Ex; - return make("const_cast", Ty, Ex); + return nullptr; + return make(Ex, Global, /*IsArray=*/Op->getFlag()); } - // cl + E # call - case 'l': { - First += 2; + case OperatorInfo::Call: { + // Function Call Node *Callee = getDerived().parseExpr(); if (Callee == nullptr) - return Callee; + return nullptr; size_t ExprsBegin = Names.size(); while (!consumeIf('E')) { Node *E = getDerived().parseExpr(); - if (E == nullptr) - return E; - Names.push_back(E); - } - return make(Callee, popTrailingNodeArray(ExprsBegin)); - } - case 'm': - First += 2; - return getDerived().parseBinaryExpr(","); - case 'o': - First += 2; - return getDerived().parsePrefixExpr("~"); - case 'v': - return getDerived().parseConversionExpr(); - } - return nullptr; - case 'd': - switch (First[1]) { - case 'a': { - First += 2; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make(Ex, Global, /*is_array=*/true); - } - case 'c': { - First += 2; - Node *T = getDerived().parseType(); - if (T == nullptr) - return T; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make("dynamic_cast", T, Ex); - } - case 'e': - First += 2; - return getDerived().parsePrefixExpr("*"); - case 'l': { - First += 2; - Node *E = getDerived().parseExpr(); - if (E == nullptr) - return E; - return make(E, Global, /*is_array=*/false); - } - case 'n': - return getDerived().parseUnresolvedName(Global); - case 's': { - First += 2; - Node *LHS = getDerived().parseExpr(); - if (LHS == nullptr) - return nullptr; - Node *RHS = getDerived().parseExpr(); - if (RHS == nullptr) - return nullptr; - return make(LHS, ".*", RHS); - } - case 't': { - First += 2; - Node *LHS = getDerived().parseExpr(); - if (LHS == nullptr) - return LHS; - Node *RHS = getDerived().parseExpr(); - if (RHS == nullptr) - return nullptr; - return make(LHS, ".", RHS); - } - case 'v': - First += 2; - return getDerived().parseBinaryExpr("/"); - case 'V': - First += 2; - return getDerived().parseBinaryExpr("/="); - } - return nullptr; - case 'e': - switch (First[1]) { - case 'o': - First += 2; - return getDerived().parseBinaryExpr("^"); - case 'O': - First += 2; - return getDerived().parseBinaryExpr("^="); - case 'q': - First += 2; - return getDerived().parseBinaryExpr("=="); - } - return nullptr; - case 'g': - switch (First[1]) { - case 'e': - First += 2; - return getDerived().parseBinaryExpr(">="); - case 't': - First += 2; - return getDerived().parseBinaryExpr(">"); - } - return nullptr; - case 'i': - switch (First[1]) { - case 'x': { - First += 2; - Node *Base = getDerived().parseExpr(); - if (Base == nullptr) - return nullptr; - Node *Index = getDerived().parseExpr(); - if (Index == nullptr) - return Index; - return make(Base, Index); - } - case 'l': { - First += 2; - size_t InitsBegin = Names.size(); - while (!consumeIf('E')) { - Node *E = getDerived().parseBracedExpr(); if (E == nullptr) return nullptr; Names.push_back(E); } - return make(nullptr, popTrailingNodeArray(InitsBegin)); - } - } - return nullptr; - case 'l': - switch (First[1]) { - case 'e': - First += 2; - return getDerived().parseBinaryExpr("<="); - case 's': - First += 2; - return getDerived().parseBinaryExpr("<<"); - case 'S': - First += 2; - return getDerived().parseBinaryExpr("<<="); - case 't': - First += 2; - return getDerived().parseBinaryExpr("<"); - } - return nullptr; - case 'm': - switch (First[1]) { - case 'c': - First += 2; - return parsePointerToMemberConversionExpr(); - case 'i': - First += 2; - return getDerived().parseBinaryExpr("-"); - case 'I': - First += 2; - return getDerived().parseBinaryExpr("-="); - case 'l': - First += 2; - return getDerived().parseBinaryExpr("*"); - case 'L': - First += 2; - return getDerived().parseBinaryExpr("*="); - case 'm': - First += 2; - if (consumeIf('_')) - return getDerived().parsePrefixExpr("--"); - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return nullptr; - return make(Ex, "--"); + return make(Callee, popTrailingNodeArray(ExprsBegin)); } - return nullptr; - case 'n': - switch (First[1]) { - case 'a': - case 'w': { - // [gs] nw * _ [pi *] E # new (expr-list) type [(init)] - // [gs] na * _ [pi *] E # new[] (expr-list) type [(init)] - bool IsArray = First[1] == 'a'; - First += 2; - size_t Exprs = Names.size(); - while (!consumeIf('_')) { - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return nullptr; - Names.push_back(Ex); + case OperatorInfo::CCast: { + // C Cast: (type)expr + Node *Ty; + { + SwapAndRestore SaveTemp(TryToParseTemplateArgs, false); + Ty = getDerived().parseType(); } - NodeArray ExprList = popTrailingNodeArray(Exprs); - Node *Ty = getDerived().parseType(); if (Ty == nullptr) return nullptr; - bool HaveInits = consumeIf("pi"); - size_t InitsBegin = Names.size(); + + size_t ExprsBegin = Names.size(); + bool IsMany = consumeIf('_'); while (!consumeIf('E')) { - if (!HaveInits) - return nullptr; - Node *Init = getDerived().parseExpr(); - if (Init == nullptr) - return Init; - Names.push_back(Init); + Node *E = getDerived().parseExpr(); + if (E == nullptr) + return E; + Names.push_back(E); + if (!IsMany) + break; } - NodeArray Inits = popTrailingNodeArray(InitsBegin); - return make(ExprList, Ty, Inits, Global, IsArray); - } - case 'e': - First += 2; - return getDerived().parseBinaryExpr("!="); - case 'g': - First += 2; - return getDerived().parsePrefixExpr("-"); - case 't': - First += 2; - return getDerived().parsePrefixExpr("!"); - case 'x': - First += 2; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make("noexcept (", Ex, ")"); - } - return nullptr; - case 'o': - switch (First[1]) { - case 'n': - return getDerived().parseUnresolvedName(Global); - case 'o': - First += 2; - return getDerived().parseBinaryExpr("||"); - case 'r': - First += 2; - return getDerived().parseBinaryExpr("|"); - case 'R': - First += 2; - return getDerived().parseBinaryExpr("|="); - } - return nullptr; - case 'p': - switch (First[1]) { - case 'm': { - First += 2; - Node *LHS = getDerived().parseExpr(); - if (LHS == nullptr) - return LHS; - Node *RHS = getDerived().parseExpr(); - if (RHS == nullptr) + NodeArray Exprs = popTrailingNodeArray(ExprsBegin); + if (!IsMany && Exprs.size() != 1) return nullptr; - return make(LHS, "->*", RHS); + return make(Ty, Exprs); } - case 'l': - First += 2; - return getDerived().parseBinaryExpr("+"); - case 'L': - First += 2; - return getDerived().parseBinaryExpr("+="); - case 'p': { - First += 2; - if (consumeIf('_')) - return getDerived().parsePrefixExpr("++"); - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make(Ex, "++"); - } - case 's': - First += 2; - return getDerived().parsePrefixExpr("+"); - case 't': { - First += 2; - Node *L = getDerived().parseExpr(); - if (L == nullptr) - return nullptr; - Node *R = getDerived().parseExpr(); - if (R == nullptr) - return nullptr; - return make(L, "->", R); - } - } - return nullptr; - case 'q': - if (First[1] == 'u') { - First += 2; + case OperatorInfo::Conditional: { + // Conditional operator: expr ? expr : expr Node *Cond = getDerived().parseExpr(); if (Cond == nullptr) return nullptr; @@ -4881,145 +4555,114 @@ return nullptr; return make(Cond, LHS, RHS); } - return nullptr; - case 'r': - switch (First[1]) { - case 'c': { - First += 2; - Node *T = getDerived().parseType(); - if (T == nullptr) - return T; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make("reinterpret_cast", T, Ex); - } - case 'm': - First += 2; - return getDerived().parseBinaryExpr("%"); - case 'M': - First += 2; - return getDerived().parseBinaryExpr("%="); - case 's': - First += 2; - return getDerived().parseBinaryExpr(">>"); - case 'S': - First += 2; - return getDerived().parseBinaryExpr(">>="); - } - return nullptr; - case 's': - switch (First[1]) { - case 'c': { - First += 2; - Node *T = getDerived().parseType(); - if (T == nullptr) - return T; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make("static_cast", T, Ex); - } - case 'o': - First += 2; - return parseSubobjectExpr(); - case 'p': { - First += 2; - Node *Child = getDerived().parseExpr(); - if (Child == nullptr) - return nullptr; - return make(Child); - } - case 'r': - return getDerived().parseUnresolvedName(Global); - case 't': { - First += 2; + case OperatorInfo::NamedCast: { + // Named cast operation, @(expr) Node *Ty = getDerived().parseType(); if (Ty == nullptr) - return Ty; - return make("sizeof (", Ty, ")"); - } - case 'z': { - First += 2; + return nullptr; Node *Ex = getDerived().parseExpr(); if (Ex == nullptr) - return Ex; - return make("sizeof (", Ex, ")"); + return nullptr; + return make(Sym, Ty, Ex); } - case 'Z': - First += 2; - if (look() == 'T') { - Node *R = getDerived().parseTemplateParam(); - if (R == nullptr) - return nullptr; - return make(R); - } else if (look() == 'f') { - Node *FP = getDerived().parseFunctionParam(); - if (FP == nullptr) - return nullptr; - return make("sizeof... (", FP, ")"); - } - return nullptr; - case 'P': { - First += 2; - size_t ArgsBegin = Names.size(); - while (!consumeIf('E')) { - Node *Arg = getDerived().parseTemplateArg(); - if (Arg == nullptr) - return nullptr; - Names.push_back(Arg); - } - auto *Pack = make(popTrailingNodeArray(ArgsBegin)); - if (!Pack) + case OperatorInfo::OfIdOp: { + // [sizeof/alignof/typeid] ( | ) + Node *Arg = + Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr(); + if (!Arg) return nullptr; - return make("sizeof... (", Pack, ")"); + return make(Sym, Arg, ")"); } } + DEMANGLE_UNREACHABLE; + } + + if (numLeft() < 2) return nullptr; - case 't': - switch (First[1]) { - case 'e': { - First += 2; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make("typeid (", Ex, ")"); - } - case 'i': { - First += 2; - Node *Ty = getDerived().parseType(); - if (Ty == nullptr) - return Ty; - return make("typeid (", Ty, ")"); + + if (look() == 'L') + return getDerived().parseExprPrimary(); + if (look() == 'T') + return getDerived().parseTemplateParam(); + if (look() == 'f') { + // Disambiguate a fold expression from a . + if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2)))) + return getDerived().parseFunctionParam(); + return getDerived().parseFoldExpr(); + } + if (consumeIf("il")) { + size_t InitsBegin = Names.size(); + while (!consumeIf('E')) { + Node *E = getDerived().parseBracedExpr(); + if (E == nullptr) + return nullptr; + Names.push_back(E); } - case 'l': { - First += 2; - Node *Ty = getDerived().parseType(); - if (Ty == nullptr) + return make(nullptr, popTrailingNodeArray(InitsBegin)); + } + if (consumeIf("mc")) + return parsePointerToMemberConversionExpr(); + if (consumeIf("nx")) { + Node *Ex = getDerived().parseExpr(); + if (Ex == nullptr) + return Ex; + return make("noexcept (", Ex, ")"); + } + if (consumeIf("so")) + return parseSubobjectExpr(); + if (consumeIf("sp")) { + Node *Child = getDerived().parseExpr(); + if (Child == nullptr) + return nullptr; + return make(Child); + } + if (consumeIf("sZ")) { + if (look() == 'T') { + Node *R = getDerived().parseTemplateParam(); + if (R == nullptr) return nullptr; - size_t InitsBegin = Names.size(); - while (!consumeIf('E')) { - Node *E = getDerived().parseBracedExpr(); - if (E == nullptr) - return nullptr; - Names.push_back(E); - } - return make(Ty, popTrailingNodeArray(InitsBegin)); + return make(R); } - case 'r': - First += 2; - return make("throw"); - case 'w': { - First += 2; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) + Node *FP = getDerived().parseFunctionParam(); + if (FP == nullptr) + return nullptr; + return make("sizeof... (", FP, ")"); + } + if (consumeIf("sP")) { + size_t ArgsBegin = Names.size(); + while (!consumeIf('E')) { + Node *Arg = getDerived().parseTemplateArg(); + if (Arg == nullptr) return nullptr; - return make(Ex); + Names.push_back(Arg); } + auto *Pack = make(popTrailingNodeArray(ArgsBegin)); + if (!Pack) + return nullptr; + return make("sizeof... (", Pack, ")"); + } + if (consumeIf("tl")) { + Node *Ty = getDerived().parseType(); + if (Ty == nullptr) + return nullptr; + size_t InitsBegin = Names.size(); + while (!consumeIf('E')) { + Node *E = getDerived().parseBracedExpr(); + if (E == nullptr) + return nullptr; + Names.push_back(E); } - return nullptr; - case 'u': { - ++First; + return make(Ty, popTrailingNodeArray(InitsBegin)); + } + if (consumeIf("tr")) + return make("throw"); + if (consumeIf("tw")) { + Node *Ex = getDerived().parseExpr(); + if (Ex == nullptr) + return nullptr; + return make(Ex); + } + if (consumeIf('u')) { Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr); if (!Name) return nullptr; @@ -5054,18 +4697,9 @@ } return make(Name, popTrailingNodeArray(ExprsBegin)); } - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return getDerived().parseUnresolvedName(Global); - } - return nullptr; + + // Only unresolved names remain. + return getDerived().parseUnresolvedName(Global); } // ::= h _ diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h --- a/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -2556,6 +2556,62 @@ Node *parseAbiTags(Node *N); + struct OperatorInfo { + enum OIKind : unsigned char { + Prefix, // Prefix unary: @ expr + Postfix, // Postfix unary: expr @ + Binary, // Binary: lhs @ rhs + Array, // Array index: lhs [ rhs ] + Member, // Member access: lhs @ rhs + New, // New + Del, // Delete + Call, // Function call: expr (expr*) + CCast, // C cast: (type)expr + Conditional, // Conditional: expr ? expr : expr + // Below do not have operator names + NamedCast, // Named cast, @(expr) + OfIdOp, // alignof, sizeof, typeid + + Unnameable = NamedCast, + }; + char Enc[2]; // Encoding + OIKind Kind; // Kind of operator + bool Flag : 1; // Entry-specific flag + 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} {} + + public: + bool operator<(const OperatorInfo &Other) const { + return *this < Other.Enc; + } + bool operator<(const char *Peek) const { + return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]); + } + bool operator==(const char *Peek) const { + return Enc[0] == Peek[0] && Enc[1] == Peek[1]; + } + bool operator!=(const char *Peek) const { return !this->operator==(Peek); } + + public: + StringView getSymbol() const { + StringView Res = Name; + if (Kind < Unnameable) { + assert(Res.startsWith("operator") && + "operator name does not start with 'operator'"); + Res = Res.dropFront(sizeof("operator") - 1); + Res.consumeFront(' '); + } + return Res; + } + StringView getName() const { return Name; } + OIKind getKind() const { return Kind; } + bool getFlag() const { return Flag; } + }; + const OperatorInfo *parseOperatorEncoding(); + /// Parse the production. Node *parseUnresolvedName(bool Global); Node *parseSimpleId(); @@ -2808,92 +2864,111 @@ return make(Name); } -// ::= aa # && -// ::= ad # & (unary) -// ::= an # & -// ::= aN # &= -// ::= aS # = -// ::= cl # () -// ::= cm # , -// ::= co # ~ -// ::= cv # (cast) -// ::= da # delete[] -// ::= de # * (unary) -// ::= dl # delete -// ::= dv # / -// ::= dV # /= -// ::= eo # ^ -// ::= eO # ^= -// ::= eq # == -// ::= ge # >= -// ::= gt # > -// ::= ix # [] -// ::= le # <= +// If the next 2 chars are an operator encoding, consume them and return their +// OperatorInfo. Otherwise return nullptr. +template +const typename AbstractManglingParser::OperatorInfo * +AbstractManglingParser::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 ("}, + {"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 ("}, + }; + const auto NumOps = sizeof(Ops) / sizeof(Ops[0]); + +#ifndef NDEBUG + { + // Verify table order. + static bool Done; + if (!Done) { + Done = true; + for (const auto *Op = &Ops[0]; Op != &Ops[NumOps - 1]; Op++) + assert(Op[0] < Op[1] && "Operator table is not ordered"); + } + } +#endif + + if (numLeft() < 2) + return nullptr; + + auto Op = std::lower_bound( + &Ops[0], &Ops[NumOps], First, + [](const OperatorInfo &Op_, const char *Enc_) { return Op_ < Enc_; }); + if (Op == &Ops[NumOps] || *Op != First) + return nullptr; + + First += 2; + return Op; +} + +// ::= See parseOperatorEncoding() // ::= li # operator "" -// ::= ls # << -// ::= lS # <<= -// ::= lt # < -// ::= mi # - -// ::= mI # -= -// ::= ml # * -// ::= mL # *= -// ::= mm # -- (postfix in context) -// ::= na # new[] -// ::= ne # != -// ::= ng # - (unary) -// ::= nt # ! -// ::= nw # new -// ::= oo # || -// ::= or # | -// ::= oR # |= -// ::= pm # ->* -// ::= pl # + -// ::= pL # += -// ::= pp # ++ (postfix in context) -// ::= ps # + (unary) -// ::= pt # -> -// ::= qu # ? -// ::= rm # % -// ::= rM # %= -// ::= rs # >> -// ::= rS # >>= -// ::= ss # <=> C++2a -// ::= v # vendor extended operator +// ::= v # vendor extended operator template Node * AbstractManglingParser::parseOperatorName(NameState *State) { - switch (look()) { - case 'a': - switch (look(1)) { - case 'a': - First += 2; - return make("operator&&"); - case 'd': - case 'n': - First += 2; - return make("operator&"); - case 'N': - First += 2; - return make("operator&="); - case 'S': - First += 2; - return make("operator="); - } - return nullptr; - case 'c': - switch (look(1)) { - case 'l': - First += 2; - return make("operator()"); - case 'm': - First += 2; - return make("operator,"); - case 'o': - First += 2; - return make("operator~"); - // ::= cv # (cast) - case 'v': { - First += 2; + if (const auto *Op = parseOperatorEncoding()) { + if (Op->getKind() == OperatorInfo::CCast) { + // ::= cv # (cast) SwapAndRestore SaveTemplate(TryToParseTemplateArgs, false); // If we're parsing an encoding, State != nullptr and the conversion // operators' could have a that refers to some @@ -2907,185 +2982,29 @@ if (State) State->CtorDtorConversion = true; return make(Ty); } - } - return nullptr; - case 'd': - switch (look(1)) { - case 'a': - First += 2; - return make("operator delete[]"); - case 'e': - First += 2; - return make("operator*"); - case 'l': - First += 2; - return make("operator delete"); - case 'v': - First += 2; - return make("operator/"); - case 'V': - First += 2; - return make("operator/="); - } - return nullptr; - case 'e': - switch (look(1)) { - case 'o': - First += 2; - return make("operator^"); - case 'O': - First += 2; - return make("operator^="); - case 'q': - First += 2; - return make("operator=="); - } - return nullptr; - case 'g': - switch (look(1)) { - case 'e': - First += 2; - return make("operator>="); - case 't': - First += 2; - return make("operator>"); - } - return nullptr; - case 'i': - if (look(1) == 'x') { - First += 2; - return make("operator[]"); - } - return nullptr; - case 'l': - switch (look(1)) { - case 'e': - First += 2; - return make("operator<="); + + if (Op->getKind() >= OperatorInfo::Unnameable) + /* Not a nameable operator. */ + return nullptr; + if (Op->getKind() == OperatorInfo::Member && !Op->getFlag()) + /* Not a nameable MemberExpr */ + return nullptr; + + return make(Op->getName()); + } + + if (consumeIf("li")) { // ::= li # operator "" - case 'i': { - First += 2; - Node *SN = getDerived().parseSourceName(State); - if (SN == nullptr) - return nullptr; - return make(SN); - } - case 's': - First += 2; - return make("operator<<"); - case 'S': - First += 2; - return make("operator<<="); - case 't': - First += 2; - return make("operator<"); - } - return nullptr; - case 'm': - switch (look(1)) { - case 'i': - First += 2; - return make("operator-"); - case 'I': - First += 2; - return make("operator-="); - case 'l': - First += 2; - return make("operator*"); - case 'L': - First += 2; - return make("operator*="); - case 'm': - First += 2; - return make("operator--"); - } - return nullptr; - case 'n': - switch (look(1)) { - case 'a': - First += 2; - return make("operator new[]"); - case 'e': - First += 2; - return make("operator!="); - case 'g': - First += 2; - return make("operator-"); - case 't': - First += 2; - return make("operator!"); - case 'w': - First += 2; - return make("operator new"); - } - return nullptr; - case 'o': - switch (look(1)) { - case 'o': - First += 2; - return make("operator||"); - case 'r': - First += 2; - return make("operator|"); - case 'R': - First += 2; - return make("operator|="); - } - return nullptr; - case 'p': - switch (look(1)) { - case 'm': - First += 2; - return make("operator->*"); - case 'l': - First += 2; - return make("operator+"); - case 'L': - First += 2; - return make("operator+="); - case 'p': - First += 2; - return make("operator++"); - case 's': - First += 2; - return make("operator+"); - case 't': - First += 2; - return make("operator->"); - } - return nullptr; - case 'q': - if (look(1) == 'u') { - First += 2; - return make("operator?"); - } - return nullptr; - case 'r': - switch (look(1)) { - case 'm': - First += 2; - return make("operator%"); - case 'M': - First += 2; - return make("operator%="); - case 's': - First += 2; - return make("operator>>"); - case 'S': - First += 2; - return make("operator>>="); - } - return nullptr; - case 's': - if (look(1) == 's') { - First += 2; - return make("operator<=>"); - } - return nullptr; - // ::= v # vendor extended operator - case 'v': - if (std::isdigit(look(1))) { - First += 2; + Node *SN = getDerived().parseSourceName(State); + if (SN == nullptr) + return nullptr; + return make(SN); + } + + if (consumeIf('v')) { + // ::= v # vendor extended operator + if (look() >= '0' && look() <= '9') { + First++; Node *SN = getDerived().parseSourceName(State); if (SN == nullptr) return nullptr; @@ -3093,6 +3012,7 @@ } return nullptr; } + return nullptr; } @@ -4374,55 +4294,34 @@ if (!consumeIf('f')) return nullptr; - char FoldKind = look(); - bool IsLeftFold, HasInitializer; - HasInitializer = FoldKind == 'L' || FoldKind == 'R'; - if (FoldKind == 'l' || FoldKind == 'L') - IsLeftFold = true; - else if (FoldKind == 'r' || FoldKind == 'R') - IsLeftFold = false; - else + bool IsLeftFold = false, HasInitializer = false; + switch (look()) { + default: return nullptr; + case 'L': + IsLeftFold = true; + HasInitializer = true; + break; + case 'R': + HasInitializer = true; + break; + case 'l': + IsLeftFold = true; + break; + case 'r': + break; + } ++First; - // FIXME: This map is duplicated in parseOperatorName and parseExpr. - StringView OperatorName; - if (consumeIf("aa")) OperatorName = "&&"; - else if (consumeIf("an")) OperatorName = "&"; - else if (consumeIf("aN")) OperatorName = "&="; - else if (consumeIf("aS")) OperatorName = "="; - else if (consumeIf("cm")) OperatorName = ","; - else if (consumeIf("ds")) OperatorName = ".*"; - else if (consumeIf("dv")) OperatorName = "/"; - else if (consumeIf("dV")) OperatorName = "/="; - else if (consumeIf("eo")) OperatorName = "^"; - else if (consumeIf("eO")) OperatorName = "^="; - else if (consumeIf("eq")) OperatorName = "=="; - else if (consumeIf("ge")) OperatorName = ">="; - else if (consumeIf("gt")) OperatorName = ">"; - else if (consumeIf("le")) OperatorName = "<="; - else if (consumeIf("ls")) OperatorName = "<<"; - else if (consumeIf("lS")) OperatorName = "<<="; - else if (consumeIf("lt")) OperatorName = "<"; - else if (consumeIf("mi")) OperatorName = "-"; - else if (consumeIf("mI")) OperatorName = "-="; - else if (consumeIf("ml")) OperatorName = "*"; - else if (consumeIf("mL")) OperatorName = "*="; - else if (consumeIf("ne")) OperatorName = "!="; - else if (consumeIf("oo")) OperatorName = "||"; - else if (consumeIf("or")) OperatorName = "|"; - else if (consumeIf("oR")) OperatorName = "|="; - else if (consumeIf("pl")) OperatorName = "+"; - else if (consumeIf("pL")) OperatorName = "+="; - else if (consumeIf("rm")) OperatorName = "%"; - else if (consumeIf("rM")) OperatorName = "%="; - else if (consumeIf("rs")) OperatorName = ">>"; - else if (consumeIf("rS")) OperatorName = ">>="; - else return nullptr; - - Node *Pack = getDerived().parseExpr(), *Init = nullptr; + const auto *Op = parseOperatorEncoding(); + if (!Op || Op->getKind() != OperatorInfo::Binary) + return nullptr; + + Node *Pack = getDerived().parseExpr(); if (Pack == nullptr) return nullptr; + + Node *Init = nullptr; if (HasInitializer) { Init = getDerived().parseExpr(); if (Init == nullptr) @@ -4432,7 +4331,7 @@ if (IsLeftFold && Init) std::swap(Pack, Init); - return make(IsLeftFold, OperatorName, Pack, Init); + return make(IsLeftFold, Op->getSymbol(), Pack, Init); } // ::= mc [] E @@ -4526,350 +4425,125 @@ template Node *AbstractManglingParser::parseExpr() { bool Global = consumeIf("gs"); - if (numLeft() < 2) - return nullptr; - switch (*First) { - case 'L': - return getDerived().parseExprPrimary(); - case 'T': - return getDerived().parseTemplateParam(); - case 'f': { - // Disambiguate a fold expression from a . - if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2)))) - return getDerived().parseFunctionParam(); - return getDerived().parseFoldExpr(); - } - case 'a': - switch (First[1]) { - case 'a': - First += 2; - return getDerived().parseBinaryExpr("&&"); - case 'd': - First += 2; - return getDerived().parsePrefixExpr("&"); - case 'n': - First += 2; - return getDerived().parseBinaryExpr("&"); - case 'N': - First += 2; - return getDerived().parseBinaryExpr("&="); - case 'S': - First += 2; - return getDerived().parseBinaryExpr("="); - case 't': { - First += 2; - Node *Ty = getDerived().parseType(); - if (Ty == nullptr) + const auto *Op = parseOperatorEncoding(); + if (Op) { + auto Sym = Op->getSymbol(); + switch (Op->getKind()) { + case OperatorInfo::Binary: + // Binary operator: lhs @ rhs + return getDerived().parseBinaryExpr(Sym); + case OperatorInfo::Prefix: + // Prefix unary operator: @ expr + return getDerived().parsePrefixExpr(Sym); + case OperatorInfo::Postfix: { + // Postfix unary operator: expr @ + if (consumeIf('_')) + return getDerived().parsePrefixExpr(Sym); + Node *Ex = getDerived().parseExpr(); + if (Ex == nullptr) return nullptr; - return make("alignof (", Ty, ")"); + return make(Ex, Sym); } - case 'z': { - First += 2; - Node *Ty = getDerived().parseExpr(); - if (Ty == nullptr) + case OperatorInfo::Array: { + // Array Index: lhs [ rhs ] + Node *Base = getDerived().parseExpr(); + if (Base == nullptr) return nullptr; - return make("alignof (", Ty, ")"); - } + Node *Index = getDerived().parseExpr(); + if (Index == nullptr) + return nullptr; + return make(Base, Index); } - return nullptr; - case 'c': - switch (First[1]) { - // cc # const_cast(expression) - case 'c': { - First += 2; + case OperatorInfo::Member: { + // Member access lhs @ rhs + Node *LHS = getDerived().parseExpr(); + if (LHS == nullptr) + return nullptr; + Node *RHS = getDerived().parseExpr(); + if (RHS == nullptr) + return nullptr; + return make(LHS, Sym, RHS); + } + case OperatorInfo::New: { + // New + // # new (expr-list) type [(init)] + // [gs] nw * _ [pi *] E + // # new[] (expr-list) type [(init)] + // [gs] na * _ [pi *] E + 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; + return nullptr; + bool HaveInits = consumeIf("pi"); + size_t InitsBegin = Names.size(); + while (!consumeIf('E')) { + if (!HaveInits) + return nullptr; + Node *Init = getDerived().parseExpr(); + if (Init == nullptr) + return Init; + Names.push_back(Init); + } + NodeArray Inits = popTrailingNodeArray(InitsBegin); + return make(ExprList, Ty, Inits, Global, + /*IsArray=*/Op->getFlag()); + } + case OperatorInfo::Del: { + // Delete Node *Ex = getDerived().parseExpr(); if (Ex == nullptr) - return Ex; - return make("const_cast", Ty, Ex); + return nullptr; + return make(Ex, Global, /*IsArray=*/Op->getFlag()); } - // cl + E # call - case 'l': { - First += 2; + case OperatorInfo::Call: { + // Function Call Node *Callee = getDerived().parseExpr(); if (Callee == nullptr) - return Callee; + return nullptr; size_t ExprsBegin = Names.size(); while (!consumeIf('E')) { Node *E = getDerived().parseExpr(); - if (E == nullptr) - return E; - Names.push_back(E); - } - return make(Callee, popTrailingNodeArray(ExprsBegin)); - } - case 'm': - First += 2; - return getDerived().parseBinaryExpr(","); - case 'o': - First += 2; - return getDerived().parsePrefixExpr("~"); - case 'v': - return getDerived().parseConversionExpr(); - } - return nullptr; - case 'd': - switch (First[1]) { - case 'a': { - First += 2; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make(Ex, Global, /*is_array=*/true); - } - case 'c': { - First += 2; - Node *T = getDerived().parseType(); - if (T == nullptr) - return T; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make("dynamic_cast", T, Ex); - } - case 'e': - First += 2; - return getDerived().parsePrefixExpr("*"); - case 'l': { - First += 2; - Node *E = getDerived().parseExpr(); - if (E == nullptr) - return E; - return make(E, Global, /*is_array=*/false); - } - case 'n': - return getDerived().parseUnresolvedName(Global); - case 's': { - First += 2; - Node *LHS = getDerived().parseExpr(); - if (LHS == nullptr) - return nullptr; - Node *RHS = getDerived().parseExpr(); - if (RHS == nullptr) - return nullptr; - return make(LHS, ".*", RHS); - } - case 't': { - First += 2; - Node *LHS = getDerived().parseExpr(); - if (LHS == nullptr) - return LHS; - Node *RHS = getDerived().parseExpr(); - if (RHS == nullptr) - return nullptr; - return make(LHS, ".", RHS); - } - case 'v': - First += 2; - return getDerived().parseBinaryExpr("/"); - case 'V': - First += 2; - return getDerived().parseBinaryExpr("/="); - } - return nullptr; - case 'e': - switch (First[1]) { - case 'o': - First += 2; - return getDerived().parseBinaryExpr("^"); - case 'O': - First += 2; - return getDerived().parseBinaryExpr("^="); - case 'q': - First += 2; - return getDerived().parseBinaryExpr("=="); - } - return nullptr; - case 'g': - switch (First[1]) { - case 'e': - First += 2; - return getDerived().parseBinaryExpr(">="); - case 't': - First += 2; - return getDerived().parseBinaryExpr(">"); - } - return nullptr; - case 'i': - switch (First[1]) { - case 'x': { - First += 2; - Node *Base = getDerived().parseExpr(); - if (Base == nullptr) - return nullptr; - Node *Index = getDerived().parseExpr(); - if (Index == nullptr) - return Index; - return make(Base, Index); - } - case 'l': { - First += 2; - size_t InitsBegin = Names.size(); - while (!consumeIf('E')) { - Node *E = getDerived().parseBracedExpr(); if (E == nullptr) return nullptr; Names.push_back(E); } - return make(nullptr, popTrailingNodeArray(InitsBegin)); - } - } - return nullptr; - case 'l': - switch (First[1]) { - case 'e': - First += 2; - return getDerived().parseBinaryExpr("<="); - case 's': - First += 2; - return getDerived().parseBinaryExpr("<<"); - case 'S': - First += 2; - return getDerived().parseBinaryExpr("<<="); - case 't': - First += 2; - return getDerived().parseBinaryExpr("<"); - } - return nullptr; - case 'm': - switch (First[1]) { - case 'c': - First += 2; - return parsePointerToMemberConversionExpr(); - case 'i': - First += 2; - return getDerived().parseBinaryExpr("-"); - case 'I': - First += 2; - return getDerived().parseBinaryExpr("-="); - case 'l': - First += 2; - return getDerived().parseBinaryExpr("*"); - case 'L': - First += 2; - return getDerived().parseBinaryExpr("*="); - case 'm': - First += 2; - if (consumeIf('_')) - return getDerived().parsePrefixExpr("--"); - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return nullptr; - return make(Ex, "--"); + return make(Callee, popTrailingNodeArray(ExprsBegin)); } - return nullptr; - case 'n': - switch (First[1]) { - case 'a': - case 'w': { - // [gs] nw * _ [pi *] E # new (expr-list) type [(init)] - // [gs] na * _ [pi *] E # new[] (expr-list) type [(init)] - bool IsArray = First[1] == 'a'; - First += 2; - size_t Exprs = Names.size(); - while (!consumeIf('_')) { - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return nullptr; - Names.push_back(Ex); + case OperatorInfo::CCast: { + // C Cast: (type)expr + Node *Ty; + { + SwapAndRestore SaveTemp(TryToParseTemplateArgs, false); + Ty = getDerived().parseType(); } - NodeArray ExprList = popTrailingNodeArray(Exprs); - Node *Ty = getDerived().parseType(); if (Ty == nullptr) return nullptr; - bool HaveInits = consumeIf("pi"); - size_t InitsBegin = Names.size(); + + size_t ExprsBegin = Names.size(); + bool IsMany = consumeIf('_'); while (!consumeIf('E')) { - if (!HaveInits) - return nullptr; - Node *Init = getDerived().parseExpr(); - if (Init == nullptr) - return Init; - Names.push_back(Init); + Node *E = getDerived().parseExpr(); + if (E == nullptr) + return E; + Names.push_back(E); + if (!IsMany) + break; } - NodeArray Inits = popTrailingNodeArray(InitsBegin); - return make(ExprList, Ty, Inits, Global, IsArray); - } - case 'e': - First += 2; - return getDerived().parseBinaryExpr("!="); - case 'g': - First += 2; - return getDerived().parsePrefixExpr("-"); - case 't': - First += 2; - return getDerived().parsePrefixExpr("!"); - case 'x': - First += 2; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make("noexcept (", Ex, ")"); - } - return nullptr; - case 'o': - switch (First[1]) { - case 'n': - return getDerived().parseUnresolvedName(Global); - case 'o': - First += 2; - return getDerived().parseBinaryExpr("||"); - case 'r': - First += 2; - return getDerived().parseBinaryExpr("|"); - case 'R': - First += 2; - return getDerived().parseBinaryExpr("|="); - } - return nullptr; - case 'p': - switch (First[1]) { - case 'm': { - First += 2; - Node *LHS = getDerived().parseExpr(); - if (LHS == nullptr) - return LHS; - Node *RHS = getDerived().parseExpr(); - if (RHS == nullptr) + NodeArray Exprs = popTrailingNodeArray(ExprsBegin); + if (!IsMany && Exprs.size() != 1) return nullptr; - return make(LHS, "->*", RHS); + return make(Ty, Exprs); } - case 'l': - First += 2; - return getDerived().parseBinaryExpr("+"); - case 'L': - First += 2; - return getDerived().parseBinaryExpr("+="); - case 'p': { - First += 2; - if (consumeIf('_')) - return getDerived().parsePrefixExpr("++"); - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make(Ex, "++"); - } - case 's': - First += 2; - return getDerived().parsePrefixExpr("+"); - case 't': { - First += 2; - Node *L = getDerived().parseExpr(); - if (L == nullptr) - return nullptr; - Node *R = getDerived().parseExpr(); - if (R == nullptr) - return nullptr; - return make(L, "->", R); - } - } - return nullptr; - case 'q': - if (First[1] == 'u') { - First += 2; + case OperatorInfo::Conditional: { + // Conditional operator: expr ? expr : expr Node *Cond = getDerived().parseExpr(); if (Cond == nullptr) return nullptr; @@ -4881,145 +4555,114 @@ return nullptr; return make(Cond, LHS, RHS); } - return nullptr; - case 'r': - switch (First[1]) { - case 'c': { - First += 2; - Node *T = getDerived().parseType(); - if (T == nullptr) - return T; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make("reinterpret_cast", T, Ex); - } - case 'm': - First += 2; - return getDerived().parseBinaryExpr("%"); - case 'M': - First += 2; - return getDerived().parseBinaryExpr("%="); - case 's': - First += 2; - return getDerived().parseBinaryExpr(">>"); - case 'S': - First += 2; - return getDerived().parseBinaryExpr(">>="); - } - return nullptr; - case 's': - switch (First[1]) { - case 'c': { - First += 2; - Node *T = getDerived().parseType(); - if (T == nullptr) - return T; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make("static_cast", T, Ex); - } - case 'o': - First += 2; - return parseSubobjectExpr(); - case 'p': { - First += 2; - Node *Child = getDerived().parseExpr(); - if (Child == nullptr) - return nullptr; - return make(Child); - } - case 'r': - return getDerived().parseUnresolvedName(Global); - case 't': { - First += 2; + case OperatorInfo::NamedCast: { + // Named cast operation, @(expr) Node *Ty = getDerived().parseType(); if (Ty == nullptr) - return Ty; - return make("sizeof (", Ty, ")"); - } - case 'z': { - First += 2; + return nullptr; Node *Ex = getDerived().parseExpr(); if (Ex == nullptr) - return Ex; - return make("sizeof (", Ex, ")"); + return nullptr; + return make(Sym, Ty, Ex); } - case 'Z': - First += 2; - if (look() == 'T') { - Node *R = getDerived().parseTemplateParam(); - if (R == nullptr) - return nullptr; - return make(R); - } else if (look() == 'f') { - Node *FP = getDerived().parseFunctionParam(); - if (FP == nullptr) - return nullptr; - return make("sizeof... (", FP, ")"); - } - return nullptr; - case 'P': { - First += 2; - size_t ArgsBegin = Names.size(); - while (!consumeIf('E')) { - Node *Arg = getDerived().parseTemplateArg(); - if (Arg == nullptr) - return nullptr; - Names.push_back(Arg); - } - auto *Pack = make(popTrailingNodeArray(ArgsBegin)); - if (!Pack) + case OperatorInfo::OfIdOp: { + // [sizeof/alignof/typeid] ( | ) + Node *Arg = + Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr(); + if (!Arg) return nullptr; - return make("sizeof... (", Pack, ")"); + return make(Sym, Arg, ")"); } } + DEMANGLE_UNREACHABLE; + } + + if (numLeft() < 2) return nullptr; - case 't': - switch (First[1]) { - case 'e': { - First += 2; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) - return Ex; - return make("typeid (", Ex, ")"); - } - case 'i': { - First += 2; - Node *Ty = getDerived().parseType(); - if (Ty == nullptr) - return Ty; - return make("typeid (", Ty, ")"); + + if (look() == 'L') + return getDerived().parseExprPrimary(); + if (look() == 'T') + return getDerived().parseTemplateParam(); + if (look() == 'f') { + // Disambiguate a fold expression from a . + if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2)))) + return getDerived().parseFunctionParam(); + return getDerived().parseFoldExpr(); + } + if (consumeIf("il")) { + size_t InitsBegin = Names.size(); + while (!consumeIf('E')) { + Node *E = getDerived().parseBracedExpr(); + if (E == nullptr) + return nullptr; + Names.push_back(E); } - case 'l': { - First += 2; - Node *Ty = getDerived().parseType(); - if (Ty == nullptr) + return make(nullptr, popTrailingNodeArray(InitsBegin)); + } + if (consumeIf("mc")) + return parsePointerToMemberConversionExpr(); + if (consumeIf("nx")) { + Node *Ex = getDerived().parseExpr(); + if (Ex == nullptr) + return Ex; + return make("noexcept (", Ex, ")"); + } + if (consumeIf("so")) + return parseSubobjectExpr(); + if (consumeIf("sp")) { + Node *Child = getDerived().parseExpr(); + if (Child == nullptr) + return nullptr; + return make(Child); + } + if (consumeIf("sZ")) { + if (look() == 'T') { + Node *R = getDerived().parseTemplateParam(); + if (R == nullptr) return nullptr; - size_t InitsBegin = Names.size(); - while (!consumeIf('E')) { - Node *E = getDerived().parseBracedExpr(); - if (E == nullptr) - return nullptr; - Names.push_back(E); - } - return make(Ty, popTrailingNodeArray(InitsBegin)); + return make(R); } - case 'r': - First += 2; - return make("throw"); - case 'w': { - First += 2; - Node *Ex = getDerived().parseExpr(); - if (Ex == nullptr) + Node *FP = getDerived().parseFunctionParam(); + if (FP == nullptr) + return nullptr; + return make("sizeof... (", FP, ")"); + } + if (consumeIf("sP")) { + size_t ArgsBegin = Names.size(); + while (!consumeIf('E')) { + Node *Arg = getDerived().parseTemplateArg(); + if (Arg == nullptr) return nullptr; - return make(Ex); + Names.push_back(Arg); } + auto *Pack = make(popTrailingNodeArray(ArgsBegin)); + if (!Pack) + return nullptr; + return make("sizeof... (", Pack, ")"); + } + if (consumeIf("tl")) { + Node *Ty = getDerived().parseType(); + if (Ty == nullptr) + return nullptr; + size_t InitsBegin = Names.size(); + while (!consumeIf('E')) { + Node *E = getDerived().parseBracedExpr(); + if (E == nullptr) + return nullptr; + Names.push_back(E); } - return nullptr; - case 'u': { - ++First; + return make(Ty, popTrailingNodeArray(InitsBegin)); + } + if (consumeIf("tr")) + return make("throw"); + if (consumeIf("tw")) { + Node *Ex = getDerived().parseExpr(); + if (Ex == nullptr) + return nullptr; + return make(Ex); + } + if (consumeIf('u')) { Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr); if (!Name) return nullptr; @@ -5054,18 +4697,9 @@ } return make(Name, popTrailingNodeArray(ExprsBegin)); } - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return getDerived().parseUnresolvedName(Global); - } - return nullptr; + + // Only unresolved names remain. + return getDerived().parseUnresolvedName(Global); } // ::= h _