summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>2014-03-21 12:59:35 +0000
committerjamborm <jamborm@138bc75d-0d04-0410-961f-82ee72b054a4>2014-03-21 12:59:35 +0000
commitfa4052b343d0013312ab14f0b67ed171c88579fc (patch)
tree9a7d70708594301be7def95ae86b5e51f4577ef8
parent95d0bdb9b19503fcd85591b7bca82a0e32413c09 (diff)
downloadppe42-gcc-fa4052b343d0013312ab14f0b67ed171c88579fc.tar.gz
ppe42-gcc-fa4052b343d0013312ab14f0b67ed171c88579fc.zip
2014-03-21 Martin Jambor <mjambor@suse.cz>
PR ipa/59176 * cgraph.h (symtab_node): New flag body_removed. * ipa.c (symtab_remove_unreachable_nodes): Set body_removed flag when removing bodies. * symtab.c (dump_symtab_base): Dump body_removed flag. * cgraph.c (verify_edge_corresponds_to_fndecl): Skip nodes which had their bodies removed. testsuite/ * g++.dg/torture/pr59176.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@208748 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/cgraph.c9
-rw-r--r--gcc/cgraph.h4
-rw-r--r--gcc/ipa.c2
-rw-r--r--gcc/symtab.c2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr59176.C41
7 files changed, 70 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c56a5b7df52..57a7688de32 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
2014-03-21 Martin Jambor <mjambor@suse.cz>
+ PR ipa/59176
+ * cgraph.h (symtab_node): New flag body_removed.
+ * ipa.c (symtab_remove_unreachable_nodes): Set body_removed flag
+ when removing bodies.
+ * symtab.c (dump_symtab_base): Dump body_removed flag.
+ * cgraph.c (verify_edge_corresponds_to_fndecl): Skip nodes which
+ had their bodies removed.
+
+2014-03-21 Martin Jambor <mjambor@suse.cz>
+
PR ipa/60419
* ipa.c (symtab_remove_unreachable_nodes): Clear thunk flag of nodes
in the border.
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 577352faa9d..abfd63c9955 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -2604,8 +2604,13 @@ verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl)
node = cgraph_get_node (decl);
/* We do not know if a node from a different partition is an alias or what it
- aliases and therefore cannot do the former_clone_of check reliably. */
- if (!node || node->in_other_partition || e->callee->in_other_partition)
+ aliases and therefore cannot do the former_clone_of check reliably. When
+ body_removed is set, we have lost all information about what was alias or
+ thunk of and also cannot proceed. */
+ if (!node
+ || node->body_removed
+ || node->in_other_partition
+ || e->callee->in_other_partition)
return false;
node = cgraph_function_or_thunk_node (node, NULL);
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 32b1ee17fa3..59d9ce66845 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -91,7 +91,9 @@ public:
unsigned forced_by_abi : 1;
/* True when the name is known to be unique and thus it does not need mangling. */
unsigned unique_name : 1;
-
+ /* True when body and other characteristics have been removed by
+ symtab_remove_unreachable_nodes. */
+ unsigned body_removed : 1;
/*** WHOPR Partitioning flags.
These flags are used at ltrans stage when only part of the callgraph is
diff --git a/gcc/ipa.c b/gcc/ipa.c
index 164de0dc9df..d23031286f2 100644
--- a/gcc/ipa.c
+++ b/gcc/ipa.c
@@ -484,6 +484,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
{
if (file)
fprintf (file, " %s", node->name ());
+ node->body_removed = true;
node->analyzed = false;
node->definition = false;
node->cpp_implicit_alias = false;
@@ -543,6 +544,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
fprintf (file, " %s", vnode->name ());
changed = true;
}
+ vnode->body_removed = true;
vnode->definition = false;
vnode->analyzed = false;
vnode->aux = NULL;
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 2d6f665b120..4db4870fa4e 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -601,6 +601,8 @@ dump_symtab_base (FILE *f, symtab_node *node)
? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME
(node->alias_target))
: IDENTIFIER_POINTER (node->alias_target));
+ if (node->body_removed)
+ fprintf (f, "\n Body removed by symtab_remove_unreachable_nodes");
fprintf (f, "\n Visibility:");
if (node->in_other_partition)
fprintf (f, " in_other_partition");
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 581efab5981..9740621934c 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2014-03-21 Martin Jambor <mjambor@suse.cz>
+ PR ipa/59176
+ * g++.dg/torture/pr59176.C: New test.
+
+2014-03-21 Martin Jambor <mjambor@suse.cz>
+
PR ipa/60419
* g++.dg/ipa/pr60419.C: New test.
diff --git a/gcc/testsuite/g++.dg/ipa/pr59176.C b/gcc/testsuite/g++.dg/ipa/pr59176.C
new file mode 100644
index 00000000000..d576bc3ba5a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr59176.C
@@ -0,0 +1,41 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+template <class> class A {
+protected:
+ void m_fn2();
+ ~A() { m_fn2(); }
+ virtual void m_fn1();
+};
+
+class D : A<int> {};
+template <class Key> void A<Key>::m_fn2() {
+ m_fn1();
+ m_fn1();
+ m_fn1();
+}
+
+#pragma interface
+class B {
+ D m_cellsAlreadyProcessed;
+ D m_cellsNotToProcess;
+
+public:
+ virtual ~B() {}
+ void m_fn1();
+};
+
+class C {
+ unsigned long m_fn1();
+ B m_fn2();
+ unsigned long m_fn3();
+};
+unsigned long C::m_fn1() {
+CellHierarchy:
+ m_fn2().m_fn1();
+}
+
+unsigned long C::m_fn3() {
+CellHierarchy:
+ m_fn2().m_fn1();
+}
OpenPOWER on IntegriCloud