1 // RUN: %clang_cc1 -std=c++20 -Wno-unused %s -verify=expected,cxx20 -Wno-vla-cxx-extension
2 // RUN: %clang_cc1 -std=c++23 -Wno-unused %s -verify=expected,sincecxx23 -Wno-vla-cxx-extension
3 // RUN: %clang_cc1 -std=c++26 -Wno-unused %s -verify=expected,sincecxx23 -Wno-vla-cxx-extension
4 // RUN: %clang_cc1 -std=c++26 -DINLINE_NAMESPACE -Wno-unused %s -verify=expected,sincecxx23 -Wno-vla-cxx-extension
6 inline constexpr void* operator new(__SIZE_TYPE__
, void* p
) noexcept
{ return p
; }
8 template<typename T
, typename
... Args
>
9 constexpr T
* construct_at(T
* p
, Args
&&... args
) { return ::new((void*)p
) T(static_cast<Args
&&>(args
)...); }
11 constexpr void destroy_at(T
* p
) { p
->~T(); }
14 constexpr T
* allocate(__SIZE_TYPE__ n
) { return static_cast<T
*>(::operator new(n
* sizeof(T
))); }
15 constexpr void deallocate(T
* p
, __SIZE_TYPE__
) { ::operator delete(p
); }
17 using nullptr_t
= decltype(nullptr);
18 template<typename T
, T v
>
19 struct integral_constant
{ static constexpr T value
= v
; };
21 using bool_constant
= integral_constant
<bool, v
>;
22 using true_type
= bool_constant
<true>;
23 using false_type
= bool_constant
<false>;
25 inline constexpr bool is_function_v
= __is_function(T
);
26 #ifdef INLINE_NAMESPACE
27 inline namespace __1
{
29 template<typename T
> requires (!is_function_v
<T
>) // #std-constraint
30 consteval
bool is_within_lifetime(const T
* p
) noexcept
{ // #std-definition
31 return __builtin_is_within_lifetime(p
);
33 #ifdef INLINE_NAMESPACE
38 consteval
bool test_union(int& i
, char& c
) {
39 if (__builtin_is_within_lifetime(&i
) || __builtin_is_within_lifetime(&c
))
41 std::construct_at(&c
, 1);
42 if (__builtin_is_within_lifetime(&i
) || !__builtin_is_within_lifetime(&c
))
44 std::construct_at(&i
, 3);
45 if (!__builtin_is_within_lifetime(&i
) || __builtin_is_within_lifetime(&c
))
51 union { int i
; char c
; } u
;
52 return test_union(u
.i
, u
.c
);
55 union { int i
; char c
; };
56 return test_union(i
, c
);
59 struct { union { int i
; char c
; }; } u
;
60 return test_union(u
.i
, u
.c
);
63 struct { union { int i
; char c
; } u
; } r
;
64 return test_union(r
.u
.i
, r
.u
.c
);
67 consteval
bool test_nested() {
69 union { int i
; char c
; } u
;
72 if (__builtin_is_within_lifetime(&l
) || __builtin_is_within_lifetime(&u
) || __builtin_is_within_lifetime(&u
.i
) || __builtin_is_within_lifetime(&u
.c
))
74 std::construct_at(&l
);
75 if (!__builtin_is_within_lifetime(&l
) || __builtin_is_within_lifetime(&u
) || __builtin_is_within_lifetime(&u
.i
) || __builtin_is_within_lifetime(&u
.c
))
77 std::construct_at(&u
);
78 std::construct_at(&u
.i
);
79 if (__builtin_is_within_lifetime(&l
) || !__builtin_is_within_lifetime(&u
) || !__builtin_is_within_lifetime(&u
.i
) || __builtin_is_within_lifetime(&u
.c
))
81 std::construct_at(&u
.c
);
82 if (__builtin_is_within_lifetime(&l
) || !__builtin_is_within_lifetime(&u
) || __builtin_is_within_lifetime(&u
.i
) || !__builtin_is_within_lifetime(&u
.c
))
86 static_assert(test_nested());
88 consteval
bool test_dynamic(bool read_after_deallocate
) {
89 std::allocator
<int> a
;
90 int* p
= a
.allocate(1);
91 // a.allocate starts the lifetime of an array,
92 // the complete object of *p has started its lifetime
93 if (__builtin_is_within_lifetime(p
))
96 if (!__builtin_is_within_lifetime(p
))
99 if (__builtin_is_within_lifetime(p
))
102 if (read_after_deallocate
)
103 __builtin_is_within_lifetime(p
); // expected-note {{read of heap allocated object that has been deleted}}
106 static_assert(test_dynamic(false));
107 static_assert(test_dynamic(true));
108 // expected-error@-1 {{static assertion expression is not an integral constant expression}}
109 // expected-note@-2 {{in call to 'test_dynamic(true)'}}
111 consteval
bool test_automatic(int read_dangling
) {
116 if (!__builtin_is_within_lifetime(p
))
121 if (read_dangling
== 1)
122 __builtin_is_within_lifetime(p
); // expected-note {{read of object outside its lifetime is not allowed in a constant expression}}
124 if (read_dangling
== 2)
125 __builtin_is_within_lifetime(p
); // expected-note {{read of object outside its lifetime is not allowed in a constant expression}}
129 if (!__builtin_is_within_lifetime(p
))
132 if (read_dangling
== 3)
133 __builtin_is_within_lifetime(p
); // expected-note {{read of object outside its lifetime is not allowed in a constant expression}}
136 std::nullptr_t np
= nullptr;
138 if (!__builtin_is_within_lifetime(q
))
141 if (read_dangling
== 4)
142 __builtin_is_within_lifetime(q
); // expected-note {{read of object outside its lifetime is not allowed in a constant expression}}
145 static_assert(test_automatic(0));
146 static_assert(test_automatic(1));
147 // expected-error@-1 {{static assertion expression is not an integral constant expression}}
148 // expected-note@-2 {{in call to 'test_automatic(1)'}}
149 static_assert(test_automatic(2));
150 // expected-error@-1 {{static assertion expression is not an integral constant expression}}
151 // expected-note@-2 {{in call to 'test_automatic(2)'}}
152 static_assert(test_automatic(3));
153 // expected-error@-1 {{static assertion expression is not an integral constant expression}}
154 // expected-note@-2 {{in call to 'test_automatic(3)'}}
155 static_assert(test_automatic(4));
156 // expected-error@-1 {{static assertion expression is not an integral constant expression}}
157 // expected-note@-2 {{in call to 'test_automatic(4)'}}
160 consteval
bool test_indeterminate() {
162 if (!__builtin_is_within_lifetime(&x
))
165 unsigned char c
= __builtin_bit_cast(unsigned char, b
);
166 if (!__builtin_is_within_lifetime(&c
))
169 unsigned char y
= __builtin_bit_cast(unsigned char, padding
);
170 if (!__builtin_is_within_lifetime(&y
))
174 static_assert(test_indeterminate());
176 consteval
bool test_volatile() {
178 if (!__builtin_is_within_lifetime(static_cast<volatile int*>(&x
)) || !__builtin_is_within_lifetime(static_cast<volatile void*>(&x
)))
181 if (!__builtin_is_within_lifetime(const_cast<int*>(&y
)) || !__builtin_is_within_lifetime(const_cast<void*>(static_cast<volatile void*>(&y
))))
185 static_assert(test_volatile());
187 constexpr bool self
= __builtin_is_within_lifetime(&self
);
188 // expected-error@-1 {{constexpr variable 'self' must be initialized by a constant expression}}
189 // expected-note@-2 {{'__builtin_is_within_lifetime' cannot be called with a pointer to an object whose lifetime has not yet begun}}
190 // expected-error@-3 {{call to consteval function '__builtin_is_within_lifetime' is not a constant expression}}
191 // expected-note@-4 {{initializer of 'self' is not a constant expression}}
192 // expected-note@-5 {{declared here}}
193 constexpr int external
{};
194 static_assert(__builtin_is_within_lifetime(&external
));
195 void not_constexpr() {
196 __builtin_is_within_lifetime(&external
);
198 void invalid_args() {
199 __builtin_is_within_lifetime(static_cast<int*>(nullptr));
200 // expected-error@-1 {{call to consteval function '__builtin_is_within_lifetime' is not a constant expression}}
201 // expected-note@-2 {{'__builtin_is_within_lifetime' cannot be called with a null pointer}}
203 // FIXME: avoid function to pointer conversion on all consteval builtins
204 __builtin_is_within_lifetime(0);
205 // expected-error@-1 {{non-pointer argument to '__builtin_is_within_lifetime' is not allowed}}
206 // expected-error@-2 {{cannot take address of consteval function '__builtin_is_within_lifetime' outside of an immediate invocation}}
207 __builtin_is_within_lifetime();
208 // expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
209 // expected-error@-2 {{cannot take address of consteval function '__builtin_is_within_lifetime' outside of an immediate invocation}}
210 __builtin_is_within_lifetime(1, 2);
211 // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
212 // expected-error@-2 {{cannot take address of consteval function '__builtin_is_within_lifetime' outside of an immediate invocation}}
213 __builtin_is_within_lifetime(&external
, &external
);
214 // expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
215 // expected-error@-2 {{cannot take address of consteval function '__builtin_is_within_lifetime' outside of an immediate invocation}}
223 mutable int mi
; // #x-mi
225 static_assert(!__builtin_is_within_lifetime(&x1
.i
));
226 static_assert(__builtin_is_within_lifetime(&x1
.c
));
227 static_assert(__builtin_is_within_lifetime(&x1
.mi
));
228 // expected-error@-1 {{static assertion expression is not an integral constant expression}}
229 // expected-note@-2 {{read of mutable member 'mi' is not allowed in a constant expression}}
230 // expected-note@#x-mi {{declared here}}
232 constexpr struct NSDMI
{ // #NSDMI
234 bool b
= __builtin_is_within_lifetime(&a
); // #NSDMI-read
236 // expected-error@-1 {{constexpr variable 'x2' must be initialized by a constant expression}}
237 // expected-note@#NSDMI-read {{'__builtin_is_within_lifetime' cannot be called with a pointer to an object whose lifetime has not yet begun}}
238 // expected-note@-3 {{in call to 'NSDMI()'}}
239 // expected-error@-4 {{call to immediate function 'NSDMI::NSDMI' is not a constant expression}}
240 // expected-note@#NSDMI {{'NSDMI' is an immediate constructor because the default initializer of 'b' contains a call to a consteval function '__builtin_is_within_lifetime' and that call is not a constant expression}}
241 // expected-note@#NSDMI-read {{'__builtin_is_within_lifetime' cannot be called with a pointer to an object whose lifetime has not yet begun}}
242 // expected-note@-7 {{in call to 'NSDMI()'}}
246 __builtin_is_within_lifetime(this); // #X3-read
249 // expected-error@-1 {{call to consteval function 'X3::X3' is not a constant expression}}
250 // expected-note@#X3-read {{'__builtin_is_within_lifetime' cannot be called with a pointer to an object whose lifetime has not yet begun}}
251 // expected-note@-3 {{in call to 'X3()'}}
254 static_assert(__builtin_is_within_lifetime(const_cast<int*>(&i
)));
255 static_assert(__builtin_is_within_lifetime(const_cast<volatile int*>(&i
)));
256 static_assert(__builtin_is_within_lifetime(static_cast<const void*>(&i
)));
258 constexpr int arr
[2]{};
259 static_assert(__builtin_is_within_lifetime(arr
));
260 static_assert(__builtin_is_within_lifetime(arr
+ 0));
261 static_assert(__builtin_is_within_lifetime(arr
+ 1));
263 __builtin_is_within_lifetime(&i
+ 1);
264 // expected-error@-1 {{call to consteval function '__builtin_is_within_lifetime' is not a constant expression}}
265 // expected-note@-2 {{'__builtin_is_within_lifetime' cannot be called with a one-past-the-end pointer}}
266 __builtin_is_within_lifetime(arr
+ 2);
267 // expected-error@-1 {{call to consteval function '__builtin_is_within_lifetime' is not a constant expression}}
268 // expected-note@-2 {{'__builtin_is_within_lifetime' cannot be called with a one-past-the-end pointer}}
272 consteval
void disallow_function_types(bool b
, const T
* p
) {
274 __builtin_is_within_lifetime(p
); // expected-error {{function pointer argument to '__builtin_is_within_lifetime' is not allowed}}
278 disallow_function_types
<void ()>(false, &f
);
279 // expected-note@-1 {{in instantiation of function template specialization 'disallow_function_types<void ()>' requested here}}
283 union { bool b
; char c
; };
285 // note: this assumes common implementation properties for bool and char:
286 // * sizeof(bool) == sizeof(char), and
287 // * the value representations for true and false are distinct
288 // from the value representation for 2
289 constexpr OptBool() : c(2) { }
290 constexpr OptBool(bool b
) : b(b
) { }
292 constexpr auto has_value() const -> bool {
293 if consteval
{ // cxx20-warning {{consteval if}}
294 return __builtin_is_within_lifetime(&b
); // during constant evaluation, cannot read from c
296 return c
!= 2; // during runtime, must read from c
300 constexpr auto operator*() const -> const bool& {
305 constexpr OptBool disengaged
;
306 constexpr OptBool
engaged(true);
307 static_assert(!disengaged
.has_value());
308 static_assert(engaged
.has_value());
309 static_assert(*engaged
);
313 consteval
bool f(int n
) {
314 int vla
[n
]; // cxx20-error {{variable of non-literal type}}
315 return __builtin_is_within_lifetime(static_cast<void*>(&vla
));
319 consteval
bool fail(int n
) {
320 int vla
[n
]; // cxx20-error {{variable of non-literal type}}
321 return __builtin_is_within_lifetime(&vla
); // expected-error {{variable length arrays are not supported in '__builtin_is_within_lifetime'}}
323 static_assert(fail(1)); // sincecxx23-error {{static assertion expression is not an integral constant expression}}
325 consteval
bool variably_modified(int n
) {
327 return __builtin_is_within_lifetime(&p
);
329 static_assert(variably_modified(1));
333 consteval
bool partial_arrays() {
335 if (!__builtin_is_within_lifetime(&arr
) || !__builtin_is_within_lifetime(&arr
[0]) || !__builtin_is_within_lifetime(&arr
[1]))
337 std::destroy_at(&arr
[0]);
338 if (!__builtin_is_within_lifetime(&arr
) || __builtin_is_within_lifetime(&arr
[0]) || !__builtin_is_within_lifetime(&arr
[1]))
340 std::construct_at(&arr
[0]);
341 if (!__builtin_is_within_lifetime(&arr
) || !__builtin_is_within_lifetime(&arr
[0]) || !__builtin_is_within_lifetime(&arr
[1]))
345 static_assert(partial_arrays());
347 consteval
bool partial_members() {
352 if (!__builtin_is_within_lifetime(&s
) || !__builtin_is_within_lifetime(&s
.x
) || !__builtin_is_within_lifetime(&s
.y
))
354 std::destroy_at(&s
.x
);
355 if (!__builtin_is_within_lifetime(&s
) || __builtin_is_within_lifetime(&s
.x
) || !__builtin_is_within_lifetime(&s
.y
))
357 std::construct_at(&s
.x
);
358 if (!__builtin_is_within_lifetime(&s
) || !__builtin_is_within_lifetime(&s
.x
) || !__builtin_is_within_lifetime(&s
.y
))
364 constexpr NonTrivial() {}
365 constexpr NonTrivial(const NonTrivial
&) {}
366 constexpr ~NonTrivial() {}
370 constexpr T
& unmove(T
&& temp
) { return static_cast<T
&>(temp
); }
372 consteval
bool test_temporaries() {
373 static_assert(__builtin_is_within_lifetime(&unmove(0)));
374 static_assert(__builtin_is_within_lifetime(&unmove(NonTrivial
{})));
375 if (!__builtin_is_within_lifetime(&unmove(0)))
377 if (!__builtin_is_within_lifetime(&unmove(NonTrivial
{})))
381 static_assert(test_temporaries());
383 constexpr const int& temp
= 0;
384 static_assert(__builtin_is_within_lifetime(&temp
));
387 constexpr T
* test_dangling() {
388 T i
; // expected-note 2 {{declared here}}
389 return &i
; // expected-warning 2 {{address of stack memory associated with local variable 'i' returned}}
391 static_assert(__builtin_is_within_lifetime(test_dangling
<int>())); // expected-note {{in instantiation of function template specialization}}
392 // expected-error@-1 {{static assertion expression is not an integral constant expression}}
393 // expected-note@-2 {{read of variable whose lifetime has ended}}
394 static_assert(__builtin_is_within_lifetime(test_dangling
<int[1]>())); // expected-note {{in instantiation of function template specialization}}
395 // expected-error@-1 {{static assertion expression is not an integral constant expression}}
396 // expected-note@-2 {{read of variable whose lifetime has ended}}
399 concept CanCallAndPassToIsWithinLifetime
= std::bool_constant
<__builtin_is_within_lifetime(F())>::value
;
400 static_assert(CanCallAndPassToIsWithinLifetime
<[]{ return &i
; }>);
401 static_assert(!CanCallAndPassToIsWithinLifetime
<[]{ return static_cast<int*>(nullptr); }>);
402 static_assert(!CanCallAndPassToIsWithinLifetime
<[]{ return static_cast<void(*)()>(&f
); }>);
403 template<auto F
> constexpr std::true_type
sfinae() requires CanCallAndPassToIsWithinLifetime
<F
> { return {}; }
404 template<auto F
> std::false_type
sfinae() { return {}; }
405 static_assert(decltype(sfinae
<[]{ return &i
; }>())::value
);
406 static_assert(!decltype(sfinae
<[]{ return static_cast<int*>(nullptr); }>())::value
);
407 std::true_type(* not_immediate
)() = &sfinae
<[]{ return &i
; }>;
409 void test_std_error_message() {
410 std::is_within_lifetime(static_cast<int*>(nullptr));
411 // expected-error@-1 {{call to consteval function 'std::is_within_lifetime<int>' is not a constant expression}}
412 // expected-note@-2 {{'std::is_within_lifetime' cannot be called with a null pointer}}
413 // expected-note@-3 {{in call to 'is_within_lifetime<int>(nullptr)'}}
414 std::is_within_lifetime
<void()>(&test_std_error_message
);
415 // expected-error@-1 {{no matching function for call to 'is_within_lifetime'}}
416 // expected-note@#std-definition {{candidate template ignored: constraints not satisfied [with T = void ()]}}
417 // expected-note@#std-constraint {{because '!is_function_v<void ()>' evaluated to false}}
418 std::is_within_lifetime(arr
+ 2);
419 // expected-error@-1 {{call to consteval function 'std::is_within_lifetime<int>' is not a constant expression}}
420 // expected-note@-2 {{'std::is_within_lifetime' cannot be called with a one-past-the-end pointer}}
421 // expected-note@-3 {{in call to 'is_within_lifetime<int>(&arr[2])'}}
425 std::is_within_lifetime(this); // #XStd-read
428 // expected-error@-1 {{call to consteval function 'XStd::XStd' is not a constant expression}}
429 // expected-note@#XStd-read {{'std::is_within_lifetime' cannot be called with a pointer to an object whose lifetime has not yet begun}}
430 // expected-note@#XStd-read {{in call to 'is_within_lifetime<XStd>(&)'}}
431 // expected-note@-4 {{in call to 'XStd()'}}