1/* { dg-do run { target hppa*-*-hpux* *-*-linux* powerpc*-*-darwin* *-*-darwin[912]* } } */
2/* { dg-options "-fexceptions -fnon-call-exceptions -O2" } */
3/* Verify that cleanups work with exception handling through realtime
4   signal frames.  */
5
6#include <unwind.h>
7#include <stdlib.h>
8#include <signal.h>
9#include <string.h>
10
11static _Unwind_Reason_Code
12force_unwind_stop (int version, _Unwind_Action actions,
13                   _Unwind_Exception_Class exc_class,
14                   struct _Unwind_Exception *exc_obj,
15                   struct _Unwind_Context *context,
16                   void *stop_parameter)
17{
18  if (actions & _UA_END_OF_STACK)
19    abort ();
20  return _URC_NO_REASON;
21}
22
23static void force_unwind ()
24{
25  struct _Unwind_Exception *exc
26    = (struct _Unwind_Exception *) malloc (sizeof (*exc));
27  memset (&exc->exception_class, 0, sizeof (exc->exception_class));
28  exc->exception_cleanup = 0;
29
30#ifndef __USING_SJLJ_EXCEPTIONS__
31  _Unwind_ForcedUnwind (exc, force_unwind_stop, 0);
32#else
33  _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0);
34#endif
35
36  abort ();
37}
38
39int count;
40char *null;
41
42static void counter (void *p __attribute__((unused)))
43{
44  ++count;
45}
46
47static void handler (void *p __attribute__((unused)))
48{
49  if (count != 2)
50    abort ();
51  exit (0);
52}
53
54static int __attribute__((noinline)) fn5 ()
55{
56  char dummy __attribute__((cleanup (counter)));
57  force_unwind ();
58  return 0;
59}
60
61static void fn4 (int sig, siginfo_t *info, void *ctx)
62{
63  char dummy __attribute__((cleanup (counter)));
64  fn5 ();
65  null = NULL;
66}
67
68static void fn3 ()
69{
70  abort ();
71}
72
73static int __attribute__((noinline)) fn2 ()
74{
75  *null = 0;
76  fn3 ();
77  return 0;
78}
79
80static int __attribute__((noinline)) fn1 ()
81{
82  struct sigaction s;
83  sigemptyset (&s.sa_mask);
84  s.sa_sigaction = fn4;
85  s.sa_flags = SA_RESETHAND | SA_SIGINFO;
86  sigaction (SIGSEGV, &s, NULL);
87  sigaction (SIGBUS, &s, NULL);
88  fn2 ();
89  return 0;
90}
91
92static int __attribute__((noinline)) fn0 ()
93{
94  char dummy __attribute__((cleanup (handler)));
95  fn1 ();
96  null = 0;
97  return 0;
98}
99
100int main()
101{
102  fn0 ();
103  abort ();
104}
105