Skip to content
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

Closed
DimitryAndric opened this issue Mar 3, 2015 · 9 comments
Closed

Error compiling std::pair constructor with gcc >= 4.7 #23145

DimitryAndric opened this issue Mar 3, 2015 · 9 comments
Labels
bugzilla Issues migrated from bugzilla libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Comments

@DimitryAndric
Copy link
Collaborator

Bugzilla Link 22771
Resolution FIXED
Resolved on Mar 30, 2015 14:29
Version unspecified
OS All
CC @emaste,@mclow,@zygoloid

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

@zygoloid
Copy link
Mannequin

zygoloid mannequin commented Mar 3, 2015

The question is whether this is a libc++ problem or a gcc problem.

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
#include <type_traits>
class X { X(const X&); };
bool b = std::is_convertible<const X&, X>::value;

(Using a public deleted copy constructor fails similarly.)

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 19, 2015

Fix and tests
I have a fix to this and a bunch of other issues that are caused by our fallback implementation of is_convertible.

@DimitryAndric
Copy link
Collaborator Author

Created attachment 14073 [details]
Fix and tests

I have a fix to this and a bunch of other issues that are caused by our
fallback implementation of is_convertible.

Hi Eric, this fix doesn't apply anymore after r232764, can you please rebase it?

@DimitryAndric
Copy link
Collaborator Author

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
/share/dim/src/libcxx/trunk/include/type_traits: In instantiation of 'struct std::__1::__is_convertible<const X&, X, false>':
/share/dim/src/libcxx/trunk/include/type_traits:901:62: required from 'struct std::__1::is_convertible<const X&, X>'
minimal.cpp:4:42: required from here
minimal.cpp:3:11: error: 'X::X(const X&)' is private
In file included from minimal.cpp:2:0:
/share/dim/src/libcxx/trunk/include/type_traits:881:8: error: within this context
/share/dim/src/libcxx/trunk/include/type_traits: In instantiation of 'struct std::__1::__is_convertible_imp<const X&, X, void>':
/share/dim/src/libcxx/trunk/include/type_traits:881:8: required from 'struct std::__1::__is_convertible<const X&, X, false>'
/share/dim/src/libcxx/trunk/include/type_traits:901:62: required from 'struct std::__1::is_convertible<const X&, X>'
minimal.cpp:4:42: required from here
minimal.cpp:3:11: error: 'X::X(const X&)' is private
In file included from minimal.cpp:2:0:
/share/dim/src/libcxx/trunk/include/type_traits:856:13: error: within this context
/share/dim/src/libcxx/trunk/include/type_traits:849:28: error: initializing argument 1 of 'void std::__1::__test_convert(_Tp) [with _Tp = X]'
minimal.cpp:3:11: error: 'X::X(const X&)' is private
In file included from minimal.cpp:2:0:
/share/dim/src/libcxx/trunk/include/type_traits:856:13: error: within this context
/share/dim/src/libcxx/trunk/include/type_traits:849:28: error: initializing argument 1 of 'void std::__1::__test_convert(_Tp) [with _Tp = X]'

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 26, 2015

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.

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 26, 2015

Woops, I saw your invocation included C++11. Let me look into this further.

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 26, 2015

Hi Dimitry, I cannot reproduce your problem with GCC 4.9. Could you please double check against the patch that is up for review?

@DimitryAndric
Copy link
Collaborator Author

I tested with:

  • gcc47 (FreeBSD Ports Collection) 4.7.4
  • gcc48 (FreeBSD Ports Collection) 4.8.5 20150319 (prerelease)
  • gcc49 (FreeBSD Ports Collection) 4.9.3 2015031 (prerelease)
  • gcc5 (FreeBSD Ports Collection) 5.0.0 20150322 (experimental)

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>':
/share/dim/src/libcxx/trunk/include/type_traits:957:62: required from 'struct std::__1::is_convertible<const X&, X>'
minimal.cpp:4:42: required from here
minimal.cpp:3:11: error: 'X::X(const X&)' is private
In file included from minimal.cpp:2:0:
/share/dim/src/libcxx/trunk/include/type_traits:893:8: error: within this context
/share/dim/src/libcxx/trunk/include/type_traits: In instantiation of 'struct std::__1::__is_convertible_imp::__is_convertible_test<const X&, X, void>':
/share/dim/src/libcxx/trunk/include/type_traits:893:8: required from 'struct std::__1::__is_convertible<const X&, X, 0u, 0u>'
/share/dim/src/libcxx/trunk/include/type_traits:957:62: required from 'struct std::__1::is_convertible<const X&, X>'
minimal.cpp:4:42: required from here
minimal.cpp:3:11: error: 'X::X(const X&)' is private
In file included from minimal.cpp:2:0:
/share/dim/src/libcxx/trunk/include/type_traits:859:1: error: within this context
/share/dim/src/libcxx/trunk/include/type_traits:851:28: error: initializing argument 1 of 'void std::__1::__is_convertible_imp::__test_convert(_Tp) [with _Tp = X]'
minimal.cpp:3:11: error: 'X::X(const X&)' is private
In file included from minimal.cpp:2:0:
/share/dim/src/libcxx/trunk/include/type_traits:859:1: error: within this context
/share/dim/src/libcxx/trunk/include/type_traits:851:28: error: initializing argument 1 of 'void std::__1::__is_convertible_imp::__test_convert(_Tp) [with _Tp = X]'

but it looks like a gcc 4.7.4 issue, since all newer versions work.

@DimitryAndric
Copy link
Collaborator Author

Fixed by r233552.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 9, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

No branches or pull requests

2 participants