1eefb6abc7699722024d757d7be96498ed4df16edDaniel Dunbar// RUN: %clangxx -emit-llvm -c -o - %s
296a2aaa2853850c2520614b6196b61daaf506ae2Sebastian Redl#include <stddef.h>
38ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor#include <stdlib.h>
48ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor#include <assert.h>
58ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
696a2aaa2853850c2520614b6196b61daaf506ae2Sebastian Redl// Placement new requires <new> to be included, but we don't support that yet.
796a2aaa2853850c2520614b6196b61daaf506ae2Sebastian Redlvoid* operator new(size_t, void* ptr) throw() {
896a2aaa2853850c2520614b6196b61daaf506ae2Sebastian Redl  return ptr;
996a2aaa2853850c2520614b6196b61daaf506ae2Sebastian Redl}
1096a2aaa2853850c2520614b6196b61daaf506ae2Sebastian Redlvoid operator delete(void*, void*) throw() {
1196a2aaa2853850c2520614b6196b61daaf506ae2Sebastian Redl}
1296a2aaa2853850c2520614b6196b61daaf506ae2Sebastian Redl
138ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregortemplate<typename T>
148ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregorclass dynarray {
15f390f634e50720c0b3324c4629212cdc744ba1feDouglas Gregorpublic:
168ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  dynarray() { Start = Last = End = 0; }
178ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
188ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  dynarray(const dynarray &other) {
198ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    Start = (T*)malloc(sizeof(T) * other.size());
208ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    Last = End = Start + other.size();
218ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
228ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    for (unsigned I = 0, N = other.size(); I != N; ++I)
2396a2aaa2853850c2520614b6196b61daaf506ae2Sebastian Redl      new (Start + I) T(other[I]);
248ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  }
258ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
268ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  ~dynarray() {
276ccc6f3f2044286d82ad46e726d4696c6673cfa8Douglas Gregor    for (unsigned I = 0, N = size(); I != N; ++I)
286ccc6f3f2044286d82ad46e726d4696c6673cfa8Douglas Gregor      Start[I].~T();
296ccc6f3f2044286d82ad46e726d4696c6673cfa8Douglas Gregor
308ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    free(Start);
318ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  }
328ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
338ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  dynarray &operator=(const dynarray &other) {
348ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    T* NewStart = (T*)malloc(sizeof(T) * other.size());
358ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
368ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    for (unsigned I = 0, N = other.size(); I != N; ++I)
37962ed0695d1083e26f79d99d6fc7aebc0ba4e70eAnders Carlsson      new (NewStart + I) T(other[I]);
3896a2aaa2853850c2520614b6196b61daaf506ae2Sebastian Redl
396ccc6f3f2044286d82ad46e726d4696c6673cfa8Douglas Gregor    for (unsigned I = 0, N = size(); I != N; ++I)
406ccc6f3f2044286d82ad46e726d4696c6673cfa8Douglas Gregor      Start[I].~T();
416ccc6f3f2044286d82ad46e726d4696c6673cfa8Douglas Gregor
428ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    free(Start);
438ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    Start = NewStart;
448ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    Last = End = NewStart + other.size();
458ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    return *this;
468ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  }
478ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
488ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  unsigned size() const { return Last - Start; }
498ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  unsigned capacity() const { return End - Start; }
508ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
510ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor  void push_back(const T& value);
520ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor
538ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  void pop_back() {
548ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    --Last;
556ccc6f3f2044286d82ad46e726d4696c6673cfa8Douglas Gregor    Last->~T();
568ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  }
578ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
588ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  T& operator[](unsigned Idx) {
598ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    return Start[Idx];
608ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  }
618ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
628ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  const T& operator[](unsigned Idx) const {
638ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    return Start[Idx];
648ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  }
658ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
668ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  typedef T* iterator;
678ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  typedef const T* const_iterator;
688ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
69f97986dce99ea113744872de1d2a6d2da274061bDouglas Gregor  iterator begin() { return Start; }
70f97986dce99ea113744872de1d2a6d2da274061bDouglas Gregor  const_iterator begin() const { return Start; }
718ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
72f97986dce99ea113744872de1d2a6d2da274061bDouglas Gregor  iterator end() { return Last; }
73f97986dce99ea113744872de1d2a6d2da274061bDouglas Gregor  const_iterator end() const { return Last; }
748ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
75cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor  bool operator==(const dynarray &other) const {
76cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor    if (size() != other.size())
77cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor      return false;
78cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor
79cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor    for (unsigned I = 0, N = size(); I != N; ++I)
80cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor      if ((*this)[I] != other[I])
81cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor        return false;
82cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor
83cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor    return true;
84cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor  }
85cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor
86cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor  bool operator!=(const dynarray &other) const {
87cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor    return !(*this == other);
88cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor  }
89cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor
908ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregorpublic:
918ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  T* Start, *Last, *End;
928ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor};
938ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
940ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregortemplate<typename T>
950ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregorvoid dynarray<T>::push_back(const T& value) {
960ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor  if (Last == End) {
970ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor    unsigned NewCapacity = capacity() * 2;
980ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor    if (NewCapacity == 0)
990ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor      NewCapacity = 4;
1000ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor
1010ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor    T* NewStart = (T*)malloc(sizeof(T) * NewCapacity);
1020ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor
1030ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor    unsigned Size = size();
1040ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor    for (unsigned I = 0; I != Size; ++I)
1050ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor      new (NewStart + I) T(Start[I]);
1060ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor
1076ccc6f3f2044286d82ad46e726d4696c6673cfa8Douglas Gregor    for (unsigned I = 0, N = size(); I != N; ++I)
1086ccc6f3f2044286d82ad46e726d4696c6673cfa8Douglas Gregor      Start[I].~T();
1090ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor    free(Start);
1100ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor
1110ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor    Start = NewStart;
1120ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor    Last = Start + Size;
1130ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor    End = Start + NewCapacity;
1140ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor  }
1150ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor
1160ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor  new (Last) T(value);
1170ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor  ++Last;
1180ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor}
1190ce8515575703c71af6b9efe0a43bc518e1fe803Douglas Gregor
1208ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregorstruct Point {
1218ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  Point() { x = y = z = 0.0; }
1228ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  Point(const Point& other) : x(other.x), y(other.y), z(other.z) { }
1238ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
1248ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  float x, y, z;
1258ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor};
1268ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
1278ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregorint main() {
1288ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  dynarray<int> di;
1298ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  di.push_back(0);
1308ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  di.push_back(1);
1318ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  di.push_back(2);
1328ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  di.push_back(3);
1338ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  di.push_back(4);
1348ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  assert(di.size() == 5);
1358ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  for (dynarray<int>::iterator I = di.begin(), IEnd = di.end(); I != IEnd; ++I)
1368ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    assert(*I == I - di.begin());
1378ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
138f97986dce99ea113744872de1d2a6d2da274061bDouglas Gregor  for (int I = 0, N = di.size(); I != N; ++I)
139f97986dce99ea113744872de1d2a6d2da274061bDouglas Gregor    assert(di[I] == I);
140f97986dce99ea113744872de1d2a6d2da274061bDouglas Gregor
1418ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  di.pop_back();
1428ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  assert(di.size() == 4);
1438ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  di.push_back(4);
1448ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
1458ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  dynarray<int> di2 = di;
1468ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  assert(di2.size() == 5);
1478ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  assert(di.begin() != di2.begin());
1488ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  for (dynarray<int>::iterator I = di2.begin(), IEnd = di2.end();
1498ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor       I != IEnd; ++I)
1508ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    assert(*I == I - di2.begin());
1518ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
1528ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  dynarray<int> di3(di);
1538ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  assert(di3.size() == 5);
1548ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  assert(di.begin() != di3.begin());
1558ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  for (dynarray<int>::iterator I = di3.begin(), IEnd = di3.end();
1568ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor       I != IEnd; ++I)
1578ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    assert(*I == I - di3.begin());
1588ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
1598ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  dynarray<int> di4;
1608ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  assert(di4.size() == 0);
1618ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  di4 = di;
1628ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  assert(di4.size() == 5);
1638ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  assert(di.begin() != di4.begin());
1648ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  for (dynarray<int>::iterator I = di4.begin(), IEnd = di4.end();
1658ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor       I != IEnd; ++I)
1668ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor    assert(*I == I - di4.begin());
1678ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor
168cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor  assert(di4 == di);
169cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor  di4[3] = 17;
170cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor  assert(di4 != di);
171cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor
172cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor  dynarray<Point> dp;
173cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor  dp.push_back(Point());
174cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor  assert(dp.size() == 1);
175cad27f643ec41875c51d5ac860abf766f0a33675Douglas Gregor
1768ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor  return 0;
1778ab892a09e1955353db19620b1a6dbadb74877fbDouglas Gregor}
178