Skip to content

Commit cdd9b65

Browse files
committed
Crash when referencing capture in static lambda
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.
1 parent 7c85fcb commit cdd9b65

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
@@ -848,6 +848,10 @@ Miscellaneous Clang Crashes Fixed
848848
`Issue 41302 <https://github.com/llvm/llvm-project/issues/41302>`_
849849
- Fixed a crash when ``-ast-dump=json`` was used for code using class
850850
template deduction guides.
851+
- Fixed a crash when a lambda marked as ``static`` referenced a captured
852+
variable in an expression.
853+
`Issue 74608 <https://github.com/llvm/llvm-project/issues/74608>`_
854+
851855

852856
OpenACC Specific Changes
853857
------------------------

clang/lib/AST/ExprConstant.cpp

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

84948494
if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) {
8495+
const auto *MD = cast<CXXMethodDecl>(Info.CurrentCall->Callee);
8496+
8497+
// Static lambda function call operators can't have captures. We already
8498+
// diagnosed this, so bail out here.
8499+
if (MD->isStatic()) {
8500+
assert(Info.CurrentCall->This == nullptr &&
8501+
"This should not be set for a static call operator");
8502+
return false;
8503+
}
8504+
84958505
// Start with 'Result' referring to the complete closure object...
8496-
if (auto *MD = cast<CXXMethodDecl>(Info.CurrentCall->Callee);
8497-
MD->isExplicitObjectMemberFunction()) {
8506+
if (MD->isExplicitObjectMemberFunction()) {
84988507
APValue *RefValue =
84998508
Info.getParamSlot(Info.CurrentCall->Arguments, MD->getParamDecl(0));
85008509
Result.setFrom(Info.Ctx, *RefValue);
85018510
} else
85028511
Result = *Info.CurrentCall->This;
8512+
85038513
// ... then update it to refer to the field of the closure object
85048514
// that represents the capture.
85058515
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)