diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-01-19 16:49:50 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-01-19 16:49:50 +0000 |
commit | 53fa0e546fadc467ed17b048a24a5a9d319b62ef (patch) | |
tree | 56b15965ef3ed95b347438b20a83a9f117a03cf6 | |
parent | 557a99fe9b89763161796e5b71f63b9a2c807576 (diff) | |
download | gcc-53fa0e546fadc467ed17b048a24a5a9d319b62ef.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@232572 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/ipa-devirt.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/devirt-50.C | 19 |
4 files changed, 64 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1e753efda90..5c4a13258f9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +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> * hsa-gen.c (get_memory_order_name): Use MEMMODEL_ constants. diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index a3cb08f7df8..736858e7236 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -2327,6 +2327,17 @@ referenced_from_vtable_p (struct cgraph_node *node) 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. 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 @@ -2341,11 +2352,12 @@ maybe_record_node (vec <cgraph_node *> &nodes, { struct cgraph_node *target_node, *alias_target; 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. 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; if (!can_refer) @@ -2388,6 +2400,7 @@ maybe_record_node (vec <cgraph_node *> &nodes, ??? Maybe it would make sense to be more aggressive for LTO even elsewhere. */ if (!flag_ltrans + && !pure_virtual && type_in_anonymous_namespace_p (DECL_CONTEXT (target)) && (!target_node || !referenced_from_vtable_p (target_node))) @@ -2401,6 +2414,20 @@ maybe_record_node (vec <cgraph_node *> &nodes, { gcc_assert (!target_node->global.inlined_to); 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)) { cached_polymorphic_call_targets->add (target_node); @@ -3328,6 +3355,9 @@ possible_polymorphic_call_target_p (tree otr_type, || fcode == BUILT_IN_TRAP)) return true; + if (is_cxa_pure_virtual_p (n->decl)) + return true; + if (!odr_hash) return true; targets = possible_polymorphic_call_targets (otr_type, otr_token, ctx, &final); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a75c88e94d1..b0a44cd3efc 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +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> PR c++/68965 diff --git a/gcc/testsuite/g++.dg/ipa/devirt-50.C b/gcc/testsuite/g++.dg/ipa/devirt-50.C new file mode 100644 index 00000000000..32071cfba06 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/devirt-50.C @@ -0,0 +1,19 @@ +/* { 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"} } */ |