aboutsummaryrefslogtreecommitdiff
path: root/clang/test/AST/ByteCode/lifetimes26.cpp
blob: c3163f8a562bfac79918d2d71d57a4dd134a39f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// RUN: %clang_cc1 -verify=expected,both -std=c++26 %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -verify=ref,both      -std=c++26 %s

// both-no-diagnostics

namespace std {
  struct type_info;
  struct destroying_delete_t {
    explicit destroying_delete_t() = default;
  } inline constexpr destroying_delete{};
  struct nothrow_t {
    explicit nothrow_t() = default;
  } inline constexpr nothrow{};
  using size_t = decltype(sizeof(0));
  enum class align_val_t : size_t {};
};

constexpr void *operator new(std::size_t, void *p) { return p; }
namespace std {
  template<typename T> constexpr T *construct_at(T *p) { return new (p) T; }
  template<typename T> constexpr void destroy_at(T *p) { p->~T(); }
}

constexpr bool foo() {
  using T = bool;
  bool b = true;
  b.~T();
  new (&b) bool(false);
  return b;
}
static_assert(!foo());

struct S {};
constexpr bool foo2() {
  S s;
  s.~S();
  new (&s) S{};
  return true;
}
static_assert(foo2());

constexpr void destroy_pointer() {
  using T = int*;
  T p;
  p.~T();
  std::construct_at(&p);
}
static_assert((destroy_pointer(), true));


namespace DestroyArrayElem {
  /// This is proof that std::destroy_at'ing an array element
  /// ends the lifetime of the entire array.
  /// See https://github.com/llvm/llvm-project/issues/147528
  /// Using destroy_at on array elements is currently a no-op due to this.
  constexpr int test() {
    int a[4] = {};

    std::destroy_at(&a[3]);
    int r = a[1];
    std::construct_at(&a[3]);

    return r;
  }
  static_assert(test() == 0);
}