1 // RUN: %clang_cc1 -fsyntax-only -Wdangling -Wdangling-field -Wreturn-stack-address -verify %s
2 struct [[gsl::Owner(int)]] MyIntOwner
{
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
12 MyIntPointer(const MyIntOwner
&);
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);
30 struct [[gsl::Owner(long)]] MyLongOwnerWithConversion
{
31 MyLongOwnerWithConversion();
32 operator MyLongPointerFromConversion();
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() {
46 // In this case we do not have enough information in a statement local
47 // analysis to detect the problem.
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
66 void dangligGslPtrFromTemporary() {
67 MyIntPointer p
= Y
{}.a
; // TODO
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() {
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
) {
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;
139 bool operator!=(basic_iterator
<T
>, basic_iterator
<T
>);
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
; };
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
>
161 typedef __gnu_cxx::basic_iterator
<T
> iterator
;
164 const T
*data() const;
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 {
184 struct 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
>;
217 T
any_cast(const any
& operand
);
220 struct reference_wrapper
{
222 reference_wrapper(U
&&);
226 reference_wrapper
<T
> ref(T
& t
) noexcept
;
230 typedef std::vector
<int>::iterator iterator
;
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}}
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();
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();
312 int &doNotFollowReferencesForLocalOwner() {
313 std::unique_ptr
<int> localOwner
;
314 int &p
= *localOwner
.get();
315 // In real world code localOwner is usually moved here.
319 const char *trackThroughMultiplePointer() {
320 return std::basic_string_view
<char>(std::basic_string
<char>()).begin(); // expected-warning {{returning address of local temporary object}}
324 X(std::unique_ptr
<int> up
) :
325 pointee(*up
), pointee2(up
.get()), pointer(std::move(up
)) {}
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.
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() {
354 std::reference_wrapper
<int> danglingPtrFromNonOwnerLocal2() {
356 return std::ref(i
); // TODO
359 std::reference_wrapper
<int> danglingPtrFromNonOwnerLocal3() {
361 return std::reference_wrapper
<int>(i
); // TODO
364 std::reference_wrapper
<Unannotated
> danglingPtrFromNonOwnerLocal4() {
366 return std::reference_wrapper
<Unannotated
>(i
); // TODO
369 std::reference_wrapper
<Unannotated
> danglingPtrFromNonOwnerLocal5() {
371 return std::ref(i
); // TODO
374 int *returnPtrToLocalArray() {
376 return std::begin(a
); // TODO
380 std::vector
<int>::iterator member
;
383 ptr_wrapper
getPtrWrapper();
385 std::vector
<int>::iterator
returnPtrFromWrapper() {
386 ptr_wrapper local
= getPtrWrapper();
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
;
402 void checkPtrMemberFromAggregate() {
403 std::vector
<int>::iterator local
= getPtrWrapper().member
; // OK.
406 std::vector
<int>::iterator
doNotInterferWithUnannotated() {
408 // Conservative choice for now. Probably not ok, but we do not warn.
409 return std::begin(value
);
412 std::vector
<int>::iterator
doNotInterferWithUnannotated2() {
417 std::vector
<int>::iterator
supportDerefAddrofChain(int a
, std::vector
<int>::iterator value
) {
430 int &supportDerefAddrofChain2(int a
, std::vector
<int>::iterator value
) {
443 int *supportDerefAddrofChain3(int a
, std::vector
<int>::iterator value
) {
452 return &*&**&*&value
;
456 MyIntPointer
handleDerivedToBaseCast1(MySpecialIntPointer 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
;
469 void testForBug49342()
471 auto it
= std::iter
<char>{} - 2; // Used to be false positive.