This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[basic-improvements] try/finally support for c/c++ - more tests
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Aldy Hernandez <aldyh at redhat dot com>
- Cc: rth at redhat dot com, gcc-patches at gcc dot gnu dot org, jason at redhat dot com
- Date: Wed, 6 Nov 2002 12:43:04 -0500
- Subject: [basic-improvements] try/finally support for c/c++ - more tests
- References: <20021105231902.GA13127@redhat.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
On Tue, Nov 05, 2002 at 03:19:02PM -0800, Aldy Hernandez wrote:
> As promised. Here are the try/finally patches for C and C++.
>
> As can be seen by the ChangeLog, the C++ bits were kindly supplied by
> Jason Merrill (thank-you beers still pending).
>
> Jakub has some tests for try/finally mixing C and C++ exceptions.
> He'll be posting those later, right? :)
Attached.
One test for throwing from C++ through C code with __try/__finally,
one test showing what approximately could libpthread do (well, there
is still a problem if some function in the backtrace from the point of
cancellation to __libc_start_main resp. pthread_start_thread is compiled
with -fno-exceptions, _Unwind_Resume will abort. I think a callback is
needed for that (e.g. calling the stop callback with
some special arguments).
2002-11-06 Jakub Jelinek <jakub@redhat.com>
* Makefile.in (USER_H): Install unwind.h.
* libgcc-std.ver (__gcc_personality_v0, __gcc_personality_sj0):
Export @GCC_3.4.
* lib/g++-dg.exp (g++-dg-test): Add g++-dg-aux-sources to additional
flags.
(dg-aux-sources): New subroutine.
* g++.dg/ext/try-finally-1.C: New test.
* g++.dg/ext/try-finally-1-aux.c: New auxiliary file for the test.
* gcc.dg/try-finally-1.c: New test.
--- gcc/Makefile.in.jj 2002-10-25 14:12:50.000000000 +0200
+++ gcc/Makefile.in 2002-11-06 18:44:16.000000000 +0100
@@ -157,7 +157,7 @@ INSTALL_HEADERS_DIR = @build_install_hea
USER_H = $(srcdir)/ginclude/stdarg.h $(srcdir)/ginclude/stddef.h \
$(srcdir)/ginclude/varargs.h \
$(srcdir)/ginclude/stdbool.h $(srcdir)/ginclude/iso646.h \
- $(EXTRA_HEADERS)
+ $(srcdir)/unwind.h $(EXTRA_HEADERS)
# The GCC to use for compiling libgcc.a, enquire, and crt*.o.
# Usually the one we just built.
--- gcc/libgcc-std.ver.jj 2001-07-22 21:34:05.000000000 +0200
+++ gcc/libgcc-std.ver 2002-11-05 14:11:03.000000000 +0100
@@ -175,3 +175,7 @@ GCC_3.0 {
_Unwind_SjLj_ForcedUnwind
_Unwind_SjLj_Resume
}
+GCC_3.4 {
+ __gcc_personality_v0
+ __gcc_personality_sj0
+}
--- gcc/testsuite/lib/g++-dg.exp.jj 2002-01-23 16:29:52.000000000 +0100
+++ gcc/testsuite/lib/g++-dg.exp 2002-11-05 13:57:13.000000000 +0100
@@ -23,6 +23,7 @@ load_lib scanasm.exp
proc g++-dg-test { prog do_what extra_tool_flags } {
# Set up the compiler flags, based on what we're going to do.
+ global g++-dg-aux-sources
switch $do_what {
"preprocess" {
@@ -59,6 +60,10 @@ proc g++-dg-test { prog do_what extra_to
}
}
set options ""
+ if { ${g++-dg-aux-sources} != "" } {
+ append extra_tool_flags "${g++-dg-aux-sources}"
+ set g++-dg-aux-sources ""
+ }
if { $extra_tool_flags != "" } {
lappend options "additional_flags=$extra_tool_flags"
}
@@ -82,3 +87,22 @@ proc g++-dg-prune { system text } {
return $text
}
+
+
+#
+# Add additional sources to compile together with the main source file
+#
+
+proc dg-aux-sources { args } {
+ global g++-dg-aux-sources
+ upvar prog myprog
+
+ foreach arg [lrange $args 1 [llength $args]] {
+ set filename "[file dirname $myprog]/$arg"
+ if { [file extension $arg] == ".c" } {
+ append g++-dg-aux-sources " -xc $filename -xnone"
+ } else {
+ append g++-dg-aux-sources " $filename"
+ }
+ }
+}
--- gcc/testsuite/g++.dg/ext/try-finally-1.C.jj 2002-11-05 14:13:46.000000000 +0100
+++ gcc/testsuite/g++.dg/ext/try-finally-1.C 2002-11-05 12:47:17.000000000 +0100
@@ -0,0 +1,31 @@
+// { dg-do run }
+// { dg-options "-O2 -fexceptions" }
+// { dg-aux-sources try-finally-1-aux.c }
+
+extern int caught;
+extern "C" void test (void);
+extern "C" void do_throw (void);
+extern "C" void abort (void);
+
+void
+do_throw (void)
+{
+ caught |= 4;
+ throw 1;
+}
+
+int
+main ()
+{
+ try
+ {
+ test ();
+ }
+ catch(...)
+ {
+ caught |= 8;
+ }
+ if (caught != 15)
+ abort ();
+ return 0;
+}
--- gcc/testsuite/g++.dg/ext/try-finally-1-aux.c.jj 2002-11-05 14:13:48.000000000 +0100
+++ gcc/testsuite/g++.dg/ext/try-finally-1-aux.c 2002-11-05 12:43:30.000000000 +0100
@@ -0,0 +1,23 @@
+int caught;
+extern void do_throw (void);
+extern void abort (void);
+
+void
+test (void)
+{
+ caught |= 1;
+ __try
+ {
+ do_throw ();
+ }
+ __finally
+ {
+ finally ();
+ }
+ abort ();
+}
+
+finally()
+{
+ caught |= 2;
+}
--- gcc/testsuite/gcc.dg/try-finally-1.c.jj 2002-07-23 20:50:16.000000000 +0200
+++ gcc/testsuite/gcc.dg/try-finally-1.c 2002-11-06 18:46:39.000000000 +0100
@@ -0,0 +1,94 @@
+/* { dg-do run { target i?86-*-linux* x86_64-*-linux* ia64-*-linux* sparc*-*-linux* } } */
+/* { dg-options "-O2 -fexceptions" } */
+
+#include <unwind.h>
+
+int caught;
+
+void finally (void);
+void do_throw (void);
+extern void abort (void);
+extern void exit (int);
+
+void
+test1 (void)
+{
+ caught |= 1;
+ __try
+ {
+ do_throw ();
+ abort ();
+ }
+ __finally
+ {
+ finally ();
+ }
+ abort ();
+}
+
+void
+test2 (void)
+{
+ caught |= 2;
+ __try
+ {
+ test1 ();
+ abort ();
+ }
+ __finally
+ {
+ caught |= 4;
+ }
+ abort ();
+}
+
+void
+test3 (void)
+{
+ test2 ();
+ caught = 0;
+}
+
+void
+finally (void)
+{
+ caught |= 8;
+}
+
+void
+exception_cleanup (_Unwind_Reason_Code code,
+ struct _Unwind_Exception *exc)
+{
+}
+
+_Unwind_Reason_Code
+stop_fn (int x, _Unwind_Action action, _Unwind_Exception_Class class,
+ struct _Unwind_Exception *exc, struct _Unwind_Context *ctx, void *arg)
+{
+ /* This would actually check for __libc_start_main or
+ pthread_start_thread. */
+ if ((void *) _Unwind_GetRegionStart (ctx) == (void *) test3)
+ {
+ if (caught != 15)
+ abort ();
+ exit (0);
+ }
+ return _URC_NO_REASON;
+}
+
+struct _Unwind_Exception ue;
+
+void
+do_throw (void)
+{
+ ue.exception_class = 1;
+ ue.exception_cleanup = exception_cleanup;
+ _Unwind_ForcedUnwind (&ue, stop_fn, 0);
+}
+
+int
+main (void)
+{
+ test3 ();
+ abort ();
+}
Jakub