[llvm-dev] RFC: [SmallVector] Adding SVec<T> and Vec<T> convenience wrappers.

Mehdi AMINI via llvm-dev llvm-dev at lists.llvm.org
Wed Dec 2 10:47:02 PST 2020


On Wed, Dec 2, 2020 at 9:52 AM James Y Knight via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

>
>
> 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...
>

It isn't clear that it makes sense to just add "noexcept" everywhere in our
codebase just because we build with -fno-exception. Should we decorate
every single API everywhere? Which one actually matters?
Why is it better to add these everywhere in the codebase rather than just
aligning our data-structure? (since there is also the `SmallVectorImpl`
issue of function arguments...).

-- 
Mehdi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20201202/21e4e02d/attachment.html>


More information about the llvm-dev mailing list