Commit ec77d61f by Jan Hubicka Committed by Jan Hubicka

re PR lto/59468 (ICE on invalid C++ code with LTO in…

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
parent 5a4dcd9b
2014-02-11 Jan Hubicka <hubicka@ucw.cz>
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.
2014-02-11 Vladimir Makarov <vmakarov@redhat.com>
PR target/49008
......
......@@ -2660,7 +2660,6 @@ import_export_decl (tree decl)
comdat_p = (targetm.cxx.class_data_always_comdat ()
|| (CLASSTYPE_KEY_METHOD (type)
&& DECL_DECLARED_INLINE_P (CLASSTYPE_KEY_METHOD (type))));
mark_needed (decl);
if (!flag_weak)
{
comdat_p = false;
......
......@@ -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
......
......@@ -36,9 +36,11 @@ extern tree gimple_fold_stmt_to_constant_1 (gimple, tree (*) (tree));
extern tree gimple_fold_stmt_to_constant (gimple, tree (*) (tree));
extern tree fold_const_aggregate_ref_1 (tree, tree (*) (tree));
extern tree fold_const_aggregate_ref (tree);
extern tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree);
extern tree gimple_get_virt_method_for_binfo (HOST_WIDE_INT, tree,
bool *can_refer = NULL);
extern tree gimple_get_virt_method_for_vtable (HOST_WIDE_INT, tree,
unsigned HOST_WIDE_INT);
unsigned HOST_WIDE_INT,
bool *can_refer = NULL);
extern bool gimple_val_nonnegative_real_p (tree);
extern tree gimple_fold_indirect_ref (tree);
extern bool arith_code_with_undefined_signed_overflow (tree_code);
......
......@@ -76,7 +76,8 @@ vec <cgraph_node *>
possible_polymorphic_call_targets (tree, HOST_WIDE_INT,
ipa_polymorphic_call_context,
bool *final = NULL,
void **cache_token = NULL);
void **cache_token = NULL,
int *nonconstruction_targets = NULL);
odr_type get_odr_type (tree, bool insert = false);
void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT,
const ipa_polymorphic_call_context &);
......@@ -105,7 +106,8 @@ bool vtable_pointer_value_to_vtable (tree, tree *, unsigned HOST_WIDE_INT *);
inline vec <cgraph_node *>
possible_polymorphic_call_targets (struct cgraph_edge *e,
bool *final = NULL,
void **cache_token = NULL)
void **cache_token = NULL,
int *nonconstruction_targets = NULL)
{
gcc_checking_assert (e->indirect_info->polymorphic);
ipa_polymorphic_call_context context = {e->indirect_info->offset,
......@@ -115,7 +117,8 @@ possible_polymorphic_call_targets (struct cgraph_edge *e,
return possible_polymorphic_call_targets (e->indirect_info->otr_type,
e->indirect_info->otr_token,
context,
final, cache_token);
final, cache_token,
nonconstruction_targets);
}
/* Same as above but taking OBJ_TYPE_REF as an parameter. */
......
2014-02-11 Jan Hubicka <hubicka@ucw.cz>
PR lto/59468
* g++.dg/ipa/devirt-27.C: New testcase.
* g++.dg/ipa/devirt-26.C: New testcase.
2014-02-11 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/60137
......
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-ipa-devirt" } */
struct A
{
int a;
virtual int bar(void) {return a;}
};
struct B
{
virtual int foo(void) {return b;}
int b;
};
struct C: A,B
{
virtual int foo(void) {return a;}
};
struct C c;
int test(void)
{
struct C *d=&c;
struct B *b=d;
return d->foo()+b->foo();
}
/* The call to b->foo() is perfectly devirtualizable because C can not be in construction
when &c was used, but we can not analyze that so far. Test that we at least speculate
that type is in the construction. */
/* { dg-final { scan-ipa-dump "Speculatively devirtualizing" "devirt" } } */
/* { dg-final { cleanup-ipa-dump "devirt" } } */
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-ipa-devirt -fdump-tree-optimized" } */
struct A
{
int a;
};
struct B
{
__attribute__ ((visibility("default")))
virtual int foo(void) {return 42;}
int b;
};
struct C: A,B
{
__attribute__ ((visibility("hidden")))
virtual int foo(void);
};
struct C c;
int test(void)
{
struct C *d=&c;
struct B *b=d;
return d->foo()+b->foo();
}
/* { dg-final { scan-tree-dump "OBJ_TYPE_REF" "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment