[clang] 5e767bd - Push immediate function context while transforming lambdas in templates. (#89702)

via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 25 00:41:30 PDT 2024


Author: Daniel M. Katz
Date: 2024-04-25T09:41:25+02:00
New Revision: 5e767bd7d16dcdfc1ad8b32ba399f969dd940f57

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

LOG: Push immediate function context while transforming lambdas in templates. (#89702)

The following program is [accepted](https://godbolt.org/z/oEc34Trh4) by
Clang, EDG, and MSVC, but rejected by Clang:
```cpp
#include <vector>

consteval auto fn() { return std::vector {1,2,3}; }

template <typename T = int>
void fn2() {
    (void)[]() consteval {
      for (auto e : fn()) {}
    };
}

void caller() {
    fn2();
}
```

The stated diagnostic is:
```cpp
<source>:8:21: error: call to consteval function 'fn' is not a constant expression
    8 |       for (auto e : fn()) {}
```

The body of the lambda should be evaluated as within an immediate
function context when the lambda is marked as `consteval`.

Co-authored-by: cor3ntin <corentinjabot at gmail.com>

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7bea43ec64f062..0bad03eda8cb54 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -564,6 +564,8 @@ Bug Fixes to C++ Support
 - Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()``
   function returns a large or negative value. Fixes (#GH89407).
 - Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235)
+- Fixed bug in which the body of a consteval lambda within a template was not parsed as within an
+  immediate function context.
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 9404be5a46f3f7..1d30ba31e17940 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -14186,6 +14186,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
   // 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(
+      E->getCallOperator()->isConsteval() ?
+      Sema::ExpressionEvaluationContext::ImmediateFunctionContext :
       Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
 
   Sema::CodeSynthesisContext C;

diff  --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp
index 192621225a543c..e198074372072d 100644
--- a/clang/test/SemaCXX/cxx2a-consteval.cpp
+++ b/clang/test/SemaCXX/cxx2a-consteval.cpp
@@ -260,6 +260,26 @@ int(*test)(int)  = l1;
 
 }
 
+namespace consteval_lambda_in_template {
+struct S {
+    int *value;
+    constexpr S(int v) : value(new int {v}) {}
+    constexpr ~S() { delete value; }
+};
+consteval S fn() { return S(5); }
+
+template <typename T>
+void fn2() {
+    (void)[]() consteval -> int {
+      return *(fn().value);  // OK, immediate context
+    };
+}
+
+void caller() {
+    fn2<int>();
+}
+}
+
 namespace std {
 
 template <typename T> struct remove_reference { using type = T; };


        


More information about the cfe-commits mailing list