[clang] Feat/suppress leak reports (PR #199240)

Shuvakant Patra via cfe-commits cfe-commits at lists.llvm.org
Fri May 22 11:24:19 PDT 2026


https://github.com/shuvakant6623 updated https://github.com/llvm/llvm-project/pull/199240

>From 5c4006ce11c9bd8aaddf04d9aa65741dbf5de508 Mon Sep 17 00:00:00 2001
From: shuvakant6623 <scientefic2612 at gmail.com>
Date: Tue, 19 May 2026 12:56:13 +0530
Subject: [PATCH 01/10] [analyzer] Add option to supress leak reports for
 selected ownership types

---
 .../clang/StaticAnalyzer/Checkers/Checkers.td |  6 ++++++
 .../StaticAnalyzer/Checkers/MallocChecker.cpp | 20 +++++++++++++++++--
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 6b9e0b50e1f59..e38752e94b91a 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -513,6 +513,12 @@ def DynamicMemoryModeling: Checker<"DynamicMemoryModeling">,
                   "true",
                   Released,
                   Hide>
+    CmdLineOption<String,
+                  "SuppressLeakReportsFor",
+                  "Comma-separated list of ownership types for which leak "
+                  "reports should be suppressed",
+                  "",
+                  InAlpha>
   ]>,
   Dependencies<[CStringModeling]>,
   Documentation<NotDocumented>,
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index a0a8bd4dfc90d..8f204e26b3ae6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -3024,8 +3024,13 @@ void MallocChecker::HandleLeak(SymbolRef Sym, ExplodedNode *N,
   assert(RS && "cannot leak an untracked symbol");
   AllocationFamily Family = RS->getAllocationFamily();
 
-  if (Family.Kind == AF_Alloca)
-    return;
+  if (Family.Kind == AF_Custom && Family.CustomName) {
+    StringRef Type = *Family.CustomName;
+
+    if (llvm::is_contained(SuppressLeakTypes, Type)) {
+      return;
+    }
+  }
 
   const Leak *Frontend = getRelevantFrontendAs<Leak>(Family);
   // Note that for leaks we don't add a sink when the relevant frontend is
@@ -4197,6 +4202,17 @@ void ento::registerInnerPointerCheckerAux(CheckerManager &Mgr) {
 
 void ento::registerDynamicMemoryModeling(CheckerManager &Mgr) {
   auto *Chk = Mgr.getChecker<MallocChecker>();
+
+  StringRef SuppressList =
+    mgr.getAnalyzerOptions().getCheckerStringOption(
+        "unix.DynamicMemoryModeling:SuppressLeakReportsFor");
+
+  SmallVector<StringRef, 8> Split;
+  SuppressList.split(Split, ',', -1, false);
+
+  for (StringRef S : Split) {
+    Chk->SuppressLeakTypes.push_back(S.trim().str());
+  }
   // FIXME: This is a "hidden" undocumented frontend but there are public
   // checker options which are attached to it.
   CheckerNameRef DMMName = Mgr.getCurrentCheckerName();

>From d5dae60783c33a76310e05ed41f6399ee18d9d41 Mon Sep 17 00:00:00 2001
From: shuvakant6623 <scientefic2612 at gmail.com>
Date: Tue, 19 May 2026 15:26:38 +0530
Subject: [PATCH 02/10] [analyzer] Add test for suppressing leak reports for
 selected ownership types

---
 .../Analysis/suppress-leak-custom-allocator.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
 create mode 100644 clang/test/Analysis/suppress-leak-custom-allocator.c

diff --git a/clang/test/Analysis/suppress-leak-custom-allocator.c b/clang/test/Analysis/suppress-leak-custom-allocator.c
new file mode 100644
index 0000000000000..885764419d892
--- /dev/null
+++ b/clang/test/Analysis/suppress-leak-custom-allocator.c
@@ -0,0 +1,19 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc \
+// RUN: -analyzer-config unix.DynamicMemoryModeling:SuppressLeakReportsFor=arena \
+// RUN: %s -verify
+
+// Custom allocator with ownership annotation
+void *arena_alloc() __attribute__((ownership_returns(arena)));
+
+void test_suppressed() {
+  void *p = arena_alloc();
+  // no-warning
+}
+
+// Same allocator but without suppression → should warn
+// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc %s -verify=expected
+
+void test_not_suppressed() {
+  void *p = arena_alloc();
+  // expected-warning at -1 {{Potential memory leak}}
+}
\ No newline at end of file

>From 100f1b0b68bd9c7e01ae389ec3aabc4e2e16e94c Mon Sep 17 00:00:00 2001
From: shuvakant6623 <scientefic2612 at gmail.com>
Date: Tue, 19 May 2026 16:59:57 +0530
Subject: [PATCH 03/10] [analyzer] Add option to suppress leak reports for
 selected ownership types

---
 clang/include/clang/StaticAnalyzer/Checkers/Checkers.td | 2 +-
 clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp     | 8 +++++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index e38752e94b91a..a5dc6c3ae60f3 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -512,7 +512,7 @@ def DynamicMemoryModeling: Checker<"DynamicMemoryModeling">,
                   "NoStoreFuncVisitor.",
                   "true",
                   Released,
-                  Hide>
+                  Hide>,
     CmdLineOption<String,
                   "SuppressLeakReportsFor",
                   "Comma-separated list of ownership types for which leak "
diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 8f204e26b3ae6..1a2ac5131e3df 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -48,6 +48,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/STLExtras.h"
 #include "AllocationState.h"
 #include "InterCheckerAPI.h"
 #include "NoOwnershipChangeVisitor.h"
@@ -458,6 +459,9 @@ class MallocChecker
 
   StringRef getDebugTag() const override { return "MallocChecker"; }
 
+public:
+  std::vector<std::string> SuppressLeakTypes;
+
 private:
 #define CHECK_FN(NAME)                                                         \
   void NAME(ProgramStateRef State, const CallEvent &Call, CheckerContext &C)   \
@@ -3024,13 +3028,15 @@ void MallocChecker::HandleLeak(SymbolRef Sym, ExplodedNode *N,
   assert(RS && "cannot leak an untracked symbol");
   AllocationFamily Family = RS->getAllocationFamily();
 
+  // --- BEGIN: Suppress leak reports for selected ownership types ---
   if (Family.Kind == AF_Custom && Family.CustomName) {
     StringRef Type = *Family.CustomName;
 
-    if (llvm::is_contained(SuppressLeakTypes, Type)) {
+    if (llvm::is_contained(this->SuppressLeakTypes, Type)) {
       return;
     }
   }
+  // --- END ---
 
   const Leak *Frontend = getRelevantFrontendAs<Leak>(Family);
   // Note that for leaks we don't add a sink when the relevant frontend is

>From 28849272730d876a3832fccbc8ce2256e7b5c8da Mon Sep 17 00:00:00 2001
From: shuvakant6623 <scientefic2612 at gmail.com>
Date: Tue, 19 May 2026 17:17:15 +0530
Subject: [PATCH 04/10] [analyzer] Add option to suppress leak reports for
 selected ownership types

---
 clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 1a2ac5131e3df..bd346b20beee4 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -4210,7 +4210,7 @@ void ento::registerDynamicMemoryModeling(CheckerManager &Mgr) {
   auto *Chk = Mgr.getChecker<MallocChecker>();
 
   StringRef SuppressList =
-    mgr.getAnalyzerOptions().getCheckerStringOption(
+    Mgr.getAnalyzerOptions().getCheckerStringOption(
         "unix.DynamicMemoryModeling:SuppressLeakReportsFor");
 
   SmallVector<StringRef, 8> Split;
@@ -4219,6 +4219,7 @@ void ento::registerDynamicMemoryModeling(CheckerManager &Mgr) {
   for (StringRef S : Split) {
     Chk->SuppressLeakTypes.push_back(S.trim().str());
   }
+
   // FIXME: This is a "hidden" undocumented frontend but there are public
   // checker options which are attached to it.
   CheckerNameRef DMMName = Mgr.getCurrentCheckerName();

>From 51054faa606518c71bb4128ae7a6c8a57d3e27b6 Mon Sep 17 00:00:00 2001
From: shuvakant6623 <scientefic2612 at gmail.com>
Date: Wed, 20 May 2026 19:09:59 +0530
Subject: [PATCH 05/10] [analyzer] Add option to suppress leak reports for
 selected ownership types

---
 clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index bd346b20beee4..b93eb24264561 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -4211,7 +4211,7 @@ void ento::registerDynamicMemoryModeling(CheckerManager &Mgr) {
 
   StringRef SuppressList =
     Mgr.getAnalyzerOptions().getCheckerStringOption(
-        "unix.DynamicMemoryModeling:SuppressLeakReportsFor");
+        Chk, "SuppressLeakReportsFor");
 
   SmallVector<StringRef, 8> Split;
   SuppressList.split(Split, ',', -1, false);

>From 754242b401ad6ae8c8956e7da7f24b495bcdd464 Mon Sep 17 00:00:00 2001
From: shuvakant6623 <scientefic2612 at gmail.com>
Date: Wed, 20 May 2026 23:15:13 +0530
Subject: [PATCH 06/10] [analyzer] Add option to suppress leak reports for
 selected ownership types

---
 .../StaticAnalyzer/Checkers/MallocChecker.cpp   |  3 ++-
 clang/test/Analysis/analyzer-config.c           |  1 +
 .../Analysis/suppress-leak-custom-allocator.c   | 17 ++++++++---------
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index b93eb24264561..85a5e784cee23 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -4208,7 +4208,8 @@ void ento::registerInnerPointerCheckerAux(CheckerManager &Mgr) {
 
 void ento::registerDynamicMemoryModeling(CheckerManager &Mgr) {
   auto *Chk = Mgr.getChecker<MallocChecker>();
-
+  auto ChkName = Mgr.getCurrentCheckerName();
+  
   StringRef SuppressList =
     Mgr.getAnalyzerOptions().getCheckerStringOption(
         Chk, "SuppressLeakReportsFor");
diff --git a/clang/test/Analysis/analyzer-config.c b/clang/test/Analysis/analyzer-config.c
index 04dc8c24421bc..972f3ecc8089a 100644
--- a/clang/test/Analysis/analyzer-config.c
+++ b/clang/test/Analysis/analyzer-config.c
@@ -136,6 +136,7 @@
 // CHECK-NEXT: track-conditions-debug = false
 // CHECK-NEXT: unix.DynamicMemoryModeling:AddNoOwnershipChangeNotes = true
 // CHECK-NEXT: unix.DynamicMemoryModeling:Optimistic = false
+// CHECK-NEXT: unix.DynamicMemoryModeling:SuppressLeakReportsFor = ""
 // CHECK-NEXT: unix.Errno:AllowErrnoReadOutsideConditionExpressions = true
 // CHECK-NEXT: unix.StdCLibraryFunctions:DisplayLoadedSummaries = false
 // CHECK-NEXT: unix.StdCLibraryFunctions:ModelPOSIX = true
diff --git a/clang/test/Analysis/suppress-leak-custom-allocator.c b/clang/test/Analysis/suppress-leak-custom-allocator.c
index 885764419d892..27b6b4b91b7d7 100644
--- a/clang/test/Analysis/suppress-leak-custom-allocator.c
+++ b/clang/test/Analysis/suppress-leak-custom-allocator.c
@@ -1,19 +1,18 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc \
 // RUN: -analyzer-config unix.DynamicMemoryModeling:SuppressLeakReportsFor=arena \
-// RUN: %s -verify
+// RUN: %s -verify=suppressed
 
-// Custom allocator with ownership annotation
-void *arena_alloc() __attribute__((ownership_returns(arena)));
+// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc \
+// RUN: %s -verify=unsuppressed
+
+void *arena_alloc(void) __attribute__((ownership_returns(arena)));
 
 void test_suppressed() {
   void *p = arena_alloc();
-  // no-warning
+  // suppressed-no-warning
 }
 
-// Same allocator but without suppression → should warn
-// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc %s -verify=expected
-
-void test_not_suppressed() {
+void test_unsuppressed() {
   void *p = arena_alloc();
-  // expected-warning at -1 {{Potential memory leak}}
+  // unsuppressed-warning at -1 {{Potential memory leak}}
 }
\ No newline at end of file

>From 8617c32813168db5ed62f94a88f8cf295f3d21bb Mon Sep 17 00:00:00 2001
From: shuvakant6623 <scientefic2612 at gmail.com>
Date: Wed, 20 May 2026 23:44:46 +0530
Subject: [PATCH 07/10] [analyzer] Add option to suppress leak reports for
 selected ownership types

---
 clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 85a5e784cee23..e542476fdab9a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -4209,10 +4209,10 @@ void ento::registerInnerPointerCheckerAux(CheckerManager &Mgr) {
 void ento::registerDynamicMemoryModeling(CheckerManager &Mgr) {
   auto *Chk = Mgr.getChecker<MallocChecker>();
   auto ChkName = Mgr.getCurrentCheckerName();
-  
+
   StringRef SuppressList =
     Mgr.getAnalyzerOptions().getCheckerStringOption(
-        Chk, "SuppressLeakReportsFor");
+        ChkName, "SuppressLeakReportsFor");
 
   SmallVector<StringRef, 8> Split;
   SuppressList.split(Split, ',', -1, false);

>From 2e45861b2b6bb312e69ab162e58c70551b59d6c1 Mon Sep 17 00:00:00 2001
From: shuvakant6623 <scientefic2612 at gmail.com>
Date: Fri, 22 May 2026 18:20:14 +0530
Subject: [PATCH 08/10] fix:{analyzer] add suppressing option for leak reports

---
 .../Analysis/suppress-leak-custom-allocator.c     | 15 ++++-----------
 1 file changed, 4 insertions(+), 11 deletions(-)

diff --git a/clang/test/Analysis/suppress-leak-custom-allocator.c b/clang/test/Analysis/suppress-leak-custom-allocator.c
index 27b6b4b91b7d7..97c018f07ea8e 100644
--- a/clang/test/Analysis/suppress-leak-custom-allocator.c
+++ b/clang/test/Analysis/suppress-leak-custom-allocator.c
@@ -1,18 +1,11 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc \
 // RUN: -analyzer-config unix.DynamicMemoryModeling:SuppressLeakReportsFor=arena \
-// RUN: %s -verify=suppressed
-
-// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc \
-// RUN: %s -verify=unsuppressed
+// RUN: %s -verify
 
+// Custom allocator
 void *arena_alloc(void) __attribute__((ownership_returns(arena)));
 
-void test_suppressed() {
-  void *p = arena_alloc();
-  // suppressed-no-warning
-}
-
-void test_unsuppressed() {
+void test() {
   void *p = arena_alloc();
-  // unsuppressed-warning at -1 {{Potential memory leak}}
+  // no-warning
 }
\ No newline at end of file

>From 8e0b67b0ac036ee7e4a9cfa78533eec4a2425774 Mon Sep 17 00:00:00 2001
From: shuvakant6623 <scientefic2612 at gmail.com>
Date: Fri, 22 May 2026 22:45:16 +0530
Subject: [PATCH 09/10] [analyzer] Fix test to use expected-no-diagnostics

---
 clang/test/Analysis/suppress-leak-custom-allocator.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang/test/Analysis/suppress-leak-custom-allocator.c b/clang/test/Analysis/suppress-leak-custom-allocator.c
index 97c018f07ea8e..1f2a67cc6652f 100644
--- a/clang/test/Analysis/suppress-leak-custom-allocator.c
+++ b/clang/test/Analysis/suppress-leak-custom-allocator.c
@@ -2,10 +2,9 @@
 // RUN: -analyzer-config unix.DynamicMemoryModeling:SuppressLeakReportsFor=arena \
 // RUN: %s -verify
 
-// Custom allocator
 void *arena_alloc(void) __attribute__((ownership_returns(arena)));
 
 void test() {
   void *p = arena_alloc();
-  // no-warning
+  // expected-no-diagnostics
 }
\ No newline at end of file

>From 85c273dfcf50891d02576fae34a0e3ce19e16388 Mon Sep 17 00:00:00 2001
From: shuvakant6623 <scientefic2612 at gmail.com>
Date: Fri, 22 May 2026 23:44:19 +0530
Subject: [PATCH 10/10] [analyzer] Address review feedback

---
 clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp  | 10 ++++++++--
 clang/test/Analysis/suppress-leak-custom-allocator.c |  2 +-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index e542476fdab9a..a2325203dff8a 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -459,7 +459,7 @@ class MallocChecker
 
   StringRef getDebugTag() const override { return "MallocChecker"; }
 
-public:
+private:
   std::vector<std::string> SuppressLeakTypes;
 
 private:
@@ -3028,6 +3028,9 @@ void MallocChecker::HandleLeak(SymbolRef Sym, ExplodedNode *N,
   assert(RS && "cannot leak an untracked symbol");
   AllocationFamily Family = RS->getAllocationFamily();
 
+  if (Family.Kind == AF_Alloca)
+  return;
+
   // --- BEGIN: Suppress leak reports for selected ownership types ---
   if (Family.Kind == AF_Custom && Family.CustomName) {
     StringRef Type = *Family.CustomName;
@@ -4218,7 +4221,10 @@ void ento::registerDynamicMemoryModeling(CheckerManager &Mgr) {
   SuppressList.split(Split, ',', -1, false);
 
   for (StringRef S : Split) {
-    Chk->SuppressLeakTypes.push_back(S.trim().str());
+    S = S.trim();
+    if (S.empty())
+      continue;
+    Chk->SuppressLeakTypes.push_back(S.str());
   }
 
   // FIXME: This is a "hidden" undocumented frontend but there are public
diff --git a/clang/test/Analysis/suppress-leak-custom-allocator.c b/clang/test/Analysis/suppress-leak-custom-allocator.c
index 1f2a67cc6652f..45ac9b7aee336 100644
--- a/clang/test/Analysis/suppress-leak-custom-allocator.c
+++ b/clang/test/Analysis/suppress-leak-custom-allocator.c
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc \
+// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc,unix.DynamicMemoryModeling \
 // RUN: -analyzer-config unix.DynamicMemoryModeling:SuppressLeakReportsFor=arena \
 // RUN: %s -verify
 



More information about the cfe-commits mailing list