Index: clang/lib/Parse/ParseDeclCXX.cpp =================================================================== --- clang/lib/Parse/ParseDeclCXX.cpp +++ clang/lib/Parse/ParseDeclCXX.cpp @@ -2974,11 +2974,20 @@ /// be a constant-expression. ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, SourceLocation &EqualLoc) { + using EEC = Sema::ExpressionEvaluationContext; + assert(Tok.isOneOf(tok::equal, tok::l_brace) && "Data member initializer not starting with '=' or '{'"); + bool IsConstexpr = false; + if (auto *VD = dyn_cast_or_null(D)) + IsConstexpr = VD->isConstexpr(); + EnterExpressionEvaluationContext Context( - Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, D); + Actions, + getLangOpts().CPlusPlus2a && IsConstexpr ? EEC::ConstantEvaluated + : EEC::PotentiallyEvaluated, + D); if (TryConsumeToken(tok::equal, EqualLoc)) { if (Tok.is(tok::kw_delete)) { // In principle, an initializer of '= delete p;' is legal, but it will Index: clang/lib/Parse/ParseStmt.cpp =================================================================== --- clang/lib/Parse/ParseStmt.cpp +++ clang/lib/Parse/ParseStmt.cpp @@ -1329,10 +1329,19 @@ // Parse the condition. StmtResult InitStmt; Sema::ConditionResult Cond; - if (ParseParenExprOrCondition(&InitStmt, Cond, IfLoc, - IsConstexpr ? Sema::ConditionKind::ConstexprIf - : Sema::ConditionKind::Boolean)) - return StmtError(); + + { + EnterExpressionEvaluationContext Unevaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated, + /*LambdaContextDecl=*/nullptr, /*ExprContext=*/ + Sema::ExpressionEvaluationContextRecord::EK_Other, + /*ShouldEnter=*/IsConstexpr); + + if (ParseParenExprOrCondition(&InitStmt, Cond, IfLoc, + IsConstexpr ? Sema::ConditionKind::ConstexprIf + : Sema::ConditionKind::Boolean)) + return StmtError(); + } llvm::Optional ConstexprCondition; if (IsConstexpr) Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4644,7 +4644,9 @@ Function->setInnerLocStart(PatternDecl->getInnerLocStart()); EnterExpressionEvaluationContext EvalContext( - *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); + *this, PatternDecl->getConstexprKind() == CSK_consteval + ? Sema::ExpressionEvaluationContext::ConstantEvaluated + : Sema::ExpressionEvaluationContext::PotentiallyEvaluated); // Introduce a new scope where local variable instantiations will be // recorded, unless we're actually a member function within a local @@ -4947,8 +4949,13 @@ Var->setImplicitlyInline(); if (OldVar->getInit()) { + bool IsConstexpr = OldVar->isConstexpr() || isConstantEvaluated(); EnterExpressionEvaluationContext Evaluated( - *this, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, Var); + *this, + getLangOpts().CPlusPlus2a && IsConstexpr + ? Sema::ExpressionEvaluationContext::ConstantEvaluated + : Sema::ExpressionEvaluationContext::PotentiallyEvaluated, + Var); // Instantiate the initializer. ExprResult Init; Index: clang/lib/Sema/TreeTransform.h =================================================================== --- clang/lib/Sema/TreeTransform.h +++ clang/lib/Sema/TreeTransform.h @@ -12169,7 +12169,9 @@ // FIXME: Sema's lambda-building mechanism expects us to push an expression // evaluation context even if we're not transforming the function body. getSema().PushExpressionEvaluationContext( - Sema::ExpressionEvaluationContext::PotentiallyEvaluated); + E->getCallOperator()->getConstexprKind() == CSK_consteval + ? Sema::ExpressionEvaluationContext::ConstantEvaluated + : Sema::ExpressionEvaluationContext::PotentiallyEvaluated); // Instantiate the body of the lambda expression. StmtResult Body =