1// RUN: %clangxx -emit-llvm -c -o - %s
2#include <stddef.h>
3#include <stdlib.h>
4#include <assert.h>
5
6// Placement new requires <new> to be included, but we don't support that yet.
7void* operator new(size_t, void* ptr) throw() {
8  return ptr;
9}
10void operator delete(void*, void*) throw() {
11}
12
13template<typename T>
14class dynarray {
15public:
16  dynarray() { Start = Last = End = 0; }
17
18  dynarray(const dynarray &other) {
19    Start = (T*)malloc(sizeof(T) * other.size());
20    Last = End = Start + other.size();
21
22    for (unsigned I = 0, N = other.size(); I != N; ++I)
23      new (Start + I) T(other[I]);
24  }
25
26  ~dynarray() {
27    for (unsigned I = 0, N = size(); I != N; ++I)
28      Start[I].~T();
29
30    free(Start);
31  }
32
33  dynarray &operator=(const dynarray &other) {
34    T* NewStart = (T*)malloc(sizeof(T) * other.size());
35
36    for (unsigned I = 0, N = other.size(); I != N; ++I)
37      new (NewStart + I) T(other[I]);
38
39    for (unsigned I = 0, N = size(); I != N; ++I)
40      Start[I].~T();
41
42    free(Start);
43    Start = NewStart;
44    Last = End = NewStart + other.size();
45    return *this;
46  }
47
48  unsigned size() const { return Last - Start; }
49  unsigned capacity() const { return End - Start; }
50
51  void push_back(const T& value);
52
53  void pop_back() {
54    --Last;
55    Last->~T();
56  }
57
58  T& operator[](unsigned Idx) {
59    return Start[Idx];
60  }
61
62  const T& operator[](unsigned Idx) const {
63    return Start[Idx];
64  }
65
66  typedef T* iterator;
67  typedef const T* const_iterator;
68
69  iterator begin() { return Start; }
70  const_iterator begin() const { return Start; }
71
72  iterator end() { return Last; }
73  const_iterator end() const { return Last; }
74
75  bool operator==(const dynarray &other) const {
76    if (size() != other.size())
77      return false;
78
79    for (unsigned I = 0, N = size(); I != N; ++I)
80      if ((*this)[I] != other[I])
81        return false;
82
83    return true;
84  }
85
86  bool operator!=(const dynarray &other) const {
87    return !(*this == other);
88  }
89
90public:
91  T* Start, *Last, *End;
92};
93
94template<typename T>
95void dynarray<T>::push_back(const T& value) {
96  if (Last == End) {
97    unsigned NewCapacity = capacity() * 2;
98    if (NewCapacity == 0)
99      NewCapacity = 4;
100
101    T* NewStart = (T*)malloc(sizeof(T) * NewCapacity);
102
103    unsigned Size = size();
104    for (unsigned I = 0; I != Size; ++I)
105      new (NewStart + I) T(Start[I]);
106
107    for (unsigned I = 0, N = size(); I != N; ++I)
108      Start[I].~T();
109    free(Start);
110
111    Start = NewStart;
112    Last = Start + Size;
113    End = Start + NewCapacity;
114  }
115
116  new (Last) T(value);
117  ++Last;
118}
119
120struct Point {
121  Point() { x = y = z = 0.0; }
122  Point(const Point& other) : x(other.x), y(other.y), z(other.z) { }
123
124  float x, y, z;
125};
126
127int main() {
128  dynarray<int> di;
129  di.push_back(0);
130  di.push_back(1);
131  di.push_back(2);
132  di.push_back(3);
133  di.push_back(4);
134  assert(di.size() == 5);
135  for (dynarray<int>::iterator I = di.begin(), IEnd = di.end(); I != IEnd; ++I)
136    assert(*I == I - di.begin());
137
138  for (int I = 0, N = di.size(); I != N; ++I)
139    assert(di[I] == I);
140
141  di.pop_back();
142  assert(di.size() == 4);
143  di.push_back(4);
144
145  dynarray<int> di2 = di;
146  assert(di2.size() == 5);
147  assert(di.begin() != di2.begin());
148  for (dynarray<int>::iterator I = di2.begin(), IEnd = di2.end();
149       I != IEnd; ++I)
150    assert(*I == I - di2.begin());
151
152  dynarray<int> di3(di);
153  assert(di3.size() == 5);
154  assert(di.begin() != di3.begin());
155  for (dynarray<int>::iterator I = di3.begin(), IEnd = di3.end();
156       I != IEnd; ++I)
157    assert(*I == I - di3.begin());
158
159  dynarray<int> di4;
160  assert(di4.size() == 0);
161  di4 = di;
162  assert(di4.size() == 5);
163  assert(di.begin() != di4.begin());
164  for (dynarray<int>::iterator I = di4.begin(), IEnd = di4.end();
165       I != IEnd; ++I)
166    assert(*I == I - di4.begin());
167
168  assert(di4 == di);
169  di4[3] = 17;
170  assert(di4 != di);
171
172  dynarray<Point> dp;
173  dp.push_back(Point());
174  assert(dp.size() == 1);
175
176  return 0;
177}
178