CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
432 lines
18 KiB
C++
432 lines
18 KiB
C++
// RUN: %clang_cc1 -std=c++20 -Wno-unused %s -verify=expected,cxx20 -Wno-vla-cxx-extension
|
|
// RUN: %clang_cc1 -std=c++23 -Wno-unused %s -verify=expected,sincecxx23 -Wno-vla-cxx-extension
|
|
// RUN: %clang_cc1 -std=c++26 -Wno-unused %s -verify=expected,sincecxx23 -Wno-vla-cxx-extension
|
|
// RUN: %clang_cc1 -std=c++26 -DINLINE_NAMESPACE -Wno-unused %s -verify=expected,sincecxx23 -Wno-vla-cxx-extension
|
|
|
|
inline constexpr void* operator new(__SIZE_TYPE__, void* p) noexcept { return p; }
|
|
namespace std {
|
|
template<typename T, typename... Args>
|
|
constexpr T* construct_at(T* p, Args&&... args) { return ::new((void*)p) T(static_cast<Args&&>(args)...); }
|
|
template<typename T>
|
|
constexpr void destroy_at(T* p) { p->~T(); }
|
|
template<typename T>
|
|
struct allocator {
|
|
constexpr T* allocate(__SIZE_TYPE__ n) { return static_cast<T*>(::operator new(n * sizeof(T))); }
|
|
constexpr void deallocate(T* p, __SIZE_TYPE__) { ::operator delete(p); }
|
|
};
|
|
using nullptr_t = decltype(nullptr);
|
|
template<typename T, T v>
|
|
struct integral_constant { static constexpr T value = v; };
|
|
template<bool v>
|
|
using bool_constant = integral_constant<bool, v>;
|
|
using true_type = bool_constant<true>;
|
|
using false_type = bool_constant<false>;
|
|
template<typename T>
|
|
inline constexpr bool is_function_v = __is_function(T);
|
|
#ifdef INLINE_NAMESPACE
|
|
inline namespace __1 {
|
|
#endif
|
|
template<typename T> requires (!is_function_v<T>) // #std-constraint
|
|
consteval bool is_within_lifetime(const T* p) noexcept { // #std-definition
|
|
return __builtin_is_within_lifetime(p);
|
|
}
|
|
#ifdef INLINE_NAMESPACE
|
|
}
|
|
#endif
|
|
}
|
|
|
|
consteval bool test_union(int& i, char& c) {
|
|
if (__builtin_is_within_lifetime(&i) || __builtin_is_within_lifetime(&c))
|
|
return false;
|
|
std::construct_at(&c, 1);
|
|
if (__builtin_is_within_lifetime(&i) || !__builtin_is_within_lifetime(&c))
|
|
return false;
|
|
std::construct_at(&i, 3);
|
|
if (!__builtin_is_within_lifetime(&i) || __builtin_is_within_lifetime(&c))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
static_assert([]{
|
|
union { int i; char c; } u;
|
|
return test_union(u.i, u.c);
|
|
}());
|
|
static_assert([]{
|
|
union { int i; char c; };
|
|
return test_union(i, c);
|
|
}());
|
|
static_assert([]{
|
|
struct { union { int i; char c; }; } u;
|
|
return test_union(u.i, u.c);
|
|
}());
|
|
static_assert([]{
|
|
struct { union { int i; char c; } u; } r;
|
|
return test_union(r.u.i, r.u.c);
|
|
}());
|
|
|
|
consteval bool test_nested() {
|
|
union {
|
|
union { int i; char c; } u;
|
|
long l;
|
|
};
|
|
if (__builtin_is_within_lifetime(&l) || __builtin_is_within_lifetime(&u) || __builtin_is_within_lifetime(&u.i) || __builtin_is_within_lifetime(&u.c))
|
|
return false;
|
|
std::construct_at(&l);
|
|
if (!__builtin_is_within_lifetime(&l) || __builtin_is_within_lifetime(&u) || __builtin_is_within_lifetime(&u.i) || __builtin_is_within_lifetime(&u.c))
|
|
return false;
|
|
std::construct_at(&u);
|
|
std::construct_at(&u.i);
|
|
if (__builtin_is_within_lifetime(&l) || !__builtin_is_within_lifetime(&u) || !__builtin_is_within_lifetime(&u.i) || __builtin_is_within_lifetime(&u.c))
|
|
return false;
|
|
std::construct_at(&u.c);
|
|
if (__builtin_is_within_lifetime(&l) || !__builtin_is_within_lifetime(&u) || __builtin_is_within_lifetime(&u.i) || !__builtin_is_within_lifetime(&u.c))
|
|
return false;
|
|
return true;
|
|
}
|
|
static_assert(test_nested());
|
|
|
|
consteval bool test_dynamic(bool read_after_deallocate) {
|
|
std::allocator<int> a;
|
|
int* p = a.allocate(1);
|
|
// a.allocate starts the lifetime of an array,
|
|
// the complete object of *p has started its lifetime
|
|
if (__builtin_is_within_lifetime(p))
|
|
return false;
|
|
std::construct_at(p);
|
|
if (!__builtin_is_within_lifetime(p))
|
|
return false;
|
|
std::destroy_at(p);
|
|
if (__builtin_is_within_lifetime(p))
|
|
return false;
|
|
a.deallocate(p, 1);
|
|
if (read_after_deallocate)
|
|
__builtin_is_within_lifetime(p); // expected-note {{read of heap allocated object that has been deleted}}
|
|
return true;
|
|
}
|
|
static_assert(test_dynamic(false));
|
|
static_assert(test_dynamic(true));
|
|
// expected-error@-1 {{static assertion expression is not an integral constant expression}}
|
|
// expected-note@-2 {{in call to 'test_dynamic(true)'}}
|
|
|
|
consteval bool test_automatic(int read_dangling) {
|
|
int* p;
|
|
{
|
|
int x = 0; // expected-note 2{{declared here}}
|
|
p = &x;
|
|
if (!__builtin_is_within_lifetime(p))
|
|
return false;
|
|
}
|
|
{
|
|
int x = 0;
|
|
if (read_dangling == 1)
|
|
__builtin_is_within_lifetime(p); // expected-note {{read of object outside its lifetime is not allowed in a constant expression}}
|
|
}
|
|
if (read_dangling == 2)
|
|
__builtin_is_within_lifetime(p); // expected-note {{read of object outside its lifetime is not allowed in a constant expression}}
|
|
{
|
|
int x[4]; // expected-note {{declared here}}
|
|
p = &x[2];
|
|
if (!__builtin_is_within_lifetime(p))
|
|
return false;
|
|
}
|
|
if (read_dangling == 3)
|
|
__builtin_is_within_lifetime(p); // expected-note {{read of object outside its lifetime is not allowed in a constant expression}}
|
|
std::nullptr_t* q;
|
|
{
|
|
std::nullptr_t np = nullptr; // expected-note {{declared here}}
|
|
q = &np;
|
|
if (!__builtin_is_within_lifetime(q))
|
|
return false;
|
|
}
|
|
if (read_dangling == 4)
|
|
__builtin_is_within_lifetime(q); // expected-note {{read of object outside its lifetime is not allowed in a constant expression}}
|
|
return true;
|
|
}
|
|
static_assert(test_automatic(0));
|
|
static_assert(test_automatic(1));
|
|
// expected-error@-1 {{static assertion expression is not an integral constant expression}}
|
|
// expected-note@-2 {{in call to 'test_automatic(1)'}}
|
|
static_assert(test_automatic(2));
|
|
// expected-error@-1 {{static assertion expression is not an integral constant expression}}
|
|
// expected-note@-2 {{in call to 'test_automatic(2)'}}
|
|
static_assert(test_automatic(3));
|
|
// expected-error@-1 {{static assertion expression is not an integral constant expression}}
|
|
// expected-note@-2 {{in call to 'test_automatic(3)'}}
|
|
static_assert(test_automatic(4));
|
|
// expected-error@-1 {{static assertion expression is not an integral constant expression}}
|
|
// expected-note@-2 {{in call to 'test_automatic(4)'}}
|
|
|
|
|
|
consteval bool test_indeterminate() {
|
|
int x;
|
|
if (!__builtin_is_within_lifetime(&x))
|
|
return false;
|
|
bool b = true;
|
|
unsigned char c = __builtin_bit_cast(unsigned char, b);
|
|
if (!__builtin_is_within_lifetime(&c))
|
|
return false;
|
|
struct {} padding;
|
|
unsigned char y = __builtin_bit_cast(unsigned char, padding);
|
|
if (!__builtin_is_within_lifetime(&y))
|
|
return false;
|
|
return true;
|
|
}
|
|
static_assert(test_indeterminate());
|
|
|
|
consteval bool test_volatile() {
|
|
int x;
|
|
if (!__builtin_is_within_lifetime(static_cast<volatile int*>(&x)) || !__builtin_is_within_lifetime(static_cast<volatile void*>(&x)))
|
|
return false;
|
|
volatile int y;
|
|
if (!__builtin_is_within_lifetime(const_cast<int*>(&y)) || !__builtin_is_within_lifetime(const_cast<void*>(static_cast<volatile void*>(&y))))
|
|
return false;
|
|
return true;
|
|
}
|
|
static_assert(test_volatile());
|
|
|
|
constexpr bool self = __builtin_is_within_lifetime(&self);
|
|
// expected-error@-1 {{constexpr variable 'self' must be initialized by a constant expression}}
|
|
// expected-note@-2 {{'__builtin_is_within_lifetime' cannot be called with a pointer to an object whose lifetime has not yet begun}}
|
|
// expected-error@-3 {{call to consteval function '__builtin_is_within_lifetime' is not a constant expression}}
|
|
// expected-note@-4 {{initializer of 'self' is not a constant expression}}
|
|
// expected-note@-5 {{declared here}}
|
|
constexpr int external{};
|
|
static_assert(__builtin_is_within_lifetime(&external));
|
|
void not_constexpr() {
|
|
__builtin_is_within_lifetime(&external);
|
|
}
|
|
void invalid_args() {
|
|
__builtin_is_within_lifetime(static_cast<int*>(nullptr));
|
|
// expected-error@-1 {{call to consteval function '__builtin_is_within_lifetime' is not a constant expression}}
|
|
// expected-note@-2 {{'__builtin_is_within_lifetime' cannot be called with a null pointer}}
|
|
|
|
// FIXME: avoid function to pointer conversion on all consteval builtins
|
|
__builtin_is_within_lifetime(0);
|
|
// expected-error@-1 {{non-pointer argument to '__builtin_is_within_lifetime' is not allowed}}
|
|
// expected-error@-2 {{cannot take address of consteval function '__builtin_is_within_lifetime' outside of an immediate invocation}}
|
|
__builtin_is_within_lifetime();
|
|
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
|
|
// expected-error@-2 {{cannot take address of consteval function '__builtin_is_within_lifetime' outside of an immediate invocation}}
|
|
__builtin_is_within_lifetime(1, 2);
|
|
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
|
|
// expected-error@-2 {{cannot take address of consteval function '__builtin_is_within_lifetime' outside of an immediate invocation}}
|
|
__builtin_is_within_lifetime(&external, &external);
|
|
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
|
|
// expected-error@-2 {{cannot take address of consteval function '__builtin_is_within_lifetime' outside of an immediate invocation}}
|
|
}
|
|
|
|
constexpr struct {
|
|
union {
|
|
int i;
|
|
char c;
|
|
};
|
|
mutable int mi; // #x-mi
|
|
} x1{ .c = 2 };
|
|
static_assert(!__builtin_is_within_lifetime(&x1.i));
|
|
static_assert(__builtin_is_within_lifetime(&x1.c));
|
|
static_assert(__builtin_is_within_lifetime(&x1.mi));
|
|
// expected-error@-1 {{static assertion expression is not an integral constant expression}}
|
|
// expected-note@-2 {{read of mutable member 'mi' is not allowed in a constant expression}}
|
|
// expected-note@#x-mi {{declared here}}
|
|
|
|
constexpr struct NSDMI { // #NSDMI
|
|
bool a = true;
|
|
bool b = __builtin_is_within_lifetime(&a); // #NSDMI-read
|
|
} x2;
|
|
// expected-error@-1 {{constexpr variable 'x2' must be initialized by a constant expression}}
|
|
// expected-note@#NSDMI-read {{'__builtin_is_within_lifetime' cannot be called with a pointer to an object whose lifetime has not yet begun}}
|
|
// expected-note@-3 {{in call to 'NSDMI()'}}
|
|
// expected-error@-4 {{call to immediate function 'NSDMI::NSDMI' is not a constant expression}}
|
|
// 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}}
|
|
// expected-note@#NSDMI-read {{'__builtin_is_within_lifetime' cannot be called with a pointer to an object whose lifetime has not yet begun}}
|
|
// expected-note@-7 {{in call to 'NSDMI()'}}
|
|
|
|
struct X3 {
|
|
consteval X3() {
|
|
__builtin_is_within_lifetime(this); // #X3-read
|
|
}
|
|
} x3;
|
|
// expected-error@-1 {{call to consteval function 'X3::X3' is not a constant expression}}
|
|
// expected-note@#X3-read {{'__builtin_is_within_lifetime' cannot be called with a pointer to an object whose lifetime has not yet begun}}
|
|
// expected-note@-3 {{in call to 'X3()'}}
|
|
|
|
constexpr int i = 2;
|
|
static_assert(__builtin_is_within_lifetime(const_cast<int*>(&i)));
|
|
static_assert(__builtin_is_within_lifetime(const_cast<volatile int*>(&i)));
|
|
static_assert(__builtin_is_within_lifetime(static_cast<const void*>(&i)));
|
|
|
|
constexpr int arr[2]{};
|
|
static_assert(__builtin_is_within_lifetime(arr));
|
|
static_assert(__builtin_is_within_lifetime(arr + 0));
|
|
static_assert(__builtin_is_within_lifetime(arr + 1));
|
|
void f() {
|
|
__builtin_is_within_lifetime(&i + 1);
|
|
// expected-error@-1 {{call to consteval function '__builtin_is_within_lifetime' is not a constant expression}}
|
|
// expected-note@-2 {{'__builtin_is_within_lifetime' cannot be called with a one-past-the-end pointer}}
|
|
__builtin_is_within_lifetime(arr + 2);
|
|
// expected-error@-1 {{call to consteval function '__builtin_is_within_lifetime' is not a constant expression}}
|
|
// expected-note@-2 {{'__builtin_is_within_lifetime' cannot be called with a one-past-the-end pointer}}
|
|
}
|
|
|
|
template<typename T>
|
|
consteval void disallow_function_types(bool b, const T* p) {
|
|
if (b) {
|
|
__builtin_is_within_lifetime(p); // expected-error {{function pointer argument to '__builtin_is_within_lifetime' is not allowed}}
|
|
}
|
|
}
|
|
void g() {
|
|
disallow_function_types<void ()>(false, &f);
|
|
// expected-note@-1 {{in instantiation of function template specialization 'disallow_function_types<void ()>' requested here}}
|
|
}
|
|
|
|
struct OptBool {
|
|
union { bool b; char c; };
|
|
|
|
// note: this assumes common implementation properties for bool and char:
|
|
// * sizeof(bool) == sizeof(char), and
|
|
// * the value representations for true and false are distinct
|
|
// from the value representation for 2
|
|
constexpr OptBool() : c(2) { }
|
|
constexpr OptBool(bool b) : b(b) { }
|
|
|
|
constexpr auto has_value() const -> bool {
|
|
if consteval { // cxx20-warning {{consteval if}}
|
|
return __builtin_is_within_lifetime(&b); // during constant evaluation, cannot read from c
|
|
} else {
|
|
return c != 2; // during runtime, must read from c
|
|
}
|
|
}
|
|
|
|
constexpr auto operator*() const -> const bool& {
|
|
return b;
|
|
}
|
|
};
|
|
|
|
constexpr OptBool disengaged;
|
|
constexpr OptBool engaged(true);
|
|
static_assert(!disengaged.has_value());
|
|
static_assert(engaged.has_value());
|
|
static_assert(*engaged);
|
|
|
|
namespace vlas {
|
|
|
|
consteval bool f(int n) {
|
|
int vla[n]; // cxx20-error {{variable of non-literal type}}
|
|
return __builtin_is_within_lifetime(static_cast<void*>(&vla));
|
|
}
|
|
static_assert(f(1));
|
|
|
|
consteval bool fail(int n) {
|
|
int vla[n]; // cxx20-error {{variable of non-literal type}}
|
|
return __builtin_is_within_lifetime(&vla); // expected-error {{variable length arrays are not supported in '__builtin_is_within_lifetime'}}
|
|
}
|
|
static_assert(fail(1)); // sincecxx23-error {{static assertion expression is not an integral constant expression}}
|
|
|
|
consteval bool variably_modified(int n) {
|
|
int(* p)[n];
|
|
return __builtin_is_within_lifetime(&p);
|
|
}
|
|
static_assert(variably_modified(1));
|
|
|
|
} // namespace vlas
|
|
|
|
consteval bool partial_arrays() {
|
|
int arr[2];
|
|
if (!__builtin_is_within_lifetime(&arr) || !__builtin_is_within_lifetime(&arr[0]) || !__builtin_is_within_lifetime(&arr[1]))
|
|
return false;
|
|
std::destroy_at(&arr[0]);
|
|
if (!__builtin_is_within_lifetime(&arr) || __builtin_is_within_lifetime(&arr[0]) || !__builtin_is_within_lifetime(&arr[1]))
|
|
return false;
|
|
std::construct_at(&arr[0]);
|
|
if (!__builtin_is_within_lifetime(&arr) || !__builtin_is_within_lifetime(&arr[0]) || !__builtin_is_within_lifetime(&arr[1]))
|
|
return false;
|
|
return true;
|
|
}
|
|
static_assert(partial_arrays());
|
|
|
|
consteval bool partial_members() {
|
|
struct S {
|
|
int x;
|
|
int y;
|
|
} s;
|
|
if (!__builtin_is_within_lifetime(&s) || !__builtin_is_within_lifetime(&s.x) || !__builtin_is_within_lifetime(&s.y))
|
|
return false;
|
|
std::destroy_at(&s.x);
|
|
if (!__builtin_is_within_lifetime(&s) || __builtin_is_within_lifetime(&s.x) || !__builtin_is_within_lifetime(&s.y))
|
|
return false;
|
|
std::construct_at(&s.x);
|
|
if (!__builtin_is_within_lifetime(&s) || !__builtin_is_within_lifetime(&s.x) || !__builtin_is_within_lifetime(&s.y))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
struct NonTrivial {
|
|
constexpr NonTrivial() {}
|
|
constexpr NonTrivial(const NonTrivial&) {}
|
|
constexpr ~NonTrivial() {}
|
|
};
|
|
|
|
template<typename T>
|
|
constexpr T& unmove(T&& temp) { return static_cast<T&>(temp); }
|
|
|
|
consteval bool test_temporaries() {
|
|
static_assert(__builtin_is_within_lifetime(&unmove(0)));
|
|
static_assert(__builtin_is_within_lifetime(&unmove(NonTrivial{})));
|
|
if (!__builtin_is_within_lifetime(&unmove(0)))
|
|
return false;
|
|
if (!__builtin_is_within_lifetime(&unmove(NonTrivial{})))
|
|
return false;
|
|
return true;
|
|
}
|
|
static_assert(test_temporaries());
|
|
|
|
constexpr const int& temp = 0;
|
|
static_assert(__builtin_is_within_lifetime(&temp));
|
|
|
|
template<typename T>
|
|
constexpr T* test_dangling() {
|
|
T i; // expected-note 2 {{declared here}}
|
|
return &i; // expected-warning 2 {{address of stack memory associated with local variable 'i' returned}}
|
|
}
|
|
static_assert(__builtin_is_within_lifetime(test_dangling<int>())); // expected-note {{in instantiation of function template specialization}}
|
|
// expected-error@-1 {{static assertion expression is not an integral constant expression}}
|
|
// expected-note@-2 {{read of object outside its lifetime}}
|
|
static_assert(__builtin_is_within_lifetime(test_dangling<int[1]>())); // expected-note {{in instantiation of function template specialization}}
|
|
// expected-error@-1 {{static assertion expression is not an integral constant expression}}
|
|
// expected-note@-2 {{read of object outside its lifetime}}
|
|
|
|
template<auto F>
|
|
concept CanCallAndPassToIsWithinLifetime = std::bool_constant<__builtin_is_within_lifetime(F())>::value;
|
|
static_assert(CanCallAndPassToIsWithinLifetime<[]{ return &i; }>);
|
|
static_assert(!CanCallAndPassToIsWithinLifetime<[]{ return static_cast<int*>(nullptr); }>);
|
|
static_assert(!CanCallAndPassToIsWithinLifetime<[]{ return static_cast<void(*)()>(&f); }>);
|
|
template<auto F> constexpr std::true_type sfinae() requires CanCallAndPassToIsWithinLifetime<F> { return {}; }
|
|
template<auto F> std::false_type sfinae() { return {}; }
|
|
static_assert(decltype(sfinae<[]{ return &i; }>())::value);
|
|
static_assert(!decltype(sfinae<[]{ return static_cast<int*>(nullptr); }>())::value);
|
|
std::true_type(* not_immediate)() = &sfinae<[]{ return &i; }>;
|
|
|
|
void test_std_error_message() {
|
|
std::is_within_lifetime(static_cast<int*>(nullptr));
|
|
// expected-error@-1 {{call to consteval function 'std::is_within_lifetime<int>' is not a constant expression}}
|
|
// expected-note@-2 {{'std::is_within_lifetime' cannot be called with a null pointer}}
|
|
// expected-note@-3 {{in call to 'is_within_lifetime<int>(nullptr)'}}
|
|
std::is_within_lifetime<void()>(&test_std_error_message);
|
|
// expected-error@-1 {{no matching function for call to 'is_within_lifetime'}}
|
|
// expected-note@#std-definition {{candidate template ignored: constraints not satisfied [with T = void ()]}}
|
|
// expected-note@#std-constraint {{because '!is_function_v<void ()>' evaluated to false}}
|
|
std::is_within_lifetime(arr + 2);
|
|
// expected-error@-1 {{call to consteval function 'std::is_within_lifetime<int>' is not a constant expression}}
|
|
// expected-note@-2 {{'std::is_within_lifetime' cannot be called with a one-past-the-end pointer}}
|
|
// expected-note@-3 {{in call to 'is_within_lifetime<int>(&arr[2])'}}
|
|
}
|
|
struct XStd {
|
|
consteval XStd() {
|
|
std::is_within_lifetime(this); // #XStd-read
|
|
}
|
|
} xstd;
|
|
// expected-error@-1 {{call to consteval function 'XStd::XStd' is not a constant expression}}
|
|
// expected-note@#XStd-read {{'std::is_within_lifetime' cannot be called with a pointer to an object whose lifetime has not yet begun}}
|
|
// expected-note@#XStd-read {{in call to 'is_within_lifetime<XStd>(&)'}}
|
|
// expected-note@-4 {{in call to 'XStd()'}}
|