On 01/07/14 16:10 +0200, Marc Glisse wrote:
On Tue, 1 Jul 2014, Markus Trippelsdorf wrote:
This patch cause yet another LLVM build error:
[...]
Reduced:
markus@x4 llvm_build % cat CompilerInvocation.ii
template <typename T> class A
{
T Obj;
public:
T element_type;
A (T *);
template <class X> A (A<X> &&p1) { p1.Obj; }
template <class X> A (A<X> &);
};
class B
{
public:
B (A<int>);
};
A<int> fn1 ()
{
A<B> a (new B (0));
return a;
}
markus@x4 llvm_build % /var/tmp/gcc_test/usr/local/bin/g++ -c -std=c++11
CompilerInvocation.ii
CompilerInvocation.ii: In instantiation of ‘A<T>::A(A<X>&&) [with X = B; T =
int]’:
CompilerInvocation.ii:20:10: required from here
CompilerInvocation.ii:3:5: error: ‘B A<B>::Obj’ is private
T Obj;
^
CompilerInvocation.ii:8:38: error: within this context
template <class X> A (A<X> &&p1) { p1.Obj; }
^
This looks invalid. As the core issue says, the return statement looks
up a as an rvalue, so it uses that constructor for A<int>, and that
uses a private member of a different specialization of A, which is
illegal.
Right, it looks as though that constructor has never been compiled or
tested before, so GCC is not only making the code faster but also
finding a bug :-)
The most obvious fix is to add:
template<class X> friend class IntrusiveRefCntPtr<X>;
so that conversion from rvalues of different types is supported.