Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / Sema / warn-lifetime-analysis-nocfg.cpp
blobb3ca173c1fdbcbd3d1dcc02e88d1e9b901ee345e
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 };
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();
17 struct MySpecialIntPointer : MyIntPointer {
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 {
25 struct [[gsl::Pointer(long)]] MyLongPointerFromConversion {
26 MyLongPointerFromConversion(long *p = nullptr);
27 long &operator*();
30 struct [[gsl::Owner(long)]] MyLongOwnerWithConversion {
31 MyLongOwnerWithConversion();
32 operator MyLongPointerFromConversion();
33 long &operator*();
34 MyIntPointer releaseAsMyPointer();
35 long *releaseAsRawPointer();
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}}
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});
52 MyIntPointer ownershipTransferToMyPointer() {
53 MyLongOwnerWithConversion t;
54 return t.releaseAsMyPointer(); // ok
57 long *ownershipTransferToRawPointer() {
58 MyLongOwnerWithConversion t;
59 return t.releaseAsRawPointer(); // ok
62 struct Y {
63 int a[4];
66 void dangligGslPtrFromTemporary() {
67 MyIntPointer p = Y{}.a; // TODO
68 (void)p;
71 struct DanglingGslPtrField {
72 MyIntPointer p; // expected-note {{pointer member declared here}}
73 MyLongPointerFromConversion p2; // expected-note {{pointer member declared here}}
74 DanglingGslPtrField(int i) : p(&i) {} // TODO
75 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}}
76 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}}
79 MyIntPointer danglingGslPtrFromLocal() {
80 int j;
81 return &j; // TODO
84 MyIntPointer returningLocalPointer() {
85 MyIntPointer localPointer;
86 return localPointer; // ok
89 MyIntPointer daglingGslPtrFromLocalOwner() {
90 MyIntOwner localOwner;
91 return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}
94 MyLongPointerFromConversion daglingGslPtrFromLocalOwnerConv() {
95 MyLongOwnerWithConversion localOwner;
96 return localOwner; // expected-warning {{address of stack memory associated with local variable 'localOwner' returned}}
99 MyIntPointer danglingGslPtrFromTemporary() {
100 return MyIntOwner{}; // expected-warning {{returning address of local temporary object}}
103 MyIntOwner makeTempOwner();
105 MyIntPointer danglingGslPtrFromTemporary2() {
106 return makeTempOwner(); // expected-warning {{returning address of local temporary object}}
109 MyLongPointerFromConversion danglingGslPtrFromTemporaryConv() {
110 return MyLongOwnerWithConversion{}; // expected-warning {{returning address of local temporary object}}
113 int *noFalsePositive(MyIntOwner &o) {
114 MyIntPointer p = o;
115 return &*p; // ok
118 MyIntPointer global;
119 MyLongPointerFromConversion global2;
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 ?
130 namespace __gnu_cxx {
131 template <typename T>
132 struct basic_iterator {
133 basic_iterator operator++();
134 T& operator*() const;
135 T* operator->() const;
138 template<typename T>
139 bool operator!=(basic_iterator<T>, basic_iterator<T>);
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; };
147 template<typename T>
148 typename remove_reference<T>::type &&move(T &&t) noexcept;
150 template <typename C>
151 auto data(const C &c) -> decltype(c.data());
153 template <typename C>
154 auto begin(C &c) -> decltype(c.begin());
156 template<typename T, int N>
157 T *begin(T (&array)[N]);
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);
168 template<typename T>
169 struct basic_string_view {
170 basic_string_view(const T *);
171 const T *begin() const;
174 template<class _Mystr> struct iter {
175 iter& operator-=(int);
177 iter operator-(int _Off) const {
178 iter _Tmp = *this;
179 return _Tmp -= _Off;
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>;
193 template<typename T>
194 struct unique_ptr {
195 T &operator*();
196 T *get() const;
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() &&;
209 template<typename T>
210 struct stack {
211 T &top();
214 struct any {};
216 template<typename T>
217 T any_cast(const any& operand);
219 template<typename T>
220 struct reference_wrapper {
221 template<typename U>
222 reference_wrapper(U &&);
225 template<typename T>
226 reference_wrapper<T> ref(T& t) noexcept;
229 struct Unannotated {
230 typedef std::vector<int>::iterator iterator;
231 iterator begin();
232 operator iterator() const;
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;
240 std::vector<int>::iterator modelIteratorReturn() {
241 return std::vector<int>().begin(); // expected-warning {{returning address of local temporary object}}
244 const int *modelFreeFunctions() {
245 return std::data(std::vector<int>()); // expected-warning {{returning address of local temporary object}}
248 int &modelAnyCast() {
249 return std::any_cast<int&>(std::any{}); // expected-warning {{returning reference to local temporary object}}
252 int modelAnyCast2() {
253 return std::any_cast<int>(std::any{}); // ok
256 int modelAnyCast3() {
257 return std::any_cast<int&>(std::any{}); // ok
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}}
265 int &danglingRawPtrFromLocal2() {
266 std::optional<int> o;
267 return o.value(); // expected-warning {{reference to stack memory associated with local variable 'o' returned}}
270 int &danglingRawPtrFromLocal3() {
271 std::optional<int> o;
272 return *o; // expected-warning {{reference to stack memory associated with local variable 'o' returned}}
275 const char *danglingRawPtrFromTemp() {
276 return std::basic_string<char>().c_str(); // expected-warning {{returning address of local temporary object}}
279 std::unique_ptr<int> getUniquePtr();
281 int *danglingUniquePtrFromTemp() {
282 return getUniquePtr().get(); // expected-warning {{returning address of local temporary object}}
285 int *danglingUniquePtrFromTemp2() {
286 return std::unique_ptr<int>().get(); // expected-warning {{returning address of local temporary object}}
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}}
296 std::vector<int> getTempVec();
297 std::optional<std::vector<int>> getTempOptVec();
299 void testLoops() {
300 for (auto i : getTempVec()) // ok
302 for (auto i : *getTempOptVec()) // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
306 int &usedToBeFalsePositive(std::vector<int> &v) {
307 std::vector<int>::iterator it = v.begin();
308 int& value = *it;
309 return value; // ok
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
319 const char *trackThroughMultiplePointer() {
320 return std::basic_string_view<char>(std::basic_string<char>()).begin(); // expected-warning {{returning address of local temporary object}}
323 struct X {
324 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;
331 std::vector<int>::iterator getIt();
332 std::vector<int> getVec();
334 const int &handleGslPtrInitsThroughReference() {
335 const auto &it = getIt(); // Ok, it is lifetime extended.
336 return *it;
339 void handleGslPtrInitsThroughReference2() {
340 const std::vector<int> &v = getVec();
341 const int *val = v.data(); // Ok, it is lifetime extended.
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}}
349 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal() {
350 int i = 5;
351 return i; // TODO
354 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal2() {
355 int i = 5;
356 return std::ref(i); // TODO
359 std::reference_wrapper<int> danglingPtrFromNonOwnerLocal3() {
360 int i = 5;
361 return std::reference_wrapper<int>(i); // TODO
364 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal4() {
365 Unannotated i;
366 return std::reference_wrapper<Unannotated>(i); // TODO
369 std::reference_wrapper<Unannotated> danglingPtrFromNonOwnerLocal5() {
370 Unannotated i;
371 return std::ref(i); // TODO
374 int *returnPtrToLocalArray() {
375 int a[5];
376 return std::begin(a); // TODO
379 struct ptr_wrapper {
380 std::vector<int>::iterator member;
383 ptr_wrapper getPtrWrapper();
385 std::vector<int>::iterator returnPtrFromWrapper() {
386 ptr_wrapper local = getPtrWrapper();
387 return local.member;
390 std::vector<int>::iterator returnPtrFromWrapperThroughRef() {
391 ptr_wrapper local = getPtrWrapper();
392 ptr_wrapper &local2 = local;
393 return local2.member;
396 std::vector<int>::iterator returnPtrFromWrapperThroughRef2() {
397 ptr_wrapper local = getPtrWrapper();
398 std::vector<int>::iterator &local2 = local.member;
399 return local2;
402 void checkPtrMemberFromAggregate() {
403 std::vector<int>::iterator local = getPtrWrapper().member; // OK.
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);
412 std::vector<int>::iterator doNotInterferWithUnannotated2() {
413 Unannotated value;
414 return 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;
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;
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;
456 MyIntPointer handleDerivedToBaseCast1(MySpecialIntPointer ptr) {
457 return ptr;
460 MyIntPointer handleDerivedToBaseCast2(MyOwnerIntPointer ptr) {
461 return ptr; // expected-warning {{address of stack memory associated with parameter 'ptr' returned}}
464 std::vector<int>::iterator noFalsePositiveWithVectorOfPointers() {
465 std::vector<std::vector<int>::iterator> iters;
466 return iters.at(0);
469 void testForBug49342()
471 auto it = std::iter<char>{} - 2; // Used to be false positive.