diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -5917,8 +5917,15 @@ assert(!InitWithCleanup->getNumObjects() && "default argument expression has capturing blocks?"); } + // C++ [expr.const]p15.1: + // An expression or conversion is in an immediate function context if it is + // potentially evaluated and [...] its innermost enclosing non-block scope + // is a function parameter scope of an immediate function. EnterExpressionEvaluationContext EvalContext( - *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param); + *this, + FD->isConsteval() ? ExpressionEvaluationContext::ImmediateFunctionContext + : ExpressionEvaluationContext::PotentiallyEvaluated, + Param); ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = SkipImmediateInvocations; MarkDeclarationsReferencedInExpr(Init, /*SkipLocalVariables*/ true); @@ -6005,8 +6012,16 @@ // Mark that we are replacing a default argument first. // If we are instantiating a template we won't have to // retransform immediate calls. + // C++ [expr.const]p15.1: + // An expression or conversion is in an immediate function context if it + // is potentially evaluated and [...] its innermost enclosing non-block + // scope is a function parameter scope of an immediate function. EnterExpressionEvaluationContext EvalContext( - *this, ExpressionEvaluationContext::PotentiallyEvaluated, Param); + *this, + FD->isConsteval() + ? ExpressionEvaluationContext::ImmediateFunctionContext + : ExpressionEvaluationContext::PotentiallyEvaluated, + Param); if (Param->hasUninstantiatedDefaultArg()) { if (InstantiateDefaultArgument(CallLoc, FD, Param)) diff --git a/clang/test/CXX/expr/expr.const/p6-2a.cpp b/clang/test/CXX/expr/expr.const/p6-2a.cpp --- a/clang/test/CXX/expr/expr.const/p6-2a.cpp +++ b/clang/test/CXX/expr/expr.const/p6-2a.cpp @@ -43,14 +43,12 @@ constexpr Temporary t = {3}; // expected-error {{must have constant destruction}} expected-note {{created here}} expected-note {{in call}} namespace P1073R3 { -consteval int f() { return 42; } // expected-note 3 {{declared here}} +consteval int f() { return 42; } // expected-note 2 {{declared here}} consteval auto g() { return f; } -// FIXME: there should be no diagnostics associated with either h() or r. -consteval int h(int (*p)() = g()) { return p(); } // expected-error {{call to consteval function 'P1073R3::g' is not a constant expression}} \ - expected-note {{declared here}} \ - expected-note {{pointer to a consteval declaration is not a constant expression}} -constexpr int r = h(); // expected-note {{in the default initalizer of 'p'}} +consteval int h(int (*p)() = g()) { return p(); } +constexpr int r = h(); constexpr auto e = g(); // expected-error {{call to consteval function 'P1073R3::g' is not a constant expression}} \ expected-error {{constexpr variable 'e' must be initialized by a constant expression}} \ expected-note 2 {{pointer to a consteval declaration is not a constant expression}} +static_assert(r == 42); } // namespace P1073R3