CUDA 3.0 nvcc bug nvcc fails to compile code properly in version 3.0

I have a set of C++ wrapper classes that abstract out host and device memory management. Since I upgraded to CUDA toolkit version 3, there are some errors that have come up

Look at the following example code derived from the original classes and simplified to the simplest case:

#include <iostream>

using namespace std;

template <class T> 

class TArray

{

public:

	T i;

	TArray(){}

	virtual bool isDeviceBuf(void) const = 0;

	template<typename T2> void assign(const T2 &other)

	{

		if(isDeviceBuf())

		{

			if(other.isDeviceBuf())   

			{

				cerr << "Device To Device" << endl;

			}

			else					

			{

				cerr << "Host To Device" << endl;

			}

		}

		else

		{

			if(other.isDeviceBuf())   

			{

				cerr << "Device To Host" << endl;

			}

			else					

			{

				cerr << "Host To Host" << endl;

			}

		}

	}

	//////////////////////////////////////////////////////////////////////////

};

//////////////////////////////////////////////////////////////////////////

template <class T> 

class TCArray : public TArray<T>

{

public:

	bool isDeviceBuf(void) const 

	{ 

		return false; 

	}

	TCArray(){}

	explicit TCArray(const TCArray &that)

	{

		assign(that);

	}

	//////////////////////////////////////////////////////////////////////////

	explicit TCArray(const TArray<T> &that) : TArray<T>()

	{

		assign(that);

	}

	//////////////////////////////////////////////////////////////////////////

	// Default = operator has to be overridden

	void operator=(const TCArray &that)

	{

		assign(that);

	}

	//////////////////////////////////////////////////////////////////////////

	void operator=(const TArray<T> &that)

	{

		assign(that);

	}

	//////////////////////////////////////////////////////////////////////////

};

//////////////////////////////////////////////////////////////////////////

template <class T> 

class TGArray : public TArray<T>

{

public:

	TGArray(){}

	bool isDeviceBuf(void) const 

	{ 

		return true; 

	}

	explicit TGArray(const TGArray &that)

	{

		assign(that);

	}

	//////////////////////////////////////////////////////////////////////////

	explicit TGArray(const TArray<T> &that) : TArray<T>()

	{

		assign(that);

	}

	//////////////////////////////////////////////////////////////////////////

	// Default = operator has to be overridden

	void operator=(const TGArray &that)

	{

		assign(that);

	}

	//////////////////////////////////////////////////////////////////////////

	void operator=(const TArray<T> &that)

	{

		assign(that);

	}

	//////////////////////////////////////////////////////////////////////////

};

//////////////////////////////////////////////////////////////////////////

int main()

{

	TCArray<int> a, b;

	TGArray<int> c, d;

	a = b;

	a = c;

	c = a;

	c = d;

	TCArray<int> a1(a), b1(c);

	TGArray<int> c1(c), d1(a);

	return 0;

}

I compiled this with Visual Studio 2008, cygwin gcc (version 3.4), gcc 4.3 on Ubuntu

All compile perfectly and the output shown is :

[font=“Courier New”]Host To Host

Device To Host

Host To Device

Device To Device

Host To Host

Device To Host

Device To Device

Host To Device

[/font]

showing the right behaviour

compiling with nvcc on windows :

C:\Data\Proj\test\cuda>nvcc testvirt.cu

testvirt.cu

tmpxft_000005f4_00000000-3_testvirt.cudafe1.gpu

tmpxft_000005f4_00000000-8_testvirt.cudafe2.gpu

testvirt.cu

tmpxft_000005f4_00000000-3_testvirt.cudafe1.cpp

tmpxft_000005f4_00000000-13_testvirt.ii

tmpxft_000005f4_00000000-14_testvirt.obj : error LNK2019: unresolved external symbol "public: virtual bool __thiscall TArray<int>::i

sDeviceBuf(void)const " (?isDeviceBuf@?$TArray@H@@UBE_NXZ) referenced in function "public: void __thiscall TArray<int>::assign<class

 TArray<int> >(class TArray<int> const &)" (??$assign@V?$TArray@H@@@?$TArray@H@@QAEXABV0@@Z)

a.exe : fatal error LNK1120: 1 unresolved externals

A similar error results on Linux.

The workaround is to use a pointer parameter rather than a reference for the assign() function :

template <class T> 

class TArray

{

public:

	T i;

	TArray(){}

	virtual bool isDeviceBuf(void) const = 0;

	template<typename T2> void assign(const T2 *other)

	{

		if(isDeviceBuf())

		{

			if(other->isDeviceBuf())   

			{

				cerr << "Device To Device" << endl;

			}

			else					

			{

				cerr << "Host To Device" << endl;

			}

		}

		else

		{

			if(other->isDeviceBuf())   

			{

				cerr << "Device To Host" << endl;

			}

			else					

			{

				cerr << "Host To Host" << endl;

			}

		}

	}

	//////////////////////////////////////////////////////////////////////////

};

//////////////////////////////////////////////////////////////////////////

template <class T> 

class TCArray : public TArray<T>

{

public:

	bool isDeviceBuf(void) const 

	{ 

		return false; 

	}

	TCArray(){}

	explicit TCArray(const TCArray &that)

	{

		assign(&that);

	}

	//////////////////////////////////////////////////////////////////////////

	explicit TCArray(const TArray<T> &that) : TArray<T>()

	{

		assign(&that);

	}

	//////////////////////////////////////////////////////////////////////////

	// Default = operator has to be overridden

	void operator=(const TCArray &that)

	{

		assign(&that);

	}

	//////////////////////////////////////////////////////////////////////////

	void operator=(const TArray<T> &that)

	{

		assign(&that);

	}

	//////////////////////////////////////////////////////////////////////////

};

//////////////////////////////////////////////////////////////////////////

template <class T> 

class TGArray : public TArray<T>

{

public:

	TGArray(){}

	bool isDeviceBuf(void) const 

	{ 

		return true; 

	}

	explicit TGArray(const TGArray &that)

	{

		assign(&that);

	}

	//////////////////////////////////////////////////////////////////////////

	explicit TGArray(const TArray<T> &that) : TArray<T>()

	{

		assign(&that);

	}

	//////////////////////////////////////////////////////////////////////////

	// Default = operator has to be overridden

	void operator=(const TGArray &that)

	{

		assign(&that);

	}

	//////////////////////////////////////////////////////////////////////////

	void operator=(const TArray<T> &that)

	{

		assign(&that);

	}

	//////////////////////////////////////////////////////////////////////////

};

This is clearly a failure to compile correct C++ code.

mov esi, bugReport

mov edi, nvidiaBugRepo

mov ecx, length(bugReport)

shr   ecx, 2

cld

rep   movsd

mov ecx, length(bugReport)

and  ecx, 3

jz	 done

rep   movsb

done: