aboutsummaryrefslogtreecommitdiff
path: root/gcc/gimple-fold.c
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@ucw.cz>2014-02-11 23:54:21 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2014-02-11 22:54:21 +0000
commitec77d61fe3a2b7882aaaae413b25aea878bed33d (patch)
tree9df630d2652c935d26cf3f91eb9ed4ef6e67f462 /gcc/gimple-fold.c
parent5a4dcd9bd902ebef3542a89eb6d71e1913052354 (diff)
downloadgcc-ec77d61fe3a2b7882aaaae413b25aea878bed33d.zip
gcc-ec77d61fe3a2b7882aaaae413b25aea878bed33d.tar.gz
gcc-ec77d61fe3a2b7882aaaae413b25aea878bed33d.tar.bz2
re PR lto/59468 (ICE on invalid C++ code with LTO in gimple_get_virt_method_for_binfo, at gimple-fold.c:3224)
PR lto/59468 * ipa-utils.h (possible_polymorphic_call_targets): Update prototype and wrapper. * ipa-devirt.c: Include demangle.h (odr_violation_reported): New static variable. (add_type_duplicate): Update odr_violations. (maybe_record_node): Add completep parameter; update it. (record_target_from_binfo): Add COMPLETEP parameter; update it as needed. (possible_polymorphic_call_targets_1): Likewise. (struct polymorphic_call_target_d): Add nonconstruction_targets; rename FINAL to COMPLETE. (record_targets_from_bases): Sanity check we found the binfo; fix COMPLETEP updating. (possible_polymorphic_call_targets): Add NONCONSTRUTION_TARGETSP parameter, fix computing of COMPLETEP. (dump_possible_polymorphic_call_targets): Imrove readability of dump; at LTO time do demangling. (ipa_devirt): Use nonconstruction_targets; Improve dumps. * gimple-fold.c (gimple_get_virt_method_for_vtable): Add can_refer parameter. (gimple_get_virt_method_for_binfo): Likewise. * gimple-fold.h (gimple_get_virt_method_for_binfo, gimple_get_virt_method_for_vtable): Update prototypes. PR lto/59468 * g++.dg/ipa/devirt-27.C: New testcase. * g++.dg/ipa/devirt-26.C: New testcase. From-SVN: r207702
Diffstat (limited to 'gcc/gimple-fold.c')
-rw-r--r--gcc/gimple-fold.c48
1 files changed, 39 insertions, 9 deletions
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index fd25939..5de4445 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -3170,22 +3170,35 @@ fold_const_aggregate_ref (tree t)
}
/* Lookup virtual method with index TOKEN in a virtual table V
- at OFFSET. */
+ at OFFSET.
+ Set CAN_REFER if non-NULL to false if method
+ is not referable or if the virtual table is ill-formed (such as rewriten
+ by non-C++ produced symbol). Otherwise just return NULL in that calse. */
tree
gimple_get_virt_method_for_vtable (HOST_WIDE_INT token,
tree v,
- unsigned HOST_WIDE_INT offset)
+ unsigned HOST_WIDE_INT offset,
+ bool *can_refer)
{
tree vtable = v, init, fn;
unsigned HOST_WIDE_INT size;
unsigned HOST_WIDE_INT elt_size, access_index;
tree domain_type;
+ if (can_refer)
+ *can_refer = true;
+
/* First of all double check we have virtual table. */
if (TREE_CODE (v) != VAR_DECL
|| !DECL_VIRTUAL_P (v))
- return NULL_TREE;
+ {
+ gcc_assert (in_lto_p);
+ /* Pass down that we lost track of the target. */
+ if (can_refer)
+ *can_refer = false;
+ return NULL_TREE;
+ }
init = ctor_for_folding (v);
@@ -3197,6 +3210,9 @@ gimple_get_virt_method_for_vtable (HOST_WIDE_INT token,
if (init == error_mark_node)
{
gcc_assert (in_lto_p);
+ /* Pass down that we lost track of the target. */
+ if (can_refer)
+ *can_refer = false;
return NULL_TREE;
}
gcc_checking_assert (TREE_CODE (TREE_TYPE (v)) == ARRAY_TYPE);
@@ -3247,7 +3263,14 @@ gimple_get_virt_method_for_vtable (HOST_WIDE_INT token,
ends up in other partition, because we found devirtualization
possibility too late. */
if (!can_refer_decl_in_current_unit_p (fn, vtable))
- return NULL_TREE;
+ {
+ if (can_refer)
+ {
+ *can_refer = false;
+ return fn;
+ }
+ return NULL_TREE;
+ }
}
/* Make sure we create a cgraph node for functions we'll reference.
@@ -3261,10 +3284,14 @@ gimple_get_virt_method_for_vtable (HOST_WIDE_INT token,
/* Return a declaration of a function which an OBJ_TYPE_REF references. TOKEN
is integer form of OBJ_TYPE_REF_TOKEN of the reference expression.
KNOWN_BINFO carries the binfo describing the true type of
- OBJ_TYPE_REF_OBJECT(REF). */
+ OBJ_TYPE_REF_OBJECT(REF).
+ Set CAN_REFER if non-NULL to false if method
+ is not referable or if the virtual table is ill-formed (such as rewriten
+ by non-C++ produced symbol). Otherwise just return NULL in that calse. */
tree
-gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
+gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo,
+ bool *can_refer)
{
unsigned HOST_WIDE_INT offset;
tree v;
@@ -3275,9 +3302,12 @@ gimple_get_virt_method_for_binfo (HOST_WIDE_INT token, tree known_binfo)
return NULL_TREE;
if (!vtable_pointer_value_to_vtable (v, &v, &offset))
- return NULL_TREE;
-
- return gimple_get_virt_method_for_vtable (token, v, offset);
+ {
+ if (can_refer)
+ *can_refer = false;
+ return NULL_TREE;
+ }
+ return gimple_get_virt_method_for_vtable (token, v, offset, can_refer);
}
/* Return true iff VAL is a gimple expression that is known to be