| // 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 |
| // RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -verify %s |
| // RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s |
| // RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s |
| // RUN: %clang_analyze_cc1 -analyzer-inline-max-stack-depth 2 -analyzer-config ipa-always-inline-size=2 -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; } // no-warning |
| }; |
| |
| 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 |
| } |