[clang] a2739f1 - [clang] Treat function parameter scope as an immediate function context

Mariya Podchishchaeva via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 7 08:51:05 PST 2023


Author: Mariya Podchishchaeva
Date: 2023-03-07T11:46:26-05:00
New Revision: a2739f111d9795fe49109c26c2d816436f2143c3

URL: https://github.com/llvm/llvm-project/commit/a2739f111d9795fe49109c26c2d816436f2143c3
DIFF: https://github.com/llvm/llvm-project/commit/a2739f111d9795fe49109c26c2d816436f2143c3.diff

LOG: [clang] Treat function parameter scope as an immediate function context

This results in expressions that appear in default function argument not
being checked for being actual constant expressions.
This aligns clang's behavior with the standard and fixes one of the
examples from https://wg21.link/P1073R3.

Reviewed By: shafik, cor3ntin

Differential Revision: https://reviews.llvm.org/D145251

Added: 
    

Modified: 
    clang/lib/Sema/SemaExpr.cpp
    clang/test/CXX/expr/expr.const/p6-2a.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 56abde04eaf0d..f01329a9dfb37 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5917,8 +5917,15 @@ bool Sema::CheckCXXDefaultArgExpr(SourceLocation CallLoc, FunctionDecl *FD,
     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 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
     // 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
index 2ef067c549003..a937474d53b22 100644
--- a/clang/test/CXX/expr/expr.const/p6-2a.cpp
+++ b/clang/test/CXX/expr/expr.const/p6-2a.cpp
@@ -43,14 +43,12 @@ struct Temporary {
 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


        


More information about the cfe-commits mailing list