1
- // RUN: %clang_cc1 --std=c++20 -fsyntax-only -Wdangling -Wdangling-field -Wreturn-stack-address - verify %s
1
+ // RUN: %clang_cc1 --std=c++20 -fsyntax-only -verify %s
2
2
3
3
#include " Inputs/lifetime-analysis.h"
4
4
5
- struct X {} x;
6
- X x;
5
+ // ****************************************************************************
6
+ // Helper class and functions.
7
+ // ****************************************************************************
8
+ // Lifetimebound helper functions: Returns a reference to the argument.
9
+ std::string_view getLifetimeBoundView (const std::string& s [[clang::lifetimebound]]);
10
+ std::string_view getNotLifetimeBoundView (const std::string& s);
11
+ const std::string& getLifetimeBoundString (const std::string &s [[clang::lifetimebound]]);
12
+ const std::string& getLifetimeBoundString (std::string_view sv [[clang::lifetimebound]]);
7
13
8
14
// ****************************************************************************
9
15
// Capture an integer
10
16
// ****************************************************************************
11
17
namespace capture_int {
18
+ struct X {} x;
12
19
void captureInt (const int &i [[clang::lifetime_capture_by(x)]], X &x);
13
20
void captureRValInt (int &&i [[clang::lifetime_capture_by(x)]], X &x);
14
21
void noCaptureInt (int i [[clang::lifetime_capture_by(x)]], X &x);
@@ -27,12 +34,8 @@ void use() {
27
34
// ****************************************************************************
28
35
// Capture std::string (gsl owner types)
29
36
// ****************************************************************************
30
- std::string_view getLifetimeBoundView (const std::string& s [[clang::lifetimebound]]);
31
- std::string_view getNotLifetimeBoundView (const std::string& s);
32
- const std::string& getLifetimeBoundString (const std::string &s [[clang::lifetimebound]]);
33
- const std::string& getLifetimeBoundString (std::string_view sv [[clang::lifetimebound]]);
34
-
35
37
namespace capture_string {
38
+ struct X {} x;
36
39
void captureString (const std::string &s [[clang::lifetime_capture_by(x)]], X &x);
37
40
void captureRValString (std::string &&s [[clang::lifetime_capture_by(x)]], X &x);
38
41
@@ -49,6 +52,7 @@ void use() {
49
52
// Capture std::string_view (gsl pointer types)
50
53
// ****************************************************************************
51
54
namespace capture_string_view {
55
+ struct X {} x;
52
56
void captureStringView (std::string_view s [[clang::lifetime_capture_by(x)]], X &x);
53
57
void captureRValStringView (std::string_view &&sv [[clang::lifetime_capture_by(x)]], X &x);
54
58
void noCaptureStringView (std::string_view sv, X &x);
@@ -92,6 +96,7 @@ const std::string* getLifetimeBoundPointer(const std::string &s [[clang::lifetim
92
96
const std::string* getNotLifetimeBoundPointer (const std::string &s);
93
97
94
98
namespace capture_pointer {
99
+ struct X {} x;
95
100
void capturePointer (const std::string* sp [[clang::lifetime_capture_by(x)]], X &x);
96
101
void use () {
97
102
capturePointer (getLifetimeBoundPointer (std::string ()), x); // expected-warning {{object whose reference is captured by 'x'}}
@@ -107,25 +112,31 @@ void use() {
107
112
// Arrays and initializer lists.
108
113
// ****************************************************************************
109
114
namespace init_lists {
115
+ struct X {} x;
110
116
void captureVector (const std::vector<int > &a [[clang::lifetime_capture_by(x)]], X &x);
111
117
void captureArray (int array [[clang::lifetime_capture_by(x)]] [2], X &x);
112
118
void captureInitList (std::initializer_list<int > abc [[clang::lifetime_capture_by(x)]], X &x);
113
119
120
+
121
+ std::initializer_list<int > getLifetimeBoundInitList (std::initializer_list<int > abc [[clang::lifetimebound]]);
122
+
114
123
void use () {
115
- captureVector ({1 , 2 , 3 }, x); // expected-warning {{capture }}
116
- captureVector (std::vector<int >{}, x); // expected-warning {{capture }}
124
+ captureVector ({1 , 2 , 3 }, x); // expected-warning {{captured by 'x' }}
125
+ captureVector (std::vector<int >{}, x); // expected-warning {{captured by 'x' }}
117
126
std::vector<int > local_vector;
118
127
captureVector (local_vector, x);
119
128
int local_array[2 ];
120
129
captureArray (local_array, x);
121
- captureInitList ({1 , 2 }, x); // expected-warning {{capture }}
122
- }
130
+ captureInitList ({1 , 2 }, x); // expected-warning {{captured by 'x' }}
131
+ captureInitList ( getLifetimeBoundInitList ({ 1 , 2 }), x); // expected-warning {{captured by 'x'} }
123
132
}
133
+ } // namespace init_lists
124
134
125
135
// ****************************************************************************
126
136
// Implicit object param 'this' is captured
127
137
// ****************************************************************************
128
138
namespace this_is_captured {
139
+ struct X {} x;
129
140
struct S {
130
141
void capture (X &x) [[clang::lifetime_capture_by(x)]];
131
142
};
@@ -148,13 +159,13 @@ void use() {
148
159
std::string local_string;
149
160
// capture by global.
150
161
captureByGlobal (std::string ()); // expected-warning {{object whose reference is captured will be destroyed at the end of the full-expression}}
151
- captureByGlobal (getLifetimeBoundView (std::string ())); // expected-warning {{captured}}
162
+ captureByGlobal (getLifetimeBoundView (std::string ())); // expected-warning {{object whose reference is captured will be destroyed at the end of the full-expression }}
152
163
captureByGlobal (local_string);
153
164
captureByGlobal (local_string_view);
154
165
155
166
// capture by unknown.
156
167
captureByUnknown (std::string ()); // expected-warning {{object whose reference is captured will be destroyed at the end of the full-expression}}
157
- captureByUnknown (getLifetimeBoundView (std::string ())); // expected-warning {{captured}}
168
+ captureByUnknown (getLifetimeBoundView (std::string ())); // expected-warning {{object whose reference is captured will be destroyed at the end of the full-expression }}
158
169
captureByUnknown (local_string);
159
170
captureByUnknown (local_string_view);
160
171
}
@@ -171,9 +182,9 @@ struct S {
171
182
void use () {
172
183
S s;
173
184
s.captureInt (1 ); // expected-warning {{object whose reference is captured by 's'}}
174
- s.captureView (std::string ()); // expected-warning {{captured}}
175
- s.captureView (getLifetimeBoundView (std::string ())); // expected-warning {{captured}}
176
- s.captureView (getLifetimeBoundString (std::string ())); // expected-warning {{captured}}
185
+ s.captureView (std::string ()); // expected-warning {{captured by 's' }}
186
+ s.captureView (getLifetimeBoundView (std::string ())); // expected-warning {{captured by 's' }}
187
+ s.captureView (getLifetimeBoundString (std::string ())); // expected-warning {{captured by 's' }}
177
188
s.captureView (getNotLifetimeBoundView (std::string ()));
178
189
}
179
190
} // namespace capture_by_this
@@ -182,13 +193,14 @@ void use() {
182
193
// Struct with field as a reference
183
194
// ****************************************************************************
184
195
namespace reference_field {
196
+ struct X {} x;
185
197
struct Foo {
186
198
const int & b;
187
199
};
188
200
void captureField (Foo param [[clang::lifetime_capture_by(x)]], X &x);
189
201
void use () {
190
202
captureField (Foo{
191
- 1 // expected-warning {{capture }}
203
+ 1 // expected-warning {{captured by 'x' }}
192
204
}, x);
193
205
int local;
194
206
captureField (Foo{local}, x);
@@ -199,11 +211,13 @@ void use() {
199
211
// Capture default argument.
200
212
// ****************************************************************************
201
213
namespace default_arg {
214
+ struct X {} x;
202
215
void captureDefaultArg (X &x, std::string_view s [[clang::lifetime_capture_by(x)]] = std::string());
203
216
void useCaptureDefaultArg () {
204
217
X x;
205
218
captureDefaultArg (x); // FIXME: Diagnose temporary default arg.
206
- captureDefaultArg (x, std::string (" temp" )); // expected-warning {{captured}}
219
+ captureDefaultArg (x, std::string (" temp" )); // expected-warning {{captured by 'x'}}
220
+ captureDefaultArg (x, getLifetimeBoundView (std::string ())); // expected-warning {{captured by 'x'}}
207
221
std::string local;
208
222
captureDefaultArg (x, local);
209
223
}
@@ -251,11 +265,11 @@ void use_container() {
251
265
252
266
MyVector<std::string_view> vector_of_view;
253
267
vector_of_view.push_back (std::string ()); // expected-warning {{object whose reference is captured by 'vector_of_view'}}
254
- vector_of_view.push_back (getLifetimeBoundView (std::string ())); // expected-warning {{captured}}
268
+ vector_of_view.push_back (getLifetimeBoundView (std::string ())); // expected-warning {{captured by 'vector_of_view' }}
255
269
256
270
MyVector<const std::string*> vector_of_pointer;
257
- vector_of_pointer.push_back (getLifetimeBoundPointer (std::string ())); // expected-warning {{captured}}
258
- vector_of_pointer.push_back (getLifetimeBoundPointer (*getLifetimeBoundPointer (std::string ()))); // expected-warning {{captured}}
271
+ vector_of_pointer.push_back (getLifetimeBoundPointer (std::string ())); // expected-warning {{captured by 'vector_of_pointer' }}
272
+ vector_of_pointer.push_back (getLifetimeBoundPointer (*getLifetimeBoundPointer (std::string ()))); // expected-warning {{captured by 'vector_of_pointer' }}
259
273
vector_of_pointer.push_back (getLifetimeBoundPointer (local));
260
274
vector_of_pointer.push_back (getNotLifetimeBoundPointer (std::string ()));
261
275
}
@@ -287,8 +301,8 @@ void use_my_view() {
287
301
vector_of_my_view.push_back (MyStringView{});
288
302
vector_of_my_view.push_back (std::string_view{});
289
303
vector_of_my_view.push_back (std::string{}); // expected-warning {{object whose reference is captured by 'vector_of_my_view'}}
290
- vector_of_my_view.push_back (getLifetimeBoundView (std::string{})); // expected-warning {{captured}}
291
- vector_of_my_view.push_back (getLifetimeBoundString (getLifetimeBoundView (std::string{}))); // expected-warning {{captured}}
304
+ vector_of_my_view.push_back (getLifetimeBoundView (std::string{})); // expected-warning {{captured by 'vector_of_my_view' }}
305
+ vector_of_my_view.push_back (getLifetimeBoundString (getLifetimeBoundView (std::string{}))); // expected-warning {{captured by 'vector_of_my_view' }}
292
306
vector_of_my_view.push_back (getNotLifetimeBoundView (getLifetimeBoundString (getLifetimeBoundView (std::string{}))));
293
307
294
308
// Use with container of other view types.
@@ -305,7 +319,7 @@ void use_with_optional_view() {
305
319
306
320
std::optional<std::string_view> optional_of_view;
307
321
vector_of_view.push_back (optional_of_view.value ());
308
- vector_of_view.push_back (getOptionalS ().value ()); // expected-warning {{captured}}
322
+ vector_of_view.push_back (getOptionalS ().value ()); // expected-warning {{captured by 'vector_of_view' }}
309
323
310
324
vector_of_view.push_back (getOptionalSV ().value ());
311
325
vector_of_view.push_back (getOptionalMySV ().value ());
0 commit comments