diff options
Diffstat (limited to 'clang/test/Analysis')
-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 +} |