[clang] c88d731 - [clang] Crash when referencing capture in static lambda (#74661)

via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 11 22:30:28 PST 2023


Author: Ben Jackson
Date: 2023-12-12T07:30:23+01:00
New Revision: c88d73164a3960c5ef3ff578631f0e765b893809

URL: https://github.com/llvm/llvm-project/commit/c88d73164a3960c5ef3ff578631f0e765b893809
DIFF: https://github.com/llvm/llvm-project/commit/c88d73164a3960c5ef3ff578631f0e765b893809.diff

LOG: [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: https://github.com/llvm/llvm-project/issues/74608

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/ExprConstant.cpp
    clang/test/Parser/cxx2b-lambdas.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d6719680d2ac70..b62293a33bb9ff 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -870,6 +870,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 f035c1419f4c98..f6aeee1a4e935d 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -8514,14 +8514,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 bb9ed226afffaf..ad975a17b6e476 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