brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.1 KiB · 62ff268 Raw
432 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -Wno-unused %s -verify=expected,cxx20 -Wno-vla-cxx-extension2// RUN: %clang_cc1 -std=c++23 -Wno-unused %s -verify=expected,sincecxx23 -Wno-vla-cxx-extension3// RUN: %clang_cc1 -std=c++26 -Wno-unused %s -verify=expected,sincecxx23 -Wno-vla-cxx-extension4// RUN: %clang_cc1 -std=c++26 -DINLINE_NAMESPACE -Wno-unused %s -verify=expected,sincecxx23 -Wno-vla-cxx-extension5 6inline constexpr void* operator new(__SIZE_TYPE__, void* p) noexcept { return p; }7namespace std {8template<typename T, typename... Args>9constexpr T* construct_at(T* p, Args&&... args) { return ::new((void*)p) T(static_cast<Args&&>(args)...); }10template<typename T>11constexpr void destroy_at(T* p) { p->~T(); }12template<typename T>13struct allocator {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); }16};17using nullptr_t = decltype(nullptr);18template<typename T, T v>19struct integral_constant { static constexpr T value = v; };20template<bool v>21using bool_constant = integral_constant<bool, v>;22using true_type = bool_constant<true>;23using false_type = bool_constant<false>;24template<typename T>25inline constexpr bool is_function_v = __is_function(T);26#ifdef INLINE_NAMESPACE27inline namespace __1 {28#endif29template<typename T> requires (!is_function_v<T>) // #std-constraint30consteval bool is_within_lifetime(const T* p) noexcept { // #std-definition31  return __builtin_is_within_lifetime(p);32}33#ifdef INLINE_NAMESPACE34}35#endif36}37 38consteval bool test_union(int& i, char& c) {39  if (__builtin_is_within_lifetime(&i) || __builtin_is_within_lifetime(&c))40    return false;41  std::construct_at(&c, 1);42  if (__builtin_is_within_lifetime(&i) || !__builtin_is_within_lifetime(&c))43    return false;44  std::construct_at(&i, 3);45  if (!__builtin_is_within_lifetime(&i) || __builtin_is_within_lifetime(&c))46    return false;47  return true;48}49 50static_assert([]{51  union { int i; char c; } u;52  return test_union(u.i, u.c);53}());54static_assert([]{55  union { int i; char c; };56  return test_union(i, c);57}());58static_assert([]{59  struct { union { int i; char c; }; } u;60  return test_union(u.i, u.c);61}());62static_assert([]{63  struct { union { int i; char c; } u; } r;64  return test_union(r.u.i, r.u.c);65}());66 67consteval bool test_nested() {68  union {69    union { int i; char c; } u;70    long l;71  };72  if (__builtin_is_within_lifetime(&l) || __builtin_is_within_lifetime(&u) || __builtin_is_within_lifetime(&u.i) || __builtin_is_within_lifetime(&u.c))73    return false;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))76    return false;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))80    return false;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))83    return false;84  return true;85}86static_assert(test_nested());87 88consteval 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 lifetime93  if (__builtin_is_within_lifetime(p))94    return false;95  std::construct_at(p);96  if (!__builtin_is_within_lifetime(p))97    return false;98  std::destroy_at(p);99  if (__builtin_is_within_lifetime(p))100    return false;101  a.deallocate(p, 1);102  if (read_after_deallocate)103    __builtin_is_within_lifetime(p); // expected-note {{read of heap allocated object that has been deleted}}104  return true;105}106static_assert(test_dynamic(false));107static_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)'}}110 111consteval bool test_automatic(int read_dangling) {112  int* p;113  {114    int x = 0;115    p = &x;116    if (!__builtin_is_within_lifetime(p))117      return false;118  }119  {120    int x = 0;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}}123  }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}}126  {127    int x[4];128    p = &x[2];129    if (!__builtin_is_within_lifetime(p))130      return false;131  }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}}134  std::nullptr_t* q;135  {136    std::nullptr_t np = nullptr;137    q = &np;138    if (!__builtin_is_within_lifetime(q))139      return false;140  }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}}143  return true;144}145static_assert(test_automatic(0));146static_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)'}}149static_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)'}}152static_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)'}}155static_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)'}}158 159 160consteval bool test_indeterminate() {161  int x;162  if (!__builtin_is_within_lifetime(&x))163    return false;164  bool b = true;165  unsigned char c = __builtin_bit_cast(unsigned char, b);166  if (!__builtin_is_within_lifetime(&c))167    return false;168  struct {} padding;169  unsigned char y = __builtin_bit_cast(unsigned char, padding);170  if (!__builtin_is_within_lifetime(&y))171    return false;172  return true;173}174static_assert(test_indeterminate());175 176consteval bool test_volatile() {177  int x;178  if (!__builtin_is_within_lifetime(static_cast<volatile int*>(&x)) || !__builtin_is_within_lifetime(static_cast<volatile void*>(&x)))179    return false;180  volatile int y;181  if (!__builtin_is_within_lifetime(const_cast<int*>(&y)) || !__builtin_is_within_lifetime(const_cast<void*>(static_cast<volatile void*>(&y))))182    return false;183  return true;184}185static_assert(test_volatile());186 187constexpr 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}}193constexpr int external{};194static_assert(__builtin_is_within_lifetime(&external));195void not_constexpr() {196  __builtin_is_within_lifetime(&external);197}198void 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}}202 203  // FIXME: avoid function to pointer conversion on all consteval builtins204  __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}}216}217 218constexpr struct {219  union {220    int i;221    char c;222  };223  mutable int mi;  // #x-mi224} x1{ .c = 2 };225static_assert(!__builtin_is_within_lifetime(&x1.i));226static_assert(__builtin_is_within_lifetime(&x1.c));227static_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}}231 232constexpr struct NSDMI { // #NSDMI233  bool a = true;234  bool b = __builtin_is_within_lifetime(&a); // #NSDMI-read235} x2;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()'}}243 244struct X3 {245  consteval X3() {246    __builtin_is_within_lifetime(this); // #X3-read247  }248} x3;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()'}}252 253constexpr int i = 2;254static_assert(__builtin_is_within_lifetime(const_cast<int*>(&i)));255static_assert(__builtin_is_within_lifetime(const_cast<volatile int*>(&i)));256static_assert(__builtin_is_within_lifetime(static_cast<const void*>(&i)));257 258constexpr int arr[2]{};259static_assert(__builtin_is_within_lifetime(arr));260static_assert(__builtin_is_within_lifetime(arr + 0));261static_assert(__builtin_is_within_lifetime(arr + 1));262void f() {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}}269}270 271template<typename T>272consteval void disallow_function_types(bool b, const T* p) {273  if (b) {274    __builtin_is_within_lifetime(p); // expected-error {{function pointer argument to '__builtin_is_within_lifetime' is not allowed}}275  }276}277void g() {278  disallow_function_types<void ()>(false, &f);279  // expected-note@-1 {{in instantiation of function template specialization 'disallow_function_types<void ()>' requested here}}280}281 282struct OptBool {283  union { bool b; char c; };284 285  // note: this assumes common implementation properties for bool and char:286  // * sizeof(bool) == sizeof(char), and287  // * the value representations for true and false are distinct288  //   from the value representation for 2289  constexpr OptBool() : c(2) { }290  constexpr OptBool(bool b) : b(b) { }291 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 c295    } else {296      return c != 2;                        // during runtime, must read from c297    }298  }299 300  constexpr auto operator*() const -> const bool& {301    return b;302  }303};304 305constexpr OptBool disengaged;306constexpr OptBool engaged(true);307static_assert(!disengaged.has_value());308static_assert(engaged.has_value());309static_assert(*engaged);310 311namespace vlas {312 313consteval 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));316}317static_assert(f(1));318 319consteval 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'}}322}323static_assert(fail(1)); // sincecxx23-error {{static assertion expression is not an integral constant expression}}324 325consteval bool variably_modified(int n) {326  int(* p)[n];327  return __builtin_is_within_lifetime(&p);328}329static_assert(variably_modified(1));330 331} // namespace vlas332 333consteval bool partial_arrays() {334  int arr[2];335  if (!__builtin_is_within_lifetime(&arr) || !__builtin_is_within_lifetime(&arr[0]) || !__builtin_is_within_lifetime(&arr[1]))336    return false;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]))339    return false;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]))342    return false;343  return true;344}345static_assert(partial_arrays());346 347consteval bool partial_members() {348  struct S {349    int x;350    int y;351  } s;352  if (!__builtin_is_within_lifetime(&s) || !__builtin_is_within_lifetime(&s.x) || !__builtin_is_within_lifetime(&s.y))353    return false;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))356    return false;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))359    return false;360  return true;361}362 363struct NonTrivial {364  constexpr NonTrivial() {}365  constexpr NonTrivial(const NonTrivial&) {}366  constexpr ~NonTrivial() {}367};368 369template<typename T>370constexpr T& unmove(T&& temp) { return static_cast<T&>(temp); }371 372consteval 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)))376    return false;377  if (!__builtin_is_within_lifetime(&unmove(NonTrivial{})))378    return false;379  return true;380}381static_assert(test_temporaries());382 383constexpr const int& temp = 0;384static_assert(__builtin_is_within_lifetime(&temp));385 386template<typename T>387constexpr 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}}390}391static_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}}394static_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}}397 398template<auto F>399concept CanCallAndPassToIsWithinLifetime = std::bool_constant<__builtin_is_within_lifetime(F())>::value;400static_assert(CanCallAndPassToIsWithinLifetime<[]{ return &i; }>);401static_assert(!CanCallAndPassToIsWithinLifetime<[]{ return static_cast<int*>(nullptr); }>);402static_assert(!CanCallAndPassToIsWithinLifetime<[]{ return static_cast<void(*)()>(&f); }>);403template<auto F> constexpr std::true_type sfinae() requires CanCallAndPassToIsWithinLifetime<F> { return {}; }404template<auto F> std::false_type sfinae() { return {}; }405static_assert(decltype(sfinae<[]{ return &i; }>())::value);406static_assert(!decltype(sfinae<[]{ return static_cast<int*>(nullptr); }>())::value);407std::true_type(* not_immediate)() = &sfinae<[]{ return &i; }>;408 409void 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])'}}422}423struct XStd {424  consteval XStd() {425    std::is_within_lifetime(this); // #XStd-read426  }427} xstd;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()'}}432