Skip to content

Commit e78a1f4

Browse files
authored
[Clang] Fix the instantiation of return type requirements in lambda bodies (#76967)
Currently, due to the incomplete implementation of p0588r1, the instantiation of lambda expressions leads to the instantiation of the body. And `EvaluateConstraints` is false during the instantiation of the body, which causes crashes during the instantiation of the return type requirement: ```cpp template<typename T> concept doesnt_matter = true; template<class T> concept test = []{ return requires(T t) { { t } -> doesnt_matter; // crash }; }(); static_assert(test<int>); ``` Although a complete implementation of p0588r1 can solve these crashes, it will take some time. Therefore, this pull request aims to fix these crashes first. Fixes #63808 Fixes #64607 Fixes #64086
1 parent 9f9dd6b commit e78a1f4

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,11 @@ Bug Fixes to C++ Support
844844
- Fix crash when parsing nested requirement. Fixes:
845845
(`#73112 <https://github.com/llvm/llvm-project/issues/73112>`_)
846846

847+
- Fixed a crash caused by using return type requirement in a lambda. Fixes:
848+
(`#63808 <https://github.com/llvm/llvm-project/issues/63808>`_)
849+
(`#64607 <https://github.com/llvm/llvm-project/issues/64607>`_)
850+
(`#64086 <https://github.com/llvm/llvm-project/issues/64086>`_)
851+
847852
Bug Fixes to AST Handling
848853
^^^^^^^^^^^^^^^^^^^^^^^^^
849854
- Fixed an import failure of recursive friend class template.

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1479,6 +1479,23 @@ namespace {
14791479
return Result;
14801480
}
14811481

1482+
StmtResult TransformLambdaBody(LambdaExpr *E, Stmt *Body) {
1483+
// Currently, we instantiate the body when instantiating the lambda
1484+
// expression. However, `EvaluateConstraints` is disabled during the
1485+
// instantiation of the lambda expression, causing the instantiation
1486+
// failure of the return type requirement in the body. If p0588r1 is fully
1487+
// implemented, the body will be lazily instantiated, and this problem
1488+
// will not occur. Here, `EvaluateConstraints` is temporarily set to
1489+
// `true` to temporarily fix this issue.
1490+
// FIXME: This temporary fix can be removed after fully implementing
1491+
// p0588r1.
1492+
bool Prev = EvaluateConstraints;
1493+
EvaluateConstraints = true;
1494+
StmtResult Stmt = inherited::TransformLambdaBody(E, Body);
1495+
EvaluateConstraints = Prev;
1496+
return Stmt;
1497+
}
1498+
14821499
ExprResult TransformRequiresExpr(RequiresExpr *E) {
14831500
LocalInstantiationScope Scope(SemaRef, /*CombineWithOuterScope=*/true);
14841501
ExprResult TransReq = inherited::TransformRequiresExpr(E);

clang/test/SemaTemplate/concepts-lambda.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,36 @@ static_assert(E<int>);
116116
// expected-note@-11{{because 'Q.template operator()<float>()' would be invalid: no matching member function for call to 'operator()'}}
117117
}
118118
}
119+
120+
namespace ReturnTypeRequirementInLambda {
121+
template <typename T>
122+
concept C1 = true;
123+
124+
template <class T>
125+
concept test = [] {
126+
return requires(T t) {
127+
{ t } -> C1;
128+
};
129+
}();
130+
131+
static_assert(test<int>);
132+
133+
template <typename T>
134+
concept C2 = true;
135+
struct S1 {
136+
int f1() { return 1; }
137+
};
138+
139+
void foo() {
140+
auto make_caller = []<auto member> {
141+
return [](S1 *ps) {
142+
if constexpr (requires {
143+
{ (ps->*member)() } -> C2;
144+
})
145+
;
146+
};
147+
};
148+
149+
auto caller = make_caller.operator()<&S1::f1>();
150+
}
151+
} // namespace ReturnTypeRequirementInLambda

0 commit comments

Comments
 (0)