diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2018-02-27 21:19:33 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2018-02-27 21:19:33 +0000 |
commit | 5337efc69cdd59950faf0579043eb7aa8b9a3f2e (patch) | |
tree | 9d88ce04723033e99770a888d0e2023c34075fcc /clang/test | |
parent | dff5a44f29f758f7e02783f16686cdd93ddc21a7 (diff) | |
download | bcm5719-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.cpp | 74 |
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 +} |