aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Jambor <mjambor@suse.cz>2013-06-25 13:09:21 +0200
committerMartin Jambor <jamborm@gcc.gnu.org>2013-06-25 13:09:21 +0200
commitc13bc3d998b26a9d50c6bb07d0f8f372117e7a20 (patch)
treed82bab7c445398d72a006a056d61c12cf0f00522
parent6cdbb7e8a1f92fcc2504d56d68ff981803d499a7 (diff)
downloadgcc-c13bc3d998b26a9d50c6bb07d0f8f372117e7a20.zip
gcc-c13bc3d998b26a9d50c6bb07d0f8f372117e7a20.tar.gz
gcc-c13bc3d998b26a9d50c6bb07d0f8f372117e7a20.tar.bz2
re PR middle-end/57670 (Member-pointer calls should not be redirected to builtin_unreachable)
2013-06-25 Martin Jambor <mjambor@suse.cz> PR middle-end/57670 * cgraph.h (cgraph_indirect_call_info): New flag member_ptr. * ipa-prop.c (ipa_print_node_jump_functions): Mark member pointer calls in the dump. (ipa_note_param_call): Initialize member_ptr flag. (ipa_analyze_indirect_call_uses): Set member_ptr flag. (ipa_make_edge_direct_to_target): Bail out if member_ptr is set. (ipa_write_indirect_edge_info): Stream member_ptr flag. (ipa_read_indirect_edge_info): Likewise. testsuite/ * g++.dg/ipa/pr57670.C (H): New test. From-SVN: r200393
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/cgraph.h2
-rw-r--r--gcc/ipa-prop.c11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr57670.C37
5 files changed, 66 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f0af61e..9367386 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2013-06-25 Martin Jambor <mjambor@suse.cz>
+
+ PR middle-end/57670
+ * cgraph.h (cgraph_indirect_call_info): New flag member_ptr.
+ * ipa-prop.c (ipa_print_node_jump_functions): Mark member pointer
+ calls in the dump.
+ (ipa_note_param_call): Initialize member_ptr flag.
+ (ipa_analyze_indirect_call_uses): Set member_ptr flag.
+ (ipa_make_edge_direct_to_target): Bail out if member_ptr is set.
+ (ipa_write_indirect_edge_info): Stream member_ptr flag.
+ (ipa_read_indirect_edge_info): Likewise.
+
2013-06-25 Richard Biener <rguenther@suse.de>
PR middle-end/56977
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 1e17cb7..e66eecd 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -440,6 +440,8 @@ struct GTY(()) cgraph_indirect_call_info
/* Set when the call is a call of a pointer loaded from contents of an
aggregate at offset. */
unsigned agg_contents : 1;
+ /* Set when this is a call through a member pointer. */
+ unsigned member_ptr : 1;
/* When the previous bit is set, this one determines whether the destination
is loaded from a parameter passed by reference. */
unsigned by_ref : 1;
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index ae6825b..62d7a3c 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -303,8 +303,9 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node)
ii = cs->indirect_info;
if (ii->agg_contents)
- fprintf (f, " indirect aggregate callsite, calling param %i, "
+ fprintf (f, " indirect %s callsite, calling param %i, "
"offset " HOST_WIDE_INT_PRINT_DEC ", %s",
+ ii->member_ptr ? "member ptr" : "aggregate",
ii->param_index, ii->offset,
ii->by_ref ? "by reference" : "by_value");
else
@@ -1626,6 +1627,7 @@ ipa_note_param_call (struct cgraph_node *node, int param_index, gimple stmt)
cs->indirect_info->offset = 0;
cs->indirect_info->polymorphic = 0;
cs->indirect_info->agg_contents = 0;
+ cs->indirect_info->member_ptr = 0;
return cs;
}
@@ -1819,6 +1821,7 @@ ipa_analyze_indirect_call_uses (struct cgraph_node *node,
struct cgraph_edge *cs = ipa_note_param_call (node, index, call);
cs->indirect_info->offset = offset;
cs->indirect_info->agg_contents = 1;
+ cs->indirect_info->member_ptr = 1;
}
return;
@@ -2239,6 +2242,10 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target)
target = canonicalize_constructor_val (target, NULL);
if (!target || TREE_CODE (target) != FUNCTION_DECL)
{
+ if (ie->indirect_info->member_ptr)
+ /* Member pointer call that goes through a VMT lookup. */
+ return NULL;
+
if (dump_file)
fprintf (dump_file, "ipa-prop: Discovered direct call to non-function"
" in %s/%i, making it unreachable.\n",
@@ -3792,6 +3799,7 @@ ipa_write_indirect_edge_info (struct output_block *ob,
bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, ii->polymorphic, 1);
bp_pack_value (&bp, ii->agg_contents, 1);
+ bp_pack_value (&bp, ii->member_ptr, 1);
bp_pack_value (&bp, ii->by_ref, 1);
streamer_write_bitpack (&bp);
@@ -3818,6 +3826,7 @@ ipa_read_indirect_edge_info (struct lto_input_block *ib,
bp = streamer_read_bitpack (ib);
ii->polymorphic = bp_unpack_value (&bp, 1);
ii->agg_contents = bp_unpack_value (&bp, 1);
+ ii->member_ptr = bp_unpack_value (&bp, 1);
ii->by_ref = bp_unpack_value (&bp, 1);
if (ii->polymorphic)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 8c9f01a..380fbf5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2013-06-25 Martin Jambor <mjambor@suse.cz>
+
+ PR middle-end/57670
+ * g++.dg/ipa/pr57670.C: New test.
+
2013-06-25 Richard Biener <rguenther@suse.de>
PR middle-end/56977
diff --git a/gcc/testsuite/g++.dg/ipa/pr57670.C b/gcc/testsuite/g++.dg/ipa/pr57670.C
new file mode 100644
index 0000000..400612e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr57670.C
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fno-early-inlining" } */
+
+class H
+{
+public:
+ virtual unsigned bar() const { return 16; }
+};
+
+class A : public H
+{
+ unsigned foo(unsigned (H::*func)(void) const) const;
+public:
+ H *h;
+ virtual unsigned bar() const;
+};
+
+unsigned A::foo(unsigned (H::*func)(void) const) const
+{
+ return (h->*func)();
+}
+
+unsigned A::bar() const
+{
+ return foo(&H::bar);
+}
+
+int main (int argc, char **argv)
+{
+ H h;
+ A a;
+ a.h = &h;
+
+ if (a.bar() != 16)
+ __builtin_abort ();
+ return 0;
+}