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

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

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

suyog sarda
Hi,

This is regarding g++ test case

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

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();
}

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>(int)'
/tmp/19095-fd27b4.o: In function `C<double>::g()':
19095.C:(.text._ZN1CIdE1gEv[_ZN1CIdE1gEv]+0x1b): undefined reference to `void f<double>(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.

--
With regards,
Suyog Sarda

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

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

John McCall
On Mar 10, 2014, at 9:07 AM, suyog sarda <[hidden email]> wrote:
This is regarding g++ test case

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

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();
}

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>(int)'
/tmp/19095-fd27b4.o: In function `C<double>::g()':
19095.C:(.text._ZN1CIdE1gEv[_ZN1CIdE1gEv]+0x1b): undefined reference to `void f<double>(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.

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

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

suyog sarda
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.


On Wed, Mar 12, 2014 at 5:24 AM, John McCall <[hidden email]> wrote:
On Mar 10, 2014, at 9:07 AM, suyog sarda <[hidden email]> wrote:
This is regarding g++ test case

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

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();
}

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>(int)'
/tmp/19095-fd27b4.o: In function `C<double>::g()':
19095.C:(.text._ZN1CIdE1gEv[_ZN1CIdE1gEv]+0x1b): undefined reference to `void f<double>(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.



--
With regards,
Suyog Sarda

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

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

John McCall
On Mar 14, 2014, at 4:36 AM, suyog sarda <[hidden email]> wrote:
> 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.
_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

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

suyog sarda
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<double>' requested
      here
  C<double> c;'  


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

4. 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.


On Fri, Mar 14, 2014 at 11:45 PM, John McCall <[hidden email]> wrote:
On Mar 14, 2014, at 4:36 AM, suyog sarda <[hidden email]> wrote:
> 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.



--
With regards,
Suyog Sarda

_______________________________________________
cfe-dev mailing list
[hidden email]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev