1// This fails for VxWorks RTPs because the initialization of
2// __cxa_allocate_exception's emergency buffer mutex will
3// itself call malloc(), and will fail if there is no more
4// memory available.
5// { dg-do run { xfail { { xstormy16-*-* *-*-darwin[3-7]* } || vxworks_rtp } } }
6// Copyright (C) 2000, 2002, 2003, 2010, 2012, 2014 Free Software Foundation, Inc.
7// Contributed by Nathan Sidwell 6 June 2000 <nathan@codesourcery.com>
8
9// Check we can throw a bad_alloc exception when malloc dies.
10
11typedef __SIZE_TYPE__ size_t;
12extern "C" void abort();
13extern "C" void *memcpy(void *, const void *, size_t);
14
15// libstdc++ requires a large initialization time allocation for the
16// emergency EH allocation pool.  Add that to the arena size.
17
18// Assume that STACK_SIZE defined implies a system that does not have a
19// large data space either, and additionally that we're not linking against
20// a shared libstdc++ (which requires quite a bit more initialization space).
21#ifdef STACK_SIZE
22const int arena_size = 256 + 8 * 128;
23#else
24#if defined(__FreeBSD__) || defined(__sun__) || defined(__hpux__)
25// FreeBSD, Solaris and HP-UX require even more space at initialization time.
26// FreeBSD 5 now requires over 131072 bytes.
27const int arena_size = 262144 + 72 * 1024;
28#else
29// Because pointers make up the bulk of our exception-initialization
30// allocations, we scale by the pointer size from the original
31// 32-bit-systems-based estimate.
32const int arena_size = 32768 * ((sizeof (void *) + 3)/4) + 72 * 1024;
33#endif
34#endif
35
36struct object
37{
38  size_t size __attribute__((aligned));
39};
40
41static char arena[arena_size] __attribute__((aligned));
42static size_t pos;
43
44// So we can force a failure when needed.
45static int fail;
46
47extern "C" void *malloc (size_t size)
48{
49  object *p = reinterpret_cast<object *>(&arena[pos]);
50
51  if (fail)
52    return 0;
53
54  p->size = size;
55  size = (size + __alignof__(object) - 1) & - __alignof__(object);
56  pos += size + sizeof(object);
57
58  // Verify that we didn't run out of memory before getting initialized.
59  if (pos > arena_size)
60    abort ();
61
62  return p + 1;
63}
64
65extern "C" void free (void *)
66{
67}
68
69extern "C" void *realloc (void *p, size_t size)
70{
71  void *r;
72
73  if (p)
74    {
75      object *o = reinterpret_cast<object *>(p) - 1;
76      size_t old_size = o->size;
77
78      if (old_size >= size)
79	{
80	  r = p;
81	  o->size = size;
82	}
83      else
84	{
85	  r = malloc (size);
86	  memcpy (r, p, old_size);
87	  free (p);
88	}
89    }
90  else
91    r = malloc (size);
92
93  return r;
94}
95
96void fn_throw() throw(int)
97{
98  throw 1;
99}
100
101void fn_rethrow() throw(int)
102{
103  try{fn_throw();}
104  catch(int a){
105    throw;}
106}
107
108void fn_catchthrow() throw(int)
109{
110  try{fn_throw();}
111  catch(int a){
112    throw a + 1;}
113}
114
115int main()
116{
117  /* On some systems (including FreeBSD and Solaris 2.10),
118     __cxa_get_globals will try to call "malloc" when threads are in
119     use.  Therefore, we throw one exception up front so that
120     __cxa_get_globals is all set up.  Ideally, this would not be
121     necessary, but it is a well-known idiom, and using this technique
122     means that we can still validate the fact that exceptions can be
123     thrown when malloc fails.  */
124  try{fn_throw();}
125  catch(int a){}
126
127  fail = 1;
128
129  try{fn_throw();}
130  catch(int a){}
131
132  try{fn_rethrow();}
133  catch(int a){}
134
135  try{fn_catchthrow();}
136  catch(int a){}
137
138  return 0;
139}
140