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 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// Assume that STACK_SIZE defined implies a system that does not have a
16// large data space either, and additionally that we're not linking against
17// a shared libstdc++ (which requires quite a bit more initialization space).
18#ifdef STACK_SIZE
19const int arena_size = 256;
20#else
21#if defined(__FreeBSD__) || defined(__sun__) || defined(__hpux__)
22// FreeBSD, Solaris and HP-UX with threads require even more
23// space at initialization time.  FreeBSD 5 now requires over 131072 bytes.
24const int arena_size = 262144;
25#else
26const int arena_size = 32768;
27#endif
28#endif
29
30struct object
31{
32  size_t size __attribute__((aligned));
33};
34
35static char arena[arena_size] __attribute__((aligned));
36static size_t pos;
37
38// So we can force a failure when needed.
39static int fail;
40
41extern "C" void *malloc (size_t size)
42{
43  object *p = reinterpret_cast<object *>(&arena[pos]);
44
45  if (fail)
46    return 0;
47
48  p->size = size;
49  size = (size + __alignof__(object) - 1) & - __alignof__(object);
50  pos += size + sizeof(object);
51
52  // Verify that we didn't run out of memory before getting initialized.
53  if (pos > arena_size)
54    abort ();
55
56  return p + 1;
57}
58
59extern "C" void free (void *)
60{
61}
62
63extern "C" void *realloc (void *p, size_t size)
64{
65  void *r;
66
67  if (p)
68    {
69      object *o = reinterpret_cast<object *>(p) - 1;
70      size_t old_size = o->size;
71
72      if (old_size >= size)
73	{
74	  r = p;
75	  o->size = size;
76	}
77      else
78	{
79	  r = malloc (size);
80	  memcpy (r, p, old_size);
81	  free (p);
82	}
83    }
84  else
85    r = malloc (size);
86
87  return r;
88}
89
90void fn_throw() throw(int)
91{
92  throw 1;
93}
94
95void fn_rethrow() throw(int)
96{
97  try{fn_throw();}
98  catch(int a){
99    throw;}
100}
101
102void fn_catchthrow() throw(int)
103{
104  try{fn_throw();}
105  catch(int a){
106    throw a + 1;}
107}
108
109int main()
110{
111  /* On some systems (including FreeBSD and Solaris 2.10),
112     __cxa_get_globals will try to call "malloc" when threads are in
113     use.  Therefore, we throw one exception up front so that
114     __cxa_get_globals is all set up.  Ideally, this would not be
115     necessary, but it is a well-known idiom, and using this technique
116     means that we can still validate the fact that exceptions can be
117     thrown when malloc fails.  */
118  try{fn_throw();}
119  catch(int a){}
120
121  fail = 1;
122
123  try{fn_throw();}
124  catch(int a){}
125
126  try{fn_rethrow();}
127  catch(int a){}
128
129  try{fn_catchthrow();}
130  catch(int a){}
131
132  return 0;
133}
134