diff options
author | Mark Mitchell <mark@codesourcery.com> | 2007-05-21 23:47:29 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 2007-05-21 23:47:29 +0000 |
commit | 5c1131547ba8afe1ca639d012b96c63d3e94767e (patch) | |
tree | 53be7e6a464964a2a2ab76a9407d12f76ef6def8 /gcc/testsuite | |
parent | 0b4cafec04e60b7a06ee01ddc752c516ddb250c7 (diff) | |
download | gcc-5c1131547ba8afe1ca639d012b96c63d3e94767e.zip gcc-5c1131547ba8afe1ca639d012b96c63d3e94767e.tar.gz gcc-5c1131547ba8afe1ca639d012b96c63d3e94767e.tar.bz2 |
decl.c (cxx_maybe_build_cleanup): Handle __attribute__((cleanup)).
* decl.c (cxx_maybe_build_cleanup): Handle
__attribute__((cleanup)).
* g++.dg/ext/cleanup-1.C: New test.
* g++.dg/ext/cleanup-2.C: Likewise.
* g++.dg/ext/cleanup-3.C: Likewise.
* g++.dg/ext/cleanup-4.C: Likewise.
* g++.dg/ext/cleanup-5.C: Likewise.
* g++.dg/ext/cleanup-6.C: Likewise.
* g++.dg/ext/cleanup-8.C: Likewise.
* g++.dg/ext/cleanup-9.C: Likewise.
* g++.dg/ext/cleanup-10.C: Likewise.
* g++.dg/ext/cleanup-11.C: Likewise.
* g++.dg/ext/cleanup-dtor.C: Likewise.
From-SVN: r124930
Diffstat (limited to 'gcc/testsuite')
-rw-r--r-- | gcc/testsuite/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/cleanup-1.C | 36 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/cleanup-10.C | 117 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/cleanup-11.C | 117 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/cleanup-2.C | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/cleanup-3.C | 45 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/cleanup-4.C | 39 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/cleanup-5.C | 54 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/cleanup-6.C | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/cleanup-8.C | 100 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/cleanup-9.C | 104 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/cleanup-dtor.C | 28 |
12 files changed, 690 insertions, 0 deletions
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e46cf78..c37b343 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,17 @@ +2007-05-21 Mark Mitchell <mark@codesourcery.com> + + * g++.dg/ext/cleanup-1.C: New test. + * g++.dg/ext/cleanup-2.C: Likewise. + * g++.dg/ext/cleanup-3.C: Likewise. + * g++.dg/ext/cleanup-4.C: Likewise. + * g++.dg/ext/cleanup-5.C: Likewise. + * g++.dg/ext/cleanup-6.C: Likewise. + * g++.dg/ext/cleanup-8.C: Likewise. + * g++.dg/ext/cleanup-9.C: Likewise. + * g++.dg/ext/cleanup-10.C: Likewise. + * g++.dg/ext/cleanup-11.C: Likewise. + * g++.dg/ext/cleanup-dtor.C: Likewise. + 2007-05-21 Andrew Pinski <andrew_pinski@playstation.sony.com> PR middle-end/31995 diff --git a/gcc/testsuite/g++.dg/ext/cleanup-1.C b/gcc/testsuite/g++.dg/ext/cleanup-1.C new file mode 100644 index 0000000..383c64e --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/cleanup-1.C @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ +/* Validate expected warnings and errors. */ + +#define U __attribute__((unused)) +#define C(x) __attribute__((cleanup(x))) + +static int f1(void *x U) { return 0; } +static void f2() { } /* { dg-error "too many arguments" } */ +static void f3(void) { } /* { dg-error "too many arguments" } */ +static void f4(void *x U) { } +static void f5(int *x U) { } +static void f6(double *x U) { } +static void f7(const int *x U) { } +static void f8(const int *x U, int y U) { } /* { dg-error "too few arguments" } */ +static void f9(int x U) { } + +void test(void) +{ + int o1 C(f1); + int o2 C(f2); /* { dg-error "at this point" } */ + int o3 C(f3); /* { dg-error "at this point" } */ + int o4 C(f4); + int o5 C(f5); + int o6 C(f6); /* { dg-error "cannot convert" } */ + int o7 C(f7); + int o8 C(f8); /* { dg-error "at this point" } */ + int o9 C(f9); /* { dg-error "conversion" } */ + int o10 U C(undef); /* { dg-error "not a function" } */ + int o11 U C(o1); /* { dg-error "not a function" } */ + int o12 U C("f1"); /* { dg-error "not an identifier" } */ + static int o13 U C(f1); /* { dg-warning "attribute ignored" } */ +} + +int o14 C(f1); /* { dg-warning "attribute ignored" } */ +void t15(int o U C(f1)) {} /* { dg-warning "attribute ignored" } */ diff --git a/gcc/testsuite/g++.dg/ext/cleanup-10.C b/gcc/testsuite/g++.dg/ext/cleanup-10.C new file mode 100644 index 0000000..c0c6971 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/cleanup-10.C @@ -0,0 +1,117 @@ +/* { dg-do run { target hppa*-*-hpux* *-*-linux* powerpc*-*-darwin* } } */ +/* { dg-options "-fexceptions -fnon-call-exceptions -O2" } */ +/* Verify that cleanups work with exception handling through signal frames + on alternate stack. */ + +#include <unwind.h> +#include <stdlib.h> +#include <signal.h> +#include <unistd.h> +#include <string.h> + +static _Unwind_Reason_Code +force_unwind_stop (int version, _Unwind_Action actions, + _Unwind_Exception_Class exc_class, + struct _Unwind_Exception *exc_obj, + struct _Unwind_Context *context, + void *stop_parameter) +{ + if (actions & _UA_END_OF_STACK) + abort (); + return _URC_NO_REASON; +} + +static void force_unwind () +{ + struct _Unwind_Exception *exc + = (struct _Unwind_Exception *) malloc (sizeof (*exc)); + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); + exc->exception_cleanup = 0; + +#ifndef __USING_SJLJ_EXCEPTIONS__ + _Unwind_ForcedUnwind (exc, force_unwind_stop, 0); +#else + _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0); +#endif + + abort (); +} + +int count; +char *null; + +static void counter (void *p __attribute__((unused))) +{ + ++count; +} + +static void handler (void *p __attribute__((unused))) +{ + if (count != 2) + abort (); + exit (0); +} + +static int __attribute__((noinline)) fn5 () +{ + char dummy __attribute__((cleanup (counter))); + force_unwind (); + return 0; +} + +static void fn4 (int sig, siginfo_t *info, void *ctx) +{ + char dummy __attribute__((cleanup (counter))); + fn5 (); + null = NULL; +} + +static void fn3 () +{ + abort (); +} + +static int __attribute__((noinline)) fn2 () +{ + *null = 0; + fn3 (); + return 0; +} + +static int __attribute__((noinline)) fn1 () +{ + stack_t ss; + struct sigaction s; + + ss.ss_size = 4 * sysconf (_SC_PAGESIZE); + if (ss.ss_size < SIGSTKSZ) + ss.ss_size = SIGSTKSZ; + ss.ss_sp = malloc (ss.ss_size); + if (ss.ss_sp == NULL) + exit (1); + ss.ss_flags = 0; + if (sigaltstack (&ss, NULL) < 0) + exit (1); + + sigemptyset (&s.sa_mask); + s.sa_sigaction = fn4; + s.sa_flags = SA_RESETHAND | SA_ONSTACK; + sigaction (SIGSEGV, &s, NULL); + sigaction (SIGBUS, &s, NULL); + fn2 (); + return 0; +} + +static int __attribute__((noinline)) fn0 () +{ + char dummy __attribute__((cleanup (handler))); + fn1 (); + null = 0; + return 0; +} + +int main() +{ + fn0 (); + abort (); +} diff --git a/gcc/testsuite/g++.dg/ext/cleanup-11.C b/gcc/testsuite/g++.dg/ext/cleanup-11.C new file mode 100644 index 0000000..06c6569 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/cleanup-11.C @@ -0,0 +1,117 @@ +/* { dg-do run { target hppa*-*-hpux* *-*-linux* powerpc*-*-darwin* } } */ +/* { dg-options "-fexceptions -fnon-call-exceptions -O2" } */ +/* Verify that cleanups work with exception handling through realtime signal + frames on alternate stack. */ + +#include <unwind.h> +#include <stdlib.h> +#include <signal.h> +#include <unistd.h> +#include <string.h> + +static _Unwind_Reason_Code +force_unwind_stop (int version, _Unwind_Action actions, + _Unwind_Exception_Class exc_class, + struct _Unwind_Exception *exc_obj, + struct _Unwind_Context *context, + void *stop_parameter) +{ + if (actions & _UA_END_OF_STACK) + abort (); + return _URC_NO_REASON; +} + +static void force_unwind () +{ + struct _Unwind_Exception *exc + = (struct _Unwind_Exception*) malloc (sizeof (*exc)); + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); + exc->exception_cleanup = 0; + +#ifndef __USING_SJLJ_EXCEPTIONS__ + _Unwind_ForcedUnwind (exc, force_unwind_stop, 0); +#else + _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0); +#endif + + abort (); +} + +int count; +char *null; + +static void counter (void *p __attribute__((unused))) +{ + ++count; +} + +static void handler (void *p __attribute__((unused))) +{ + if (count != 2) + abort (); + exit (0); +} + +static int __attribute__((noinline)) fn5 () +{ + char dummy __attribute__((cleanup (counter))); + force_unwind (); + return 0; +} + +static void fn4 (int sig, siginfo_t *info, void *ctx) +{ + char dummy __attribute__((cleanup (counter))); + fn5 (); + null = NULL; +} + +static void fn3 () +{ + abort (); +} + +static int __attribute__((noinline)) fn2 () +{ + *null = 0; + fn3 (); + return 0; +} + +static int __attribute__((noinline)) fn1 () +{ + stack_t ss; + struct sigaction s; + + ss.ss_size = 4 * sysconf (_SC_PAGESIZE); + if (ss.ss_size < SIGSTKSZ) + ss.ss_size = SIGSTKSZ; + ss.ss_sp = malloc (ss.ss_size); + if (ss.ss_sp == NULL) + exit (1); + ss.ss_flags = 0; + if (sigaltstack (&ss, NULL) < 0) + exit (1); + + sigemptyset (&s.sa_mask); + s.sa_sigaction = fn4; + s.sa_flags = SA_RESETHAND | SA_ONSTACK | SA_SIGINFO; + sigaction (SIGSEGV, &s, NULL); + sigaction (SIGBUS, &s, NULL); + fn2 (); + return 0; +} + +static int __attribute__((noinline)) fn0 () +{ + char dummy __attribute__((cleanup (handler))); + fn1 (); + null = 0; + return 0; +} + +int main() +{ + fn0 (); + abort (); +} diff --git a/gcc/testsuite/g++.dg/ext/cleanup-2.C b/gcc/testsuite/g++.dg/ext/cleanup-2.C new file mode 100644 index 0000000..d9033b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/cleanup-2.C @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-options "" } */ +/* Verify that cleanup works in the most basic of ways. */ + +extern "C" void exit(int); +extern "C" void abort(void); + +static void handler(void *p __attribute__((unused))) +{ + exit (0); +} + +static void doit(void) +{ + int x __attribute__((cleanup (handler))); +} + +int main() +{ + doit (); + abort (); +} diff --git a/gcc/testsuite/g++.dg/ext/cleanup-3.C b/gcc/testsuite/g++.dg/ext/cleanup-3.C new file mode 100644 index 0000000..5367c49 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/cleanup-3.C @@ -0,0 +1,45 @@ +/* { dg-do run } */ +/* { dg-options "" } */ +/* Verify that the cleanup handler receives the proper contents + of the variable. */ + +extern "C" void exit(int); +extern "C" void abort(void); + +static int expected; + +static void +handler(int *p) +{ + if (*p != expected) + abort (); +} + +static void __attribute__((noinline)) +bar(void) +{ +} + +static void doit(int x, int y) +{ + int r __attribute__((cleanup (handler))); + if (x < y) + { + r = 0; + return; + } + + bar(); + r = x + y; +} + +int main() +{ + expected = 0; + doit (1, 2); + + expected = 3; + doit (2, 1); + + return 0; +} diff --git a/gcc/testsuite/g++.dg/ext/cleanup-4.C b/gcc/testsuite/g++.dg/ext/cleanup-4.C new file mode 100644 index 0000000..ae9a6e4 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/cleanup-4.C @@ -0,0 +1,39 @@ +/* { dg-do run } */ +/* { dg-options "" } */ +/* Verify cleanup execution on non-trivial exit from a block. */ + +extern "C" void exit(int); +extern "C" void abort(void); + +static int counter; + +static void +handler(int *p) +{ + counter += *p; +} + +static void __attribute__((noinline)) +bar(void) +{ +} + +static void doit(int n, int n2) +{ + int i; + for (i = 0; i < n; ++i) + { + int dummy __attribute__((cleanup (handler))) = i; + if (i == n2) + break; + bar(); + } +} + +int main() +{ + doit (10, 6); + if (counter != 0 + 1 + 2 + 3 + 4 + 5 + 6) + abort (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/ext/cleanup-5.C b/gcc/testsuite/g++.dg/ext/cleanup-5.C new file mode 100644 index 0000000..db4c2bb --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/cleanup-5.C @@ -0,0 +1,54 @@ +/* HP-UX libunwind.so doesn't provide _UA_END_OF_STACK */ +/* { dg-do run } */ +/* { dg-options "-fexceptions" } */ +/* { dg-skip-if "" { "ia64-*-hpux11.*" } { "*" } { "" } } */ +/* Verify that cleanups work with exception handling. */ + +#include <unwind.h> +#include <stdlib.h> +#include <string.h> + +static _Unwind_Reason_Code +force_unwind_stop (int version, _Unwind_Action actions, + _Unwind_Exception_Class exc_class, + struct _Unwind_Exception *exc_obj, + struct _Unwind_Context *context, + void *stop_parameter) +{ + if (actions & _UA_END_OF_STACK) + abort (); + return _URC_NO_REASON; +} + +static void force_unwind () +{ + struct _Unwind_Exception *exc + = (struct _Unwind_Exception *) malloc (sizeof (*exc)); + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); + exc->exception_cleanup = 0; + +#ifndef __USING_SJLJ_EXCEPTIONS__ + _Unwind_ForcedUnwind (exc, force_unwind_stop, 0); +#else + _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0); +#endif + + abort (); +} + +static void handler (void *p __attribute__((unused))) +{ + exit (0); +} + +static void doit () +{ + char dummy __attribute__((cleanup (handler))); + force_unwind (); +} + +int main() +{ + doit (); + abort (); +} diff --git a/gcc/testsuite/g++.dg/ext/cleanup-6.C b/gcc/testsuite/g++.dg/ext/cleanup-6.C new file mode 100644 index 0000000..4e3d538 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/cleanup-6.C @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ +/* Verify that a cleanup marked "inline" gets inlined. */ + +static inline void xyzzy(void *p __attribute__((unused))) +{ +} + +void doit(void) +{ + int x __attribute__((cleanup (xyzzy))); +} + +/* { dg-final { scan-assembler-not "xyzzy" } } */ diff --git a/gcc/testsuite/g++.dg/ext/cleanup-8.C b/gcc/testsuite/g++.dg/ext/cleanup-8.C new file mode 100644 index 0000000..ece12e8 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/cleanup-8.C @@ -0,0 +1,100 @@ +/* { dg-do run { target hppa*-*-hpux* *-*-linux* powerpc*-*-darwin* } } */ +/* { dg-options "-fexceptions -fnon-call-exceptions -O2" } */ +/* Verify that cleanups work with exception handling through signal + frames. */ + +#include <unwind.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> + +static _Unwind_Reason_Code +force_unwind_stop (int version, _Unwind_Action actions, + _Unwind_Exception_Class exc_class, + struct _Unwind_Exception *exc_obj, + struct _Unwind_Context *context, + void *stop_parameter) +{ + if (actions & _UA_END_OF_STACK) + abort (); + return _URC_NO_REASON; +} + +static void force_unwind () +{ + struct _Unwind_Exception *exc + = (struct _Unwind_Exception *) malloc (sizeof (*exc)); + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); + exc->exception_cleanup = 0; + +#ifndef __USING_SJLJ_EXCEPTIONS__ + _Unwind_ForcedUnwind (exc, force_unwind_stop, 0); +#else + _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0); +#endif + + abort (); +} + +int count; +char *null; + +static void counter (void *p __attribute__((unused))) +{ + ++count; +} + +static void handler (void *p __attribute__((unused))) +{ + if (count != 2) + abort (); + exit (0); +} + +static int __attribute__((noinline)) fn5 () +{ + char dummy __attribute__((cleanup (counter))); + force_unwind (); + return 0; +} + +static void fn4 (int sig) +{ + char dummy __attribute__((cleanup (counter))); + fn5 (); + null = NULL; +} + +static void fn3 () +{ + abort (); +} + +static int __attribute__((noinline)) fn2 () +{ + *null = 0; + fn3 (); + return 0; +} + +static int __attribute__((noinline)) fn1 () +{ + signal (SIGSEGV, fn4); + signal (SIGBUS, fn4); + fn2 (); + return 0; +} + +static int __attribute__((noinline)) fn0 () +{ + char dummy __attribute__((cleanup (handler))); + fn1 (); + null = 0; + return 0; +} + +int main() +{ + fn0 (); + abort (); +} diff --git a/gcc/testsuite/g++.dg/ext/cleanup-9.C b/gcc/testsuite/g++.dg/ext/cleanup-9.C new file mode 100644 index 0000000..59a9735 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/cleanup-9.C @@ -0,0 +1,104 @@ +/* { dg-do run { target hppa*-*-hpux* *-*-linux* powerpc*-*-darwin* } } */ +/* { dg-options "-fexceptions -fnon-call-exceptions -O2" } */ +/* Verify that cleanups work with exception handling through realtime + signal frames. */ + +#include <unwind.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> + +static _Unwind_Reason_Code +force_unwind_stop (int version, _Unwind_Action actions, + _Unwind_Exception_Class exc_class, + struct _Unwind_Exception *exc_obj, + struct _Unwind_Context *context, + void *stop_parameter) +{ + if (actions & _UA_END_OF_STACK) + abort (); + return _URC_NO_REASON; +} + +static void force_unwind () +{ + struct _Unwind_Exception *exc + = (struct _Unwind_Exception *) malloc (sizeof (*exc)); + memset (&exc->exception_class, 0, sizeof (exc->exception_class)); + exc->exception_cleanup = 0; + +#ifndef __USING_SJLJ_EXCEPTIONS__ + _Unwind_ForcedUnwind (exc, force_unwind_stop, 0); +#else + _Unwind_SjLj_ForcedUnwind (exc, force_unwind_stop, 0); +#endif + + abort (); +} + +int count; +char *null; + +static void counter (void *p __attribute__((unused))) +{ + ++count; +} + +static void handler (void *p __attribute__((unused))) +{ + if (count != 2) + abort (); + exit (0); +} + +static int __attribute__((noinline)) fn5 () +{ + char dummy __attribute__((cleanup (counter))); + force_unwind (); + return 0; +} + +static void fn4 (int sig, siginfo_t *info, void *ctx) +{ + char dummy __attribute__((cleanup (counter))); + fn5 (); + null = NULL; +} + +static void fn3 () +{ + abort (); +} + +static int __attribute__((noinline)) fn2 () +{ + *null = 0; + fn3 (); + return 0; +} + +static int __attribute__((noinline)) fn1 () +{ + struct sigaction s; + sigemptyset (&s.sa_mask); + s.sa_sigaction = fn4; + s.sa_flags = SA_RESETHAND | SA_SIGINFO; + sigaction (SIGSEGV, &s, NULL); + sigaction (SIGBUS, &s, NULL); + fn2 (); + return 0; +} + +static int __attribute__((noinline)) fn0 () +{ + char dummy __attribute__((cleanup (handler))); + fn1 (); + null = 0; + return 0; +} + +int main() +{ + fn0 (); + abort (); +} diff --git a/gcc/testsuite/g++.dg/ext/cleanup-dtor.C b/gcc/testsuite/g++.dg/ext/cleanup-dtor.C new file mode 100644 index 0000000..58da646 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/cleanup-dtor.C @@ -0,0 +1,28 @@ +// Check that destructors are run after cleanup functions. +// { dg-do run } + +extern "C" void abort (); + +int i; + +struct S { + ~S() { + if (i != 1) + abort (); + i = 2; + } +}; + +void f(void *) { + if (i != 0) + abort (); + i = 1; +} + +int main () { + { + S s __attribute__((cleanup (f))); + } + if (i != 2) + abort (); +} |