[clang] [clang] Crash when referencing capture in static lambda (PR #74661)
Ben Jackson via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 7 06:47:03 PST 2023
https://github.com/puremourning updated https://github.com/llvm/llvm-project/pull/74661
>From 13afd0e5087340c62b31ff5d35c06b28f93086a5 Mon Sep 17 00:00:00 2001
From: Ben Jackson <puremourning at gmail.com>
Date: Wed, 6 Dec 2023 21:59:21 +0000
Subject: [PATCH] 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.
---
clang/docs/ReleaseNotes.rst | 4 ++++
clang/lib/AST/ExprConstant.cpp | 14 ++++++++++++--
clang/test/Parser/cxx2b-lambdas.cpp | 12 ++++++++++++
3 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 1fbd332f74057..43292d1eef227 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -848,6 +848,10 @@ Miscellaneous Clang Crashes Fixed
`Issue 41302 <https://github.com/llvm/llvm-project/issues/41302>`_
- Fixed a crash when ``-ast-dump=json`` was used for code using class
template deduction guides.
+- Fixed a crash when a lambda marked as `static` referenced a captured variable
+ in an expression.
+ `Issue 74608 <https://github.com/llvm/llvm-project/issues/74608>`_
+
OpenACC Specific Changes
------------------------
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 986302e1fd225..41cf9443a6481 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8492,14 +8492,24 @@ bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
return false;
if (auto *FD = Info.CurrentCall->LambdaCaptureFields.lookup(VD)) {
+ const auto *MD = cast<CXXMethodDecl>(Info.CurrentCall->Callee);
+
+ // Static lambda function call operators can't have captures. We already
+ // diagnosed this, so bail out here.
+ if (MD->isStatic()) {
+ assert(Info.CurrentCall->This == nullptr &&
+ "This should not be set for a static call operator");
+ return false;
+ }
+
// Start with 'Result' referring to the complete closure object...
- if (auto *MD = cast<CXXMethodDecl>(Info.CurrentCall->Callee);
- MD->isExplicitObjectMemberFunction()) {
+ if (MD->isExplicitObjectMemberFunction()) {
APValue *RefValue =
Info.getParamSlot(Info.CurrentCall->Arguments, MD->getParamDecl(0));
Result.setFrom(Info.Ctx, *RefValue);
} else
Result = *Info.CurrentCall->This;
+
// ... then update it to refer to the field of the closure object
// that represents the capture.
if (!HandleLValueMember(Info, E, Result, FD))
diff --git a/clang/test/Parser/cxx2b-lambdas.cpp b/clang/test/Parser/cxx2b-lambdas.cpp
index bb9ed226afffa..ad975a17b6e47 100644
--- a/clang/test/Parser/cxx2b-lambdas.cpp
+++ b/clang/test/Parser/cxx2b-lambdas.cpp
@@ -66,3 +66,15 @@ void static_captures() {
}
};
}
+
+constexpr auto static_capture_constexpr() {
+ char n = 'n';
+ return [n] static { return n; }(); // expected-error {{a static lambda cannot have any captures}}
+}
+static_assert(static_capture_constexpr()); // expected-error {{static assertion expression is not an integral constant expression}}
+
+constexpr auto capture_constexpr() {
+ char n = 'n';
+ return [n] { return n; }();
+}
+static_assert(capture_constexpr());
More information about the cfe-commits
mailing list