[clang] Feat/suppress leak reports (PR #199240)
via cfe-commits
cfe-commits at lists.llvm.org
Fri May 22 10:28:15 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-static-analyzer-1
Author: Shuvakant Patra (shuvakant6623)
<details>
<summary>Changes</summary>
This patch introduces a new checker option
'unix.DynamicMemoryModeling:SuppressLeakReportsFor' that allows
suppressing leak reports for selected ownership types.
Motivation:
Some allocators (such as arena-style allocators used in systems like
PostgreSQL) intentionally do not free memory individually. In such cases,
reporting memory leaks is misleading, as memory is expected to be released
at a higher level (e.g., by destroying the entire memory context).
This patch provides a mechanism to suppress leak reports for such
allocators based on their ownership type.
Implementation details:
- Added a string checker option 'SuppressLeakReportsFor' to
DynamicMemoryModeling
- Parsed the option in registerDynamicMemoryModeling
- Added an early return in MallocChecker::HandleLeak to skip
reporting leaks for matching ownership types
Tests:
- Updated analyzer-config.c to include the new checker option
- Added a test case to verify that no diagnostics are produced when
suppression is enabled
This follows the discussion in issue #<!-- -->196798.
---
Full diff: https://github.com/llvm/llvm-project/pull/199240.diff
4 Files Affected:
- (modified) clang/include/clang/StaticAnalyzer/Checkers/Checkers.td (+7-1)
- (modified) clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (+26-2)
- (modified) clang/test/Analysis/analyzer-config.c (+1)
- (added) clang/test/Analysis/suppress-leak-custom-allocator.c (+10)
``````````diff
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 6b9e0b50e1f59..a5dc6c3ae60f3 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -512,7 +512,13 @@ def DynamicMemoryModeling: Checker<"DynamicMemoryModeling">,
"NoStoreFuncVisitor.",
"true",
Released,
- Hide>
+ 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..e542476fdab9a 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,8 +3028,15 @@ 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;
+
+ 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
@@ -4197,6 +4208,19 @@ void ento::registerInnerPointerCheckerAux(CheckerManager &Mgr) {
void ento::registerDynamicMemoryModeling(CheckerManager &Mgr) {
auto *Chk = Mgr.getChecker<MallocChecker>();
+ auto ChkName = Mgr.getCurrentCheckerName();
+
+ StringRef SuppressList =
+ Mgr.getAnalyzerOptions().getCheckerStringOption(
+ ChkName, "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();
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
new file mode 100644
index 0000000000000..1f2a67cc6652f
--- /dev/null
+++ b/clang/test/Analysis/suppress-leak-custom-allocator.c
@@ -0,0 +1,10 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=unix.Malloc \
+// RUN: -analyzer-config unix.DynamicMemoryModeling:SuppressLeakReportsFor=arena \
+// RUN: %s -verify
+
+void *arena_alloc(void) __attribute__((ownership_returns(arena)));
+
+void test() {
+ void *p = arena_alloc();
+ // expected-no-diagnostics
+}
\ No newline at end of file
``````````
</details>
https://github.com/llvm/llvm-project/pull/199240
More information about the cfe-commits
mailing list