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.

Reply via email to