This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] PR c++/27574
- From: Dodji Seketeli <dodji at redhat dot com>
- To: jh at suse dot cz
- Cc: Gcc Patch List <gcc-patches at gcc dot gnu dot org>, Jason Merrill <jason at redhat dot com>, Jan Hubicka <hubicka at ucw dot cz>
- Date: Thu, 09 Oct 2008 09:05:08 +0200
- Subject: Re: [PATCH] PR c++/27574
- References: <48C056E3.1020305@redhat.com> <48DA9B09.7060001@redhat.com> <48DCDAA5.6000809@redhat.com> <48DD597D.6090705@redhat.com> <20080926215724.GB746@atrey.karlin.mff.cuni.cz> <48E24B64.3060608@redhat.com> <48EA68F0.60905@redhat.com> <48EA92AA.6080105@redhat.com>
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;
+}
+