summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2018-02-27 21:19:33 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2018-02-27 21:19:33 +0000
commit5337efc69cdd59950faf0579043eb7aa8b9a3f2e (patch)
tree9d88ce04723033e99770a888d0e2023c34075fcc /clang/test
parentdff5a44f29f758f7e02783f16686cdd93ddc21a7 (diff)
downloadbcm5719-llvm-5337efc69cdd59950faf0579043eb7aa8b9a3f2e.tar.gz
bcm5719-llvm-5337efc69cdd59950faf0579043eb7aa8b9a3f2e.zip
[analyzer] MallocChecker: Suppress false positives in shared pointers.
Throw away MallocChecker warnings that occur after releasing a pointer within a destructor (or its callees) after performing C11 atomic fetch_add or fetch_sub within that destructor (or its callees). This is an indication that the destructor's class is likely a reference-counting pointer. The analyzer is not able to understand that the original reference count is usually large enough to avoid most use-after-frees. Even when the smart pointer is a local variable, we still have these false positives that this patch suppresses, because the analyzer doesn't currently support atomics well enough. Differential Revision: https://reviews.llvm.org/D43791 llvm-svn: 326249
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/Analysis/NewDelete-atomics.cpp74
1 files changed, 74 insertions, 0 deletions
diff --git a/clang/test/Analysis/NewDelete-atomics.cpp b/clang/test/Analysis/NewDelete-atomics.cpp
new file mode 100644
index 00000000000..275cf143899
--- /dev/null
+++ b/clang/test/Analysis/NewDelete-atomics.cpp
@@ -0,0 +1,74 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
+
+// expected-no-diagnostics
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+typedef enum memory_order {
+ memory_order_relaxed = __ATOMIC_RELAXED,
+ memory_order_consume = __ATOMIC_CONSUME,
+ memory_order_acquire = __ATOMIC_ACQUIRE,
+ memory_order_release = __ATOMIC_RELEASE,
+ memory_order_acq_rel = __ATOMIC_ACQ_REL,
+ memory_order_seq_cst = __ATOMIC_SEQ_CST
+} memory_order;
+
+class Obj {
+ int RefCnt;
+
+public:
+ int incRef() {
+ return __c11_atomic_fetch_add((volatile _Atomic(int) *)&RefCnt, 1,
+ memory_order_relaxed);
+ }
+
+ int decRef() {
+ return __c11_atomic_fetch_sub((volatile _Atomic(int) *)&RefCnt, 1,
+ memory_order_relaxed);
+ }
+
+ void foo();
+};
+
+class IntrusivePtr {
+ Obj *Ptr;
+
+public:
+ IntrusivePtr(Obj *Ptr) : Ptr(Ptr) {
+ Ptr->incRef();
+ }
+
+ IntrusivePtr(const IntrusivePtr &Other) : Ptr(Other.Ptr) {
+ Ptr->incRef();
+ }
+
+ ~IntrusivePtr() {
+ // We should not take the path on which the object is deleted.
+ if (Ptr->decRef() == 1)
+ delete Ptr;
+ }
+
+ Obj *getPtr() const { return Ptr; }
+};
+
+void testDestroyLocalRefPtr() {
+ IntrusivePtr p1(new Obj());
+ {
+ IntrusivePtr p2(p1);
+ }
+
+ // p1 still maintains ownership. The object is not deleted.
+ p1.getPtr()->foo(); // no-warning
+}
+
+void testDestroySymbolicRefPtr(const IntrusivePtr &p1) {
+ {
+ IntrusivePtr p2(p1);
+ }
+
+ // p1 still maintains ownership. The object is not deleted.
+ p1.getPtr()->foo(); // no-warning
+}
OpenPOWER on IntegriCloud