diff options
author | Jan Hubicka <jh@suse.cz> | 2014-02-04 06:40:21 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2014-02-04 05:40:21 +0000 |
commit | 5bccb77a773b916d4824688e9138921f93c35039 (patch) | |
tree | c78cc4b81e9fffb8c0810f34976aecfcf20b5c3d /gcc/ipa-devirt.c | |
parent | 9de2f554ec689296676dee4f4482e059438a5991 (diff) | |
download | gcc-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.c | 64 |
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 |