New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Error compiling std::pair constructor with gcc >= 4.7 #23145
Comments
It's a libc++ bug. libc++ should be doing this check in a SFINAE context to catch the case where the initialization is ill-formed, instead of only catching the case where overload resolution doesn't like it. This doesn't affect clang, because clang uses the __is_convertible_to-based definition above. Here's a testcase that fails with Clang: #define __has_feature(x) 0 (Using a public deleted copy constructor fails similarly.) |
Fix and tests |
Hi Eric, this fix doesn't apply anymore after r232764, can you please rebase it? |
Of course reverting my libcxx tree to just before r232764, I can apply your fix, and then the simple pair test compiles with g++ without problems. However, Richard's minimal example still does not: $ g++49 -std=c++11 -I/share/dim/src/libcxx/trunk/include -c minimal.cpp |
You should be able to track the patch here: http://reviews.llvm.org/D8461 What standards mode are you compiling Richards test case in? It won't compile in C++03 w/ g++ but it should (and must) compile in C++ > 11. |
Woops, I saw your invocation included C++11. Let me look into this further. |
Hi Dimitry, I cannot reproduce your problem with GCC 4.9. Could you please double check against the patch that is up for review? |
I tested with:
The std::pair test case now compiles with all of them. Richard's minimal test case compiles with all of them, except gcc 4.7.4, which results in: /share/dim/src/libcxx/trunk/include/type_traits: In instantiation of 'struct std::__1::__is_convertible<const X&, X, 0u, 0u>': but it looks like a gcc 4.7.4 issue, since all newer versions work. |
Fixed by r233552. |
Extended Description
One of the FreeBSD developers attempted to build the -CURRENT source tree (which includes a relatively new snapshot of libc++) using gcc 4.9.1, and encountered an error about std::make_pair during compilation of clang's lib/AST/DeclBase.cpp [1]:
In file included from /usr/src/lib/clang/libclangast/../../../contrib/llvm/include/llvm/Support/type_traits.h:17:0,
from /usr/src/lib/clang/libclangast/../../../contrib/llvm/include/llvm/Support/Casting.h:19,
from /usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/include/clang/Basic/LLVM.h:22,
from /usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/include/clang/AST/AttrIterator.h:17,
from /usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/include/clang/AST/DeclBase.h:17,
from /usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/lib/AST/DeclBase.cpp:14:
/usr/obj/usr/src/tmp/usr/include/c++/v1/type_traits: In instantiation of 'struct std::__1::__is_convertible<const clang::StoredDeclsList&, clang::StoredDeclsList, 0u, 0u>':
/usr/obj/usr/src/tmp/usr/include/c++/v1/type_traits:943:62: required from 'struct std::__1::is_convertible<const clang::StoredDeclsList&, clang::StoredDeclsList>'
/usr/obj/usr/src/tmp/usr/include/c++/v1/utility:269:77: required by substitution of 'template<class _U1, class _U2> std::__1::pair<_T1, _T2>::pair(const std::__1::pair<_U1, _U2>&, typename std::__1::enable_if<(std::__1::is_convertible<const _U1&, _T1>::value && std::__1::is_convertible<const _U2&, _T2>::value)>::type*) [with _U1 = clang::DeclarationName; _U2 = clang::StoredDeclsList]'
/usr/obj/usr/src/tmp/usr/include/c++/v1/utility:491:69: required from 'std::__1::pair<typename std::__1::__make_pair_return<_Tp>::type, typename std::__1::__make_pair_return<_T2>::type> std::__1::make_pair(_T1&&, _T2&&) [with _T1 = clang::DeclarationName&; _T2 = clang::StoredDeclsList; typename std::__1::__make_pair_return<_T2>::type = clang::StoredDeclsList; typename std::__1::__make_pair_return<_Tp>::type = clang::DeclarationName]'
/usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/lib/AST/DeclBase.cpp:1313:59: required from here
/usr/obj/usr/src/tmp/usr/include/c++/v1/type_traits:881:87: error: use of deleted function 'constexpr clang::StoredDeclsList::StoredDeclsList(const clang::StoredDeclsList&)'
sizeof(__is_convertible_imp::__test<_T2>(__is_convertible_imp::__source<_T1>())) == 1
^
In file included from /usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/lib/AST/DeclBase.cpp:20:0:
/usr/src/lib/clang/libclangast/../../../contrib/llvm/tools/clang/include/clang/AST/DeclContextInternals.h:32:8: note: 'constexpr clang::StoredDeclsList::StoredDeclsList(const clang::StoredDeclsList&)' is implicitly declared as deleted because 'clang::StoredDeclsList' declares a move constructor or move assignment operator
struct StoredDeclsList {
^
Apparently, gcc concludes that 1) it requires a copy constructor for StoredDeclsList, and 2) the copy constructor is deleted because StoredDeclsList declares a move constructor. Clang obviously has no problem compiling this code.
A minimal test case is as follows:
#include
struct Foo {
Foo() {}
Foo(Foo &&RHS) {}
};
void pairtest(int i)
{
auto p1 = std::make_pair(i, Foo());
}
Compiling this with gcc 4.9.1, and using libc++ trunk r230867 as headers, results in a similar error:
$ g++49 -std=c++11 -I/share/dim/src/libcxx/trunk/include -c pairtest.cpp
In file included from /share/dim/src/libcxx/trunk/include/__tuple:16:0,
from /share/dim/src/libcxx/trunk/include/utility:157,
from pairtest.cpp:1:
/share/dim/src/libcxx/trunk/include/type_traits: In instantiation of 'struct std::__1::__is_convertible<const Foo&, Foo, 0u, 0u>':
/share/dim/src/libcxx/trunk/include/type_traits:949:62: required from 'struct std::__1::is_convertible<const Foo&, Foo>'
/share/dim/src/libcxx/trunk/include/utility:274:77: required by substitution of 'template<class _U1, class _U2> std::__1::pair<_T1, _T2>::pair(const std::__1::pair<_U1, _U2>&, typename std::__1::enable_if<(std::__1::is_convertible<const _U1&, _T1>::value && std::__1::is_convertible<const _U2&, _T2>::value)>::type*) [with _U1 = int; _U2 = Foo]'
pairtest.cpp:10:36: required from here
/share/dim/src/libcxx/trunk/include/type_traits:887:87: error: use of deleted function 'constexpr Foo::Foo(const Foo&)'
sizeof(__is_convertible_imp::__test<_T2>(__is_convertible_imp::__source<_T1>())) == 1
^
pairtest.cpp:3:8: note: 'constexpr Foo::Foo(const Foo&)' is implicitly declared as deleted because 'Foo' declares a move constructor or move assignment operator
struct Foo {
^
In file included from /share/dim/src/libcxx/trunk/include/__tuple:16:0,
from /share/dim/src/libcxx/trunk/include/utility:157,
from pairtest.cpp:1:
/share/dim/src/libcxx/trunk/include/type_traits:851:28: error: initializing argument 1 of 'char std::__1::__is_convertible_imp::__test(_Tp) [with _Tp = Foo]'
template char __test(_Tp);
^
The question is whether this is a libc++ problem or a gcc problem.
[1] https://jenkins.freebsd.org/job/FreeBSD_HEAD_external_toolchain_gcc/6/console
The text was updated successfully, but these errors were encountered: