https://github.com/capitan-davide created 
https://github.com/llvm/llvm-project/pull/176727

With the option 'Strict' the checker warns every
time the denominator of a division is potentially
zero.

Does this make sense? If so, I will add tests and update the documentation.

>From fe01f248c620d55991e60c04e634207ba67e9906 Mon Sep 17 00:00:00 2001
From: Davide Cunial <[email protected]>
Date: Mon, 19 Jan 2026 10:35:45 +0000
Subject: [PATCH] [clang][analyzer] Add 'Strict' option to 'core.DivideZero'
 checker

With the option 'Strict' the checker warns every
time the denominator of a division is potentially
zero.
---
 .../clang/StaticAnalyzer/Checkers/Checkers.td |  8 ++++++
 .../Checkers/DivZeroChecker.cpp               | 25 +++++++++++++------
 clang/test/Analysis/analyzer-config.c         |  1 +
 3 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td 
b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e1662e0792e69..976268a76c8b9 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -214,6 +214,14 @@ def VLASizeChecker : Checker<"VLASize">,
 
 def DivZeroChecker : Checker<"DivideZero">,
   HelpText<"Check for division by zero">,
+  CheckerOptions<[
+    CmdLineOption<Boolean
+                  "Strict",
+                  "Warn on all potential divisions by zero i.e., if zero "
+                  "falls within the range of possible divisor values.",
+                  "false",
+                  InAlpha>,
+  ]>,
   Documentation<HasDocumentation>;
 
 def UndefResultChecker : Checker<"UndefinedBinaryOperatorResult">,
diff --git a/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
index ab90615f63182..777576153fab2 100644
--- a/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp
@@ -13,6 +13,7 @@
 
 #include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
 #include "clang/StaticAnalyzer/Checkers/Taint.h"
+#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
 #include "clang/StaticAnalyzer/Core/Checker.h"
@@ -42,6 +43,11 @@ class DivZeroChecker : public 
CheckerFamily<check::PreStmt<BinaryOperator>> {
 
   /// Identifies this checker family for debugging purposes.
   StringRef getDebugTag() const override { return "DivZeroChecker"; }
+
+public:
+  /// In strict mode, the checker warns about all potential divisions by zero
+  /// i.e., if zero falls within the range of possible divisor values.
+  bool Strict = true;
 };
 } // end anonymous namespace
 
@@ -73,7 +79,7 @@ void DivZeroChecker::reportTaintBug(
     auto R =
         std::make_unique<PathSensitiveBugReport>(TaintedDivChecker, Msg, N);
     bugreporter::trackExpressionValue(N, getDenomExpr(N), *R);
-    for (auto Sym : TaintedSyms)
+    for (const auto *Sym : TaintedSyms)
       R->markInteresting(Sym);
     C.emitReport(std::move(R));
   }
@@ -82,10 +88,7 @@ void DivZeroChecker::reportTaintBug(
 void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
                                   CheckerContext &C) const {
   BinaryOperator::Opcode Op = B->getOpcode();
-  if (Op != BO_Div &&
-      Op != BO_Rem &&
-      Op != BO_DivAssign &&
-      Op != BO_RemAssign)
+  if (Op != BO_Div && Op != BO_Rem && Op != BO_DivAssign && Op != BO_RemAssign)
     return;
 
   if (!B->getRHS()->getType()->isScalarType())
@@ -112,11 +115,13 @@ void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
 
   if ((stateNotZero && stateZero)) {
     std::vector<SymbolRef> taintedSyms = getTaintedSymbols(C.getState(), *DV);
-    if (!taintedSyms.empty()) {
+    if (Strict) {
+      reportBug("Potential division by zero", stateZero, C);
+    } else if (!taintedSyms.empty()) {
       reportTaintBug("Division by a tainted value, possibly zero", stateZero, 
C,
                      taintedSyms);
-      // Fallthrough to continue analysis in case of non-zero denominator.
     }
+    // Fallthrough to continue analysis in case of non-zero denominator.
   }
 
   // If we get here, then the denom should not be zero. We abandon the implicit
@@ -125,7 +130,11 @@ void DivZeroChecker::checkPreStmt(const BinaryOperator *B,
 }
 
 void ento::registerDivZeroChecker(CheckerManager &Mgr) {
-  Mgr.getChecker<DivZeroChecker>()->DivideZeroChecker.enable(Mgr);
+  auto *Chk = Mgr.getChecker<DivZeroChecker>();
+  CheckerNameRef ChkName = Mgr.getCurrentCheckerName();
+  Chk->Strict =
+      Mgr.getAnalyzerOptions().getcheckerBooleanOption(ChkName, "Strict");
+  Chk->DivideZeroChecker.enable(Mgr);
 }
 
 bool ento::shouldRegisterDivZeroChecker(const CheckerManager &) { return true; 
}
diff --git a/clang/test/Analysis/analyzer-config.c 
b/clang/test/Analysis/analyzer-config.c
index 4e1f5336a9040..37cc514216e12 100644
--- a/clang/test/Analysis/analyzer-config.c
+++ b/clang/test/Analysis/analyzer-config.c
@@ -38,6 +38,7 @@
 // CHECK-NEXT: core.CallAndMessage:NilReceiver = true
 // CHECK-NEXT: core.CallAndMessage:ParameterCount = true
 // CHECK-NEXT: core.CallAndMessage:UndefReceiver = true
+// CHECK-NEXT: core.DivideZero:Strict = false
 // CHECK-NEXT: cplusplus.Move:WarnOn = KnownsAndLocals
 // CHECK-NEXT: cplusplus.SmartPtrModeling:ModelSmartPtrDereference = false
 // CHECK-NEXT: crosscheck-with-z3 = false

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

Reply via email to