Chris Lattner via llvm-dev
2020-Dec-02 05:04 UTC
[llvm-dev] RFC: [SmallVector] Adding SVec<T> and Vec<T> convenience wrappers.
> On Dec 1, 2020, at 4:07 PM, Duncan P. N. Exon Smith <dexonsmith at apple.com> wrote: >> >> Can you spell this out for me? Why do we need noexcept if we’re building with -fno-exceptions? What is going on here? > > Sure. It's a bit convoluted. Here's my understanding: > > First, here's why std::vector has this behaviour: > - std::vector grow operations need to transfer their existing elements over to the new storage. > - The grow operations are usually required to meet the "strong exception guarantee": if something throws, this function has no effect. > - If move operations throw, you can't provide this guarantee unless you copy (you can't move back the elements that have been half-moved over, in case another exception is thrown; but if it was just a copy, the original storage still has the elements safely unmodified). > - There's a caveat / carve out, that if T cannot be copy-constructed AND T's move constructor is not noexcept, then the guarantee is waived (since there's no way to implement it). > - Implementation is to call std::move_if_noexcept (https://en.cppreference.com/w/cpp/utility/move_if_noexcept <https://en.cppreference.com/w/cpp/utility/move_if_noexcept>), which moves if it's a noexcept operation, or if T is not copy-constructible. > > Second, here's why the behaviour doesn't change when -fno-exceptions: > - -fno-exceptions does NOT imply `noexcept` (maybe it should?, but it doesn't). > - This is implemented by detecting via SFINAE whether something is `noexcept` (maybe std::vector::resize/push_back/etc should have a special case? but that's controversial). > > IMO, until all the C++ standard libraries and host compilers that we support being built with will consistently use std::move on grow operations in std::vector in -fno-exceptions mode, we should only use std::vector when we absolutely have to. It's not designed for -fno-exceptions codebasesWow, thank you for the great explanation. I agree with you that this seems like a pretty credible reason why we can’t depend on every host std::vector to do what we need, so we should use something like an llvm::Vector. Two thoughts: 1) are you, or anyone else, interested in driving an llvm::Vector proposal + coding standard change to get us going in the right direction? I don’t think we need a mass migration of the code base, just get the policy aligned right plus the new type name to exist. 2) I think we should pursue Richard’s proposal or something like it to make Clang provide better C++ performance out of the box. I assume that all the STL containers will have similar issues (not to mention user defined ones), and noexcept isn’t widely used. Some flag that turns noexcept on by default (or for everything even with an exception spec?) in -fno-exceptions mode seems like a great thing to do. -Chris> . > > ( > There's some discussion in this thread: > http://lists.llvm.org/pipermail/libcxx-dev/2019-April/000344.html <http://lists.llvm.org/pipermail/libcxx-dev/2019-April/000344.html> > > And Richard had a proposal that made sense to me: > http://lists.llvm.org/pipermail/libcxx-dev/2019-April/000343.html <http://lists.llvm.org/pipermail/libcxx-dev/2019-April/000343.html> >> I'm wondering if we should have an experimental >> option to specify that functions are noexcept by default (overridable >> by an explicit exception specification) > > > But that only fixes it in host compilers that implemented this experimental mode. > )-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201201/453ae8c6/attachment.html>
James Y Knight via llvm-dev
2020-Dec-02 17:51 UTC
[llvm-dev] RFC: [SmallVector] Adding SVec<T> and Vec<T> convenience wrappers.
On Wed, Dec 2, 2020 at 12:05 AM Chris Lattner <clattner at nondot.org> wrote:> On Dec 1, 2020, at 4:07 PM, Duncan P. N. Exon Smith <dexonsmith at apple.com> > wrote: > > > Can you spell this out for me? Why do we need noexcept if we’re building > with -fno-exceptions? What is going on here? > > > Sure. It's a bit convoluted. Here's my understanding: > > First, here's why std::vector has this behaviour: > - std::vector grow operations need to transfer their existing elements > over to the new storage. > - The grow operations are usually required to meet the "strong exception > guarantee": if something throws, this function has no effect. > - If move operations throw, you can't provide this guarantee unless you > copy (you can't move back the elements that have been half-moved over, in > case another exception is thrown; but if it was just a copy, the original > storage still has the elements safely unmodified). > - There's a caveat / carve out, that if T cannot be copy-constructed AND > T's move constructor is not noexcept, then the guarantee is waived (since > there's no way to implement it). > - Implementation is to call std::move_if_noexcept ( > https://en.cppreference.com/w/cpp/utility/move_if_noexcept), which moves > if it's a noexcept operation, or if T is not copy-constructible. > > Second, here's why the behaviour doesn't change when -fno-exceptions: > - -fno-exceptions does NOT imply `noexcept` (maybe it should?, but it > doesn't). > - This is implemented by detecting via SFINAE whether something is > `noexcept` (maybe std::vector::resize/push_back/etc should have a special > case? but that's controversial). > > IMO, until all the C++ standard libraries and host compilers that we > support being built with will consistently use std::move on grow operations > in std::vector in -fno-exceptions mode, we should only use std::vector when > we absolutely have to. It's not designed for -fno-exceptions codebases > > > Wow, thank you for the great explanation. I agree with you that this > seems like a pretty credible reason why we can’t depend on every host > std::vector to do what we need, so we should use something like an > llvm::Vector. >I strongly disagree here. Not wanting to bother to add 'noexcept' to user-defined move-constructors is a poor justification for switching to a different vector type. Perhaps there are *other* reasons which might justify avoiding std::vector, but not that... -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201202/a3d519e3/attachment.html>
Duncan P. N. Exon Smith via llvm-dev
2020-Dec-02 20:39 UTC
[llvm-dev] RFC: [SmallVector] Adding SVec<T> and Vec<T> convenience wrappers.
> On 2020 Dec 1, at 21:04, Chris Lattner <clattner at nondot.org> wrote: > > 1) are you, or anyone else, interested in driving an llvm::Vector proposal + coding standard change to get us going in the right direction? I don’t think we need a mass migration of the code base, just get the policy aligned right plus the new type name to exist.I'll try to get a minimal patch together with docs and send an RFC later this week. ( I think the initial patch could be as simple as: ``` template <class T> using Vector = SmallVector<T, 0>; ``` but maybe we'd want to rename `SmallVectorImpl` to `VectorImpl`, or maybe there are other ideas, but off topic for this thread... )> On 2020 Dec 2, at 09:51, James Y Knight <jyknight at google.com> wrote: > > I strongly disagree here. Not wanting to bother to add 'noexcept' to user-defined move-constructors is a poor justification for switching to a different vector type. Perhaps there are other reasons which might justify avoiding std::vector, but not that...I'll be sure to mention this alternative in the RFC for llvm::Vector; we can talk about it there; maybe you'll convince the rest of us to add the `noexcept`s everywhere and then the justification for llvm::Vector would indeed be weaker (not completely absent though)... -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201202/20f02486/attachment.html>