[demangler] Support for fold expressions.

llvm-svn: 329601
This commit is contained in:
Erik Pilkington 2018-04-09 18:33:01 +00:00
parent 452e2ef996
commit d43931dcb8
3 changed files with 258 additions and 6 deletions

View File

@ -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':

View File

@ -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]);

View File

@ -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
#include "llvm/Demangle/Demangle.h"
@ -1687,6 +1686,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;
@ -2055,6 +2103,7 @@ struct Db {
Node *parseNewExpr();
Node *parseConversionExpr();
Node *parseBracedExpr();
Node *parseFoldExpr();
/// Parse the <type> production.
Node *parseType();
@ -3799,6 +3848,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>
@ -3853,8 +3972,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':