1/* { dg-do compile } */
2
3void *fastMalloc (int n);
4void fastFree (void *p);
5template <class T> struct C
6{
7  void deref () { delete static_cast <T *>(this); }
8};
9template <typename T>
10struct D
11{
12  D (T *ptr) : m_ptr (ptr) { }
13  ~D () { if (T * ptr = m_ptr) ptr->deref (); }
14  T *operator-> () const;
15  T *m_ptr;
16  typedef T *UnspecifiedBoolType;
17  operator UnspecifiedBoolType () const;
18};
19template <typename T> struct E
20{
21  static void destruct (T * begin, T * end)
22    {
23      for (T * cur = begin; cur != end; ++cur)
24	cur->~T ();
25    }
26};
27template <typename T> class F;
28template <typename T> struct G
29{
30  static void destruct (T * begin, T * end)
31    {
32      E <T>::destruct (begin, end);
33    }
34  static void uninitializedFill (T * dst, T * dstEnd, const T & val)
35    {
36      F<T>::uninitializedFill (dst, dstEnd, val);
37    }
38};
39template <typename T> struct H
40{
41  void allocateBuffer (int newCapacity)
42    {
43      m_buffer = static_cast <T *>(fastMalloc (newCapacity * sizeof (T)));
44    }
45  void deallocateBuffer (T * bufferToDeallocate)
46    {
47      if (m_buffer == bufferToDeallocate)
48	fastFree (bufferToDeallocate);
49    }
50  T *buffer () { }
51  int capacity () const { }
52  T *m_buffer;
53};
54template <typename T, int cap> class I;
55template <typename T> struct I <T, 0> : H <T>
56{
57  I (int capacity) { allocateBuffer (capacity); }
58  ~I () { this->deallocateBuffer (buffer ()); }
59  using H <T>::allocateBuffer;
60  H <T>::buffer; // { dg-warning "deprecated" }
61};
62template <typename T, int cap = 0> struct J
63{
64  typedef T *iterator;
65  ~J () { if (m_size) shrink (0); }
66  J (const J &);
67  int capacity () const { m_buffer.capacity (); }
68  T & operator[](int i) { }
69  iterator begin () { }
70  iterator end () { return begin () + m_size; }
71  void shrink (int size);
72  template <typename U> void append (const U &);
73  int m_size;
74  I <T, cap> m_buffer;
75};
76template <typename T, int cap>
77J <T, cap>::J (const J & other) : m_buffer (other.capacity ())
78{
79}
80template <typename T, int cap>
81void J <T, cap>::shrink (int size)
82{
83  G <T>::destruct (begin () + size, end ());
84  m_size = size;
85}
86struct A : public C <A>
87{
88  virtual ~A ();
89  typedef J <D <A> > B;
90  virtual A *firstChild () const;
91  virtual A *nextSibling () const;
92  virtual const B & children (int length);
93  B m_children;
94};
95const A::B &
96A::children (int length)
97{
98  for (D <A> obj = firstChild (); obj; obj = obj->nextSibling ())
99    {
100      B children = obj->children (2);
101      for (unsigned i = 0; i <length; ++i)
102	m_children.append (children[i]);
103    }
104}
105
106