1 // RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=false -verify %s
2 // RUN: %clang_cc1 -analyze -std=c++11 -analyzer-checker=core,unix.Malloc,debug.ExprInspection -analyzer-config c++-inlining=destructors -analyzer-config c++-container-inlining=true -DINLINE=1 -verify %s
3 
4 #ifndef HEADER
5 
6 void clang_analyzer_eval(bool);
7 void clang_analyzer_checkInlined(bool);
8 
9 #define HEADER
10 #include "containers.cpp"
11 #undef HEADER
12 
13 void test() {
14   MySet set(0);
15 
16   clang_analyzer_eval(set.isEmpty());
17 #if INLINE
18   // expected-warning@-2 {{TRUE}}
19 #else
20   // expected-warning@-4 {{UNKNOWN}}
21 #endif
22 
23   clang_analyzer_eval(set.raw_begin() == set.raw_end());
24 #if INLINE
25   // expected-warning@-2 {{TRUE}}
26 #else
27   // expected-warning@-4 {{UNKNOWN}}
28 #endif
29 
30   clang_analyzer_eval(set.begin().impl == set.end().impl);
31 #if INLINE
32   // expected-warning@-2 {{TRUE}}
33 #else
34   // expected-warning@-4 {{UNKNOWN}}
35 #endif
36 }
37 
38 void testSubclass(MySetSubclass &sub) {
39   sub.useIterator(sub.begin());
40 
41   MySetSubclass local;
42 }
43 
44 void testWrappers(BeginOnlySet &w1, IteratorStructOnlySet &w2,
45                   IteratorTypedefOnlySet &w3, IteratorUsingOnlySet &w4) {
46   BeginOnlySet local1;
47   IteratorStructOnlySet local2;
48   IteratorTypedefOnlySet local3;
49   IteratorUsingOnlySet local4;
50 
51   clang_analyzer_eval(w1.begin().impl.impl == w1.begin().impl.impl);
52 #if INLINE
53   // expected-warning@-2 {{TRUE}}
54 #else
55   // expected-warning@-4 {{UNKNOWN}}
56 #endif
57 
58   clang_analyzer_eval(w2.start().impl == w2.start().impl);
59 #if INLINE
60   // expected-warning@-2 {{TRUE}}
61 #else
62   // expected-warning@-4 {{UNKNOWN}}
63 #endif
64 
65   clang_analyzer_eval(w3.start().impl == w3.start().impl);
66 #if INLINE
67   // expected-warning@-2 {{TRUE}}
68 #else
69   // expected-warning@-4 {{UNKNOWN}}
70 #endif
71 
72   clang_analyzer_eval(w4.start().impl == w4.start().impl);
73 #if INLINE
74   // expected-warning@-2 {{TRUE}}
75 #else
76   // expected-warning@-4 {{UNKNOWN}}
77 #endif
78 }
79 
80 
81 #else
82 
83 class MySet {
84   int *storage;
85   unsigned size;
86 public:
87   MySet() : storage(0), size(0) {
88     clang_analyzer_checkInlined(true);
89 #if INLINE
90     // expected-warning@-2 {{TRUE}}
91 #endif
92   }
93 
94   MySet(unsigned n) : storage(new int[n]), size(n) {
95     clang_analyzer_checkInlined(true);
96 #if INLINE
97     // expected-warning@-2 {{TRUE}}
98 #endif
99   }
100 
101   ~MySet() { delete[] storage; }
102 
103   bool isEmpty() {
104     clang_analyzer_checkInlined(true); // expected-warning {{TRUE}}
105     return size == 0;
106   }
107 
108   struct iterator {
109     int *impl;
110 
111     iterator(int *p) : impl(p) {}
112   };
113 
114   iterator begin() {
115     clang_analyzer_checkInlined(true); // expected-warning {{TRUE}}
116     return iterator(storage);
117   }
118 
119   iterator end() {
120     clang_analyzer_checkInlined(true); // expected-warning {{TRUE}}
121     return iterator(storage+size);
122   }
123 
124   typedef int *raw_iterator;
125 
126   raw_iterator raw_begin() {
127     clang_analyzer_checkInlined(true); // expected-warning {{TRUE}}
128     return storage;
129   }
130   raw_iterator raw_end() {
131     clang_analyzer_checkInlined(true); // expected-warning {{TRUE}}
132     return storage + size;
133   }
134 };
135 
136 class MySetSubclass : public MySet {
137 public:
138   MySetSubclass() {
139     clang_analyzer_checkInlined(true);
140 #if INLINE
141     // expected-warning@-2 {{TRUE}}
142 #endif
143   }
144 
145   void useIterator(iterator i) {
146     clang_analyzer_checkInlined(true); // expected-warning {{TRUE}}
147   }
148 };
149 
150 class BeginOnlySet {
151   MySet impl;
152 public:
153   struct IterImpl {
154     MySet::iterator impl;
155     IterImpl(MySet::iterator i) : impl(i) {
156       clang_analyzer_checkInlined(true); // expected-warning {{TRUE}}
157     }
158   };
159 
160   BeginOnlySet() {
161     clang_analyzer_checkInlined(true);
162 #if INLINE
163     // expected-warning@-2 {{TRUE}}
164 #endif
165   }
166 
167   typedef IterImpl wrapped_iterator;
168 
169   wrapped_iterator begin() {
170     clang_analyzer_checkInlined(true); // expected-warning {{TRUE}}
171     return IterImpl(impl.begin());
172   }
173 };
174 
175 class IteratorTypedefOnlySet {
176   MySet impl;
177 public:
178 
179   IteratorTypedefOnlySet() {
180     clang_analyzer_checkInlined(true);
181 #if INLINE
182     // expected-warning@-2 {{TRUE}}
183 #endif
184   }
185 
186   typedef MySet::iterator iterator;
187 
188   iterator start() {
189     clang_analyzer_checkInlined(true); // expected-warning {{TRUE}}
190     return impl.begin();
191   }
192 };
193 
194 class IteratorUsingOnlySet {
195   MySet impl;
196 public:
197 
198   IteratorUsingOnlySet() {
199     clang_analyzer_checkInlined(true);
200 #if INLINE
201     // expected-warning@-2 {{TRUE}}
202 #endif
203   }
204 
205   using iterator = MySet::iterator;
206 
207   iterator start() {
208     clang_analyzer_checkInlined(true); // expected-warning {{TRUE}}
209     return impl.begin();
210   }
211 };
212 
213 class IteratorStructOnlySet {
214   MySet impl;
215 public:
216 
217   IteratorStructOnlySet() {
218     clang_analyzer_checkInlined(true);
219 #if INLINE
220     // expected-warning@-2 {{TRUE}}
221 #endif
222   }
223 
224   struct iterator {
225     int *impl;
226   };
227 
228   iterator start() {
229     clang_analyzer_checkInlined(true); // expected-warning {{TRUE}}
230     return iterator{impl.begin().impl};
231   }
232 };
233 
234 #endif
235