[clang] 4a043c6 - PotentiallyEvaluatedContext in a ImmediateFunctionContext.

Utkarsh Saxena via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 26 01:30:23 PDT 2022


Author: Utkarsh Saxena
Date: 2022-08-26T10:30:10+02:00
New Revision: 4a043c6376468f1883bbfcdac1a160e5bc97f640

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

LOG: PotentiallyEvaluatedContext in a ImmediateFunctionContext.

Body of `consteval` should be in an `ImmediateFunctionContext` instead of `ConstantEvaluated`.
PotentiallyEvaluated expressions in Immediate functions are in a `ImmediateFunctionContext` as well.

Fixes https://github.com/llvm/llvm-project/issues/51182
Original divergence: https://godbolt.org/z/vadGT5j6f

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

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaDecl.cpp
    clang/lib/Sema/SemaExpr.cpp
    clang/test/SemaCXX/cxx2a-consteval.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 6b68172a79d2c..82f4ee482c9d9 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -174,6 +174,9 @@ C++20 Feature Support
 - Class member variables are now in scope when parsing a ``requires`` clause. Fixes
   `GH55216 <https://github.com/llvm/llvm-project/issues/55216>`_.
 
+- Correctly set expression evaluation context as 'immediate function context' in
+  consteval functions.
+  This fixes `GH51182 https://github.com/llvm/llvm-project/issues/51182`
 
 
 C++2b Feature Support

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 3e9a748346250..0ee21cf64aa34 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -1351,6 +1351,15 @@ class Sema final {
     bool isImmediateFunctionContext() const {
       return Context == ExpressionEvaluationContext::ImmediateFunctionContext ||
              (Context == ExpressionEvaluationContext::DiscardedStatement &&
+              InImmediateFunctionContext) ||
+             // C++2b [expr.const]p14:
+             // An expression or conversion is in an immediate function
+             // context if it is potentially evaluated and either:
+             //   * its innermost enclosing non-block scope is a function
+             //     parameter scope of an immediate function, or
+             //   * its enclosing statement is enclosed by the compound-
+             //     statement of a consteval if statement.
+             (Context == ExpressionEvaluationContext::PotentiallyEvaluated &&
               InImmediateFunctionContext);
     }
 

diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 873051fd3a3f4..1a29e6bb86f39 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14800,8 +14800,12 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
   // Do not push if it is a lambda because one is already pushed when building
   // the lambda in ActOnStartOfLambdaDefinition().
   if (!isLambdaCallOperator(FD))
+    // [expr.const]/p14.1
+    // An expression or conversion is in an immediate function context if it is
+    // potentially evaluated and either: its innermost enclosing non-block scope
+    // is a function parameter scope of an immediate function.
     PushExpressionEvaluationContext(
-        FD->isConsteval() ? ExpressionEvaluationContext::ConstantEvaluated
+        FD->isConsteval() ? ExpressionEvaluationContext::ImmediateFunctionContext
                           : ExprEvalContexts.back().Context);
 
   // Check for defining attributes before the check for redefinition.

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index eb1690c007885..80ac6733cbef2 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -19675,8 +19675,8 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
 
   if (auto *FD = dyn_cast<FunctionDecl>(E->getDecl()))
     if (!isUnevaluatedContext() && !isConstantEvaluated() &&
-        FD->isConsteval() && !RebuildingImmediateInvocation &&
-        !FD->isDependentContext())
+        !isImmediateFunctionContext() && FD->isConsteval() &&
+        !RebuildingImmediateInvocation && !FD->isDependentContext())
       ExprEvalContexts.back().ReferenceToConsteval.insert(E);
   MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse,
                      RefsMinusAssignments);

diff  --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index 78011e2003417..09129a27818d3 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -908,3 +908,34 @@ int test() {
   return testDefaultArgForParam() + testDefaultArgForParam((E)1);
 }
 }
+
+namespace GH51182 {
+// Nested consteval function.
+consteval int f(int v) {
+  return v;
+}
+
+template <typename T>
+consteval int g(T a) {
+  // An immediate function context.
+  int n = f(a);
+  return n;
+}
+static_assert(g(100) == 100);
+// --------------------------------------
+template <typename T>
+consteval T max(const T& a, const T& b) {
+    return (a > b) ? a : b;
+}
+template <typename T>
+consteval T mid(const T& a, const T& b, const T& c) {
+    T m = max(max(a, b), c);
+    if (m == a)
+        return max(b, c);
+    if (m == b)
+        return max(a, c);
+    return max(a, b);
+}
+static_assert(max(1,2)==2);
+static_assert(mid(1,2,3)==2);
+} // namespace GH51182


        


More information about the cfe-commits mailing list