Commit ceda2c69 by Jan Hubicka Committed by Jan Hubicka

re PR ipa/66223 (Diagnostic of pure virtual function call broken, including __cxa_pure_virtual)


	PR ipa/66223
	* ipa-devirt.c (is_cxa_pure_virtual_p): New function.
	(maybe_record_node): Record cxa_pure_virtual as the only possible
	target if there are not ohter candidates.
	(possible_polymorphic_call_target_p): Accept cxa_pure_virtual.

	* g++.dg/ipa/devirt-50.C: New testcase.

From-SVN: r232572
parent b1b6d906
2016-01-19 Jan Hubicka <hubicka@ucw.cz>
PR ipa/66223
* ipa-devirt.c (is_cxa_pure_virtual_p): New function.
(maybe_record_node): Record cxa_pure_virtual as the only possible
target if there are not ohter candidates.
(possible_polymorphic_call_target_p): Accept cxa_pure_virtual.
2016-01-19 Richard Biener <rguenther@suse.de> 2016-01-19 Richard Biener <rguenther@suse.de>
* hsa-gen.c (get_memory_order_name): Use MEMMODEL_ constants. * hsa-gen.c (get_memory_order_name): Use MEMMODEL_ constants.
......
...@@ -2327,6 +2327,17 @@ referenced_from_vtable_p (struct cgraph_node *node) ...@@ -2327,6 +2327,17 @@ referenced_from_vtable_p (struct cgraph_node *node)
return found; return found;
} }
/* Return if TARGET is cxa_pure_virtual. */
static bool
is_cxa_pure_virtual_p (tree target)
{
return target && TREE_CODE (TREE_TYPE (target)) != METHOD_TYPE
&& DECL_NAME (target)
&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (target)),
"__cxa_pure_virtual");
}
/* If TARGET has associated node, record it in the NODES array. /* If TARGET has associated node, record it in the NODES array.
CAN_REFER specify if program can refer to the target directly. CAN_REFER specify if program can refer to the target directly.
if TARGET is unknown (NULL) or it can not be inserted (for example because if TARGET is unknown (NULL) or it can not be inserted (for example because
...@@ -2341,11 +2352,12 @@ maybe_record_node (vec <cgraph_node *> &nodes, ...@@ -2341,11 +2352,12 @@ maybe_record_node (vec <cgraph_node *> &nodes,
{ {
struct cgraph_node *target_node, *alias_target; struct cgraph_node *target_node, *alias_target;
enum availability avail; enum availability avail;
bool pure_virtual = is_cxa_pure_virtual_p (target);
/* cxa_pure_virtual and __builtin_unreachable do not need to be added into /* __builtin_unreachable do not need to be added into
list of targets; the runtime effect of calling them is undefined. list of targets; the runtime effect of calling them is undefined.
Only "real" virtual methods should be accounted. */ Only "real" virtual methods should be accounted. */
if (target && TREE_CODE (TREE_TYPE (target)) != METHOD_TYPE) if (target && TREE_CODE (TREE_TYPE (target)) != METHOD_TYPE && !pure_virtual)
return; return;
if (!can_refer) if (!can_refer)
...@@ -2388,6 +2400,7 @@ maybe_record_node (vec <cgraph_node *> &nodes, ...@@ -2388,6 +2400,7 @@ maybe_record_node (vec <cgraph_node *> &nodes,
??? Maybe it would make sense to be more aggressive for LTO even ??? Maybe it would make sense to be more aggressive for LTO even
elsewhere. */ elsewhere. */
if (!flag_ltrans if (!flag_ltrans
&& !pure_virtual
&& type_in_anonymous_namespace_p (DECL_CONTEXT (target)) && type_in_anonymous_namespace_p (DECL_CONTEXT (target))
&& (!target_node && (!target_node
|| !referenced_from_vtable_p (target_node))) || !referenced_from_vtable_p (target_node)))
...@@ -2401,6 +2414,20 @@ maybe_record_node (vec <cgraph_node *> &nodes, ...@@ -2401,6 +2414,20 @@ maybe_record_node (vec <cgraph_node *> &nodes,
{ {
gcc_assert (!target_node->global.inlined_to); gcc_assert (!target_node->global.inlined_to);
gcc_assert (target_node->real_symbol_p ()); gcc_assert (target_node->real_symbol_p ());
/* Only add pure virtual if it is the only possible target. This way
we will preserve the diagnostics about pure virtual called in many
cases without disabling optimization in other. */
if (pure_virtual)
{
if (nodes.length ())
return;
}
/* If we found a real target, take away cxa_pure_virtual. */
else if (!pure_virtual && nodes.length () == 1
&& is_cxa_pure_virtual_p (nodes[0]->decl))
nodes.pop ();
if (pure_virtual && nodes.length ())
return;
if (!inserted->add (target)) if (!inserted->add (target))
{ {
cached_polymorphic_call_targets->add (target_node); cached_polymorphic_call_targets->add (target_node);
...@@ -3328,6 +3355,9 @@ possible_polymorphic_call_target_p (tree otr_type, ...@@ -3328,6 +3355,9 @@ possible_polymorphic_call_target_p (tree otr_type,
|| fcode == BUILT_IN_TRAP)) || fcode == BUILT_IN_TRAP))
return true; return true;
if (is_cxa_pure_virtual_p (n->decl))
return true;
if (!odr_hash) if (!odr_hash)
return true; return true;
targets = possible_polymorphic_call_targets (otr_type, otr_token, ctx, &final); targets = possible_polymorphic_call_targets (otr_type, otr_token, ctx, &final);
......
2016-01-19 Jan Hubicka <hubicka@ucw.cz>
PR ipa/66223
* g++.dg/ipa/devirt-50.C: New testcase.
2016-01-19 Marek Polacek <polacek@redhat.com> 2016-01-19 Marek Polacek <polacek@redhat.com>
PR c++/68965 PR c++/68965
......
/* { dg-do compile } */
/* { dg-options "-O3 -fdump-tree-optimized" } */
struct B {
B* self;
B() : self( this ) { self->f(); }
virtual void f() = 0;
};
struct D : B
{
void f() {}
};
int main()
{
D d;
}
/* { dg-final { scan-tree-dump "cxa_pure_virtual" "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