[Bug] Undefined reference to function template declared friend and defined in template class

Hi,

This is regarding g++ test case

g++.old-deja/g++.pt/friend10.C

<i>template <class T>
void f(T);

template <class U>
class C
{ 
  template <class T>
  friend void f(T)
  {
     C<U> c;
     c.i = 3;
  }

  public :

     void g()
     {
       f(3.0);
     }
    int i;
};

int main ()
{
  f(7);
  C<double> c;
  c.g();
}</i>

Here, even when the body of function f() is defined, compiler throws error :

In function main':* *19095.C:(.text+0x16): undefined reference to void f(int)’
/tmp/19095-fd27b4.o: In function C<double>::g()':* *19095.C:(.text._ZN1CIdE1gEv[_ZN1CIdE1gEv]+0x1b): undefined reference to void f(double)’
clang-3.5: error: linker command failed with exit code 1

I have filed a bug related to this llvm.org/bugs/show_bug.cgi?id=19095

g++ compiles this without any error.

Please help in verifying if above is real bug. In my view this is a bug since function body has been defined and as it is declared friend it is a non-member function of class template.

It does look like a bug. Note that you can only instantiate this class template once, since the second instantiation would introduce a redefinition of f.

John.

Will the second instantiation of the class template introduce redefinition of f? In my opinion, friend functions are
non-member functions of class (independent of the class). So, no matter how many times we instantiate the class template,
there won’t be redefinition of the function. Please correct me if i am wrong.

You are correct that a friend function is not a class member. However, it is still templated, and instantiating a class effectively inserts redeclarations of its friend functions into the appropriate scopes. When those redeclarations resolve to the same entity (i.e. when their signature does not depend on the enclosing template parameters), they can end up defining it multiple times.

Among other things, recall that the definition appears within a template and therefore its body can depend on those template parameters.

We should fix the bug that you’ve identified, but I highly recommend actually moving the function definition outside of the class.

John.

I observed following points by changing the test case as per above discussion :

  1. If i move the function template definition outside the class template, the compiler doesn’t complain about not finding the definition and compiles the code without any error. This is normal behavior and the bug was not related to this case, as the compiler finds the function definition.

  2. If i change the friend function template (defined inside the class) into non-template friend function with definition inside the class template, the compiler complains of redefinition of the function :

’ error: redefinition of ‘f’
friend void f(int r){
^
19095.cpp:28:13: note: in instantiation of template class ‘C’ requested
here
C c;’

  1. If the test case is unchanged, then compiler complains of not finding the body.

  2. Agreed to above point that when class template will be instantiated twice, it will result in redefinition of the friend function.

I agree that with respect to use case, its always good to move definition outside the class. However, as it is legal to define friend function inside class, hence the above bug.

I have sent a patch related to this test case to cfe-commits under the subject

‘[PATCH] PR19095 Undefined reference to friend template function defined inside template class’

which resolves the ‘undefined reference’ error. I haven’t included test case yet in the patch. Please help in reviewing the same.