LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 22771 - Error compiling std::pair constructor with gcc >= 4.7
Summary: Error compiling std::pair constructor with gcc >= 4.7
Status: RESOLVED FIXED
Alias: None
Product: libc++
Classification: Unclassified
Component: All Bugs (show other bugs)
Version: unspecified
Hardware: All All
: P normal
Assignee: Eric Fiselier
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-03-03 11:11 PST by Dimitry Andric
Modified: 2015-03-30 14:29 PDT (History)
4 users (show)

See Also:
Fixed By Commit(s):


Attachments
Fix and tests (7.62 KB, patch)
2015-03-18 19:39 PDT, Eric Fiselier
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Dimitry Andric 2015-03-03 11:11:33 PST
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 <utility>

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 <class _Tp> 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
Comment 1 Richard Smith 2015-03-03 15:02:25 PST
(In reply to comment #0)
> 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.)
Comment 2 Eric Fiselier 2015-03-18 19:39:47 PDT
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.
Comment 3 Dimitry Andric 2015-03-23 02:43:55 PDT
(In reply to comment #2)
> 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?
Comment 4 Dimitry Andric 2015-03-23 02:49:23 PDT
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]'
Comment 5 Eric Fiselier 2015-03-26 10:35:29 PDT
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.
Comment 6 Eric Fiselier 2015-03-26 10:36:10 PDT
Woops, I saw your invocation included C++11. Let me look into this further.
Comment 7 Eric Fiselier 2015-03-26 11:41:44 PDT
Hi Dimitry, I cannot reproduce your problem with GCC 4.9. Could you please double check against the patch that is up for review?
Comment 8 Dimitry Andric 2015-03-28 10:57:33 PDT
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 20150318 (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.
Comment 9 Dimitry Andric 2015-03-30 14:29:35 PDT
Fixed by r233552.