forked from OSchip/llvm-project
Sema: Do not allow lambda expressions to appear inside of constant expressions
We would previously not diagnose this which would lead to crashes (on very strange code). This fixes PR17675. llvm-svn: 193397
This commit is contained in:
parent
be9cdbb58c
commit
9adc361008
|
@ -5067,6 +5067,8 @@ let CategoryName = "Lambda Issue" in {
|
|||
def note_lambda_decl : Note<"lambda expression begins here">;
|
||||
def err_lambda_unevaluated_operand : Error<
|
||||
"lambda expression in an unevaluated operand">;
|
||||
def err_lambda_in_constant_expression : Error<
|
||||
"a lambda expression may not appear inside of a constant expression">;
|
||||
def err_lambda_return_init_list : Error<
|
||||
"cannot deduce lambda return type from initializer list">;
|
||||
def err_lambda_capture_default_arg : Error<
|
||||
|
|
|
@ -10962,13 +10962,22 @@ void Sema::PopExpressionEvaluationContext() {
|
|||
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
|
||||
|
||||
if (!Rec.Lambdas.empty()) {
|
||||
if (Rec.isUnevaluated()) {
|
||||
// C++11 [expr.prim.lambda]p2:
|
||||
// A lambda-expression shall not appear in an unevaluated operand
|
||||
// (Clause 5).
|
||||
if (Rec.isUnevaluated() || Rec.Context == ConstantEvaluated) {
|
||||
unsigned D;
|
||||
if (Rec.isUnevaluated()) {
|
||||
// C++11 [expr.prim.lambda]p2:
|
||||
// A lambda-expression shall not appear in an unevaluated operand
|
||||
// (Clause 5).
|
||||
D = diag::err_lambda_unevaluated_operand;
|
||||
} else {
|
||||
// C++1y [expr.const]p2:
|
||||
// A conditional-expression e is a core constant expression unless the
|
||||
// evaluation of e, following the rules of the abstract machine, would
|
||||
// evaluate [...] a lambda-expression.
|
||||
D = diag::err_lambda_in_constant_expression;
|
||||
}
|
||||
for (unsigned I = 0, N = Rec.Lambdas.size(); I != N; ++I)
|
||||
Diag(Rec.Lambdas[I]->getLocStart(),
|
||||
diag::err_lambda_unevaluated_operand);
|
||||
Diag(Rec.Lambdas[I]->getLocStart(), D);
|
||||
} else {
|
||||
// Mark the capture expressions odr-used. This was deferred
|
||||
// during lambda expression creation.
|
||||
|
|
|
@ -1229,20 +1229,25 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body,
|
|||
CaptureInits, ArrayIndexVars,
|
||||
ArrayIndexStarts, Body->getLocEnd(),
|
||||
ContainsUnexpandedParameterPack);
|
||||
// C++11 [expr.prim.lambda]p2:
|
||||
// A lambda-expression shall not appear in an unevaluated operand
|
||||
// (Clause 5).
|
||||
|
||||
if (!CurContext->isDependentContext()) {
|
||||
switch (ExprEvalContexts.back().Context) {
|
||||
// C++11 [expr.prim.lambda]p2:
|
||||
// A lambda-expression shall not appear in an unevaluated operand
|
||||
// (Clause 5).
|
||||
case Unevaluated:
|
||||
case UnevaluatedAbstract:
|
||||
// C++1y [expr.const]p2:
|
||||
// A conditional-expression e is a core constant expression unless the
|
||||
// evaluation of e, following the rules of the abstract machine, would
|
||||
// evaluate [...] a lambda-expression.
|
||||
case ConstantEvaluated:
|
||||
// We don't actually diagnose this case immediately, because we
|
||||
// could be within a context where we might find out later that
|
||||
// the expression is potentially evaluated (e.g., for typeid).
|
||||
ExprEvalContexts.back().Lambdas.push_back(Lambda);
|
||||
break;
|
||||
|
||||
case ConstantEvaluated:
|
||||
case PotentiallyEvaluated:
|
||||
case PotentiallyEvaluatedIfUsed:
|
||||
break;
|
||||
|
|
|
@ -275,9 +275,7 @@ namespace UndefinedBehavior {
|
|||
|
||||
// - a lambda-expression (5.1.2);
|
||||
struct Lambda {
|
||||
// FIXME: clang crashes when trying to parse this! Revisit this check once
|
||||
// lambdas are fully implemented.
|
||||
//int n : []{ return 1; }();
|
||||
int n : []{ return 1; }(); // expected-error {{constant expression}} expected-error {{integral constant expression}}
|
||||
};
|
||||
|
||||
// - an lvalue-to-rvalue conversion (4.1) unless it is applied to
|
||||
|
|
|
@ -21,7 +21,9 @@ void bad_news(int *ip)
|
|||
auto s = new int*[[]{return 1;}()][2]; // expected-error {{expected ']'}}
|
||||
// ... but not here:
|
||||
auto t = new (int(*)[[]]); // expected-error {{an attribute list cannot appear here}}
|
||||
auto u = new (int(*)[[]{return 1;}()][2]); // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}} expected-error {{variably modified type}}
|
||||
auto u = new (int(*)[[]{return 1;}()][2]); // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}} \
|
||||
expected-error {{variably modified type}} \
|
||||
expected-error {{a lambda expression may not appear inside of a constant expression}}
|
||||
}
|
||||
|
||||
void good_deletes()
|
||||
|
|
Loading…
Reference in New Issue