egcs 1.0.1 bug

Adam P. Jenkins ajenkins@cs.umass.edu
Fri Jan 9 10:59:00 GMT 1998


Gabriel Dos Reis writes:
 > >>>>> «Alexandre», Alexandre Oliva <oliva@dcc.unicamp.br> wrote:
 > 
 > Alexandre> Adam P Jenkins writes:
 > >> it seems to crash when using explicit template
 > >> arguments in a friend function declaration in a template class.
 > 
 > Alexandre> That's because the template function must be declared before you refer
 > Alexandre> to an specialization thereof.  According to Mark Mitchell, this should
 > Alexandre> be fixed with an appropriate error message in the next snapshot of
 > Alexandre> egcs, so expect this to be fixed in the next release.  The following
 > Alexandre> declarations, before the template class body, would fix the problem:
 > 
 > Alexandre> template <class T> class A;
 > Alexandre> template <class T> A<T> foo(A<T>);
 > 
 > 	This kind of question has become common. Isn't it a good
 > candidate to be included in the FAQ ?
 > 

Part of the problem is that the warning message g++ gives when it
encounters a friend declaration in a template class is unclear.
Here's an example

--------------- tmp.cc ---------------
template <class T>
class A {
public:
  friend A<T> foo(A<T> a);
};

template <class T> A<T> foo(A<T> a) { return a; }

int main()
{
  A<int> a;
  A<int> b = foo(a);
  return 0;
}
---------------------------------------

/usr/local/bin/g++ tmp.cc
tmp.cc:3: warning: friend declaration `class A<T> foo(class A<T>)'
tmp.cc:3: warning:   will not be treated as a template instantiation
tmp.cc:3: warning:   unless you compile with -fguiding-decls
tmp.cc:3: warning:   or add <> after the function name
/tmp/cca007971.o: In function `main':
/tmp/cca007971.o(.text+0x19): undefined reference to `foo(A<int>)'
collect2: ld returned 1 exit status


Notice what it says, about adding <> after the function name.  If I
just change the friend declaration to 
     friend A<T> foo<> (A<T> a);
I get a syntax error like I'd expect.  Then I tried changing it to
     friend A<T> foo<T> (A<T> a);
at which point I got an internal compiler error.  I figured that
regardless of whether it was a syntax error, the compiler shouldn't
crash, so I sent a bug report.  If I add the declarations that
Alexandre suggested:

template <class T> class A;       
template <class T> A<T> foo(A<T>);

before the class declaration, I still get the same warning, and link
error.

--------------- tmp.cc ---------------
template <class T> class A;       
template <class T> A<T> foo(A<T>);

template <class T>
class A {
public:
  friend A<T> foo(A<T> a);
};

template <class T> A<T> foo(A<T> a) { return a; }

int main()
{
  A<int> a;
  A<int> b = foo(a);
  return 0;
}
---------------------------------------

/usr/local/bin/g++ tmp.cc
tmp.cc:6: warning: friend declaration `class A<T> foo(class A<T>)'
tmp.cc:6: warning:   will not be treated as a template instantiation
tmp.cc:6: warning:   unless you compile with -fguiding-decls
tmp.cc:6: warning:   or add <> after the function name
/tmp/cca008151.o: In function `main':
/tmp/cca008151.o(.text+0x19): undefined reference to `foo(A<int>)'
collect2: ld returned 1 exit status

Finally, if I change the call to foo, in main, to foo<int>(a);, then
it compiles, though I still get the warning message.  I guess this is
what the warning message was saying to do, but in that case, I think
the warning message should be changed to 

   "... or add <> after the function name when calling the function"

so that it's clear that it's not saying to add <> after the function
name in the friend declaration, which is where the warning is.  

Adam



More information about the Gcc-bugs mailing list