gcc41 removal: Part 1 of 2: makefiles
[dragonfly.git] / contrib / gcc-4.1 / libstdc++-v3 / libsupc++ / eh_call.cc
1 // -*- C++ -*- Helpers for calling unextected and terminate
2 // Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
3 //
4 // This file is part of GCC.
5 //
6 // GCC is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2, or (at your option)
9 // any later version.
10 //
11 // GCC is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with GCC; see the file COPYING.  If not, write to
18 // the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19 // Boston, MA 02110-1301, USA.
20
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29
30
31 #include <bits/c++config.h>
32 #include <cstdlib>
33 #include <exception_defines.h>
34 #include "unwind-cxx.h"
35
36 using namespace __cxxabiv1;
37
38 #include "unwind-pe.h"
39
40
41 // Helper routine for when the exception handling code needs to call
42 // terminate.
43
44 extern "C" void
45 __cxa_call_terminate(_Unwind_Exception* ue_header)
46 {
47
48   if (ue_header)
49     {
50       // terminate is classed as a catch handler.
51       __cxa_begin_catch(ue_header);
52
53       // Call the terminate handler that was in effect when we threw this
54       // exception.  */
55       if (__is_gxx_exception_class(ue_header->exception_class))
56         {
57           __cxa_exception* xh;
58
59           xh = __get_exception_header_from_ue(ue_header);
60           __terminate(xh->terminateHandler);
61         }
62     }
63   /* Call the global routine if we don't have anything better.  */
64   std::terminate();
65 }
66
67
68 #ifdef __ARM_EABI_UNWINDER__
69 // The ARM EABI __cxa_call_unexpected has the same semantics as the generic
70 // routine, but the exception specification has a different format.
71 extern "C" void
72 __cxa_call_unexpected(void* exc_obj_in)
73 {
74   _Unwind_Exception* exc_obj
75     = reinterpret_cast<_Unwind_Exception*>(exc_obj_in);
76
77   int rtti_count = 0;
78   _Unwind_Word rtti_stride = 0;
79   _Unwind_Word* rtti_list = NULL;
80   bool foreign_exception;
81   std::unexpected_handler unexpectedHandler = NULL;
82   std::terminate_handler terminateHandler = NULL;
83   __cxa_exception* xh;
84   if (__is_gxx_exception_class(exc_obj->exception_class))
85     {
86       // Save data from the EO, which may be clobbered by _cxa_begin_catch.
87       xh = __get_exception_header_from_ue(exc_obj);
88       unexpectedHandler = xh->unexpectedHandler;
89       terminateHandler = xh->terminateHandler;
90       rtti_count = exc_obj->barrier_cache.bitpattern[1];
91
92       rtti_stride = exc_obj->barrier_cache.bitpattern[3];
93       rtti_list = (_Unwind_Word*) exc_obj->barrier_cache.bitpattern[4];
94       foreign_exception = false;
95     }
96   else
97     foreign_exception = true;
98
99   /* This must be called after extracting data from the EO, but before
100      calling unexpected().   */
101   __cxa_begin_catch(exc_obj);
102
103   // This function is a handler for our exception argument.  If we exit
104   // by throwing a different exception, we'll need the original cleaned up.
105   struct end_catch_protect
106   {
107     end_catch_protect() { }
108     ~end_catch_protect() { __cxa_end_catch(); }
109   } end_catch_protect_obj;
110
111
112   try 
113     { 
114       if (foreign_exception)
115         std::unexpected();
116       else
117         __unexpected(unexpectedHandler);
118     }
119   catch(...) 
120     {
121       /* See if the new exception matches the rtti list.  */
122       if (foreign_exception)
123         std::terminate();
124
125       // Get the exception thrown from unexpected.
126
127       __cxa_eh_globals* globals = __cxa_get_globals_fast();
128       __cxa_exception* new_xh = globals->caughtExceptions;
129       void* new_ptr = new_xh + 1;
130       const std::type_info* catch_type;
131       int n;
132       bool bad_exception_allowed = false;
133       const std::type_info& bad_exc = typeid(std::bad_exception);
134
135       // Check the new exception against the rtti list
136       for (n = 0; n < rtti_count; n++)
137         {
138           _Unwind_Word offset;
139
140           offset = (_Unwind_Word) &rtti_list[n * (rtti_stride >> 2)];
141           offset = _Unwind_decode_target2(offset);
142           catch_type = (const std::type_info*) (offset);
143
144           if (__cxa_type_match(&new_xh->unwindHeader, catch_type, false,
145                                &new_ptr) != ctm_failed)
146             __throw_exception_again;
147
148           if (catch_type->__do_catch(&bad_exc, 0, 1))
149             bad_exception_allowed = true;
150         }
151
152       // If the exception spec allows std::bad_exception, throw that.
153 #ifdef __EXCEPTIONS  
154       if (bad_exception_allowed)
155         throw std::bad_exception();
156 #endif   
157
158       // Otherwise, die.
159       __terminate(terminateHandler);
160     }
161 }
162 #endif // __ARM_EABI_UNWINDER__