1 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -verify %s |
2 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -verify %s |
3 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s |
4 | // RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s |
5 | // 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 |
6 | // 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 |
7 | // 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 |
8 | // 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 |
9 | |
10 | // expected-no-diagnostics |
11 | |
12 | #include "Inputs/system-header-simulator-cxx.h" |
13 | |
14 | typedef enum memory_order { |
15 | memory_order_relaxed = __ATOMIC_RELAXED, |
16 | memory_order_consume = __ATOMIC_CONSUME, |
17 | memory_order_acquire = __ATOMIC_ACQUIRE, |
18 | memory_order_release = __ATOMIC_RELEASE, |
19 | memory_order_acq_rel = __ATOMIC_ACQ_REL, |
20 | memory_order_seq_cst = __ATOMIC_SEQ_CST |
21 | } memory_order; |
22 | |
23 | class Obj { |
24 | int RefCnt; |
25 | |
26 | public: |
27 | int incRef() { |
28 | return __c11_atomic_fetch_add((volatile _Atomic(int) *)&RefCnt, 1, |
29 | memory_order_relaxed); |
30 | } |
31 | |
32 | int decRef() { |
33 | return __c11_atomic_fetch_sub((volatile _Atomic(int) *)&RefCnt, 1, |
34 | memory_order_relaxed); |
35 | } |
36 | |
37 | void foo(); |
38 | }; |
39 | |
40 | class IntrusivePtr { |
41 | Obj *Ptr; |
42 | |
43 | public: |
44 | IntrusivePtr(Obj *Ptr) : Ptr(Ptr) { |
45 | Ptr->incRef(); |
46 | } |
47 | |
48 | IntrusivePtr(const IntrusivePtr &Other) : Ptr(Other.Ptr) { |
49 | Ptr->incRef(); |
50 | } |
51 | |
52 | ~IntrusivePtr() { |
53 | // We should not take the path on which the object is deleted. |
54 | if (Ptr->decRef() == 1) |
55 | delete Ptr; |
56 | } |
57 | |
58 | Obj *getPtr() const { return Ptr; } // no-warning |
59 | }; |
60 | |
61 | void testDestroyLocalRefPtr() { |
62 | IntrusivePtr p1(new Obj()); |
63 | { |
64 | IntrusivePtr p2(p1); |
65 | } |
66 | |
67 | // p1 still maintains ownership. The object is not deleted. |
68 | p1.getPtr()->foo(); // no-warning |
69 | } |
70 | |
71 | void testDestroySymbolicRefPtr(const IntrusivePtr &p1) { |
72 | { |
73 | IntrusivePtr p2(p1); |
74 | } |
75 | |
76 | // p1 still maintains ownership. The object is not deleted. |
77 | p1.getPtr()->foo(); // no-warning |
78 | } |
79 | |