This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[gomp] Fix C -fopenmp -fexceptions (PR c/29955)


Hi!

The testcase below ICEs on ia64 and generates weird unwind info elsewhere.
The problem is that in C when exceptions are enabled, but
__attribute__((cleanup ())) wasn't seen (yet), omp-low.c generates
MUST_NOT_THROW catch handler for various #pragma omp constructs, but
eh_personality_libfunc isn't set.  On ia64 (or any TARGET_UNWIND_INFO
arch) the presence of LSDA data (.handlerdata directive) requires
.personality directive too, but when eh_personality_libfunc is NULL,
it is dereferenced and crashes.  On e.g. x86-64, we ATM generate
LSDA info, but no personality routine is set (zLR augmentation in CIE),
which is pointless, because LSDA data is only parsed by the personality
routine and thus makes nose sense at all otherwise.

To fix this, there are plenty of possibilities:
1) set eh_personality_libfunc in C whenever either __attribute__((cleanup ()))
   was seen or #pragma omp {single,parallel,for,etc.} was seen
   (this is implemented in the patch below)
2) in omp-low.c's maybe_catch_exception do nothing not only when
   !flag_exceptions, but also when eh_personality_libfunc == NULL
3) in output_function_exception_table output .personality
   __gcc_personality_v0 as the default if eh_personality_libfunc
   is missing
I think 1) is cleanest.  C++ is not affected (eh_personality_libfunc
is set there whenever flag_exceptions) and Fortran is not either
(flag_exceptions is never set).

Ok for 4.2/4.3?

2006-11-23  Jakub Jelinek  <jakub@redhat.com>

	PR c/29955
	* c-tree.h (c_maybe_initialize_eh): New prototype.
	* c-decl.c (finish_decl): Move EH initialization...
	(c_maybe_initialize_eh): ... here.  New function.
	* c-parser.c (c_parser_omp_construct): Call c_maybe_initialize_eh
	if not #pragma omp atomic.

	* gcc.dg/gomp/pr29955.c: New test.

--- gcc/c-decl.c.jj	2006-11-07 21:46:17.000000000 +0100
+++ gcc/c-decl.c	2006-11-23 11:27:49.000000000 +0100
@@ -3385,6 +3385,23 @@ start_decl (struct c_declarator *declara
   return tem;
 }
 
+/* Initialize EH if not initialized yet and exceptions are enabled.  */
+
+void
+c_maybe_initialize_eh (void)
+{
+  if (!flag_exceptions || c_eh_initialized_p)
+    return;
+
+  c_eh_initialized_p = true;
+  eh_personality_libfunc
+    = init_one_libfunc (USING_SJLJ_EXCEPTIONS
+			? "__gcc_personality_sj0"
+			: "__gcc_personality_v0");
+  default_init_unwind_resume_libfunc ();
+  using_eh_for_cleanups ();
+}
+
 /* Finish processing of a declaration;
    install its initial value.
    If the length of an array type is not known before,
@@ -3676,16 +3693,7 @@ finish_decl (tree decl, tree init, tree 
 	  TREE_USED (cleanup_decl) = 1;
 
 	  /* Initialize EH, if we've been told to do so.  */
-	  if (flag_exceptions && !c_eh_initialized_p)
-	    {
-	      c_eh_initialized_p = true;
-	      eh_personality_libfunc
-		= init_one_libfunc (USING_SJLJ_EXCEPTIONS
-				    ? "__gcc_personality_sj0"
-				    : "__gcc_personality_v0");
-	      default_init_unwind_resume_libfunc ();
-	      using_eh_for_cleanups ();
-	    }
+	  c_maybe_initialize_eh ();
 
 	  push_cleanup (decl, cleanup, false);
 	}
--- gcc/c-tree.h.jj	2006-11-01 10:31:36.000000000 +0100
+++ gcc/c-tree.h	2006-11-23 11:31:59.000000000 +0100
@@ -456,6 +456,7 @@ extern void declare_parm_level (void);
 extern void undeclared_variable (tree, location_t);
 extern tree declare_label (tree);
 extern tree define_label (location_t, tree);
+extern void c_maybe_initialize_eh (void);
 extern void finish_decl (tree, tree, tree);
 extern tree finish_enum (tree, tree, tree);
 extern void finish_function (void);
--- gcc/c-parser.c.jj	2006-10-22 10:39:42.000000000 +0200
+++ gcc/c-parser.c	2006-11-23 11:34:18.000000000 +0100
@@ -7755,6 +7755,12 @@ c_parser_omp_construct (c_parser *parser
   p_kind = c_parser_peek_token (parser)->pragma_kind;
   c_parser_consume_pragma (parser);
 
+  /* For all constructs below except #pragma omp atomic
+     MUST_NOT_THROW catch handlers are needed when exceptions
+     are enabled.  */
+  if (p_kind != PRAGMA_OMP_ATOMIC)
+    c_maybe_initialize_eh ();
+
   switch (p_kind)
     {
     case PRAGMA_OMP_ATOMIC:
--- gcc/testsuite/gcc.dg/gomp/pr29955.c.jj	2006-11-23 11:44:42.000000000 +0100
+++ gcc/testsuite/gcc.dg/gomp/pr29955.c	2006-11-23 11:44:37.000000000 +0100
@@ -0,0 +1,14 @@
+/* PR c/29955 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fopenmp -fexceptions" } */
+
+extern void bar (int);
+
+void
+foo (int n)
+{
+  int i;
+#pragma omp parallel for schedule(dynamic)
+  for (i = 0; i < n; i++)
+    bar (0);
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]