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