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)10void* 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)18void 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)26void 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)35void 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)53void 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> fY74struct Y { int i; virtual void f () {}; }; 75 76 // A class with a non-trivial destructor -- it needs a cookie. ~ZZ77struct Z { ~Z () {}; }; 78 // Likewise, but this class needs a bigger cookie so that the array 79 // elements are correctly aligned. ~Z2Z280struct 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()94int 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()125int main () 126 { 127 } 128 129 #endif /* !(defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100) */ 130