[libc++] Potential bug in debug/array

Hi all,

using Clang 3.9.1 on Ubuntu 14.04, I have trouble compiling with the checked STL version.

Error message:

/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/debug/array:86:52: 
error: too many arguments to function call, expected single argument '__other', have 2 arguments

with debug flags

-O2 -DDEBUG -g -ggdb3 -D_GLIBCXX_DEBUG

that is, with the checked STL implementation.

The problem is the swap function:

void
swap(array& __other)
noexcept(noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
{ std::swap_ranges(begin(), end(), __other.begin()); }

The issue was discussed here: where suggested that the problem might be a missing std in front of the swap() call:

void
swap(array& __other)
noexcept(noexcept(**std::**swap(std::declval<_Tp&>(), std::declval<_Tp&>())))
{ std::swap_ranges(begin(), end(), __other.begin()); }

Please let me know if this is a bug in libc++, or an issue with sparsepp, where the problem manifests.

Thanks
Lucas

Error message:

>/usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/debug/array:86:52:

This is a libstdc++ header, so it cannot be a libc++ bug.

It is however a clang bug. See below.

The issue was discussed here: https://github.com/greg7mdp/sparsepp/issues/61
where greg7mdp <https://github.com/greg7mdp> suggested that the problem might be a missing `std` in front of the swap() call:

It might resolve the issue but is not a correct solution.

>void swap(array& __other) noexcept(noexcept(_*std::*_swap(std::declval<_Tp&>(), std::declval<_Tp&>()))) { std::swap_ranges(begin(), end(), __other.begin()); }|

The second, unqualified `swap` is envisioned to involve the Argument Dependent Lookup (ADL) and call whatever ADL finds, and if ADL fails to find (a most probably user-defined) one, call the one in `std`.

Here clang behaves as if the second `swap` is hidden by the first one being declared. This is the bug, because the exception specification is part of the function declarator and is before the point of declaration of the function being declared, and consequently, shall not make the name of the function in question visible.

The use of the qualified name `std::swap` prevents the second `swap` from being hidden as described above, but it also forbids ADL so user-defined `swap` functions cannot be found at all. This is a minor issue if you have had move assignment operators implemented properly, nevertheless.

Looks like libstdc++ fixed this 3 years ago: https://gcc.gnu.org/r224153

/Eric