diff options
author | Erik Pilkington <erik.pilkington@gmail.com> | 2018-04-09 18:33:01 +0000 |
---|---|---|
committer | Erik Pilkington <erik.pilkington@gmail.com> | 2018-04-09 18:33:01 +0000 |
commit | b443601a26ef6093b9e1b40747f9dbac071afc12 (patch) | |
tree | 512b9405228405eca73b8389d48bbd057d0a6c5e /libcxxabi/src | |
parent | f109bba97d4c344675078803cfa432889d899a5e (diff) |
[demangler] Support for fold expressions.
Diffstat (limited to 'libcxxabi/src')
-rw-r--r-- | libcxxabi/src/cxa_demangle.cpp | 129 |
1 files changed, 126 insertions, 3 deletions
diff --git a/libcxxabi/src/cxa_demangle.cpp b/libcxxabi/src/cxa_demangle.cpp index 5261363c360..1348b104d2d 100644 --- a/libcxxabi/src/cxa_demangle.cpp +++ b/libcxxabi/src/cxa_demangle.cpp @@ -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': |