Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -1396,7 +1396,8 @@ }; ExprResult ParseExpression(TypeCastState isTypeCast = NotTypeCast); - ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast); + ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast, + bool IsArrayBound = false); ExprResult ParseConstraintExpression(); // Expr that doesn't include commas. ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast); Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -854,6 +854,9 @@ /// suffice, e.g., in a default function argument. Decl *ManglingContextDecl; + /// \brief Whether an array bound in a BlockContext is being parsed. + bool IsArrayBound; + /// \brief The context information used to mangle lambda expressions /// and block literals within this context. /// @@ -873,11 +876,12 @@ unsigned NumCleanupObjects, bool ParentNeedsCleanups, Decl *ManglingContextDecl, - bool IsDecltype) + bool IsDecltype, bool IsArrayBound) : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups), IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects), NumTypos(0), - ManglingContextDecl(ManglingContextDecl), MangleNumbering() { } + ManglingContextDecl(ManglingContextDecl), + IsArrayBound(IsArrayBound), MangleNumbering() {} /// \brief Retrieve the mangling numbering context, used to consistently /// number constructs like lambdas for mangling. @@ -3639,7 +3643,8 @@ void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr, - bool IsDecltype = false); + bool IsDecltype = false, + bool IsArrayBound = false); enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl }; void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t, @@ -9494,10 +9499,11 @@ EnterExpressionEvaluationContext(Sema &Actions, Sema::ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr, - bool IsDecltype = false) + bool IsDecltype = false, + bool IsArrayBound = false) : Actions(Actions) { Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, - IsDecltype); + IsDecltype, IsArrayBound); } EnterExpressionEvaluationContext(Sema &Actions, Sema::ExpressionEvaluationContext NewContext, Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -6103,7 +6103,8 @@ // Parse the constant-expression or assignment-expression now (depending // on dialect). if (getLangOpts().CPlusPlus) { - NumElements = ParseConstantExpression(); + NumElements = ParseConstantExpression( + Parser::NotTypeCast, D.getContext() == Declarator::BlockContext); } else { EnterExpressionEvaluationContext Unevaluated(Actions, Sema::ConstantEvaluated); Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -194,13 +194,14 @@ } -ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { +ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast, + bool IsArrayBound) { // C++03 [basic.def.odr]p2: // An expression is potentially evaluated unless it appears where an // integral constant expression is required (see 5.19) [...]. // C++98 and C++11 have no such rule, but this is only a defect in C++98. - EnterExpressionEvaluationContext Unevaluated(Actions, - Sema::ConstantEvaluated); + EnterExpressionEvaluationContext Unevaluated(Actions, Sema::ConstantEvaluated, + nullptr, false, IsArrayBound); ExprResult LHS(ParseCastExpression(false, false, isTypeCast)); ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -124,7 +124,8 @@ // Tell diagnostics how to render things from the AST library. Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context); - ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, false, nullptr, false); + ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, false, nullptr, false, + false); FunctionScopes.push_back(new FunctionScopeInfo(Diags)); Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -12791,10 +12791,10 @@ void Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl, - bool IsDecltype) { + bool IsDecltype, bool IsArrayBound) { ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), ExprNeedsCleanups, LambdaContextDecl, - IsDecltype); + IsDecltype, IsArrayBound); ExprNeedsCleanups = false; if (!MaybeODRUseExprs.empty()) std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); @@ -12814,21 +12814,22 @@ if (!Rec.Lambdas.empty()) { 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 { + for (const auto *L : Rec.Lambdas) + Diag(L->getLocStart(), diag::err_lambda_unevaluated_operand); + // Don't error out on lambdas used to compute array size in a + // BlockContext. + } else if (!Rec.IsArrayBound) { // 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 (const auto *L : Rec.Lambdas) + Diag(L->getLocStart(), diag::err_lambda_in_constant_expression); } - for (const auto *L : Rec.Lambdas) - Diag(L->getLocStart(), D); } else { // Mark the capture expressions odr-used. This was deferred // during lambda expression creation. Index: test/SemaCXX/lambda-expressions.cpp =================================================================== --- test/SemaCXX/lambda-expressions.cpp +++ test/SemaCXX/lambda-expressions.cpp @@ -499,3 +499,12 @@ }; } } + +namespace array_bound { +void foo() { + int a0[([](){ return 4; })()]; + int a2[([](int n){ return n; })(4)]; +} + +int a2[([](){ return 4; })()]; // expected-error {{a lambda expression may not appear inside of a constant expression}} expected-error {{variable length array declaration not allowed at file scope}} +}