"invalid type argument of unary ‘*’" with template function pointers

With this file foo.cu:

template<typename T>
class foo
{
    void bar();
    void baz();
};

template<typename T>
void foo<T>::bar()
{
}

template<typename T>
void foo<T>::baz()
{
    auto ptr = (void*)(&foo::bar);
}

nvcc reports a mysterious error:

$ nvcc foo.cu 
foo.cu(16): warning: nonstandard conversion of pointer-to-member to a function pointer

foo.cu: In member function ‘void foo<T>::baz()’:
foo.cu:16:25: error: invalid type argument of unary ‘*’ (have ‘int’)
     auto ptr = (void*)(&foo::bar);
                         ^

The example is modified from a third-party library header. I’m not sure if that’s valid C++, but I think nvcc should always give a clearer error message instead of such a mysterious one.

Environment: Ubuntu 20.04.4 with gcc 9.4.0-1ubuntu1~20.04.1

Seems cudafe++ incorrectly parses line 16.

$ nvcc foo.cu -v -save-temps
#$ _SPACE_= 
#$ _CUDART_=cudart
#$ _HERE_=/usr/lib/nvidia-cuda-toolkit/bin
#$ _THERE_=/usr/lib/nvidia-cuda-toolkit/bin
#$ _TARGET_SIZE_=
#$ _TARGET_DIR_=
#$ _TARGET_SIZE_=64
#$ NVVMIR_LIBRARY_DIR=/usr/lib/nvidia-cuda-toolkit/libdevice
#$ PATH=/usr/lib/nvidia-cuda-toolkit/bin:/home/chyen/bin:/home/chyen/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
#$ LIBRARIES=  -L/usr/lib/x86_64-linux-gnu/stubs -L/usr/lib/x86_64-linux-gnu
#$ rm a_dlink.reg.c
#$ gcc -D__CUDA_ARCH__=300 -E -x c++  -DCUDA_DOUBLE_MATH_FUNCTIONS -D__CUDACC__ -D__NVCC__   -D__CUDACC_VER_MAJOR__=10 -D__CUDACC_VER_MINOR__=1 -D__CUDACC_VER_BUILD__=243 -include "cuda_runtime.h" -m64 "foo.cu" > "foo.cpp1.ii" 
#$ cicc --c++14 --gnu_version=90400 --allow_managed  -arch compute_30 -m64 -ftz=0 -prec_div=1 -prec_sqrt=1 -fmad=1 --include_file_name "foo.fatbin.c" -tused -nvvmir-library "/usr/lib/nvidia-cuda-toolkit/libdevice/libdevice.10.bc" --gen_module_id_file --module_id_file_name "foo.module_id" --orig_src_file_name "foo.cu" --gen_c_file_name "foo.cudafe1.c" --stub_file_name "foo.cudafe1.stub.c" --gen_device_file_name "foo.cudafe1.gpu"  "foo.cpp1.ii" -o "foo.ptx"
#$ ptxas -arch=sm_30 -m64 "foo.ptx"  -o "foo.sm_30.cubin" 
#$ fatbinary --create="foo.fatbin" -64 --cmdline="" "--image=profile=sm_30,file=foo.sm_30.cubin" "--image=profile=compute_30,file=foo.ptx" --embedded-fatbin="foo.fatbin.c" 
#$ gcc -E -x c++ -D__CUDACC__ -D__NVCC__   -D__CUDACC_VER_MAJOR__=10 -D__CUDACC_VER_MINOR__=1 -D__CUDACC_VER_BUILD__=243 -include "cuda_runtime.h" -m64 "foo.cu" > "foo.cpp4.ii" 
#$ cudafe++ --c++14 --gnu_version=90400 --allow_managed --m64 --parse_templates --gen_c_file_name "foo.cudafe1.cpp" --stub_file_name "foo.cudafe1.stub.c" --module_id_file_name "foo.module_id" "foo.cpp4.ii" 
foo.cu(16): warning: nonstandard conversion of pointer-to-member to a function pointer

#$ gcc -D__CUDA_ARCH__=300 -c -x c++  -DCUDA_DOUBLE_MATH_FUNCTIONS -m64 -o "foo.o" "foo.cudafe1.cpp" 
foo.cu: In member function ‘void foo<T>::baz()’:
foo.cu:16:25: error: invalid type argument of unary ‘*’ (have ‘int’)
      auto ptr = (void*)(&foo::bar);
                         ^
# --error 0x1 --
$ grep 'auto ptr' foo.cudafe1.cpp 
auto ptr = (void *)((*(0)).*(&::foo< T> ::bar));

*(0) is apparently wrong

I had an issue similar to this where I was getting “invalid type argument of unary ‘*’ (have ‘int’)” while trying to compile cuda on linux.

The issue for me was that I was using gcc 12, the solution was to force gcc 11 to be used. For my system that meant setting the appropriate environment variables before compiling cuda:

export CC=/usr/bin/gcc-11; export CXX=/usr/bin/g++-11