]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/libsupc++/exception_support.cc
java-tree.h (throw_node): Define as a single member of java_global_trees instead...
[thirdparty/gcc.git] / libstdc++-v3 / libsupc++ / exception_support.cc
CommitLineData
0a8c4c0c 1// Functions for Exception Support for -*- C++ -*-
d34786e3 2
e2c09482
BK
3// Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
4// Free Software Foundation
5//
0a8c4c0c 6// This file is part of GNU CC.
e2c09482 7//
0a8c4c0c
BK
8// GNU CC is free software; you can redistribute it and/or modify
9// it under the terms of the GNU General Public License as published by
10// the Free Software Foundation; either version 2, or (at your option)
11// any later version.
12
13// GNU CC is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17
18// You should have received a copy of the GNU General Public License
19// along with GNU CC; see the file COPYING. If not, write to
20// the Free Software Foundation, 59 Temple Place - Suite 330,
21// Boston, MA 02111-1307, USA.
22
23// As a special exception, you may use this file as part of a free software
24// library without restriction. Specifically, if other files instantiate
25// templates or use macros or inline functions from this file, or you compile
26// this file and link it with other files to produce an executable, this
27// file does not by itself cause the resulting executable to be covered by
28// the GNU General Public License. This exception does not however
29// invalidate any other reasons why the executable file might be covered by
30// the GNU General Public License.
31
0a8c4c0c
BK
32#include "typeinfo"
33#include "exception"
6b76f569 34#include <cstddef>
f1f0c5a2 35#include "exception_support.h"
e2c09482 36#include "exception_defines.h"
0a8c4c0c
BK
37
38/* Define terminate, unexpected, set_terminate, set_unexpected as
39 well as the default terminate func and default unexpected func. */
40
17fd8a87
CD
41/* __terminate and __terminate_set_func, defined in libgcc2. */
42typedef void (*__terminate_func_ptr)(void) __attribute__ ((__noreturn__));
43extern "C" void __terminate (void) __attribute__ ((__noreturn__));
44extern "C" __terminate_func_ptr __terminate_set_func (__terminate_func_ptr);
45
0a8c4c0c
BK
46using std::terminate;
47
48void
49std::terminate ()
50{
17fd8a87 51 __terminate ();
0a8c4c0c
BK
52}
53
54void
55__default_unexpected ()
56{
57 terminate ();
58}
59
60static std::unexpected_handler __unexpected_func __attribute__((__noreturn__))
61 = __default_unexpected;
62
63std::terminate_handler
d34786e3 64std::set_terminate (std::terminate_handler func) throw()
0a8c4c0c 65{
17fd8a87 66 return __terminate_set_func (func);
0a8c4c0c
BK
67}
68
69std::unexpected_handler
d34786e3 70std::set_unexpected (std::unexpected_handler func) throw()
0a8c4c0c
BK
71{
72 std::unexpected_handler old = __unexpected_func;
73
74 __unexpected_func = func;
75 return old;
76}
77
78void
79std::unexpected ()
80{
81 __unexpected_func ();
82}
83
0a8c4c0c 84/* Language-specific EH info pointer, defined in libgcc2. */
0a8c4c0c 85extern "C" cp_eh_info **__get_eh_info (); // actually void **
e2c09482 86#define CP_EH_INFO ((cp_eh_info *) *__get_eh_info ())
0a8c4c0c
BK
87
88/* Exception allocate and free, defined in libgcc2. */
6b76f569 89extern "C" void *__eh_alloc(std::size_t);
0a8c4c0c
BK
90extern "C" void __eh_free(void *);
91
92/* Is P the type_info node for a pointer of some kind? */
0a8c4c0c
BK
93extern bool __is_pointer (void *);
94
95
e2c09482 96#ifdef __EXCEPTIONS
0a8c4c0c
BK
97/* OLD Compiler hook to return a pointer to the info for the current exception.
98 Used by get_eh_info (). This fudges the actualy returned value to
99 point to the beginning of what USE to be the cp_eh_info structure.
100 THis is so that old code that dereferences this pointer will find
101 things where it expects it to be.*/
102extern "C" void *
103__cp_exception_info (void)
104{
105 return &((*__get_eh_info ())->value);
106}
107
0a8c4c0c
BK
108/* Old Compiler hook to return a pointer to the info for the current exception.
109 Used by get_eh_info (). */
110
111extern "C" cp_eh_info *
112__cp_eh_info (void)
113{
114 cp_eh_info *p = CP_EH_INFO;
115 return p;
116}
117
118/* Compiler hook to return a pointer to the info for the current exception,
119 Set the caught bit, and increment the number of handlers that are
120 looking at this exception. This makes handlers smaller. */
121
122extern "C" cp_eh_info *
123__start_cp_handler (void)
124{
125 cp_eh_info *p = CP_EH_INFO;
126 p->caught = 1;
127 p->handlers++;
128 return p;
129}
130
131extern "C" int __throw_type_match_rtti_2 (const void *, const void *,
132 void *, void **);
133
134extern "C" void *
135__cplus_type_matcher (__eh_info *info_, void *match_info,
136 exception_descriptor *exception_table)
137{
138 cp_eh_info *info = (cp_eh_info *)info_;
139
140 /* No exception table implies the old style mechanism, so don't check. */
141 if (exception_table != NULL
142 && exception_table->lang.language != EH_LANG_C_plus_plus)
143 return NULL;
144
145 if (match_info == CATCH_ALL_TYPE)
146 return (void *)1;
147
148 /* we don't worry about version info yet, there is only one version! */
149
150 void *match_type = match_info;
151
0a8c4c0c
BK
152 if (__throw_type_match_rtti_2 (match_type, info->type,
153 info->original_value, &info->value))
154 // Arbitrary non-null pointer.
155 return (void *)1;
156 else
157 return NULL;
158}
159
160/* Compiler hook to push a new exception onto the stack.
161 Used by expand_throw(). */
162
163extern "C" void
164__cp_push_exception (void *value, void *type, cleanup_fn cleanup)
165{
166 cp_eh_info *p = (cp_eh_info *) __eh_alloc (sizeof (cp_eh_info));
167
168 p->value = value;
169 p->type = type;
170 p->cleanup = cleanup;
171 p->handlers = 0;
172 p->caught = false;
173 p->original_value = value;
174
175 p->eh_info.match_function = __cplus_type_matcher;
176 p->eh_info.language = EH_LANG_C_plus_plus;
177 p->eh_info.version = 1;
178
179 cp_eh_info **q = __get_eh_info ();
180
181 p->next = *q;
182 *q = p;
183}
184
185/* Compiler hook to pop an exception that has been finalized. Used by
186 push_eh_cleanup(). P is the info for the exception caught by the
187 current catch block. */
188
189extern "C" void
96070989 190__cp_pop_exception (void* p_)
0a8c4c0c 191{
96070989 192 cp_eh_info *p = static_cast <cp_eh_info *> (p_);
0a8c4c0c
BK
193 cp_eh_info **stack = __get_eh_info ();
194 cp_eh_info **q = stack;
195
196 --p->handlers;
197
198 /* Do nothing if our exception is being rethrown (i.e. if the active
199 exception is our exception and it is uncaught). */
200 if (p == *q && !p->caught)
201 return;
202
203 /* Don't really pop if there are still active handlers for our exception;
204 rather, push it down past any uncaught exceptions. */
205 if (p->handlers != 0)
206 {
207 if (p == *q && p->next && !p->next->caught)
208 {
209 q = &(p->next);
210 while (1)
211 {
212 if (*q == 0 || (*q)->caught)
213 break;
214
215 q = &((*q)->next);
216 }
217 *stack = p->next;
218 p->next = *q;
219 *q = p;
220 }
221 return;
222 }
223
224 for (; *q; q = &((*q)->next))
225 if (*q == p)
226 break;
227
228 if (! *q)
229 terminate ();
230
231 *q = p->next;
232
233 if (p->cleanup)
234 // value may have been adjusted.
235 CALL_CLEANUP (p->cleanup, p->original_value);
236
237 if (! __is_pointer (p->type))
238 __eh_free (p->original_value); // value may have been adjusted.
239
240 __eh_free (p);
241}
242
243/* We're doing a rethrow. Find the currently handled exception, mark it
244 uncaught, and move it to the top of the EH stack. */
245
f1f0c5a2 246extern "C" cp_eh_info *
0a8c4c0c
BK
247__uncatch_exception (void)
248{
249 cp_eh_info **stack = __get_eh_info ();
250 cp_eh_info **q = stack;
251 cp_eh_info *p;
252
253 while (1)
254 {
255 p = *q;
256
257 if (p == 0)
258 terminate ();
259 if (p->caught)
260 break;
261
262 q = &(p->next);
263 }
264
265 if (q != stack)
266 {
267 *q = p->next;
268 p->next = *stack;
269 *stack = p;
270 }
271
272 p->caught = false;
f1f0c5a2
MM
273
274 return p;
275}
276
277/* Mark P as caught after we previously marked it as uncaught. */
278
279extern "C" void
280__recatch_exception (cp_eh_info *p)
281{
282 p->caught = true;
0a8c4c0c
BK
283}
284
285/* As per [except.unexpected]:
286 If an exception is thrown, we check it against the spec. If it doesn't
287 match, we call unexpected (). If unexpected () throws, we check that
288 exception against the spec. If it doesn't match, if the spec allows
289 bad_exception we throw that; otherwise we call terminate ().
290
291 The compiler treats an exception spec as a try block with a generic
292 handler that just calls this function with a list of the allowed
293 exception types, so we have an active exception that can be rethrown.
294
295 This function does not return. */
296
297extern "C" void
298__check_eh_spec (int n, const void **spec)
299{
300 cp_eh_info *p = CP_EH_INFO;
301 void *d;
302
303 for (int i = 0; i < n; ++i)
304 {
305 if (__throw_type_match_rtti_2 (spec[i], p->type, p->value, &d))
306 throw;
307 }
308
309 try
310 {
311 std::unexpected ();
312 }
313 catch (...)
314 {
315 // __exception_info is an artificial var pushed into each catch block.
316 if (p != __exception_info)
317 {
318 p = __exception_info;
319 for (int i = 0; i < n; ++i)
320 {
321 if (__throw_type_match_rtti_2 (spec[i], p->type, p->value, &d))
322 throw;
323 }
324 }
325
326 const std::type_info &bad_exc = typeid (std::bad_exception);
327 for (int i = 0; i < n; ++i)
328 {
329 if (__throw_type_match_rtti_2 (spec[i], &bad_exc, p->value, &d))
330 throw std::bad_exception ();
331 }
332
333 terminate ();
334 }
335}
336
337/* Special case of the above for throw() specs. */
338
339extern "C" void
340__check_null_eh_spec (void)
341{
342 __check_eh_spec (0, 0);
343}
e2c09482 344#endif //__EXCEPTIONS
0a8c4c0c
BK
345
346// Helpers for rtti. Although these don't return, we give them return types so
347// that the type system is not broken.
0a8c4c0c 348extern "C" void *
94083e5d 349__cxa_bad_cast ()
0a8c4c0c 350{
e2c09482
BK
351#ifdef __EXCEPTIONS
352 throw std::bad_cast();
353#else
354 std::abort();
355#endif
0a8c4c0c
BK
356 return 0;
357}
358
359extern "C" std::type_info const &
94083e5d 360__cxa_bad_typeid ()
0a8c4c0c 361{
e2c09482
BK
362#ifdef __EXCEPTIONS
363 throw std::bad_typeid();
364#else
365 std::abort();
366#endif
0a8c4c0c
BK
367 return typeid (void);
368}
369
370/* Has the current exception been caught? */
0a8c4c0c 371bool
e2c09482 372std::uncaught_exception() throw()
0a8c4c0c
BK
373{
374 cp_eh_info *p = CP_EH_INFO;
375 return p && ! p->caught;
376}
377
f68147f7
BK
378std::exception::~exception() throw() { }
379
380std::bad_exception::~bad_exception() throw() { }
381
e2c09482
BK
382const char*
383std::exception::what() const throw()
384{ return typeid (*this).name (); }
f68147f7
BK
385
386
387
388