summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2005-04-24 22:06:37 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2005-04-24 22:06:37 +0000
commit880afb804d8c8dd903dacb8c3e1383a80eba225c (patch)
treeceb41f874d3b1e3d612a3d2785020f503973c21a /gcc
parent37f365e40bb5019ddbc2feb1828501587dc6b43b (diff)
downloadgcc-880afb804d8c8dd903dacb8c3e1383a80eba225c.tar.gz
PR middle-end/20991
* cgraph.h (cgraph_local_info): Add vtable_method field. * varasm.c (mark_decl_referenced): If cgraph_global_info_ready and node is vtable_method, finalized and not reachable, don't do anything. * class.c: Include cgraph.h. (cp_fold_obj_type_ref): Set node->local.vtable_method. * Make-lang.in (cgraph.o): Depend on $(CGRAPH_H). * g++.dg/opt/pr20991.C: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@98674 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/cgraph.h4
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/Make-lang.in3
-rw-r--r--gcc/cp/class.c3
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/opt/pr20991.C34
-rw-r--r--gcc/varasm.c12
8 files changed, 70 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2b72034591b..b392d668df3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2005-04-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/20991
+ * cgraph.h (cgraph_local_info): Add vtable_method field.
+ * varasm.c (mark_decl_referenced): If cgraph_global_info_ready
+ and node is vtable_method, finalized and not reachable, don't do
+ anything.
+
2005-04-24 Kazu Hirata <kazu@cs.umass.edu>
* tree-ssa-copy.c (copy_prop_visit_cond_stmt): Use
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 02fa662061f..fc0fa7858e5 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -51,6 +51,10 @@ struct cgraph_local_info GTY(())
/* True if statics_read_for_function and
statics_written_for_function contain valid data. */
bool for_functions_valid;
+
+ /* True if the function is going to be emitted in some other translation
+ unit, referenced from vtable. */
+ bool vtable_method;
};
/* Information about the function that needs to be computed globally
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a0ebc891a55..07f7daa5f5b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2005-04-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/20991
+ * class.c: Include cgraph.h.
+ (cp_fold_obj_type_ref): Set node->local.vtable_method.
+ * Make-lang.in (cgraph.o): Depend on $(CGRAPH_H).
+
2005-04-12 Markus F.X.J. Oberhumer <markus@oberhumer.com>
* mangle.c (write_builtin_type): Handle integer types which are
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 00075b30a9f..eeb41290892 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -243,7 +243,8 @@ cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h $(TM_
diagnostic.h gt-cp-typeck2.h
cp/typeck.o: cp/typeck.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) $(EXPR_H) toplev.h \
diagnostic.h convert.h c-common.h
-cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(TARGET_H) convert.h
+cp/class.o: cp/class.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(TARGET_H) \
+ convert.h $(CGRAPH_H)
cp/call.o: cp/call.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h $(RTL_H) $(EXPR_H) \
diagnostic.h intl.h gt-cp-call.h convert.h target.h
cp/friend.o: cp/friend.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) toplev.h $(EXPR_H)
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 6423fbcf894..5052aaaf6b0 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -35,6 +35,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "target.h"
#include "convert.h"
+#include "cgraph.h"
/* The number of nested classes being processed. If we are not in the
scope of any class, this is zero. */
@@ -7719,6 +7720,8 @@ cp_fold_obj_type_ref (tree ref, tree known_type)
DECL_VINDEX (fndecl)));
#endif
+ cgraph_node (fndecl)->local.vtable_method = true;
+
return build_address (fndecl);
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 79373868287..f58b43c1ac7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2005-04-24 Jakub Jelinek <jakub@redhat.com>
+ PR middle-end/20991
+ * g++.dg/opt/pr20991.C: New test.
+
* gcc.dg/compat/struct-layout-1_generate.c: In arrays avoid types
where sizeof (type) < __alignof__ (type).
* gcc.dg/compat/struct-layout-1.h: Likewise.
diff --git a/gcc/testsuite/g++.dg/opt/pr20991.C b/gcc/testsuite/g++.dg/opt/pr20991.C
new file mode 100644
index 00000000000..32b3d05c351
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr20991.C
@@ -0,0 +1,34 @@
+// PR middle-end/20991
+// { dg-options "-O2" }
+// { dg-do compile }
+
+struct S
+{
+ virtual inline int foo () const;
+ virtual inline bool bar () const;
+ virtual int baz (int) const;
+};
+
+inline int S::foo () const
+{
+ return 1;
+}
+
+inline bool S::bar () const
+{
+ return foo () == 0;
+}
+
+void A ()
+{
+ S s;
+ if (s.bar ())
+ s.foo ();
+}
+
+void B ()
+{
+ S s;
+ if (s.bar ())
+ s.foo ();
+}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 86d386e0ff8..bab9437ec0a 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -1955,9 +1955,15 @@ mark_decl_referenced (tree decl)
{
if (TREE_CODE (decl) == FUNCTION_DECL)
{
- /* Extern inline functions don't become needed when referenced. */
- if (!DECL_EXTERNAL (decl))
- cgraph_mark_needed_node (cgraph_node (decl));
+ /* Extern inline functions don't become needed when referenced.
+ If we know a method will be emitted in other TU and no new
+ functions can be marked reachable, just use the external
+ definition. */
+ struct cgraph_node *node = cgraph_node (decl);
+ if (!DECL_EXTERNAL (decl)
+ && (!node->local.vtable_method || !cgraph_global_info_ready
+ || !node->local.finalized))
+ cgraph_mark_needed_node (node);
}
else if (TREE_CODE (decl) == VAR_DECL)
{