[cfe-users] bug in libc++

Marshall Clow mclow.lists at gmail.com
Sat Oct 5 10:59:25 PDT 2013


On Oct 4, 2013, at 3:54 PM, Steve Ramsey <clang at lucena.com> wrote:

> On Oct 3, 2013, at 2:58 PM, Manu <monamimani at gmail.com> wrote:
>> I thought that std::vector would have a noexcept move constructor and assignment given that all of it's member are noexcept in regard of move construction and assignment. Then again, i forgot about the allocator. But that mean that the default allocator is not noexcept when doing a move construction of assignment?
>> 
>> When we do a move construction or assignment of a vector with the default allocator, there shouldn't be any actual heap allocation going on. no?
>> 
>> Also if it now crash thats is new. I am synched from about 3 days ago and it was compiling with error but not crashing.
> 
> My initial response was based on the spec - neither vector’s move constructor nor its move-assignment operator are required to be noexcept (true). However, looking at the source for libc++, I see that both of those special member functions have optional noexcept specifications; so when using libc++, at least, it’s possible for std::vector to be nothrow in these cases.
> 
> Poking around with your example, I noticed a few interesting things:
> 
> 	* is_nothrow_move_constructible and is_nothrow_move_assignable both return true for std::basic_string <char>, std::string, and std::vector <std::string>. For that matter, so does std::allocator when templatized on each of those classes. Just to be absolutely certain of this last case, I also checked std::__1::is_nothrow_move_constructible <std::__1::allocator <std::__1::basic_string <char>>> and it’s still true.
> 
> 	* The compiler complains about your Foo class, essentially claiming that is_nothrow_move_constructible <std::allocator <string>> is false.
> 
> So, yeah, a conflict.
> 
> A few things to note: std::allocator explicitly defines a copy constructor but no copy-assignment operator. This means that its move constructor and move-assignment operator are implicitly deleted (and that the copy-assignment operator is implicitly defined, though this behavior is deprecated). That means any time you invoke a move special member function, you’re actually getting the copy special member function. In the case of a class like vector, this behavior shouldn’t be a problem for moves since the allocator doesn’t actually get moved/copied - it’s more of a policy class.
> 
> All I can figure here is that the noexcept specification is tripping on the allocator type traits because it’s checking them before it has full “visibility” of allocator’s implicit special member functions. I don’t know enough about noexcept to know exactly what’s happening, but my gut feeling, based on explicit testing with is_nothrow_xxx, is that this is a subtle clang bug after all (or possibly an abuse of noexcept specifications by libc++). It would be nice if an actual expert would weigh in, though.

I have received (and tested) a patch from Alp Toker for clang which fixes this problem (Manu's original code now compiles w/o errors).
This doesn't seem to have been committed yet.

-- Marshall

Marshall Clow     Idio Software   <mailto:mclow.lists at gmail.com>

A.D. 1517: Martin Luther nails his 95 Theses to the church door and is promptly moderated down to (-1, Flamebait).
        -- Yu Suzuki





More information about the cfe-users mailing list