1 // Origin: Mark Mitchell <mark@codesourcery.com>
2 
3 #if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
4 
5 #include <cstdlib>
6 #include <new>
7 
8 void* p;
9 
throw(std::bad_alloc)10 void* operator new[](size_t s) throw (std::bad_alloc)
11 {
12   // Record the base of the last array allocated.
13   p = malloc (s);
14   return p;
15 }
16 
17 template <typename T>
check_no_cookie(int i)18 void check_no_cookie (int i)
19 {
20   void* a = new T[7];
21   if (p != a)
22     exit (i);
23 }
24 
25 template <typename T>
check_no_placement_cookie(int i)26 void check_no_placement_cookie (int i)
27 {
28   p = malloc (13 * sizeof (T));
29   void* a = new (p) T[13];
30   if (p != a)
31     exit (i);
32 }
33 
34 template <typename T>
check_cookie(int i)35 void check_cookie (int i)
36 {
37   void* a = new T[11];
38 
39   // Compute the cookie location manually.
40   size_t x = __alignof__ (T);
41   if (x < sizeof (size_t))
42     x = sizeof (size_t);
43   if ((char *) a - x != (char *) p)
44     exit (i);
45 
46   // Check the cookie value.
47   size_t *sp = ((size_t *) a) - 1;
48   if (*sp != 11)
49     exit (i);
50 }
51 
52 template <typename T>
check_placement_cookie(int i)53 void check_placement_cookie (int i)
54 {
55   p = malloc (sizeof (T) * 11 + 100);
56   void* a = new (p) T[11];
57 
58   // Compute the cookie location manually.
59   size_t x = __alignof__ (T);
60   if (x < sizeof (size_t))
61     x = sizeof (size_t);
62   if ((char *) a - x != (char *) p)
63     exit (i);
64 
65   // Check the cookie value.
66   size_t *sp = ((size_t *) a) - 1;
67   if (*sp != 11)
68     exit (i);
69 }
70 
71 struct X {};
72 
73 template <typename T>
fY74 struct Y { int i; virtual void f () {}; };
75 
76 // A class with a non-trivial destructor -- it needs a cookie.
~ZZ77 struct Z { ~Z () {}; };
78 // Likewise, but this class needs a bigger cookie so that the array
79 // elements are correctly aligned.
~Z2Z280 struct Z2 { ~Z2 () {}; long double d; };
81 
82 struct W1 { void operator delete[] (void *, size_t) {}; };
83 struct W2 { void operator delete[] (void *) {};
84             void operator delete[] (void *, size_t) {}; };
85 struct W3 { void operator delete[] (void *, size_t) {};
86             void operator delete[] (void *) {}; };
87 struct W4 : public W1 {};
88 
89 struct V { void *operator new[] (size_t s, void *p)
90              { return p; }
~VV91            ~V () {}
92          };
93 
main()94 int main ()
95 {
96   // There should be no cookies for types with trivial destructors.
97   check_no_cookie<int> (1);
98   check_no_cookie<X> (2);
99   check_no_cookie<Y<double> > (3);
100 
101   // There should be no cookies for allocations using global placement
102   // new.
103   check_no_placement_cookie<int> (4);
104   check_no_placement_cookie<X> (5);
105   check_no_placement_cookie<Z> (6);
106 
107   // There should be a cookie when using a non-trivial destructor.
108   check_cookie<Z> (7);
109   check_cookie<Z2> (8);
110 
111   // There should be a cookie when using the two-argument array delete
112   // operator.
113   check_cookie<W1> (9);
114   check_cookie<W4> (10);
115   // But not when the one-argument version is also available.
116   check_no_cookie<W2> (11);
117   check_no_cookie<W3> (12);
118 
119   // There should be a cookie when using a non-global placement new.
120   check_placement_cookie<V> (13);
121 }
122 
123 #else /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
124 
main()125 int main ()
126 {
127 }
128 
129 #endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */
130