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<
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.
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;
// - 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
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()