This is an archive of the discontinued LLVM Phabricator instance.

Fix for libc++ bug #20096 http://llvm.org/bugs/show_bug.cgi?id=20096
AbandonedPublic

Authored by mclow.lists on Jun 25 2014, 6:26 PM.

Details

Reviewers
None
Summary

The existing implementation of is_destructible assumes that if a class is abstract, then it is not destructible. Apparently, the fact that you can't construct one of these objects doesn't mean that you can't destruct them.

Diff Detail

Event Timeline

mclow.lists retitled this revision from to Fix for libc++ bug #20096 http://llvm.org/bugs/show_bug.cgi?id=20096.
mclow.lists updated this object.
mclow.lists edited the test plan for this revision. (Show Details)
mclow.lists set the repository for this revision to rL LLVM.
mclow.lists added a subscriber: Unknown Object (MLST).

The existing implementation is the correct one for C++11, where is_destructible<T> is defined as:

For a complete type T and given template <class U> struct test { U u; };, test<T>::˜test() is not deleted.

Yes, but this was changed for the resolution of http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2049, which was a defect in C++11.

Apparently, when I worked on this issue, I missed the part about abstract classes being destructible.

EricWF added a subscriber: EricWF.Jun 26 2014, 3:53 PM

I reviewed the changes and are inline with the new rules. I verified the bug and testcases. This looks good to me.

I'm getting a failure in C++03 mode; that's why I haven't committed this.

EricWF added inline comments.Jul 4 2014, 1:09 PM
test/utilities/meta/meta.unary/meta.unary.prop/is_destructible.pass.cpp
55–58

Since the destructor is private, this tests access control SFINAE and not the abstract destructor. After making the abstract destructor public, this test fails for both C++11 and C++03.

EricWF added a comment.Jul 5 2014, 2:16 PM

Hi Marshall,

Would you be able to explain why AbstractDestructor should not be destructible?

My reading of the standard seems to suggest that because AbstractDestructor should be destructible because " decltype(_VSTD::declval<_Tp1&>().~_Tp1())" only has to be well formed in an un-evaluated context. It seems to me that invoking the destructor is well formed in this case.

Please let me know if I've made any mistakes.

Eric - I believe that invoking the destructor in this case is not well formed, because the destructor has been explicitly deleted.

See section 8.4.2/2:
A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not potentially-evaluated. If a function
is overloaded, it is referenced only if the function is selected by overload resolution. — end note ]

EricWF added a comment.Jul 9 2014, 1:00 PM

Indeed, and if you test this change with a deleted destructor it is not destructible.
However I don't see why a pure virtual destructor is explicitly deleted. Can you clarify on that?

P.S. A deleted destructor test-case should probably be added.

I don't know what the correct answer is for a publicly accessible destructor that has been marked = 0;

mclow.lists abandoned this revision.Jul 29 2014, 12:20 PM

A fix has been committed