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
This commit is contained in:
Martin Jambor 2013-06-25 13:09:21 +02:00 committed by Martin Jambor
parent 6cdbb7e8a1
commit c13bc3d998
5 changed files with 66 additions and 1 deletions

View File

@ -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

View File

@ -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;

View File

@ -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)
{

View File

@ -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

View File

@ -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;
}