diff options
author | Jason Merrill <jason@redhat.com> | 2014-03-14 15:06:54 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2014-03-14 15:06:54 -0400 |
commit | 7e343703fe22b55b9e6a446a0c0fdef989207c9d (patch) | |
tree | b0eec92fff85e3e1e0053ea49ba468b4ea9a3644 /gcc | |
parent | b1520f3d2cc2d07adf4f3af242917ca7b290b62f (diff) | |
download | gcc-7e343703fe22b55b9e6a446a0c0fdef989207c9d.zip gcc-7e343703fe22b55b9e6a446a0c0fdef989207c9d.tar.gz gcc-7e343703fe22b55b9e6a446a0c0fdef989207c9d.tar.bz2 |
re PR c++/58678 (pykde4-4.11.2 link error (devirtualization too trigger happy))
PR c++/58678
* search.c (dfs_get_pure_virtuals): Treat the destructor of an
abstract class as pure.
From-SVN: r208573
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/search.c | 16 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ipa/devirt-30.C | 25 |
3 files changed, 47 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index d90b988..b752ebe 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2014-03-14 Jason Merrill <jason@redhat.com> + + PR c++/58678 + * search.c (dfs_get_pure_virtuals): Treat the destructor of an + abstract class as pure. + 2014-03-13 Paolo Carlini <paolo.carlini@oracle.com> PR c++/60383 diff --git a/gcc/cp/search.c b/gcc/cp/search.c index c3eed90..66c6df5 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -2096,6 +2096,22 @@ dfs_get_pure_virtuals (tree binfo, void *data) if (DECL_PURE_VIRTUAL_P (BV_FN (virtuals))) vec_safe_push (CLASSTYPE_PURE_VIRTUALS (type), BV_FN (virtuals)); } + /* Treat a virtual destructor in an abstract class as pure even if it + isn't declared as pure; there is no way it would be called through the + vtable except during construction, which causes undefined behavior. */ + if (binfo == TYPE_BINFO (type) + && CLASSTYPE_PURE_VIRTUALS (type) + && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) + { + tree dtor = CLASSTYPE_DESTRUCTORS (type); + if (DECL_VIRTUAL_P (dtor) && !DECL_PURE_VIRTUAL_P (dtor)) + { + tree clone; + DECL_PURE_VIRTUAL_P (dtor) = true; + FOR_EACH_CLONE (clone, dtor) + DECL_PURE_VIRTUAL_P (clone) = true; + } + } return NULL_TREE; } diff --git a/gcc/testsuite/g++.dg/ipa/devirt-30.C b/gcc/testsuite/g++.dg/ipa/devirt-30.C new file mode 100644 index 0000000..c4ac694 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/devirt-30.C @@ -0,0 +1,25 @@ +// PR c++/58678 +// { dg-options "-O3 -fdump-ipa-devirt" } + +// We shouldn't speculatively devirtualize to ~B because B is an abstract +// class; any actual object passed to f will be of some derived class which +// has its own destructor. + +struct A +{ + virtual void f() = 0; + virtual ~A(); +}; + +struct B : A +{ + virtual ~B() {} +}; + +void f(B* b) +{ + delete b; +} + +// { dg-final { scan-ipa-dump-not "Speculatively devirtualizing" "devirt" } } +// { dg-final { cleanup-ipa-dump "devirt" } } |