https://github.com/benedekaibas created 
https://github.com/llvm/llvm-project/pull/219726

Currently explicit object parameters are not modeled in the 
`VisitCommonDeclRefExpr` function in `ExprEngine`. Because of this when a 
lambda has an explicit object parameter and a possible division by zero the 
`core.DivideZero` checker does not emit warning. This PR solves that issue by 
deciding if the lambda has an explicit object parameter and then records the 
binding (if the parameter has the reference type) between the parameter and the 
argument's expression otherwise it returns the captured field's lvalue.

This PR fixes #218708

>From cd800a911d402fafe1f32e4ff2709d5061732e08 Mon Sep 17 00:00:00 2001
From: benedekaibas <[email protected]>
Date: Sat, 29 Aug 2026 22:41:18 +0200
Subject: [PATCH] [analyzer] Resolve lambda captures for explicit object
 parameters

---
 clang/lib/StaticAnalyzer/Core/ExprEngine.cpp  | 26 +++++++++--
 .../test/Analysis/explicit-lambda-capture.cpp | 43 +++++++++++++++++++
 2 files changed, 65 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/Analysis/explicit-lambda-capture.cpp

diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp 
b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index e6349eb4eba2a..01e05924a2537 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -3040,12 +3040,30 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, 
const NamedDecl *D,
       // Sema follows a sequence of complex rules to determine whether the
       // variable should be captured.
       if (const FieldDecl *FD = LambdaCaptureFields[VD]) {
-        Loc CXXThis = svalBuilder.getCXXThis(MD, SF);
-        SVal CXXThisVal = state->getSVal(CXXThis);
-        return std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());
+        if (MD->isImplicitObjectMemberFunction()) {
+          Loc CXXThis = svalBuilder.getCXXThis(MD, SF);
+          SVal CXXThisVal = state->getSVal(CXXThis);
+          return std::make_pair(state->getLValue(FD, CXXThisVal),
+                                FD->getType());
+        }
+        const ParmVarDecl *PVD = MD->getParamDecl(0);
+        if (const Expr *CallSite = SF->getCallSite()) {
+          unsigned Idx = PVD->getFunctionScopeIndex();
+          const ParamVarRegion *PVR =
+              state->getStateManager().getRegionManager().getParamVarRegion(
+                  CallSite, Idx, SF);
+          const Expr *SelfArgExpr = cast<CallExpr>(CallSite)->getArg(0);
+          state =
+              state->bindLoc(loc::MemRegionVal(PVR),
+                             state->getSVal(SelfArgExpr, SF->getParent()), SF);
+          SVal ParamSVal = state->getSVal(loc::MemRegionVal(PVR));
+          if (!PVD->getType()->isReferenceType())
+            return std::make_pair(state->getLValue(FD, loc::MemRegionVal(PVR)),
+                                  FD->getType());
+          return std::make_pair(state->getLValue(FD, ParamSVal), 
FD->getType());
+        }
       }
     }
-
     return std::nullopt;
   };
 
diff --git a/clang/test/Analysis/explicit-lambda-capture.cpp 
b/clang/test/Analysis/explicit-lambda-capture.cpp
new file mode 100644
index 0000000000000..2d98b80ce9637
--- /dev/null
+++ b/clang/test/Analysis/explicit-lambda-capture.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -analyze -std=c++23 -analyzer-checker=core.DivideZero 
-verify %s
+
+int implicit_capture_by_value() {
+  int d = 0;
+  auto lam = [d]() { return 1 / d; }; // expected-warning {{Division by zero}}
+  return lam(); 
+}
+
+int explicit_rvalue_self_capture_by_reference() {
+  int d = 0;
+  auto lam = [&d](this auto &&self) { return 1 / d; }; // expected-warning 
{{Division by zero}}
+  return lam(); 
+}
+
+int gh218708_explicit_rvalue_self() {
+  int d = 0;
+  auto lam = [d](this auto &&self) { return 1 / d; }; // expected-warning 
{{Division by zero}}
+  return lam(); 
+}
+
+int gh218708_explicit_lvalue_self() {
+  int d = 0;
+  auto lam = [d](this auto &self) { return 1 / d; }; // expected-warning 
{{Division by zero}}
+  return lam(); 
+}
+
+int gh218708_explicit_by_value_self() {
+  int d = 0;
+  auto lam = [d](this auto self) { return 1 / d; }; // expected-warning 
{{Division by zero}}
+  return lam();
+}
+
+int explicit_rvalue_no_error() {
+  int d = 5;
+  auto lam = [d](this auto &&self) { return 1 / d; }; // 'd' is non-zero so 
there is no division by zero error. 
+  return lam(); 
+}
+
+int explicit_by_value_no_error() {
+  int d = 9;
+  auto lam = [d](this auto self) { return 1 / d; }; // 'd' is non-zero so 
there is no division by zero error.
+  return lam();
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to