mirror of https://github.com/microsoft/clang.git
Parse a possible trailing postfix expression suffix after a fold expression
Summary: This patch allows the parsing of a postfix expression involving a fold expression, which is legal as a fold-expression is a primary-expression. See also https://llvm.org/pr38282 Reviewers: rsmith Reviewed By: rsmith Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D49848 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338170 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
66f2c636c4
commit
459648c52e
|
@ -1653,6 +1653,7 @@ private:
|
|||
/// ParenParseOption - Control what ParseParenExpression will parse.
|
||||
enum ParenParseOption {
|
||||
SimpleExpr, // Only parse '(' expression ')'
|
||||
FoldExpr, // Also allow fold-expression <anything>
|
||||
CompoundStmt, // Also allow '(' compound-statement ')'
|
||||
CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
|
||||
CastExpr // Also allow '(' type-name ')' <anything>
|
||||
|
|
|
@ -789,6 +789,10 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression,
|
|||
// We have parsed the cast-expression and no postfix-expr pieces are
|
||||
// following.
|
||||
return Res;
|
||||
case FoldExpr:
|
||||
// We only parsed a fold-expression. There might be postfix-expr pieces
|
||||
// afterwards; parse them now.
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -2523,8 +2527,9 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
|
|||
Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
|
||||
return ExprError();
|
||||
}
|
||||
} else if (Tok.is(tok::ellipsis) &&
|
||||
} else if (ExprType >= FoldExpr && Tok.is(tok::ellipsis) &&
|
||||
isFoldOperator(NextToken().getKind())) {
|
||||
ExprType = FoldExpr;
|
||||
return ParseFoldExpression(ExprResult(), T);
|
||||
} else if (isTypeCast) {
|
||||
// Parse the expression-list.
|
||||
|
@ -2536,9 +2541,11 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
|
|||
if (!ParseSimpleExpressionList(ArgExprs, CommaLocs)) {
|
||||
// FIXME: If we ever support comma expressions as operands to
|
||||
// fold-expressions, we'll need to allow multiple ArgExprs here.
|
||||
if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) &&
|
||||
NextToken().is(tok::ellipsis))
|
||||
if (ExprType >= FoldExpr && ArgExprs.size() == 1 &&
|
||||
isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {
|
||||
ExprType = FoldExpr;
|
||||
return ParseFoldExpression(ArgExprs[0], T);
|
||||
}
|
||||
|
||||
ExprType = SimpleExpr;
|
||||
Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
|
||||
|
@ -2553,10 +2560,13 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
|
|||
// expressions are parsed correctly.
|
||||
Result = Actions.CorrectDelayedTyposInExpr(Result);
|
||||
}
|
||||
ExprType = SimpleExpr;
|
||||
|
||||
if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis))
|
||||
if (ExprType >= FoldExpr && isFoldOperator(Tok.getKind()) &&
|
||||
NextToken().is(tok::ellipsis)) {
|
||||
ExprType = FoldExpr;
|
||||
return ParseFoldExpression(Result, T);
|
||||
}
|
||||
ExprType = SimpleExpr;
|
||||
|
||||
// Don't build a paren expression unless we actually match a ')'.
|
||||
if (!Result.isInvalid() && Tok.is(tok::r_paren))
|
||||
|
|
|
@ -60,3 +60,29 @@ template <int... N> constexpr int nestedFoldOperator() {
|
|||
}
|
||||
|
||||
static_assert(nestedFoldOperator<3, 1>() == 1);
|
||||
|
||||
// A fold-expression is a primary-expression.
|
||||
template <typename T, typename... Ts>
|
||||
constexpr auto castSum(Ts... Args) {
|
||||
return (T)(Args + ...).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
constexpr auto simpleSum(Ts... Args) {
|
||||
return (... + Args).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
|
||||
}
|
||||
|
||||
void prim() {
|
||||
castSum<int>(1, 2);
|
||||
// expected-note@-1{{in instantiation of function template specialization}}
|
||||
simpleSum(1, 2);
|
||||
// expected-note@-1{{in instantiation of function template specialization}}
|
||||
|
||||
struct Number {
|
||||
int Value;
|
||||
constexpr Number operator+(Number Rhs) const { return {Rhs.Value + Value}; }
|
||||
};
|
||||
|
||||
static_assert(castSum<long>(Number{1}, Number{2}) == 3);
|
||||
static_assert(simpleSum(Number{1}, Number{2}) == 3);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue