Author: epilk Date: Mon Apr 9 11:33:01 2018 New Revision: 329601 URL: http://llvm.org/viewvc/llvm-project?rev=329601&view=rev Log: [demangler] Support for fold expressions.
Modified: libcxxabi/trunk/src/cxa_demangle.cpp libcxxabi/trunk/test/test_demangle.pass.cpp Modified: libcxxabi/trunk/src/cxa_demangle.cpp URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp?rev=329601&r1=329600&r2=329601&view=diff ============================================================================== --- libcxxabi/trunk/src/cxa_demangle.cpp (original) +++ libcxxabi/trunk/src/cxa_demangle.cpp Mon Apr 9 11:33:01 2018 @@ -10,7 +10,6 @@ // FIXME: (possibly) incomplete list of features that clang mangles that this // file does not yet support: // - C++ modules TS -// - All C++14 and C++17 features #define _LIBCPP_NO_EXCEPTIONS @@ -1695,6 +1694,55 @@ public: } }; +struct FoldExpr : Expr { + Node *Pack, *Init; + StringView OperatorName; + bool IsLeftFold; + + FoldExpr(bool IsLeftFold_, StringView OperatorName_, Node *Pack_, Node *Init_) + : Pack(Pack_), Init(Init_), OperatorName(OperatorName_), + IsLeftFold(IsLeftFold_) {} + + void printLeft(OutputStream &S) const override { + auto PrintPack = [&] { + S += '('; + ParameterPackExpansion(Pack).print(S); + S += ')'; + }; + + S += '('; + + if (IsLeftFold) { + // init op ... op pack + if (Init != nullptr) { + Init->print(S); + S += ' '; + S += OperatorName; + S += ' '; + } + // ... op pack + S += "... "; + S += OperatorName; + S += ' '; + PrintPack(); + } else { // !IsLeftFold + // pack op ... + PrintPack(); + S += ' '; + S += OperatorName; + S += " ..."; + // pack op ... op init + if (Init != nullptr) { + S += ' '; + S += OperatorName; + S += ' '; + Init->print(S); + } + } + S += ')'; + } +}; + class ThrowExpr : public Expr { const Node *Op; @@ -2063,6 +2111,7 @@ struct Db { Node *parseNewExpr(); Node *parseConversionExpr(); Node *parseBracedExpr(); + Node *parseFoldExpr(); /// Parse the <type> production. Node *parseType(); @@ -3807,6 +3856,76 @@ Node *Db::parseBracedExpr() { return parseExpr(); } +// (not yet in the spec) +// <fold-expr> ::= fL <binary-operator-name> <expression> <expression> +// ::= fR <binary-operator-name> <expression> <expression> +// ::= fl <binary-operator-name> <expression> +// ::= fr <binary-operator-name> <expression> +Node *Db::parseFoldExpr() { + 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 + return nullptr; + ++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 = parseExpr(), *Init = nullptr; + if (Pack == nullptr) + return nullptr; + if (HasInitializer) { + Init = parseExpr(); + if (Init == nullptr) + return nullptr; + } + + if (IsLeftFold && Init) + std::swap(Pack, Init); + + return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init); +} + // <expression> ::= <unary operator-name> <expression> // ::= <binary operator-name> <expression> <expression> // ::= <ternary operator-name> <expression> <expression> <expression> @@ -3861,8 +3980,12 @@ Node *Db::parseExpr() { return parseExprPrimary(); case 'T': return parseTemplateParam(); - case 'f': - return parseFunctionParam(); + case 'f': { + // Disambiguate a fold expression from a <function-param>. + if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2)))) + return parseFunctionParam(); + return parseFoldExpr(); + } case 'a': switch (First[1]) { case 'a': Modified: libcxxabi/trunk/test/test_demangle.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxxabi/trunk/test/test_demangle.pass.cpp?rev=329601&r1=329600&r2=329601&view=diff ============================================================================== --- libcxxabi/trunk/test/test_demangle.pass.cpp (original) +++ libcxxabi/trunk/test/test_demangle.pass.cpp Mon Apr 9 11:33:01 2018 @@ -29743,6 +29743,12 @@ const char* cases[][2] = {"_ZNK13StaticMembersIfE1xMUlvE_clEv", "StaticMembers<float>::x::'lambda'()::operator()() const"}, {"_ZNK10inline_varMUlvE_clEv", "inline_var::'lambda'()::operator()() const"}, + // C++1z fold expressions: + {"_Z6foldl1IJLi1ELi2ELi3EEEv1AIXfLplLi1ET_EE", "void foldl1<1, 2, 3>(A<(1 + ... + (1, 2, 3))>)"}, + {"_Z6foldr1IJLi1ELi2ELi3EEEv1AIXfRplT_Li1EEE", "void foldr1<1, 2, 3>(A<((1, 2, 3) + ... + 1)>)"}, + {"_Z5foldlIJLi1ELi2ELi3EEEv1AIXflplT_EE", "void foldl<1, 2, 3>(A<(... + (1, 2, 3))>)"}, + {"_Z5foldrIJLi1ELi2ELi3EEEv1AIXfrplT_EE", "void foldr<1, 2, 3>(A<((1, 2, 3) + ...)>)"}, + {"_ZN7PartialIJLi1ELi2EEE5foldrIJLi3ELi4EEEEv1AIXplLi1EplLi2EfRplT_plLi1EplLi2EfrplT_EE", "void Partial<1, 2>::foldr<3, 4>(A<(1) + ((2) + (((3, 4) + ... + (1) + ((2) + (((3, 4) + ...))))))>)"}, }; const unsigned N = sizeof(cases) / sizeof(cases[0]); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits