197403Sobrien// -*- C++ -*- Exception handling routines for catching.
2132720Skan// Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
397403Sobrien//
4132720Skan// This file is part of GCC.
597403Sobrien//
6132720Skan// GCC is free software; you can redistribute it and/or modify
797403Sobrien// it under the terms of the GNU General Public License as published by
897403Sobrien// the Free Software Foundation; either version 2, or (at your option)
997403Sobrien// any later version.
1097403Sobrien//
11132720Skan// GCC is distributed in the hope that it will be useful,
1297403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1397403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1497403Sobrien// GNU General Public License for more details.
1597403Sobrien//
1697403Sobrien// You should have received a copy of the GNU General Public License
17132720Skan// along with GCC; see the file COPYING.  If not, write to
18169691Skan// the Free Software Foundation, 51 Franklin Street, Fifth Floor,
19169691Skan// Boston, MA 02110-1301, USA.
2097403Sobrien
2197403Sobrien// As a special exception, you may use this file as part of a free software
2297403Sobrien// library without restriction.  Specifically, if other files instantiate
2397403Sobrien// templates or use macros or inline functions from this file, or you compile
2497403Sobrien// this file and link it with other files to produce an executable, this
2597403Sobrien// file does not by itself cause the resulting executable to be covered by
2697403Sobrien// the GNU General Public License.  This exception does not however
2797403Sobrien// invalidate any other reasons why the executable file might be covered by
2897403Sobrien// the GNU General Public License.
2997403Sobrien
3097403Sobrien#include <cstdlib>
3197403Sobrien#include "unwind-cxx.h"
3297403Sobrien
3397403Sobrienusing namespace __cxxabiv1;
3497403Sobrien
35169691Skanextern "C" void *
36169691Skan__cxxabiv1::__cxa_get_exception_ptr(void *exc_obj_in) throw()
37169691Skan{
38169691Skan  _Unwind_Exception *exceptionObject
39169691Skan    = reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
4097403Sobrien
41169691Skan  return __gxx_caught_object(exceptionObject);
42169691Skan}
43169691Skan
4497403Sobrienextern "C" void *
45169691Skan__cxxabiv1::__cxa_begin_catch (void *exc_obj_in) throw()
4697403Sobrien{
4797403Sobrien  _Unwind_Exception *exceptionObject
4897403Sobrien    = reinterpret_cast <_Unwind_Exception *>(exc_obj_in);
49117397Skan  __cxa_eh_globals *globals = __cxa_get_globals ();
50117397Skan  __cxa_exception *prev = globals->caughtExceptions;
51117397Skan  __cxa_exception *header = __get_exception_header_from_ue (exceptionObject);
52169691Skan  void* objectp;
5397403Sobrien
54117397Skan  // Foreign exceptions can't be stacked here.  If the exception stack is
55117397Skan  // empty, then fine.  Otherwise we really have no choice but to terminate.
56117397Skan  // Note that this use of "header" is a lie.  It's fine so long as we only
57117397Skan  // examine header->unwindHeader though.
58169691Skan  if (!__is_gxx_exception_class(header->unwindHeader.exception_class))
59117397Skan    {
60117397Skan      if (prev != 0)
61117397Skan	std::terminate ();
6297403Sobrien
63117397Skan      // Remember for end_catch and rethrow.
64117397Skan      globals->caughtExceptions = header;
65117397Skan
66117397Skan      // ??? No sensible value to return; we don't know what the
67117397Skan      // object is, much less where it is in relation to the header.
68117397Skan      return 0;
69117397Skan    }
70117397Skan
7197403Sobrien  int count = header->handlerCount;
72169691Skan  // Count is less than zero if this exception was rethrown from an
73169691Skan  // immediately enclosing region.
7497403Sobrien  if (count < 0)
7597403Sobrien    count = -count + 1;
7697403Sobrien  else
77169691Skan    count += 1;
7897403Sobrien  header->handlerCount = count;
79169691Skan  globals->uncaughtExceptions -= 1;
8097403Sobrien
8197403Sobrien  if (header != prev)
8297403Sobrien    {
8397403Sobrien      header->nextException = prev;
8497403Sobrien      globals->caughtExceptions = header;
8597403Sobrien    }
8697403Sobrien
87169691Skan  objectp = __gxx_caught_object(exceptionObject);
88169691Skan#ifdef __ARM_EABI_UNWINDER__
89169691Skan  _Unwind_Complete(exceptionObject);
90169691Skan#endif
91169691Skan  return objectp;
9297403Sobrien}
9397403Sobrien
9497403Sobrien
9597403Sobrienextern "C" void
96169691Skan__cxxabiv1::__cxa_end_catch ()
9797403Sobrien{
9897403Sobrien  __cxa_eh_globals *globals = __cxa_get_globals_fast ();
9997403Sobrien  __cxa_exception *header = globals->caughtExceptions;
100117397Skan
101117397Skan  // A rethrow of a foreign exception will be removed from the
102117397Skan  // the exception stack immediately by __cxa_rethrow.
103117397Skan  if (!header)
104117397Skan    return;
105117397Skan
106117397Skan  // A foreign exception couldn't have been stacked (see above),
107117397Skan  // so by definition processing must be complete.
108169691Skan  if (!__is_gxx_exception_class(header->unwindHeader.exception_class))
109117397Skan    {
110117397Skan      globals->caughtExceptions = 0;
111117397Skan      _Unwind_DeleteException (&header->unwindHeader);
112117397Skan      return;
113117397Skan    }
114117397Skan
11597403Sobrien  int count = header->handlerCount;
11697403Sobrien  if (count < 0)
11797403Sobrien    {
11897403Sobrien      // This exception was rethrown.  Decrement the (inverted) catch
11997403Sobrien      // count and remove it from the chain when it reaches zero.
12097403Sobrien      if (++count == 0)
121169691Skan	globals->caughtExceptions = header->nextException;
12297403Sobrien    }
12397403Sobrien  else if (--count == 0)
12497403Sobrien    {
12597403Sobrien      // Handling for this exception is complete.  Destroy the object.
12697403Sobrien      globals->caughtExceptions = header->nextException;
12797403Sobrien      _Unwind_DeleteException (&header->unwindHeader);
12897403Sobrien      return;
12997403Sobrien    }
13097403Sobrien  else if (count < 0)
13197403Sobrien    // A bug in the exception handling library or compiler.
132117397Skan    std::terminate ();
13397403Sobrien
13497403Sobrien  header->handlerCount = count;
13597403Sobrien}
13697403Sobrien
13797403Sobrien
13897403Sobrienbool
13997403Sobrienstd::uncaught_exception() throw()
14097403Sobrien{
14197403Sobrien  __cxa_eh_globals *globals = __cxa_get_globals ();
14297403Sobrien  return globals->uncaughtExceptions != 0;
14397403Sobrien}
144