summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2016-01-19 16:49:50 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2016-01-19 16:49:50 +0000
commit53fa0e546fadc467ed17b048a24a5a9d319b62ef (patch)
tree56b15965ef3ed95b347438b20a83a9f117a03cf6
parent557a99fe9b89763161796e5b71f63b9a2c807576 (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/ipa-devirt.c34
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/ipa/devirt-50.C19
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"} } */