Hi,
while working on the devirt code, I noticed that sometimes we get
as a type of object a non-classes (like void types).  This is
because we look up object's class from the OBJ_TYPE_REF_OBJECT
and this is a generic pointer that gimple passes like to change
type of.

I tracked down few cases. For example when compiling passes.c one
gets copyrename changing

from
void execute_ipa_summary_passes(ipa_opt_pass_d*) (struct ipa_opt_pass_d * 
ipa_pass)
{
...
   struct opt_pass * pass
...
   pass_12 = ipa_pass_1;
...
  _20 = OBJ_TYPE_REF(_18;pass_12->3) (pass_12);


to

  ipa_pass_12 = ipa_pass_1
...
  _20 = OBJ_TYPE_REF(_18;ipa_pass_12->3) (ipa_pass_12);

Ths makes us to believe that OBJ_TYPE_REF reffers to call of
method of ipa_opt_pass_d instead of opt_pass.  This is wrong and
I believe it may lead to wrong code, too - the tokens have
different meanings.

This patch changes code looking up OTR types to actually look
into OTR type (that is pointer to method) and look the class
type from type of the method's this pointer.

Bootstrapped/regtested x86_64-linux, OK?

        * tree.c (obj_type_ref_class): New function.
        * tree.h (obj_type_ref_class): Declare.
        * ipa-prop.c (ipa_analyze_virtual_call_uses): Use it.


Index: tree.c
===================================================================
--- tree.c      (revision 201764)
+++ tree.c      (working copy)
@@ -11864,6 +11892,21 @@ types_same_for_odr (tree type1, tree typ
   return true;
 }
 
+/* REF is OBJ_TYPE_REF, return the class the ref corresponds to.  */
+
+tree
+obj_type_ref_class (tree ref)
+{
+  gcc_checking_assert (TREE_CODE (ref) == OBJ_TYPE_REF);
+  ref = TREE_TYPE (ref);
+  gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
+  ref = TREE_TYPE (ref);
+  gcc_checking_assert (TREE_CODE (ref) == METHOD_TYPE);
+  ref = TREE_VALUE (TYPE_ARG_TYPES (ref));
+  gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
+  return TREE_TYPE (ref);
+}
+
 /* Try to find a base info of BINFO that would have its field decl at offset
    OFFSET within the BINFO type and which is of EXPECTED_TYPE.  If it can be
    found, return, otherwise return NULL_TREE.  */
Index: tree.h
===================================================================
--- tree.h      (revision 201764)
+++ tree.h      (working copy)
@@ -5974,6 +5974,7 @@ extern location_t tree_nonartificial_loc
 extern tree block_ultimate_origin (const_tree);
 
 extern tree get_binfo_at_offset (tree, HOST_WIDE_INT, tree);
+extern tree obj_type_ref_class (tree ref);
 extern bool types_same_for_odr (tree type1, tree type2);
 extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
                                     HOST_WIDE_INT *, HOST_WIDE_INT *);
Index: ipa-prop.c
===================================================================
--- ipa-prop.c  (revision 201764)
+++ ipa-prop.c  (working copy)
@@ -1903,7 +1903,7 @@ ipa_analyze_virtual_call_uses (struct cg
   ii = cs->indirect_info;
   ii->offset = anc_offset;
   ii->otr_token = tree_low_cst (OBJ_TYPE_REF_TOKEN (target), 1);
-  ii->otr_type = TREE_TYPE (TREE_TYPE (OBJ_TYPE_REF_OBJECT (target)));
+  ii->otr_type = obj_type_ref_class (target);
   ii->polymorphic = 1;
 }
 

Reply via email to