aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/StaticAnalyzer/Checkers/Checkers.td6
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp15
-rw-r--r--test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp8
-rw-r--r--test/Analysis/Malloc+NewDelete_intersections.cpp5
-rw-r--r--test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp3
-rw-r--r--test/Analysis/NewDelete-checker-test.cpp33
-rw-r--r--test/Analysis/NewDelete-custom.cpp35
-rw-r--r--test/Analysis/NewDelete-intersections.mm18
-rw-r--r--test/Analysis/NewDelete-variadic.cpp2
9 files changed, 99 insertions, 26 deletions
diff --git a/lib/StaticAnalyzer/Checkers/Checkers.td b/lib/StaticAnalyzer/Checkers/Checkers.td
index 3db3fb9962..a29f53bb79 100644
--- a/lib/StaticAnalyzer/Checkers/Checkers.td
+++ b/lib/StaticAnalyzer/Checkers/Checkers.td
@@ -176,7 +176,11 @@ def VirtualCallChecker : Checker<"VirtualCall">,
DescFile<"VirtualCallChecker.cpp">;
def NewDeleteChecker : Checker<"NewDelete">,
- HelpText<"Check for memory leaks, double free, and use-after-free problems. Traces memory managed by new/delete.">,
+ HelpText<"Check for double-free and use-after-free problems. Traces memory managed by new/delete.">,
+ DescFile<"MallocChecker.cpp">;
+
+def NewDeleteLeaksChecker : Checker<"NewDeleteLeaks">,
+ HelpText<"Check for memory leaks. Traces memory managed by new/delete.">,
DescFile<"MallocChecker.cpp">;
} // end: "alpha.cplusplus"
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 318be5bf10..851aa0ca36 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -164,6 +164,7 @@ public:
DefaultBool CMallocPessimistic;
DefaultBool CMallocOptimistic;
DefaultBool CNewDeleteChecker;
+ DefaultBool CNewDeleteLeaksChecker;
DefaultBool CMismatchedDeallocatorChecker;
};
@@ -1536,12 +1537,21 @@ void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N,
CheckerContext &C) const {
if (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic &&
- !Filter.CNewDeleteChecker)
+ !Filter.CNewDeleteLeaksChecker)
return;
- if (!isTrackedFamily(C, Sym))
+ const RefState *RS = C.getState()->get<RegionState>(Sym);
+ assert(RS && "cannot leak an untracked symbol");
+ AllocationFamily Family = RS->getAllocationFamily();
+ if (!isTrackedFamily(Family))
return;
+ // Special case for new and new[]; these are controlled by a separate checker
+ // flag so that they can be selectively disabled.
+ if (Family == AF_CXXNew || Family == AF_CXXNewArray)
+ if (!Filter.CNewDeleteLeaksChecker)
+ return;
+
assert(N);
if (!BT_Leak) {
BT_Leak.reset(new BugType("Memory leak", "Memory Error"));
@@ -2115,4 +2125,5 @@ void ento::register##name(CheckerManager &mgr) {\
REGISTER_CHECKER(MallocPessimistic)
REGISTER_CHECKER(MallocOptimistic)
REGISTER_CHECKER(NewDeleteChecker)
+REGISTER_CHECKER(NewDeleteLeaksChecker)
REGISTER_CHECKER(MismatchedDeallocatorChecker)
diff --git a/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp b/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp
index b0bb1735b4..22742f4ed3 100644
--- a/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp
+++ b/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,alpha.cplusplus.NewDelete -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s
typedef __typeof(sizeof(int)) size_t;
void *malloc(size_t);
@@ -52,7 +53,10 @@ void testNewDoubleFree() {
void testNewLeak() {
int *p = new int;
-} // expected-warning{{Memory is never released; potential leak of memory pointed to by 'p'}}
+}
+#ifdef LEAKS
+// expected-warning@-2 {{Memory is never released; potential leak of memory pointed to by 'p'}}
+#endif
void testNewUseAfterFree() {
int *p = (int *)operator new(0);
diff --git a/test/Analysis/Malloc+NewDelete_intersections.cpp b/test/Analysis/Malloc+NewDelete_intersections.cpp
index 7a0ef8e13c..272813d47b 100644
--- a/test/Analysis/Malloc+NewDelete_intersections.cpp
+++ b/test/Analysis/Malloc+NewDelete_intersections.cpp
@@ -1,11 +1,12 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,alpha.cplusplus.NewDelete -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -std=c++11 -verify %s
typedef __typeof(sizeof(int)) size_t;
void *malloc(size_t);
void free(void *);
//-------------------------------------------------------------------
-// Check that unix.Malloc + alpha.cplusplus.NewDelete does not enable
+// Check that unix.Malloc + cplusplus.NewDelete does not enable
// warnings produced by unix.MismatchedDeallocator.
//-------------------------------------------------------------------
void testMismatchedDeallocator() {
diff --git a/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp b/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp
index 23b70b89fb..84ecbaddc7 100644
--- a/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp
+++ b/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.MismatchedDeallocator -analyzer-store region -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.MismatchedDeallocator -std=c++11 -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks,unix.MismatchedDeallocator -DLEAKS -std=c++11 -verify %s
// expected-no-diagnostics
typedef __typeof(sizeof(int)) size_t;
diff --git a/test/Analysis/NewDelete-checker-test.cpp b/test/Analysis/NewDelete-checker-test.cpp
index c31d7f3032..74116fb7bc 100644
--- a/test/Analysis/NewDelete-checker-test.cpp
+++ b/test/Analysis/NewDelete-checker-test.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s
#include "Inputs/system-header-simulator-cxx.h"
typedef __typeof__(sizeof(int)) size_t;
@@ -12,28 +13,46 @@ int *global;
//----- Standard non-placement operators
void testGlobalOpNew() {
void *p = operator new(0);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2{{Memory is never released; potential leak}}
+#endif
void testGlobalOpNewArray() {
void *p = operator new[](0);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2{{Memory is never released; potential leak}}
+#endif
void testGlobalNewExpr() {
int *p = new int;
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2{{Memory is never released; potential leak}}
+#endif
void testGlobalNewExprArray() {
int *p = new int[0];
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2{{Memory is never released; potential leak}}
+#endif
//----- Standard nothrow placement operators
void testGlobalNoThrowPlacementOpNewBeforeOverload() {
void *p = operator new(0, std::nothrow);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2{{Memory is never released; potential leak}}
+#endif
void testGlobalNoThrowPlacementExprNewBeforeOverload() {
int *p = new(std::nothrow) int;
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2{{Memory is never released; potential leak}}
+#endif
//----- Standard pointer placement operators
diff --git a/test/Analysis/NewDelete-custom.cpp b/test/Analysis/NewDelete-custom.cpp
index 7d7796bccb..a4665a1757 100644
--- a/test/Analysis/NewDelete-custom.cpp
+++ b/test/Analysis/NewDelete-custom.cpp
@@ -1,6 +1,12 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.Malloc -analyzer-store region -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.Malloc -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -DLEAKS -fblocks -verify %s
#include "Inputs/system-header-simulator-cxx.h"
+#ifndef LEAKS
+// expected-no-diagnostics
+#endif
+
+
void *allocator(std::size_t size);
void *operator new[](std::size_t size) throw() { return allocator(size); }
@@ -19,7 +25,10 @@ void testNewMethod() {
C *p2 = new C; // no warn
C *c3 = ::new C;
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2{{Memory is never released; potential leak}}
+#endif
void testOpNewArray() {
void *p = operator new[](0); // call is inlined, no warn
@@ -27,7 +36,11 @@ void testOpNewArray() {
void testNewExprArray() {
int *p = new int[0];
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2{{Memory is never released; potential leak}}
+#endif
+
//----- Custom non-placement operators
void testOpNew() {
@@ -36,16 +49,26 @@ void testOpNew() {
void testNewExpr() {
int *p = new int;
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2{{Memory is never released; potential leak}}
+#endif
+
//----- Custom NoThrow placement operators
void testOpNewNoThrow() {
void *p = operator new(0, std::nothrow);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2{{Memory is never released; potential leak}}
+#endif
void testNewExprNoThrow() {
int *p = new(std::nothrow) int;
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2{{Memory is never released; potential leak}}
+#endif
//----- Custom placement operators
void testOpNewPlacement() {
diff --git a/test/Analysis/NewDelete-intersections.mm b/test/Analysis/NewDelete-intersections.mm
index 3a87e4f3f1..247fef80af 100644
--- a/test/Analysis/NewDelete-intersections.mm
+++ b/test/Analysis/NewDelete-intersections.mm
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks -std=c++11 -DLEAKS -fblocks -verify %s
#include "Inputs/system-header-simulator-cxx.h"
#include "Inputs/system-header-simulator-objc.h"
@@ -39,16 +40,25 @@ void testDeleteMalloced() {
void testFreeOpNew() {
void *p = operator new(0);
free(p);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2 {{Memory is never released; potential leak}}
+#endif
void testFreeNewExpr() {
int *p = new int;
free(p);
-} // expected-warning{{Memory is never released; potential leak}}
+}
+#ifdef LEAKS
+// expected-warning@-2 {{Memory is never released; potential leak}}
+#endif
void testObjcFreeNewed() {
int *p = new int;
- NSData *nsdata = [NSData dataWithBytesNoCopy:p length:sizeof(int) freeWhenDone:1]; // expected-warning{{Memory is never released; potential leak}}
+ NSData *nsdata = [NSData dataWithBytesNoCopy:p length:sizeof(int) freeWhenDone:1];
+#ifdef LEAKS
+ // expected-warning@-2 {{Memory is never released; potential leak}}
+#endif
}
void testFreeAfterDelete() {
diff --git a/test/Analysis/NewDelete-variadic.cpp b/test/Analysis/NewDelete-variadic.cpp
index 129af1f9c6..02d6a9abce 100644
--- a/test/Analysis/NewDelete-variadic.cpp
+++ b/test/Analysis/NewDelete-variadic.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.Malloc -analyzer-store region -std=c++11 -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,alpha.cplusplus.NewDeleteLeaks,unix.Malloc -std=c++11 -fblocks -verify %s
// expected-no-diagnostics
namespace std {