[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / test / Analysis / inner-pointer.cpp
blob4cb194409412c624af17e437b8fbad0e2945fb6f
1 // RUN: %clang_analyze_cc1 -std=c++14 -analyzer-checker=cplusplus.InnerPointer \
2 // RUN: -Wno-dangling -Wno-dangling-field -Wno-return-stack-address \
3 // RUN: %s -analyzer-output=text -verify
5 #include "Inputs/system-header-simulator-cxx.h"
6 namespace std {
8 template <typename T>
9 void func_ref(T &a);
11 template <typename T>
12 void func_const_ref(const T &a);
14 template <typename T>
15 void func_value(T a);
17 string my_string = "default";
18 void default_arg(int a = 42, string &b = my_string);
20 template <class T>
21 T *addressof(T &arg);
23 template <class T>
24 T *__addressof(T &arg);
26 char *data(std::string &c);
28 } // end namespace std
30 void consume(const char *) {}
31 void consume(const wchar_t *) {}
32 void consume(const char16_t *) {}
33 void consume(const char32_t *) {}
35 //=--------------------------------------=//
36 // `std::string` member functions //
37 //=--------------------------------------=//
39 void deref_after_scope_char(bool cond) {
40 const char *c, *d;
42 std::string s;
43 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
44 d = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
45 } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
46 // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
47 std::string s;
48 const char *c2 = s.c_str();
49 if (cond) {
50 // expected-note@-1 {{Assuming 'cond' is true}}
51 // expected-note@-2 {{Taking true branch}}
52 // expected-note@-3 {{Assuming 'cond' is false}}
53 // expected-note@-4 {{Taking false branch}}
54 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
55 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
56 } else {
57 consume(d); // expected-warning {{Inner pointer of container used after re/deallocation}}
58 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
62 void deref_after_scope_char_data_non_const() {
63 char *c;
65 std::string s;
66 c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
67 } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
68 std::string s;
69 char *c2 = s.data();
70 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
71 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
74 void deref_after_scope_wchar_t(bool cond) {
75 const wchar_t *c, *d;
77 std::wstring s;
78 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::wstring' obtained here}}
79 d = s.data(); // expected-note {{Pointer to inner buffer of 'std::wstring' obtained here}}
80 } // expected-note {{Inner buffer of 'std::wstring' deallocated by call to destructor}}
81 // expected-note@-1 {{Inner buffer of 'std::wstring' deallocated by call to destructor}}
82 std::wstring s;
83 const wchar_t *c2 = s.c_str();
84 if (cond) {
85 // expected-note@-1 {{Assuming 'cond' is true}}
86 // expected-note@-2 {{Taking true branch}}
87 // expected-note@-3 {{Assuming 'cond' is false}}
88 // expected-note@-4 {{Taking false branch}}
89 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
90 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
91 } else {
92 consume(d); // expected-warning {{Inner pointer of container used after re/deallocation}}
93 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
97 void deref_after_scope_char16_t_cstr() {
98 const char16_t *c16;
100 std::u16string s16;
101 c16 = s16.c_str(); // expected-note {{Pointer to inner buffer of 'std::u16string' obtained here}}
102 } // expected-note {{Inner buffer of 'std::u16string' deallocated by call to destructor}}
103 std::u16string s16;
104 const char16_t *c16_2 = s16.c_str();
105 consume(c16); // expected-warning {{Inner pointer of container used after re/deallocation}}
106 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
109 void deref_after_scope_char32_t_data() {
110 const char32_t *c32;
112 std::u32string s32;
113 c32 = s32.data(); // expected-note {{Pointer to inner buffer of 'std::u32string' obtained here}}
114 } // expected-note {{Inner buffer of 'std::u32string' deallocated by call to destructor}}
115 std::u32string s32;
116 const char32_t *c32_2 = s32.data();
117 consume(c32); // expected-warning {{Inner pointer of container used after re/deallocation}}
118 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
121 void multiple_symbols(bool cond) {
122 const char *c1, *d1;
124 std::string s1;
125 c1 = s1.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
126 d1 = s1.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
127 const char *local = s1.c_str();
128 consume(local); // no-warning
129 } // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
130 // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
131 std::string s2;
132 const char *c2 = s2.c_str();
133 if (cond) {
134 // expected-note@-1 {{Assuming 'cond' is true}}
135 // expected-note@-2 {{Taking true branch}}
136 // expected-note@-3 {{Assuming 'cond' is false}}
137 // expected-note@-4 {{Taking false branch}}
138 consume(c1); // expected-warning {{Inner pointer of container used after re/deallocation}}
139 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
140 } else {
141 consume(d1); // expected-warning {{Inner pointer of container used after re/deallocation}}
142 } // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
145 void deref_after_scope_ok(bool cond) {
146 const char *c, *d;
147 std::string s;
149 c = s.c_str();
150 d = s.data();
152 if (cond)
153 consume(c); // no-warning
154 else
155 consume(d); // no-warning
158 void deref_after_equals() {
159 const char *c;
160 std::string s = "hello";
161 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
162 s = "world"; // expected-note {{Inner buffer of 'std::string' reallocated by call to 'operator='}}
163 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
164 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
167 void deref_after_plus_equals() {
168 const char *c;
169 std::string s = "hello";
170 c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
171 s += " world"; // expected-note {{Inner buffer of 'std::string' reallocated by call to 'operator+='}}
172 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
173 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
176 void deref_after_clear() {
177 const char *c;
178 std::string s;
179 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
180 s.clear(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'clear'}}
181 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
182 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
185 void deref_after_append() {
186 const char *c;
187 std::string s = "hello";
188 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
189 s.append(2, 'x'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'append'}}
190 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
191 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
194 void deref_after_assign() {
195 const char *c;
196 std::string s;
197 c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
198 s.assign(4, 'a'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'assign'}}
199 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
200 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
203 void deref_after_erase() {
204 const char *c;
205 std::string s = "hello";
206 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
207 s.erase(0, 2); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'erase'}}
208 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
209 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
212 void deref_after_insert() {
213 const char *c;
214 std::string s = "ello";
215 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
216 s.insert(0, 1, 'h'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'insert'}}
217 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
218 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
221 void deref_after_replace() {
222 const char *c;
223 std::string s = "hello world";
224 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
225 s.replace(6, 5, "string"); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'replace'}}
226 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
227 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
230 void deref_after_pop_back() {
231 const char *c;
232 std::string s;
233 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
234 s.pop_back(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'pop_back'}}
235 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
236 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
239 void deref_after_push_back() {
240 const char *c;
241 std::string s;
242 c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
243 s.push_back('c'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'push_back'}}
244 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
245 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
248 void deref_after_reserve() {
249 const char *c;
250 std::string s;
251 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
252 s.reserve(5); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'reserve'}}
253 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
254 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
257 void deref_after_resize() {
258 const char *c;
259 std::string s;
260 c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
261 s.resize(5); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'resize'}}
262 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
263 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
266 void deref_after_shrink_to_fit() {
267 const char *c;
268 std::string s;
269 c = s.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
270 s.shrink_to_fit(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'shrink_to_fit'}}
271 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
272 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
275 void deref_after_swap() {
276 const char *c;
277 std::string s1, s2;
278 c = s1.data(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
279 s1.swap(s2); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'swap'}}
280 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
281 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
284 void deref_after_std_data() {
285 const char *c;
286 std::string s;
287 c = std::data(s); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
288 s.push_back('c'); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'push_back'}}
289 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
290 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
293 struct S {
294 std::string s;
295 const char *name() {
296 return s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
297 // expected-note@-1 {{Pointer to inner buffer of 'std::string' obtained here}}
299 void clear() {
300 s.clear(); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'clear'}}
302 ~S() {} // expected-note {{Inner buffer of 'std::string' deallocated by call to destructor}}
305 void cleared_through_method() {
306 S x;
307 const char *c = x.name(); // expected-note {{Calling 'S::name'}}
308 // expected-note@-1 {{Returning from 'S::name'}}
309 x.clear(); // expected-note {{Calling 'S::clear'}}
310 // expected-note@-1 {{Returning; inner buffer was reallocated}}
311 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
312 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
315 void destroyed_through_method() {
316 S y;
317 const char *c = y.name(); // expected-note {{Calling 'S::name'}}
318 // expected-note@-1 {{Returning from 'S::name'}}
319 y.~S(); // expected-note {{Calling '~S'}}
320 // expected-note@-1 {{Returning; inner buffer was deallocated}}
321 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
322 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
325 //=---------------------------=//
326 // Other STL functions //
327 //=---------------------------=//
329 void STL_func_ref() {
330 const char *c;
331 std::string s;
332 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
333 std::func_ref(s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'func_ref'}}
334 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
335 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
338 void STL_func_const_ref() {
339 const char *c;
340 std::string s;
341 c = s.c_str();
342 std::func_const_ref(s);
343 consume(c); // no-warning
346 void STL_func_value() {
347 const char *c;
348 std::string s;
349 c = s.c_str();
350 std::func_value(s);
351 consume(c); // no-warning
354 void func_ptr_known() {
355 const char *c;
356 std::string s;
357 void (*func_ptr)(std::string &) = std::func_ref<std::string>;
358 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
359 func_ptr(s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'func_ref'}}
360 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
361 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
364 void func_ptr_unknown(void (*func_ptr)(std::string &)) {
365 const char *c;
366 std::string s;
367 c = s.c_str();
368 func_ptr(s);
369 consume(c); // no-warning
372 void func_default_arg() {
373 const char *c;
374 std::string s;
375 c = s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
376 default_arg(3, s); // expected-note {{Inner buffer of 'std::string' reallocated by call to 'default_arg'}}
377 consume(c); // expected-warning {{Inner pointer of container used after re/deallocation}}
378 // expected-note@-1 {{Inner pointer of container used after re/deallocation}}
381 void func_addressof() {
382 const char *c;
383 std::string s;
384 c = s.c_str();
385 (void)addressof(s);
386 consume(c); // no-warning
389 void func_AddressofFn_() {
390 const char *c;
391 std::string s;
392 c = s.c_str();
393 (void)std::__addressof(s);
394 consume(c); // no-warning
397 void func_std_data() {
398 const char *c;
399 std::string s;
400 c = std::data(s);
401 consume(c); // no-warning
404 struct T {
405 std::string to_string() { return s; }
407 private:
408 std::string s;
411 const char *escape_via_return_temp() {
412 T x;
413 return x.to_string().c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
414 // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
415 // expected-warning@-2 {{Inner pointer of container used after re/deallocation}}
416 // expected-note@-3 {{Inner pointer of container used after re/deallocation}}
419 const char *escape_via_return_local() {
420 std::string s;
421 return s.c_str(); // expected-note {{Pointer to inner buffer of 'std::string' obtained here}}
422 // expected-note@-1 {{Inner buffer of 'std::string' deallocated by call to destructor}}
423 // expected-warning@-2 {{Inner pointer of container used after re/deallocation}}
424 // expected-note@-3 {{Inner pointer of container used after re/deallocation}}
428 char *c();
429 class A {};
431 void no_CXXRecordDecl() {
432 A a, *b;
433 *(void **)&b = c() + 1;
434 *b = a; // no-crash
437 void checkReference(std::string &s) {
438 const char *c = s.c_str();