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]

[C++ PATCH] Fix finish_function recursion (PR c++/37189)


Hi!

This is admittedly ugly, but I don't know how to solve it differently
without rewriting substantial part of the OpenMP support.

The problem is that the discovery of OpenMP implicitly determined variables
is done at gimplification time.  If a variable is implicitly determined
as firstprivate and it has a class type, we need its copy ctor and dtor, but
it is possible it needs to be synthetized.  This leads to calling
cp_genericize while in the gimplifier for another function, which is fatal.
Here is a backtrace of the ICE.

#0  fancy_abort (file=0x112e351 "../../gcc/gimplify.c", line=7199, function=0x112fba5 "gimplify_body")
    at ../../gcc/diagnostic.c:699
#1  0x00000000009423fd in gimplify_body (body_p=0x7ffff3286498, fndecl=0x7ffff3286400, do_parms=1 '\001')
    at ../../gcc/gimplify.c:7199
#2  0x000000000094295c in gimplify_function_tree (fndecl=0x7ffff3286400) at ../../gcc/gimplify.c:7296
#3  0x00000000006bb0af in c_genericize (fndecl=0x7ffff3286400) at ../../gcc/c-gimplify.c:105
#4  0x000000000065b22b in cp_genericize (fndecl=0x7ffff3286400) at ../../gcc/cp/cp-gimplify.c:823
#5  0x000000000046b21e in finish_function (flags=0) at ../../gcc/cp/decl.c:12193
#6  0x00000000005ce1ce in synthesize_method (fndecl=0x7ffff3286400) at ../../gcc/cp/method.c:804
#7  0x0000000000542498 in mark_used (decl=0x7ffff3286500) at ../../gcc/cp/decl2.c:3829
#8  0x000000000041c26e in build_over_call (cand=0x170a950, flags=3, complain=tf_warning_or_error) at ../../gcc/cp/call.c:5317
#9  0x000000000041f908 in build_new_method_call (instance=0x7ffff3288b80, fns=0x7ffff3285360, args=0x7ffff3285690, 
    conversion_path=0x7ffff3283310, flags=3, fn_p=0x0, complain=tf_warning_or_error) at ../../gcc/cp/call.c:5935
#10 0x000000000041e1a4 in build_special_member_call (instance=0x7ffff3288b80, name=0x7ffff3328c00, args=0x7ffff3285690, 
    binfo=0x7ffff3283310, flags=3, complain=tf_warning_or_error) at ../../gcc/cp/call.c:5642
#11 0x00000000005ec604 in cxx_omp_create_clause_info (c=0x7ffff3288ac0, type=0x7ffff3281600, need_default_ctor=0 '\0', 
    need_copy_ctor=1 '\001', need_copy_assignment=0 '\0') at ../../gcc/cp/semantics.c:3427
#12 0x000000000065cc65 in cxx_omp_finish_clause (c=0x7ffff3288ac0) at ../../gcc/cp/cp-gimplify.c:1100
#13 0x0000000000935975 in gimplify_adjust_omp_clauses_1 (n=0x1706440, data=0x7ffff3288978) at ../../gcc/gimplify.c:5637
...
#24 0x0000000000931efc in gimplify_stmt (stmt_p=0x7ffff3286098, seq_p=0x7fffffffdb78) at ../../gcc/gimplify.c:5025
#25 0x00000000009424c2 in gimplify_body (body_p=0x7ffff3286098, fndecl=0x7ffff3286000, do_parms=1 '\001')
    at ../../gcc/gimplify.c:7218
#26 0x000000000094295c in gimplify_function_tree (fndecl=0x7ffff3286000) at ../../gcc/gimplify.c:7296
#27 0x00000000006bb0af in c_genericize (fndecl=0x7ffff3286000) at ../../gcc/c-gimplify.c:105
#28 0x000000000065b22b in cp_genericize (fndecl=0x7ffff3286000) at ../../gcc/cp/cp-gimplify.c:823
#29 0x000000000046b21e in finish_function (flags=0) at ../../gcc/cp/decl.c:12193

Rewriting OpenMP support to move discovery of implicitly determined variables
to the FEs would mean code duplication, and the gimplifier would need to
keep the code anyway to handle gimplifier generated variables.  So
this patch instead will defer all mark_used calls encountered during finish_function
call until the end of that function.  Regtested on x86_64-linux, ok for trunk?

2008-09-03  Jakub Jelinek  <jakub@redhat.com>

	PR c++/37189
	* cp-tree.h (defer_mark_used_calls, deferred_mark_used_calls): New
	extern decls.
	* decl2.c (mark_used): If defer_mark_used_calls, push decl into
	deferred_mark_used_calls vector and exit early.
	* decl.c (defer_mark_used_calls, deferred_mark_used_calls): New
	variables.
	(finish_function): Set defer_mark_used_calls for the duration of the
	function.  Call mark_used on any queued decls.

	* g++.dg/gomp/pr37189.C: New test.

--- gcc/cp/cp-tree.h.jj	2008-09-01 10:44:36.000000000 +0200
+++ gcc/cp/cp-tree.h	2008-09-03 10:33:52.000000000 +0200
@@ -4375,6 +4375,9 @@ extern void initialize_artificial_var		(
 extern tree check_var_type			(tree, tree);
 extern tree reshape_init (tree, tree);
 
+extern bool defer_mark_used_calls;
+extern GTY(()) VEC(tree, gc) *deferred_mark_used_calls;
+
 /* in decl2.c */
 extern bool check_java_method			(tree);
 extern tree build_memfn_type			(tree, tree, cp_cv_quals);
--- gcc/cp/decl2.c.jj	2008-08-19 14:20:30.000000000 +0200
+++ gcc/cp/decl2.c	2008-09-03 10:42:08.000000000 +0200
@@ -3770,6 +3770,15 @@ mark_used (tree decl)
   /* If we don't need a value, then we don't need to synthesize DECL.  */
   if (skip_evaluation)
     return;
+
+  /* If within finish_function, defer the rest until that function
+     finishes, otherwise it might recurse.  */
+  if (defer_mark_used_calls)
+    {
+      VEC_safe_push (tree, gc, deferred_mark_used_calls, decl);
+      return;
+    }
+
   /* Normally, we can wait until instantiation-time to synthesize
      DECL.  However, if DECL is a static data member initialized with
      a constant, we need the value right now because a reference to
--- gcc/cp/decl.c.jj	2008-09-01 10:44:36.000000000 +0200
+++ gcc/cp/decl.c	2008-09-03 10:27:27.000000000 +0200
@@ -227,6 +227,11 @@ struct named_label_entry GTY(())
    function, two inside the body of a function in a local class, etc.)  */
 int function_depth;
 
+/* To avoid unwanted recursion, finish_function defers all mark_used calls
+   encountered during its execution until it finishes.  */
+bool defer_mark_used_calls;
+VEC(tree, gc) *deferred_mark_used_calls;
+
 /* States indicating how grokdeclarator() should handle declspecs marked
    with __attribute__((deprecated)).  An object declared as
    __attribute__((deprecated)) suppresses warnings of uses of other
@@ -12033,6 +12038,8 @@ finish_function (int flags)
   if (fndecl == NULL_TREE)
     return error_mark_node;
 
+  defer_mark_used_calls = true;
+
   if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
       && DECL_VIRTUAL_P (fndecl)
       && !processing_template_decl)
@@ -12232,6 +12239,17 @@ finish_function (int flags)
        cxx_pop_function_context and then reset via pop_function_context.  */
     current_function_decl = NULL_TREE;
 
+  defer_mark_used_calls = false;
+  if (deferred_mark_used_calls)
+    {
+      unsigned int i;
+      tree decl;
+
+      for (i = 0; VEC_iterate (tree, deferred_mark_used_calls, i, decl); i++)
+	mark_used (decl);
+      VEC_free (tree, gc, deferred_mark_used_calls);
+    }
+
   return fndecl;
 }
 
--- gcc/testsuite/g++.dg/gomp/pr37189.C.jj	2008-09-03 10:44:41.000000000 +0200
+++ gcc/testsuite/g++.dg/gomp/pr37189.C	2008-09-03 10:44:17.000000000 +0200
@@ -0,0 +1,27 @@
+// PR c++/37189
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+struct S
+{
+  S () {}
+  S (S const &) {}
+};
+
+struct T
+{
+  S s;
+};
+
+void
+bar (T &)
+{
+}
+
+int
+foo ()
+{
+  T t;
+  #pragma omp task
+    bar (t);
+}

	Jakub


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