File: op_subscript.runtime.pass.cpp

package info (click to toggle)
llvm-toolchain-20 1%3A20.1.6-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 2,111,304 kB
  • sloc: cpp: 7,438,677; ansic: 1,393,822; asm: 1,012,926; python: 241,650; f90: 86,635; objc: 75,479; lisp: 42,144; pascal: 17,286; sh: 10,027; ml: 5,082; perl: 4,730; awk: 3,523; makefile: 3,349; javascript: 2,251; xml: 892; fortran: 672
file content (161 lines) | stat: -rw-r--r-- 4,388 bytes parent folder | download | duplicates (6)
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// <memory>

// unique_ptr

// T& unique_ptr::operator[](size_t) const

#include <memory>
#include <cassert>
#include <type_traits>
#include <array>

#include "test_macros.h"
#include "type_algorithms.h"

static int next = 0;
struct EnumeratedDefaultCtor {
  EnumeratedDefaultCtor() : value(0) { value = ++next; }
  int value;
};

template <std::size_t Size>
struct WithTrivialDtor {
  std::array<char, Size> padding = {'x'};
  TEST_CONSTEXPR_CXX23 friend bool operator==(WithTrivialDtor const& x, WithTrivialDtor const& y) {
    return x.padding == y.padding;
  }
};

template <std::size_t Size>
struct WithNonTrivialDtor {
  std::array<char, Size> padding = {'x'};
  TEST_CONSTEXPR_CXX23 friend bool operator==(WithNonTrivialDtor const& x, WithNonTrivialDtor const& y) {
    return x.padding == y.padding;
  }
  TEST_CONSTEXPR_CXX23 ~WithNonTrivialDtor() {}
};

template <class T>
struct CustomDeleter : std::default_delete<T> {};

struct NoopDeleter {
  template <class T>
  TEST_CONSTEXPR_CXX23 void operator()(T*) const {}
};

TEST_CONSTEXPR_CXX23 bool test() {
  // Basic test
  {
    std::unique_ptr<int[]> p(new int[3]);
    {
      int& result = p[0];
      result      = 0;
    }
    {
      int& result = p[1];
      result      = 1;
    }
    {
      int& result = p[2];
      result      = 2;
    }

    assert(p[0] == 0);
    assert(p[1] == 1);
    assert(p[2] == 2);
  }

  // Ensure that the order of access is correct after initializing a unique_ptr but
  // before actually modifying any of its elements. The implementation would have to
  // really try for this not to be the case, but we still check it.
  //
  // This requires assigning known values to the elements when they are first constructed,
  // which requires global state.
  {
    if (!TEST_IS_CONSTANT_EVALUATED) {
      std::unique_ptr<EnumeratedDefaultCtor[]> p(new EnumeratedDefaultCtor[3]);
      assert(p[0].value == 1);
      assert(p[1].value == 2);
      assert(p[2].value == 3);
    }
  }

  // Make sure operator[] is const-qualified
  {
    std::unique_ptr<int[]> const p(new int[3]);
    p[0] = 42;
    assert(p[0] == 42);
  }

  // Make sure we properly handle types with trivial and non-trivial destructors of different
  // sizes. This is relevant because some implementations may want to use properties of the
  // ABI like array cookies and these properties often depend on e.g. the triviality of T's
  // destructor, T's size and so on.
#if TEST_STD_VER >= 20 // this test is too painful to write before C++20
  {
    using TrickyCookieTypes = types::type_list<
        WithTrivialDtor<1>,
        WithTrivialDtor<2>,
        WithTrivialDtor<3>,
        WithTrivialDtor<4>,
        WithTrivialDtor<8>,
        WithTrivialDtor<16>,
        WithTrivialDtor<256>,
        WithNonTrivialDtor<1>,
        WithNonTrivialDtor<2>,
        WithNonTrivialDtor<3>,
        WithNonTrivialDtor<4>,
        WithNonTrivialDtor<8>,
        WithNonTrivialDtor<16>,
        WithNonTrivialDtor<256>>;
    types::for_each(TrickyCookieTypes(), []<class T> {
      // Array allocated with `new T[n]`, default deleter
      {
        std::unique_ptr<T[], std::default_delete<T[]>> p(new T[3]);
        assert(p[0] == T());
        assert(p[1] == T());
        assert(p[2] == T());
      }

      // Array allocated with `new T[n]`, custom deleter
      {
        std::unique_ptr<T[], CustomDeleter<T[]>> p(new T[3]);
        assert(p[0] == T());
        assert(p[1] == T());
        assert(p[2] == T());
      }

      // Array not allocated with `new T[n]`, custom deleter
      //
      // This test aims to ensure that the implementation doesn't try to use an array cookie
      // when there is none.
      {
        T array[50] = {};
        std::unique_ptr<T[], NoopDeleter> p(&array[0]);
        assert(p[0] == T());
        assert(p[1] == T());
        assert(p[2] == T());
      }
    });
  }
#endif // C++20

  return true;
}

int main(int, char**) {
  test();
#if TEST_STD_VER >= 23
  static_assert(test());
#endif

  return 0;
}