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