aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-devirt.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2014-02-04 06:40:21 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2014-02-04 05:40:21 +0000
commit5bccb77a773b916d4824688e9138921f93c35039 (patch)
treec78cc4b81e9fffb8c0810f34976aecfcf20b5c3d /gcc/ipa-devirt.c
parent9de2f554ec689296676dee4f4482e059438a5991 (diff)
downloadgcc-5bccb77a773b916d4824688e9138921f93c35039.zip
gcc-5bccb77a773b916d4824688e9138921f93c35039.tar.gz
gcc-5bccb77a773b916d4824688e9138921f93c35039.tar.bz2
ipa-cp.c (ipa_get_indirect_edge_target_1): Do direct lookup via vtable pointer...
* ipa-cp.c (ipa_get_indirect_edge_target_1): Do direct lookup via vtable pointer; check for type consistency and turn inconsitent facts into UNREACHABLE. * ipa-prop.c (try_make_edge_direct_virtual_call): Likewise. * gimple-fold.c (gimple_get_virt_method_for_vtable): Do not ICE on type inconsistent querries; return UNREACHABLE instead. * testsuite/g++.dg/ipa/devirt-25.C: New testcase. From-SVN: r207448
Diffstat (limited to 'gcc/ipa-devirt.c')
-rw-r--r--gcc/ipa-devirt.c64
1 files changed, 56 insertions, 8 deletions
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index fb9c666..f137874 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -1071,6 +1071,60 @@ vtable_pointer_value_to_binfo (tree t)
offset, vtable);
}
+/* Proudce polymorphic call context for call method of instance
+ that is located within BASE (that is assumed to be a decl) at OFFSET. */
+
+static void
+get_polymorphic_call_info_for_decl (ipa_polymorphic_call_context *context,
+ tree base, HOST_WIDE_INT offset)
+{
+ gcc_assert (DECL_P (base));
+
+ context->outer_type = TREE_TYPE (base);
+ context->offset = offset;
+ /* Make very conservative assumption that all objects
+ may be in construction.
+ TODO: ipa-prop already contains code to tell better.
+ merge it later. */
+ context->maybe_in_construction = true;
+ context->maybe_derived_type = false;
+}
+
+/* CST is an invariant (address of decl), try to get meaningful
+ polymorphic call context for polymorphic call of method
+ if instance of OTR_TYPE that is located at OFFSET of this invariant.
+ Return FALSE if nothing meaningful can be found. */
+
+bool
+get_polymorphic_call_info_from_invariant (ipa_polymorphic_call_context *context,
+ tree cst,
+ tree otr_type,
+ HOST_WIDE_INT offset)
+{
+ HOST_WIDE_INT offset2, size, max_size;
+ tree base;
+
+ if (TREE_CODE (cst) != ADDR_EXPR)
+ return NULL_TREE;
+
+ cst = TREE_OPERAND (cst, 0);
+ base = get_ref_base_and_extent (cst, &offset2, &size, &max_size);
+ if (!DECL_P (base)
+ || max_size == -1
+ || max_size != size)
+ return NULL_TREE;
+
+ /* Only type inconsistent programs can have otr_type that is
+ not part of outer type. */
+ if (!contains_type_p (TREE_TYPE (base),
+ offset, otr_type))
+ return NULL_TREE;
+
+ get_polymorphic_call_info_for_decl (context,
+ base, offset);
+ return true;
+}
+
/* Given REF call in FNDECL, determine class of the polymorphic
call (OTR_TYPE), its token (OTR_TOKEN) and CONTEXT.
Return pointer to object described by the context */
@@ -1136,14 +1190,8 @@ get_polymorphic_call_info (tree fndecl,
if (!contains_type_p (TREE_TYPE (base),
context->offset + offset2, *otr_type))
return base_pointer;
- context->outer_type = TREE_TYPE (base);
- context->offset += offset2;
- /* Make very conservative assumption that all objects
- may be in construction.
- TODO: ipa-prop already contains code to tell better.
- merge it later. */
- context->maybe_in_construction = true;
- context->maybe_derived_type = false;
+ get_polymorphic_call_info_for_decl (context, base,
+ context->offset + offset2);
return NULL;
}
else