Search code examples
c++compiler-errorscudanvccfriend-function

friend function in CUDA C++


I am working on a problem that class A and B are declared in namespace test0 and a friend function f of class A declared in namespace test1. Function f receives a reference of a class B object as the parameter. Here is an simplified example.

namespace test0 {
    class B;
}

namespace test1 {
    void f(test0::B& b);
}

namespace test0 {
    class A {
        friend void test1::f(test0::B& b);
    };
}

The code works with g++. But nvcc gives the following compilation error.

a.cu:11:22: error: ‘B’ has not been declared
        friend void test1::f(test0::B& b);
                    ^
a.cu:11:27: error: ‘void test1::f(int&)’ should have been declared inside ‘test1’
        friend void test1::f(test0::B& b);
                        ^

Could you please help me figure out what the problem is? Thank you in advance.


Solution

  • It is important to understand that nvcc isn't a compiler, it is a compiler driver, and in both cases, the code is compiled with gcc and the error is a gcc generated error. If you put that code in a .cc extension file and compile it via nvcc, there will no be no error.

    But when compiling CUDA code (in a .cu file in this case), there are some intermediate processing stages between your code and the final g++ pass which compiles it. Under the hood, what is happening is that your code is being transformed by the CUDA C++ front end parser to this:

    # 1
    # 2
    namespace test0 { 
    # 3
        class B; 
    # 4
    }
    # 6
    namespace test1 { 
    # 7
        void f(test0::B & b); 
    # 8
    }
    # 10
    namespace test0 { 
    # 11
        class A { 
    # 12
            friend void test1::f(B & b); 
    # 13
        }; 
    # 14
    }
    

    compare that to the original friend void test1::f(test0::B& b); and you can see that the namespace has been stripped out by the cudafe++ pass. I don't know why it has been stripped out, but that is the source of the error.

    I would recommend reporting this as a bug to NVIDIA if it is a real problem in your application.