1 // RUN: %clang_cc1 -fsyntax-only -Wdangling -Wdangling-field -Wreturn-stack-address -verify %s
2 struct [[gsl::Owner(int)]] MyIntOwner {
3 MyIntOwner();
4 int &operator*();
5 };
6
7 struct [[gsl::Pointer(int)]] MyIntPointer {
8 MyIntPointer(int *p = nullptr);
9 // Conversion operator and constructor conversion will result in two
10 // different ASTs. The former is tested with another owner and
11 // pointer type.
12 MyIntPointer(const MyIntOwner &);
13 int &operator*();
14 MyIntOwner toOwner();
15 };
16
17 struct MySpecialIntPointer : MyIntPointer {
18 };
19
20 // We did see examples in the wild when a derived class changes
21 // the ownership model. So we have a test for it.
22 struct [[gsl::Owner(int)]] MyOwnerIntPointer : MyIntPointer {
23 };
24
25 struct [[gsl::Pointer(long)]] MyLongPointerFromConversion {
26 MyLongPointerFromConversion(long *p = nullptr);
27 long &operator*();
28 };
29
30 struct [[gsl::Owner(long)]] MyLongOwnerWithConversion {
31 MyLongOwnerWithConversion();
32 operator MyLongPointerFromConversion();
33 long &operator*();
34 MyIntPointer releaseAsMyPointer();
35 long *releaseAsRawPointer();
36 };
37
danglingHeapObject()38 void danglingHeapObject() {
39 new MyLongPointerFromConversion(MyLongOwnerWithConversion{}); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
40 new MyIntPointer(MyIntOwner{}); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
41 }
42
intentionalFalseNegative()43 void intentionalFalseNegative() {
44 int i;
45 MyIntPointer p{&i};
46 // In this case we do not have enough information in a statement local
47 // analysis to detect the problem.
48 new MyIntPointer(p);
49 new MyIntPointer(MyIntPointer{p});
50 }
51
ownershipTransferToMyPointer()52 MyIntPointer ownershipTransferToMyPointer() {
53 MyLongOwnerWithConversion t;
54 return t.releaseAsMyPointer(); // ok
55 }
56
ownershipTransferToRawPointer()57 long *ownershipTransferToRawPointer() {
58 MyLongOwnerWithConversion t;
59 return t.releaseAsRawPointer(); // ok
60 }
61
62 struct Y {
63 int a[4];
64 };
65
dangligGslPtrFromTemporary()66 void dangligGslPtrFromTemporary() {
67 MyIntPointer p = Y{}.a; // TODO
68 (void)p;
69 }
70
71 struct DanglingGslPtrField {
72 MyIntPointer p; // expected-note {{pointer member declared here}}
73 MyLongPointerFromConversion p2; // expected-note {{pointer member declared here}}
DanglingGslPtrFieldDanglingGslPtrField74 DanglingGslPtrField(int i) : p(&i) {} // TODO
DanglingGslPtrFieldDanglingGslPtrField75 DanglingGslPtrField() : p2(MyLongOwnerWithConversion{}) {} // expected-warning {{initializing pointer member 'p2' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}}
DanglingGslPtrFieldDanglingGslPtrField76 DanglingGslPtrField(double) : p(MyIntOwner{}) {} // expected-warning {{initializing pointer member 'p' to point to a temporary object whose lifetime is shorter than the lifetime of the constructed object}}
77 };
78
danglingGslPtrFromLocal()79 MyIntPointer danglingGslPtrFromLocal() {
80 int j;
81 return &j; // TODO
82 }
83
returningLocalPointer()84 MyIntPointer returningLocalPointer() {
85 MyIntPointer localPointer;
86 return localPointer; // ok
87 }
88
daglingGslPtrFromLocalOwner()89 MyIntPointer daglingGslPtrFromLocalOwner() {
90 MyIntOwner localOwner;
91 return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}
92 }
93
daglingGslPtrFromLocalOwnerConv()94 MyLongPointerFromConversion daglingGslPtrFromLocalOwnerConv() {
95 MyLongOwnerWithConversion localOwner;
96 return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}
97 }
98
danglingGslPtrFromTemporary()99 MyIntPointer danglingGslPtrFromTemporary() {
100 return MyIntOwner{}; // expected-warning {{returning address of local temporary object}}
101 }
102
103 MyIntOwner makeTempOwner();
104
danglingGslPtrFromTemporary2()105 MyIntPointer danglingGslPtrFromTemporary2() {
106 return makeTempOwner(); // expected-warning {{returning address of local temporary object}}
107 }
108
danglingGslPtrFromTemporaryConv()109 MyLongPointerFromConversion danglingGslPtrFromTemporaryConv() {
110 return MyLongOwnerWithConversion{}; // expected-warning {{returning address of local temporary object}}
111 }
112
noFalsePositive(MyIntOwner & o)113 int *noFalsePositive(MyIntOwner &o) {
114 MyIntPointer p = o;
115 return &*p; // ok
116 }
117
118 MyIntPointer global;
119 MyLongPointerFromConversion global2;
120
initLocalGslPtrWithTempOwner()121 void initLocalGslPtrWithTempOwner() {
122 MyIntPointer p = MyIntOwner{}; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
123 p = MyIntOwner{}; // TODO ?
124 global = MyIntOwner{}; // TODO ?
125 MyLongPointerFromConversion p2 = MyLongOwnerWithConversion{}; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
126 p2 = MyLongOwnerWithConversion{}; // TODO ?
127 global2 = MyLongOwnerWithConversion{}; // TODO ?
128 }
129
130 namespace __gnu_cxx {
131 template <typename T>
132 struct basic_iterator {
133 basic_iterator operator++();
134 T& operator*() const;
135 T* operator->() const;
136 };
137
138 template<typename T>
139 bool operator!=(basic_iterator<T>, basic_iterator<T>);
140 }
141
142 namespace std {
143 template<typename T> struct remove_reference { typedef T type; };
144 template<typename T> struct remove_reference<T &> { typedef T type; };
145 template<typename T> struct remove_reference<T &&> { typedef T type; };
146
147 template<typename T>
148 typename remove_reference<T>::type &&move(T &&t) noexcept;
149
150 template <typename C>
151 auto data(const C &c) -> decltype(c.data());
152
153 template <typename C>
154 auto begin(C &c) -> decltype(c.begin());
155
156 template<typename T, int N>
157 T *begin(T (&array)[N]);
158
159 template <typename T>
160 struct vector {
161 typedef __gnu_cxx::basic_iterator<T> iterator;
162 iterator begin();
163 iterator end();
164 const T *data() const;
165 T &at(int n);
166 };
167
168 template<typename T>
169 struct basic_string_view {
170 basic_string_view(const T *);
171 const T *begin() const;
172 };
173
174 template<class _Mystr> struct iter {
175 iter& operator-=(int);
176
operator -std::iter177 iter operator-(int _Off) const {
178 iter _Tmp = *this;
179 return _Tmp -= _Off;
180 }
181 };
182
183 template<typename T>
184 struct basic_string {
185 basic_string();
186 basic_string(const T *);
187 const T *c_str() const;
188 operator basic_string_view<T> () const;
189 using const_iterator = iter<T>;
190 };
191
192
193 template<typename T>
194 struct unique_ptr {
195 T &operator*();
196 T *get() const;
197 };
198
199 template<typename T>
200 struct optional {
201 optional();
202 optional(const T&);
203 T &operator*() &;
204 T &&operator*() &&;
205 T &value() &;
206 T &&value() &&;
207 };
208
209 template<typename T>
210 struct stack {
211 T &top();
212 };
213
214 struct any {};
215
216 template<typename T>
217 T any_cast(const any& operand);
218
219 template<typename T>
220 struct reference_wrapper {
221 template<typename U>
222 reference_wrapper(U &&);
223 };
224
225 template<typename T>
226 reference_wrapper<T> ref(T& t) noexcept;
227 }
228
229 struct Unannotated {
230 typedef std::vector<int>::iterator iterator;
231 iterator begin();
232 operator iterator() const;
233 };
234
modelIterators()235 void modelIterators() {
236 std::vector<int>::iterator it = std::vector<int>().begin(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
237 (void)it;
238 }
239
modelIteratorReturn()240 std::vector<int>::iterator modelIteratorReturn() {
241 return std::vector<int>().begin(); // expected-warning {{returning address of local temporary object}}
242 }
243
modelFreeFunctions()244 const int *modelFreeFunctions() {
245 return std::data(std::vector<int>()); // expected-warning {{returning address of local temporary object}}
246 }
247
modelAnyCast()248 int &modelAnyCast() {
249 return std::any_cast<int&>(std::any{}); // expected-warning {{returning reference to local temporary object}}
250 }
251
modelAnyCast2()252 int modelAnyCast2() {
253 return std::any_cast<int>(std::any{}); // ok
254 }
255
modelAnyCast3()256 int modelAnyCast3() {
257 return std::any_cast<int&>(std::any{}); // ok
258 }
259
danglingRawPtrFromLocal()260 const char *danglingRawPtrFromLocal() {
261 std::basic_string<char> s;
262 return s.c_str(); // expected-warning {{address of stack memory associated with local variable 's' returned}}
263 }
264
danglingRawPtrFromLocal2()265 int &danglingRawPtrFromLocal2() {
266 std::optional<int> o;
267 return o.value(); // expected-warning {{reference to stack memory associated with local variable 'o' returned}}
268 }
269
danglingRawPtrFromLocal3()270 int &danglingRawPtrFromLocal3() {
271 std::optional<int> o;
272 return *o; // expected-warning {{reference to stack memory associated with local variable 'o' returned}}
273 }
274
danglingRawPtrFromTemp()275 const char *danglingRawPtrFromTemp() {
276 return std::basic_string<char>().c_str(); // expected-warning {{returning address of local temporary object}}
277 }
278
279 std::unique_ptr<int> getUniquePtr();
280
danglingUniquePtrFromTemp()281 int *danglingUniquePtrFromTemp() {
282 return getUniquePtr().get(); // expected-warning {{returning address of local temporary object}}
283 }
284
danglingUniquePtrFromTemp2()285 int *danglingUniquePtrFromTemp2() {
286 return std::unique_ptr<int>().get(); // expected-warning {{returning address of local temporary object}}
287 }
288
danglingReferenceFromTempOwner()289 void danglingReferenceFromTempOwner() {
290 int &&r = *std::optional<int>(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
291 int &&r2 = *std::optional<int>(5); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
292 int &&r3 = std::optional<int>(5).value(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
293 int &r4 = std::vector<int>().at(3); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
294 }
295
296 std::vector<int> getTempVec();
297 std::optional<std::vector<int>> getTempOptVec();
298
testLoops()299 void testLoops() {
300 for (auto i : getTempVec()) // ok
301 ;
302 for (auto i : *getTempOptVec()) // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
303 ;
304 }
305
usedToBeFalsePositive(std::vector<int> & v)306 int &usedToBeFalsePositive(std::vector<int> &v) {
307 std::vector<int>::iterator it = v.begin();
308 int& value = *it;
309 return value; // ok
310 }
311
doNotFollowReferencesForLocalOwner()312 int &doNotFollowReferencesForLocalOwner() {
313 std::unique_ptr<int> localOwner;
314 int &p = *localOwner.get();
315 // In real world code localOwner is usually moved here.
316 return p; // ok
317 }
318
trackThroughMultiplePointer()319 const char *trackThroughMultiplePointer() {
320 return std::basic_string_view<char>(std::basic_string<char>()).begin(); // expected-warning {{returning address of local temporary object}}
321 }
322
323 struct X {
XX324 X(std::unique_ptr<int> up) :
325 pointee(*up), pointee2(up.get()), pointer(std::move(up)) {}
326 int &pointee;
327 int *pointee2;
328 std::unique_ptr<int> pointer;
329 };
330
331 std::vector<int>::iterator getIt();
332 std::vector<int> getVec();
333
handleGslPtrInitsThroughReference()334 const int &handleGslPtrInitsThroughReference() {
335 const auto &it = getIt(); // Ok, it is lifetime extended.
336 return *it;
337 }
338
handleGslPtrInitsThroughReference2()339 void handleGslPtrInitsThroughReference2() {
340 const std::vector<int> &v = getVec();
341 const int *val = v.data(); // Ok, it is lifetime extended.
342 }
343
handleTernaryOperator(bool cond)344 void handleTernaryOperator(bool cond) {
345 std::basic_string<char> def;
346 std::basic_string_view<char> v = cond ? def : ""; // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
347 }
348
danglingPtrFromNonOwnerLocal()349 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal() {
350 int i = 5;
351 return i; // TODO
352 }
353
danglingPtrFromNonOwnerLocal2()354 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal2() {
355 int i = 5;
356 return std::ref(i); // TODO
357 }
358
danglingPtrFromNonOwnerLocal3()359 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal3() {
360 int i = 5;
361 return std::reference_wrapper<int>(i); // TODO
362 }
363
danglingPtrFromNonOwnerLocal4()364 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal4() {
365 Unannotated i;
366 return std::reference_wrapper<Unannotated>(i); // TODO
367 }
368
danglingPtrFromNonOwnerLocal5()369 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal5() {
370 Unannotated i;
371 return std::ref(i); // TODO
372 }
373
returnPtrToLocalArray()374 int *returnPtrToLocalArray() {
375 int a[5];
376 return std::begin(a); // TODO
377 }
378
379 struct ptr_wrapper {
380 std::vector<int>::iterator member;
381 };
382
383 ptr_wrapper getPtrWrapper();
384
returnPtrFromWrapper()385 std::vector<int>::iterator returnPtrFromWrapper() {
386 ptr_wrapper local = getPtrWrapper();
387 return local.member;
388 }
389
returnPtrFromWrapperThroughRef()390 std::vector<int>::iterator returnPtrFromWrapperThroughRef() {
391 ptr_wrapper local = getPtrWrapper();
392 ptr_wrapper &local2 = local;
393 return local2.member;
394 }
395
returnPtrFromWrapperThroughRef2()396 std::vector<int>::iterator returnPtrFromWrapperThroughRef2() {
397 ptr_wrapper local = getPtrWrapper();
398 std::vector<int>::iterator &local2 = local.member;
399 return local2;
400 }
401
checkPtrMemberFromAggregate()402 void checkPtrMemberFromAggregate() {
403 std::vector<int>::iterator local = getPtrWrapper().member; // OK.
404 }
405
doNotInterferWithUnannotated()406 std::vector<int>::iterator doNotInterferWithUnannotated() {
407 Unannotated value;
408 // Conservative choice for now. Probably not ok, but we do not warn.
409 return std::begin(value);
410 }
411
doNotInterferWithUnannotated2()412 std::vector<int>::iterator doNotInterferWithUnannotated2() {
413 Unannotated value;
414 return value;
415 }
416
supportDerefAddrofChain(int a,std::vector<int>::iterator value)417 std::vector<int>::iterator supportDerefAddrofChain(int a, std::vector<int>::iterator value) {
418 switch (a) {
419 default:
420 return value;
421 case 1:
422 return *&value;
423 case 2:
424 return *&*&value;
425 case 3:
426 return *&*&*&value;
427 }
428 }
429
supportDerefAddrofChain2(int a,std::vector<int>::iterator value)430 int &supportDerefAddrofChain2(int a, std::vector<int>::iterator value) {
431 switch (a) {
432 default:
433 return *value;
434 case 1:
435 return **&value;
436 case 2:
437 return **&*&value;
438 case 3:
439 return **&*&*&value;
440 }
441 }
442
supportDerefAddrofChain3(int a,std::vector<int>::iterator value)443 int *supportDerefAddrofChain3(int a, std::vector<int>::iterator value) {
444 switch (a) {
445 default:
446 return &*value;
447 case 1:
448 return &*&*value;
449 case 2:
450 return &*&**&value;
451 case 3:
452 return &*&**&*&value;
453 }
454 }
455
handleDerivedToBaseCast1(MySpecialIntPointer ptr)456 MyIntPointer handleDerivedToBaseCast1(MySpecialIntPointer ptr) {
457 return ptr;
458 }
459
handleDerivedToBaseCast2(MyOwnerIntPointer ptr)460 MyIntPointer handleDerivedToBaseCast2(MyOwnerIntPointer ptr) {
461 return ptr; // expected-warning {{address of stack memory associated with parameter 'ptr' returned}}
462 }
463
noFalsePositiveWithVectorOfPointers()464 std::vector<int>::iterator noFalsePositiveWithVectorOfPointers() {
465 std::vector<std::vector<int>::iterator> iters;
466 return iters.at(0);
467 }
468
testForBug49342()469 void testForBug49342()
470 {
471 auto it = std::iter<char>{} - 2; // Used to be false positive.
472 }
473