[clang] Push immediate function context while transforming lambdas in templates. (PR #89702)
Daniel M. Katz via cfe-commits
cfe-commits at lists.llvm.org
Mon Apr 22 20:03:17 PDT 2024
https://github.com/katzdm created https://github.com/llvm/llvm-project/pull/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`.
>From 1db83800ef13fae454709c8ba4a7b80728c7bcbe Mon Sep 17 00:00:00 2001
From: Dan Katz <katzdm at gmail.com>
Date: Mon, 22 Apr 2024 22:39:06 -0400
Subject: [PATCH] Push immediate function context while transforming lambdas in
templates.
---
clang/docs/ReleaseNotes.rst | 3 +++
clang/lib/Sema/TreeTransform.h | 2 ++
clang/test/SemaCXX/cxx2a-consteval.cpp | 20 ++++++++++++++++++++
3 files changed, 25 insertions(+)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 45a9a79739a4eb..0efdcac3c4b8e1 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -420,6 +420,9 @@ Bug Fixes in This Version
- Fixed a regression in CTAD that a friend declaration that befriends itself may cause
incorrect constraint substitution. (#GH86769).
+- 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 Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 284c9173e68ed5..a3ddebb3ca5963 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -14044,6 +14044,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..b19e25e26c214c 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_dependent_lambda {
+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