This is an archive of the discontinued LLVM Phabricator instance.

P0722R3: Implement library support for destroying delete
ClosedPublic

Authored by EricWF on Dec 18 2018, 10:52 AM.

Details

Summary

This provides the std::destroying_delete_t declaration in C++2a and after. (Even when the compiler doesn't support the language feature).

However, the feature test macro __cpp_lib_destroying_delete is only defined when we have both language support and C++2a.

Diff Detail

Repository
rCXX libc++

Event Timeline

ckennelly created this revision.Dec 18 2018, 10:52 AM

This is going to need some work before landing.

  • The feature test macro should be defined in <version>, not in <new>
  • Testing for the feature-test macro should go into the feature test stuff; look in test/std/language.support/support.limits/support.limits.general.
  • Should we have a libc++ macro _LIBCPP_HAS_NO_DESTROYING_DELETE, which gets defined in <config>, and then used in <new>? [ I am unsure; if there was a new replaceable overload of operator delete then I would say "absolutely". ]

Another question - why do we need to check if clang supports destroying delete to define the type destroying_delete_t? Why not define it always, and just define the feature test macro when we have compiler support?

You should also update www/cxx2a_status.html to show that P0722 is "complete".

Another question - why do we need to check if clang supports destroying delete to define the type destroying_delete_t? Why not define it always, and just define the feature test macro when we have compiler support?

I'm not a big fan of this approach. It seems better to define __cpp_lib_destroying_delete if and only if we provide destroying_delete_t, which makes sense if and only if the compiler has support for it (i.e. __cpp_impl_destroying_delete is defined).

include/new
37

Please note that those are C++20 additions.

169

Please guard with > C++17. We should not enable features in older standards unless we have a compelling reason to.

ckennelly marked an inline comment as done.Jan 11 2019, 9:33 AM

Another question - why do we need to check if clang supports destroying delete to define the type destroying_delete_t? Why not define it always, and just define the feature test macro when we have compiler support?

I'm not a big fan of this approach. It seems better to define __cpp_lib_destroying_delete if and only if we provide destroying_delete_t, which makes sense if and only if the compiler has support for it (i.e. __cpp_impl_destroying_delete is defined).

P1353 describes the impl macro as "whether the library feature can be provided," so that implied guarding exposing the library features with that macro as well.

include/new
169

If there's compiler support (we're checking _impl), would it be reasonable to provide it with C++17 as well?

mclow.lists added inline comments.Jan 11 2019, 11:26 AM
include/new
169

Not reasonable, no.
I did this one, for something that I thought was a slam-dunk (string_view in pre-c++17) and it has been nothing but a series of small annoyances.

ldionne requested changes to this revision.Jan 28 2019, 11:50 AM

Requesting changes so it shows up in my review queue properly.

This revision now requires changes to proceed.Jan 28 2019, 11:50 AM
EricWF added inline comments.Feb 2 2019, 2:26 PM
include/new
167

Please use the generate_feature_test_macro_components.py script to handle defining and testing the feature test macros.

169

This is a separate question from std::string_view. This is a core-language feature that needs library support. The compiler decides whether this feature is on or off.

Like aligned allocation and sized delete, the library should provide destroying_delete_t whenever the compiler defines its language feature test macro. Otherwise, Clang can't do its job. This approach allows users to opt-into important new language features as an extension, or to opt-out of them when availability is a concern (this is particularly important for allocation/deallocation functions).

We should enable the typedef when either _LIBCPP_STD_VER > 17 or defined(__cpp_impl_destroying_delete). The latter macro signify that Clang needs us to provide the type because *clang* has chosen to provide this language feature as an extension.

EricWF added a comment.Feb 2 2019, 3:18 PM

Question:

In C++20 we should declare destroying_delete_t, even if __cpp_impl_destroying_delete isn't defined.
But in that case should be define __cpp_lib_destroying_delete? The library has the type, but users
can't actually perform destroying delete.

Since __cpp_impl_destroyng_delete isn't for users, but __cpp_lib_destroying_delete is, then I don't think we should define it unless the compiler actually provides the language feature.

Question:

In C++20 we should declare destroying_delete_t, even if __cpp_impl_destroying_delete isn't defined.
But in that case should be define __cpp_lib_destroying_delete? The library has the type, but users
can't actually perform destroying delete.

Since __cpp_impl_destroyng_delete isn't for users, but __cpp_lib_destroying_delete is, then I don't think we should define it unless the compiler actually provides the language feature.

I think I agree. We should only define __cpp_lib_destroying_delete when the feature can be used sanely. TBH, I don't think that's a question the committee even thought about when introducing feature-test macros? There has to be an expected behaviour for us stdlib implementers here.

ldionne added inline comments.Feb 12 2019, 9:31 AM
include/new
169

I agree, this should be #if _LIBCPP_STD_VER > 17 || defined(__cpp_impl_destroying_delete).

See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89345#c3 for what I've done in libstdc++

tl;dr the type and variable depend on C++2a, the __cpp_lib macro depends on the type being defined and the compiler defining the impl macro to say it will recognise the type.

include/new
169

That will break for C++98 mode, because constexpr (and defaulted special members and inline variables) gives an error in C++98. That's the problem I was asked to fix in libstdc++, to be compatible with Clang.

TBH, I don't think that's a question the committee even thought about when introducing feature-test macros?

Well when we introduced feature test macros we didn't have any of these "the compiler defines the impl part and the library defines the one for end users" cases. I think the intention is that the library macro tells users if the feature actually works, and so it should definitely depend on the compiler promising to keep its side of the bargain, which is what the impl macro tells you.

jwakely added inline comments.Feb 13 2019, 2:54 PM
include/new
169

This approach allows users to opt-into important new language features as an extension, or to opt-out of them when availability is a concern (this is particularly important for allocation/deallocation functions).

If there was a -fdestroying-delete option to opt in or out of the compiler feature, I'd agree. But IIUC correctly, clang enables it unconditionally, so there's no opt-out, and no way for users to say "please don't define destroying_delete in C++11 mode, I use that name as a macro because I'm annoying like that".

jwakely added inline comments.Feb 13 2019, 3:02 PM
include/new
169

Also at https://reviews.llvm.org/D55741#1360693 Richard says Clang expects the library to decide whether to provide it, and you're saying "Clang has decided to provide it, so we should respect that" ... you can't both defer to the other, you should decide who's in charge here :-)
My decision for libstdc++ was to not make it available pre-C++2a, for the sake of strict conformance and simplicity.

ldionne added inline comments.Feb 15 2019, 12:11 PM
include/new
169

If there was a -fdestroying-delete option to opt in or out of the compiler feature, I'd agree.

This. I revert to my original stance of "we should only provide it in C++20 and above", unless there's a way that users can actually opt-in with some Clang flag.

EricWF commandeered this revision.Mar 18 2019, 2:34 PM
EricWF edited reviewers, added: ckennelly; removed: EricWF.

Hijacking the revision with Chris's blessing.

include/new
169

:-(

I was wrong. Clang enables destroying delete unconditionally, and somewhat carelessly.

We need to find another mechanism allowing users to opt in.

EricWF updated this revision to Diff 191180.Mar 18 2019, 2:37 PM
EricWF marked 4 inline comments as done.

This re-works how we allow using destroying delete as an extension.

First, it turns the extension off by default. Even if Clang would support it.
Second, it adds the _LIBCPP_ENABLE_DESTROYING_DELETE_EXT which can be used to enable the declarations of std::destroying_delete_t and std::destroying_delete in any dialect.

Finally, __cpp_lib_destroying_delete is defined only when libc++ provides the library declarations and the compiler supports the language features.

ldionne requested changes to this revision.Mar 19 2019, 6:51 AM

Please explain to me why we should have this in pre-C++20 dialects.

include/new
37

This comment stands, those declarations should have // C++20 in the synopsis.

169

See, that's one reason why I don't like back-porting recent features to older dialects.

This revision now requires changes to proceed.Mar 19 2019, 6:51 AM
EricWF marked 3 inline comments as done.Mar 19 2019, 10:54 AM

Please explain to me why we should have this in pre-C++20 dialects.

My users get meaningful performance improvements with this feature, but we can't upgrade everything to C++20 just yet.
For portable code, having different performance characteristics between C++17 and C++20 is a problem.

Destroying delete is a language feature first; much like aligned allocation and sized deallocation.
Given a cooperative standard library, Clang offers these features as extensions. We should cooperate.

Like aligned allocation, destroying delete is off by default and requires user opt-in.

Allowing this extension provides value to users. And it is consistent with our handling of
aligned allocation and sized deallocation.

include/new
169

I don't love it either. But it's not as bad as it seams. The explicit constructor prevents {} from converting to destroying_delete_t. But in C++03 {} isn't a thing, so we don't have to worry about it [1].

Clang offers the language extension in C++03. It just needs a destroying_delete_t definition. Users want to use destroying delete before C++20. We allow similar extensions for aligned allocation and sized deallocation.

[1] https://godbolt.org/z/EV2Efy

EricWF updated this revision to Diff 191354.Mar 19 2019, 10:55 AM
EricWF marked an inline comment as done.
  • Address inline review comments.
  • Update the feature test macro script.
ldionne requested changes to this revision.Apr 2 2019, 1:12 PM

Please explain to me why we should have this in pre-C++20 dialects.

My users get meaningful performance improvements with this feature, but we can't upgrade everything to C++20 just yet.

This is true for almost any C++20 feature. This isn't a reason to backport everything that we can to earlier standards. I don't want to litter the library with opt-ins like _LIBCPP_ENABLE_DESTROYING_DELETE_EXT, as it adds complexity and it creates more flavours of the library that we should be testing.

We're just turning in circles here since we've had that discussion before and we just disagree more fundamentally on providing extensions. Would you be willing not to tie this review to providing an extension so we can have a proper policy discussion to solve this matter once and for all?

test/std/language.support/support.dynamic/destroying_delete_t.pass.cpp
6

This is the old license.

This revision now requires changes to proceed.Apr 2 2019, 1:12 PM
EricWF updated this revision to Diff 201090.May 23 2019, 4:30 PM

Implement the minimal feature without extension as requested.

EricWF edited the summary of this revision. (Show Details)May 23 2019, 4:31 PM
EricWF accepted this revision.May 23 2019, 4:42 PM

Accepting after addressing Louis comments.

This revision was not accepted when it landed; it landed in state Needs Review.May 23 2019, 4:47 PM
This revision was automatically updated to reflect the committed changes.

I don't think P0722 got checked off in the 2a status.