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]

Re: [PATCH] PR c++/27574


Jason Merrill a écrit :

[...]

Jan, I did post a superset of Ian's patch to make the sanity check code not cry when it encounters abstract functions. Could you please tell if it looks okay to you so that I can push it to the released branches ? The post is at http://gcc.gnu.org/ml/gcc-patches/2008-09/msg01815.html.

s/comply/complain/



Thanks. The first attached patch named PR27574-patch-for-released-branches.txt fixes that.


[...]

I think it would be better to do it the other way around; if a function we still need has DECL_ABSTRACT_ORIGIN, we need to keep the decl it points to.

[...]


The second attached patch named patches/PR27574-patch-for-trunk.txt tries to implement that approach.

So would the first patch be OK to apply to the released branches and the second for trunk ? Both pass distcheck on x86_64.

Cheers,

Dodji.

gcc/Changelog:
    PR c++/27574
    * gcc/cgraph.c (cgraph_remove_node): Do not remove the body of
      abstract functions. It might be useful to emit debugging
      information. This is a patch from Ian Lance Taylor.
    * cgraphunit.c (cgraph_optimize): Do not cry when bodies of abstract
      functions are still around. They are useful to output debug info.

gcc/testsuite/ChangeLog:
    PR c++/27574
    * g++.dg/debug/dwarf2/local-var-in-contructor.C: New testcase.


diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 199c639..3d21190 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -479,6 +479,14 @@ cgraph_remove_node (struct cgraph_node *node)
 	kill_body = true;
     }
 
+  /* We don't release the body of abstract functions, because they may
+     be needed when emitting debugging information.  In particular
+     this will happen for C++ constructors/destructors.  FIXME:
+     Ideally we would check to see whether there are any reachable
+     functions whose DECL_ABSTRACT_ORIGIN points to this decl.  */
+  if (DECL_ABSTRACT (node->decl))
+    kill_body = false;
+
   if (kill_body && !dump_enabled_p (TDI_tree_all) && flag_unit_at_a_time)
     {
       DECL_SAVED_TREE (node->decl) = NULL;
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 65a8651..83b070d 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1391,7 +1391,10 @@ cgraph_optimize (void)
       for (node = cgraph_nodes; node; node = node->next)
 	if (node->analyzed
 	    && (node->global.inlined_to
-	        || DECL_SAVED_TREE (node->decl)))
+	        || DECL_SAVED_TREE (node->decl))
+            /* Abstract functions are needed to output debug info,
+               so don't complain about them if they are still around.  */
+            && !DECL_ABSTRACT (node->decl))
 	  {
 	    error_found = true;
 	    dump_cgraph_node (stderr, node);
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/local-var-in-contructor.C b/gcc/testsuite/g++.dg/debug/dwarf2/local-var-in-contructor.C
new file mode 100644
index 0000000..d61d27f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/local-var-in-contructor.C
@@ -0,0 +1,30 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR27574
+// { dg-do compile }
+// { dg-options "-O0 -g" }
+// { dg-final { scan-assembler "problem" } }
+
+void f (int *)
+{
+}
+
+class A
+{
+public:
+ A(int i);
+};
+
+A::A(int i)
+{
+ int *problem = new int(i);
+ f (problem);
+}
+
+int
+main (void)
+{
+  A a (0);
+
+  return 0;
+}
+
gcc/ChangeLog:
2008-10-08  Dodji Seketeli  <dodji@redhat.com>

	PR debug/27574
	* cgraph.h: New abstract_and_needed member to struct cgraph_node.
	* cgraphunit.c (cgraph_analyze_functions): Flag abstract functions
	  - which clones are reachable - as "abstract and needed".
	  Then make sure the body of those abstract and needed functions
	  are not dropped because they are used to emit debug info.
	  (cgraph_mark_functions_to_output): Do not complain if some abstract and
	  needed functions are still around.
	  (cgraph_optimize): Likewise.
	* ipa.c (cgraph_remove_unreachable_nodes): Do not remove abstract and
	  needed functions nodes.

gcc/testsuite/ChangeLog:
2008-10-08  Dodji Seketeli  <dodji@redhat.com>

	PR debug/27574
	* g++.dg/debug/dwarf2/local-var-in-contructor.C: New test.


diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index a6018dc..7825804 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -166,6 +166,9 @@ struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous")))
   /* Set when function must be output - it is externally visible
      or its address is taken.  */
   unsigned needed : 1;
+  /* Set when decl is an abstract function pointed to by the
+     ABSTRACT_DECL_ORIGIN of a reachable function.  */
+  unsigned abstract_and_needed : 1;
   /* Set when function is reachable by call from other function
      that is either reachable or needed.  */
   unsigned reachable : 1;
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 7c84573..754d4e7 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -896,6 +896,15 @@ cgraph_analyze_functions (void)
 	if (!edge->callee->reachable)
 	  cgraph_mark_reachable_node (edge->callee);
 
+      /* If decl is a clone of an abstract function, mark that abstract
+	 function so that we don't release its body. That abstract function body will
+	 be needed to output debug info.  */
+      if (DECL_ABSTRACT_ORIGIN (decl))
+	{
+	  struct cgraph_node *origin_node = cgraph_node (DECL_ABSTRACT_ORIGIN (decl));
+	  origin_node->abstract_and_needed = true;
+	}
+
       /* We finalize local static variables during constructing callgraph
          edges.  Process their attributes too.  */
       process_function_and_variable_attributes (first_processed,
@@ -928,7 +937,7 @@ cgraph_analyze_functions (void)
       if (node->local.finalized && !gimple_has_body_p (decl))
 	cgraph_reset_node (node);
 
-      if (!node->reachable && gimple_has_body_p (decl))
+      if (!node->reachable && gimple_has_body_p (decl) && !node->abstract_and_needed)
 	{
 	  if (cgraph_dump_file)
 	    fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
@@ -1003,7 +1012,8 @@ cgraph_mark_functions_to_output (void)
 #ifdef ENABLE_CHECKING
 	  if (!node->global.inlined_to
 	      && gimple_has_body_p (decl)
-	      && !DECL_EXTERNAL (decl))
+	      && !DECL_EXTERNAL (decl)
+	      && !node->abstract_and_needed)
 	    {
 	      dump_cgraph_node (stderr, node);
 	      internal_error ("failed to reclaim unneeded function");
@@ -1011,7 +1021,8 @@ cgraph_mark_functions_to_output (void)
 #endif
 	  gcc_assert (node->global.inlined_to
 		      || !gimple_has_body_p (decl)
-		      || DECL_EXTERNAL (decl));
+		      || DECL_EXTERNAL (decl)
+		      || node->abstract_and_needed);
 
 	}
 
@@ -1325,7 +1336,11 @@ cgraph_optimize (void)
       for (node = cgraph_nodes; node; node = node->next)
 	if (node->analyzed
 	    && (node->global.inlined_to
-		|| gimple_has_body_p (node->decl)))
+		|| gimple_has_body_p (node->decl))
+            /* Abstract functions are needed to output debug info,
+	       so don't complain about them if they are
+               still around.  */
+	    && !node->abstract_and_needed)
 	  {
 	    error_found = true;
 	    dump_cgraph_node (stderr, node);
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 0e2cb2d..e5c3115 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -160,8 +160,8 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
           node->global.inlined_to = NULL;
 	  if (file)
 	    fprintf (file, " %s", cgraph_node_name (node));
-	  if (!node->analyzed || !DECL_EXTERNAL (node->decl)
-	      || before_inlining_p)
+	  if ((!node->analyzed || !DECL_EXTERNAL (node->decl)
+	      || before_inlining_p) && !node->abstract_and_needed)
 	    cgraph_remove_node (node);
 	  else
 	    {
@@ -187,7 +187,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
 		  node->analyzed = false;
 		  node->local.inlinable = false;
 		}
-	      else
+	      else if (!node->abstract_and_needed)
 		cgraph_remove_node (node);
 	    }
 	  changed = true;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/local-var-in-contructor.C b/gcc/testsuite/g++.dg/debug/dwarf2/local-var-in-contructor.C
new file mode 100644
index 0000000..d61d27f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/local-var-in-contructor.C
@@ -0,0 +1,30 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR27574
+// { dg-do compile }
+// { dg-options "-O0 -g" }
+// { dg-final { scan-assembler "problem" } }
+
+void f (int *)
+{
+}
+
+class A
+{
+public:
+ A(int i);
+};
+
+A::A(int i)
+{
+ int *problem = new int(i);
+ f (problem);
+}
+
+int
+main (void)
+{
+  A a (0);
+
+  return 0;
+}
+

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