@@ -20,7 +20,7 @@ typedef enum memory_order {
20
20
memory_order_seq_cst = __ATOMIC_SEQ_CST
21
21
} memory_order;
22
22
23
- class Obj {
23
+ class RawObj {
24
24
int RefCnt;
25
25
26
26
public:
@@ -37,11 +37,27 @@ class Obj {
37
37
void foo ();
38
38
};
39
39
40
+ class StdAtomicObj {
41
+ std::atomic<int > RefCnt;
42
+
43
+ public:
44
+ int incRef () {
45
+ return ++RefCnt;
46
+ }
47
+
48
+ int decRef () {
49
+ return --RefCnt;
50
+ }
51
+
52
+ void foo ();
53
+ };
54
+
55
+ template <typename T>
40
56
class IntrusivePtr {
41
- Obj *Ptr;
57
+ T *Ptr;
42
58
43
59
public:
44
- IntrusivePtr (Obj *Ptr) : Ptr(Ptr) {
60
+ IntrusivePtr (T *Ptr) : Ptr(Ptr) {
45
61
Ptr->incRef ();
46
62
}
47
63
@@ -55,22 +71,106 @@ class IntrusivePtr {
55
71
delete Ptr;
56
72
}
57
73
58
- Obj *getPtr () const { return Ptr; } // no-warning
74
+ T *getPtr () const { return Ptr; } // no-warning
75
+ };
76
+
77
+ // Also IntrusivePtr but let's dodge name-based heuristics.
78
+ template <typename T>
79
+ class DifferentlyNamed {
80
+ T *Ptr;
81
+
82
+ public:
83
+ DifferentlyNamed (T *Ptr) : Ptr(Ptr) {
84
+ Ptr->incRef ();
85
+ }
86
+
87
+ DifferentlyNamed (const DifferentlyNamed &Other) : Ptr(Other.Ptr) {
88
+ Ptr->incRef ();
89
+ }
90
+
91
+ ~DifferentlyNamed () {
92
+ // We should not take the path on which the object is deleted.
93
+ if (Ptr->decRef () == 1 )
94
+ delete Ptr;
95
+ }
96
+
97
+ T *getPtr () const { return Ptr; } // no-warning
59
98
};
60
99
61
100
void testDestroyLocalRefPtr () {
62
- IntrusivePtr p1 (new Obj ());
101
+ IntrusivePtr<RawObj> p1 (new RawObj ());
102
+ {
103
+ IntrusivePtr<RawObj> p2 (p1);
104
+ }
105
+
106
+ // p1 still maintains ownership. The object is not deleted.
107
+ p1.getPtr ()->foo (); // no-warning
108
+ }
109
+
110
+ void testDestroySymbolicRefPtr (const IntrusivePtr<RawObj> &p1) {
111
+ {
112
+ IntrusivePtr<RawObj> p2 (p1);
113
+ }
114
+
115
+ // p1 still maintains ownership. The object is not deleted.
116
+ p1.getPtr ()->foo (); // no-warning
117
+ }
118
+
119
+ void testDestroyLocalRefPtrWithAtomics () {
120
+ IntrusivePtr<StdAtomicObj> p1 (new StdAtomicObj ());
121
+ {
122
+ IntrusivePtr<StdAtomicObj> p2 (p1);
123
+ }
124
+
125
+ // p1 still maintains ownership. The object is not deleted.
126
+ p1.getPtr ()->foo (); // no-warning
127
+ }
128
+
129
+
130
+ void testDestroyLocalRefPtrWithAtomics (const IntrusivePtr<StdAtomicObj> &p1) {
63
131
{
64
- IntrusivePtr p2 (p1);
132
+ IntrusivePtr<StdAtomicObj> p2 (p1);
65
133
}
66
134
67
135
// p1 still maintains ownership. The object is not deleted.
68
136
p1.getPtr ()->foo (); // no-warning
69
137
}
70
138
71
- void testDestroySymbolicRefPtr (const IntrusivePtr &p1) {
139
+ void testDestroyLocalRefPtrDifferentlyNamed () {
140
+ DifferentlyNamed<RawObj> p1 (new RawObj ());
141
+ {
142
+ DifferentlyNamed<RawObj> p2 (p1);
143
+ }
144
+
145
+ // p1 still maintains ownership. The object is not deleted.
146
+ p1.getPtr ()->foo (); // no-warning
147
+ }
148
+
149
+ void testDestroySymbolicRefPtrDifferentlyNamed (
150
+ const DifferentlyNamed<RawObj> &p1) {
151
+ {
152
+ DifferentlyNamed<RawObj> p2 (p1);
153
+ }
154
+
155
+ // p1 still maintains ownership. The object is not deleted.
156
+ p1.getPtr ()->foo (); // no-warning
157
+ }
158
+
159
+ void testDestroyLocalRefPtrWithAtomicsDifferentlyNamed () {
160
+ DifferentlyNamed<StdAtomicObj> p1 (new StdAtomicObj ());
161
+ {
162
+ DifferentlyNamed<StdAtomicObj> p2 (p1);
163
+ }
164
+
165
+ // p1 still maintains ownership. The object is not deleted.
166
+ p1.getPtr ()->foo (); // no-warning
167
+ }
168
+
169
+
170
+ void testDestroyLocalRefPtrWithAtomicsDifferentlyNamed (
171
+ const DifferentlyNamed<StdAtomicObj> &p1) {
72
172
{
73
- IntrusivePtr p2 (p1);
173
+ DifferentlyNamed<StdAtomicObj> p2 (p1);
74
174
}
75
175
76
176
// p1 still maintains ownership. The object is not deleted.
0 commit comments