Skip to content

Commit c88d731

Browse files
authored
[clang] Crash when referencing capture in static lambda (#74661)
The constant evaluator could try to reference a lambda capture in a static lambda call operator. Static lambdas can't have captures, so we simply abort. Either the lambda needs to be made non-static, or the capture (and reference to it) need to be removed. Fixes: #74608
1 parent 5d12274 commit c88d731

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,10 @@ Miscellaneous Clang Crashes Fixed
870870
`Issue 41302 <https://github.com/llvm/llvm-project/issues/41302>`_
871871
- Fixed a crash when ``-ast-dump=json`` was used for code using class
872872
template deduction guides.
873+
- Fixed a crash when a lambda marked as ``static`` referenced a captured
874+
variable in an expression.
875+
`Issue 74608 <https://github.com/llvm/llvm-project/issues/74608>`_
876+
873877

874878
OpenACC Specific Changes
875879
------------------------

clang/lib/AST/ExprConstant.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8514,14 +8514,24 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
85148514
return false;
85158515

85168516
if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) {
8517+
const auto *MD = cast<CXXMethodDecl>(Info.CurrentCall->Callee);
8518+
8519+
// Static lambda function call operators can't have captures. We already
8520+
// diagnosed this, so bail out here.
8521+
if (MD->isStatic()) {
8522+
assert(Info.CurrentCall->This == nullptr &&
8523+
"This should not be set for a static call operator");
8524+
return false;
8525+
}
8526+
85178527
// Start with 'Result' referring to the complete closure object...
8518-
if (auto *MD = cast<CXXMethodDecl>(Info.CurrentCall->Callee);
8519-
MD->isExplicitObjectMemberFunction()) {
8528+
if (MD->isExplicitObjectMemberFunction()) {
85208529
APValue *RefValue =
85218530
Info.getParamSlot(Info.CurrentCall->Arguments, MD->getParamDecl(0));
85228531
Result.setFrom(Info.Ctx, *RefValue);
85238532
} else
85248533
Result = *Info.CurrentCall->This;
8534+
85258535
// ... then update it to refer to the field of the closure object
85268536
// that represents the capture.
85278537
if (!HandleLValueMember(Info, E, Result, FD))

clang/test/Parser/cxx2b-lambdas.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,15 @@ void static_captures() {
6666
}
6767
};
6868
}
69+
70+
constexpr auto static_capture_constexpr() {
71+
char n = 'n';
72+
return [n] static { return n; }(); // expected-error {{a static lambda cannot have any captures}}
73+
}
74+
static_assert(static_capture_constexpr()); // expected-error {{static assertion expression is not an integral constant expression}}
75+
76+
constexpr auto capture_constexpr() {
77+
char n = 'n';
78+
return [n] { return n; }();
79+
}
80+
static_assert(capture_constexpr());

0 commit comments

Comments
 (0)