bug in nvcc parser << < is not the same as <<<

When attempting to combine a huge heavily-templatized library with my CUDA code, I compiled one of the library’s files as a cuda file

(by replacing the file extension from cpp to cu and invoking nvcc), only to see nvcc fail.

After scrutinizing the error messages I identified the source of the bug being a sequence of characters << < in a valid C++ code

(operator << followed by a space(s), and this followed by the less-then sign opening the list of template parameters).

This, apparently, is interpreted by the nvcc parser as equivalent to the CUDA magic sequence <<<.

Below is an example of a code that is a valid c++ program (although some warnings may be issued about defining but not using some objects),

but cannot be compiled by nvcc:

#include <iostream>

template <typename T>

class X

{

public: 

 int i;

template <typename T1>

 std::ostream & operator<< (T1 t)

 {

 return std::cout << t;

 }

};

struct Y

{

 friend std::ostream & X<double>::operator<< <double> (double d);

 int i;

};

int main()

{

 X<double> x; 

 Y y;

}

Even though the example is artificial, a friend template member function declaration like this is quite normal in C++.

If this example is compiled as a cu file, nvcc says:

nvcc --version && nvcc --compiler-bindir=$HOME/bin/cuda test.cu

nvcc: NVIDIA (R) Cuda compiler driver

Copyright (c) 2005-2011 NVIDIA Corporation

Built on Sun_Mar_20_16:47:09_PDT_2011

Cuda compilation tools, release 4.0, V0.2.1221

test.cu(18): error: expected an operator

test.cu(18): error: invalid friend declaration

test.cu(18): error: expected a ";"

test.cu(25): warning: variable "x" was declared but never referenced

test.cu(26): warning: variable "y" was declared but never referenced

3 errors detected in the compilation of "/tmp/tmpxft_00000fc7_00000000-4_test.cpp1.ii

The same program compiled as a *.cpp compiles smoothly.

Here’s a minimal reproducer:

template<typename T> void operator<<(T, T);

struct bar {};

template<> void operator<< <bar>(bar, bar);

int main()

{

  return 0;

}

I’ll file a bug with the compiler folks.

Our compiler team recommends (as an emergency workaround that at least lets you make forward progress) to separate the “<<” and “<” by a line break. For example:

friend std::ostream & X<double>::operator<< 

                                            <double>(double d);

I realize that this may not be a very attractive workaround when dealing with a large body of existing code. If possible, I would recommend to process as much of your existing code with your host’s C++ compiler, then link in the CUDA code compiled with nvcc. This should minimize exposure to this issue.

I think the CUDA team might also look at my post http://forums.nvidia…5&#entry1274445 about argument declaration of
cudaPointerGetAttributes. I can see no reason why a function that merely tests the attributes of a pointer does not declare this pointer to be a const pointer.
This makes an impression as if it was illegal to call this function on const pointers.
I don’t believe it and I circumvent the problem by using const_cast, but this is not the way it should be done.