]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/57670 (Member-pointer calls should not be redirected to builtin_unre...
authorMartin Jambor <mjambor@suse.cz>
Tue, 25 Jun 2013 11:09:21 +0000 (13:09 +0200)
committerMartin Jambor <jamborm@gcc.gnu.org>
Tue, 25 Jun 2013 11:09:21 +0000 (13:09 +0200)
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

gcc/ChangeLog
gcc/cgraph.h
gcc/ipa-prop.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ipa/pr57670.C [new file with mode: 0644]

index f0af61e8f996e06064ece548e35dad9eb6826255..9367386a2f6c97834b6e936d7650751e1a4abe91 100644 (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
index 1e17cb70e8dbe5a99fc1b6edc259e2d56a80faee..e66eecd4d2712c367085177c96b41eaeb0ef251c 100644 (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;
index ae6825b003a807810729162f3797d94adba58a97..62d7a3c5e845f1f9b40fea42c1cf97a21e5417ca 100644 (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)
     {
index 8c9f01af686f0a71b0bf928b2c74b0062ba29ecf..380fbf5978d183f5d4284d9263bd6c33593bced9 100644 (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
diff --git a/gcc/testsuite/g++.dg/ipa/pr57670.C b/gcc/testsuite/g++.dg/ipa/pr57670.C
new file mode 100644 (file)
index 0000000..400612e
--- /dev/null
@@ -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;
+}