Skip to content

Commit 5e767bd

Browse files
katzdmcor3ntin
andauthored
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@gmail.com>
1 parent 0894946 commit 5e767bd

File tree

3 files changed

+24
-0
lines changed

3 files changed

+24
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,8 @@ Bug Fixes to C++ Support
564564
- Fixed a crash when trying to evaluate a user-defined ``static_assert`` message whose ``size()``
565565
function returns a large or negative value. Fixes (#GH89407).
566566
- Fixed a use-after-free bug in parsing of type constraints with default arguments that involve lambdas. (#GH67235)
567+
- Fixed bug in which the body of a consteval lambda within a template was not parsed as within an
568+
immediate function context.
567569

568570
Bug Fixes to AST Handling
569571
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/TreeTransform.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14186,6 +14186,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1418614186
// FIXME: Sema's lambda-building mechanism expects us to push an expression
1418714187
// evaluation context even if we're not transforming the function body.
1418814188
getSema().PushExpressionEvaluationContext(
14189+
E->getCallOperator()->isConsteval() ?
14190+
Sema::ExpressionEvaluationContext::ImmediateFunctionContext :
1418914191
Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
1419014192

1419114193
Sema::CodeSynthesisContext C;

clang/test/SemaCXX/cxx2a-consteval.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,26 @@ int(*test)(int) = l1;
260260

261261
}
262262

263+
namespace consteval_lambda_in_template {
264+
struct S {
265+
int *value;
266+
constexpr S(int v) : value(new int {v}) {}
267+
constexpr ~S() { delete value; }
268+
};
269+
consteval S fn() { return S(5); }
270+
271+
template <typename T>
272+
void fn2() {
273+
(void)[]() consteval -> int {
274+
return *(fn().value); // OK, immediate context
275+
};
276+
}
277+
278+
void caller() {
279+
fn2<int>();
280+
}
281+
}
282+
263283
namespace std {
264284

265285
template <typename T> struct remove_reference { using type = T; };

0 commit comments

Comments
 (0)