From: otto%isis@hermes.informatik.unibw-muenchen.de (Otto)
Subject: Bug in g++-2.3.1
Organization: GNUs Not Usenet
Distribution: gnu
Date: Thu, 5 Nov 1992 19:05:25 GMT

Bug (?) in gcc-2.3.1
---------------------

Recompiling my old sources (successful with g++ 2.2.2) with the new version
2.3.1 of g++ wouldn't work because of unreferenced symbols in the executable. I
finally got a solution to the problem and I am not quite sure, whether this is a
bug in g++.

The difference lies in the definition of inline friend functions. The original
source comes from C++-Class library LEDA. (on many ftp servers)

<CmdLine:> g++ -c  -DDEBUG -DTEST   Party.cc -o Party.o

In LEDA/basic.h is the definition of the classes

class string : ...
	{
	...                                                
	//-------------------------------------------------
	//-- inline friend functions in class definition
	//-------------------------------------------------
	friend void Print(const string& x, ostream& out = cout) { out << x; }
	friend void Read(string&  x, istream& in = cin)   { in  >> x; }
	friend GenPtr  Copy(const string& x) { x.ptr()->count++;  return x.PTR; }
	friend void    Clear(string& x)      { x.clear(); }
	friend string& Access(const string&, const GenPtr& p){ return *(string*)&p; }
	};
          
With nm Party.o, I got undefined symbols (here are only some of them)

           U Access__FRC6stringRCPv
           U Clear__FR6string
           U Copy__FRC6string
           U Print__FRC6stringR7ostream
           U Read__FR6stringR7istream

I changed LEDA/basic.h to

class string : ...
	{
   ...
	friend void Print(const string& x, ostream& out = cout);
	friend void Read(string&  x, istream& in = cin);
	friend GenPtr  Copy(const string& x);
	friend void    Clear(string& x);
	friend string& Access(const string&, const GenPtr& p);
	};

//-------------------------------------------------
//-- inline friend functions out of class definition
//-------------------------------------------------
inline void    Print(const string& x, ostream& out = cout) { out << x; }
inline void    Read(string&  x, istream& in = cin)   { in  >> x; }
inline GenPtr  Copy(const string& x) { x.ptr()->count++;  return x.PTR; }
inline void    Clear(string& x)      { x.clear(); }
inline string& Access(const string&, const GenPtr& p){ return *(string*)&p; }
                              
and nm showed no more undefined symbols. 

0x00013a7a s Access__FRC6stringRCPv
0x000139e8 s Clear__FR6string
0x00013a02 s Copy__FRC6string
0x00013a52 s Print__FRC6stringR7ostream
0x00013a2a s Read__FR6stringR7istream

After recompiling all sources, the executable linked without problem.
 
So, is the compiler supposed to make any difference in inline
functions defined in the scope of a class definition or outwards?
To repeat: I only changed from version 2.2.2 to 2.3.1, using the standard
installation procedures. 'make compare' after stage1 and stage2 showed no diffs.
My configuration is Apollo DomainOS 10.3.4 on a HP 425dt with 68040 cpu.

Some more remarks to the installation on Apollo:
------------------------------------------------
1) I added the definition of __va_list to stdio.h. Is that the right place?

	typedef __gnuc_va_list __va_list;
	_DECL_FUNC(int,		vfprintf,	(FILE *__stream, const char *__format, __va_list __arg))
	_DECL_FUNC(int,		vprintf,	(const char *__format, __va_list __arg))
	_DECL_FUNC(int,		vsprintf,	(char *__s, const char *__format, __va_list __arg))

2) The procedure fixincludes didn't work. I tracked it down to the result of `pwd`. I am
	not sure what it returns on standard unix systems, but on my Apollo it returns a
	path like '//isis/usr/include'. The double slash is allowed at the beginning, but
	not somethere in the middle, and that was the problem. I am using the Korn-Shell, so I
	changed #!/bin/sh to #!/bin/ksh and set an alias
	alias pwd=~/bin/Pwd. 
	Pwd only deletes the root node.
	~/bin/Pwd: dir=$(pwd);dir=${dir#//isis};echo $dir
                             

	With best regards
	Otto Schindler
	(otto@isis.informatik.unibw-muenchen.de)


PS: I can mail the sources if necessary. I compiled the same souce Party.cc, first
	 with basic.h.org, then second with basic.h.new as basic.h.

Original basic.h.org: g++ -c -S -DDEBUG -DTEST   Party.cc -o Party.S.old  (80460)
Original basic.h.org: g++ -c -E -DDEBUG -DTEST   Party.cc -o Party.E.old  (76579)

Modified basic.h.org: g++ -c -S -DDEBUG -DTEST   Party.cc -o Party.S.new  (81800)
Modified basic.h.org: g++ -c -E -DDEBUG -DTEST   Party.cc -o Party.S.new  (77145)

diff -c Party.S.old  Party.S.new > Party.S.diff  (111141)

The difference is mainly due to different labels. The relevant difference si as follows

*** Party.S.old	Thu Nov  5 16:43:58 1992
--- Party.S.new	Thu Nov  5 16:41:33 1992
...
***************
*** 4868,4884 ****
  	movel %d2,%sp@-
  	movel %a6@(8),%d2
  	tstl %d2
! 	jeq .L496
  	pea 1:w
  	movel %d2,%sp@-
  	jbsr __builtin_delete
  	addqw #8,%sp
! .L496:
! .L495:
  	movel %a6@(-4),%d2
  	unlk %a6
  	rts
  	.even
  error_handler__FiPc:
  	link %a6,#0
  	moveml #0x3020,%sp@-
--- 4870,4977 ----
  	movel %d2,%sp@-
  	movel %a6@(8),%d2
  	tstl %d2
! 	jeq .L508
  	pea 1:w
  	movel %d2,%sp@-
  	jbsr __builtin_delete
  	addqw #8,%sp
! .L508:
! .L507:
  	movel %a6@(-4),%d2
  	unlk %a6
  	rts
  	.even
+ Convert__FRC11LEDA_SIMPLE:			<------------ Missing functions in original
+ 	link %a6,#0
+ 	movel %a6@(8),%a0
+ 	movel %a0@,%d0
+ 	jra .L289
+ 	jra .L289
+ .L289:
+ 	unlk %a6
+ 	rts
+ 	.even
+ Init__FR11LEDA_SIMPLE:
+ 	link %a6,#0
+ 	movel %a6@(8),%d0
+ .L287:
+ 	unlk %a6
+ 	rts
+ 	.even
+ Clear__FR6string:
+ 	link %a6,#0
+ 	movel %d2,%sp@-
+ 	movel %a6@(8),%d2
+ 	movel %d2,%sp@-
+ 	jbsr clear__6string
+ 	addqw #4,%sp
+ .L387:
+ 	movel %a6@(-4),%d2
+ 	unlk %a6
+ 	rts
+ 	.even
+ Copy__FRC6string:
+ 	link %a6,#0
+ 	movel %a2,%sp@-
+ 	movel %a6@(8),%a2
+ 	movel %a2,%sp@-
+ 	jbsr ptr__C6string
+ 	addqw #4,%sp
+ 	movel %d0,%a0
+ 	addql #1,%a0@(4)
+ 	movel %a2@,%d0
+ 	jra .L386
+ 	jra .L386
+ .L386:
+ 	movel %a6@(-4),%a2
+ 	unlk %a6
+ 	rts
+ 	.even
+ Read__FR6stringR7istream:
+ 	link %a6,#0
+ 	movel %d3,%sp@-
+ 	movel %d2,%sp@-
+ 	movel %a6@(8),%d2
+ 	movel %a6@(12),%d3
+ 	movel %d2,%sp@-
+ 	movel %d3,%sp@-
+ 	jbsr __rs__FR7istreamR6string
+ 	addqw #8,%sp
+ .L385:
+ 	movel %a6@(-8),%d2
+ 	movel %a6@(-4),%d3
+ 	unlk %a6
+ 	rts
+ 	.even
+ Print__FRC6stringR7ostream:
+ 	link %a6,#0
+ 	movel %d3,%sp@-
+ 	movel %d2,%sp@-
+ 	movel %a6@(8),%d2
+ 	movel %a6@(12),%d3
+ 	movel %d2,%sp@-
+ 	movel %d3,%sp@-
+ 	jbsr __ls__FR7ostreamRC6string
+ 	addqw #8,%sp
+ .L384:
+ 	movel %a6@(-8),%d2
+ 	movel %a6@(-4),%d3
+ 	unlk %a6
+ 	rts
+ 	.even
+ Access__FRC6stringRCPv:
+ 	link %a6,#0
+ 	movel %d2,%sp@-
+ 	movel %a6@(8),%d1
+ 	movel %a6@(12),%d2
+ 	movel %d2,%d0
+ 	jra .L388
+ 	jra .L388
+ .L388:
+ 	movel %a6@(-4),%d2
+ 	unlk %a6
+ 	rts
+ 	.even
  error_handler__FiPc:
  	link %a6,#0
  	moveml #0x3020,%sp@-
***************

diff -c -b -B basic.h.org basic.h.new

*** basic.h.org	Thu Sep 17 09:58:26 1992
--- basic.h.new	Thu Nov  5 16:42:43 1992
***************
*** 90,108 ****
  
  GenPtr PTR;
  
! friend int  compare(const LEDA_SIMPLE& x, const LEDA_SIMPLE& y) 
                                        { return int(x.PTR) - int(y.PTR);}
  
! friend void Print(const LEDA_SIMPLE& x, ostream& out = cout) 
                                        { out << "L" << int(x.PTR); }
  
! friend void Read(LEDA_SIMPLE&, istream& = cin) {}
! friend void Clear(LEDA_SIMPLE&)             {}
! friend void Init(LEDA_SIMPLE&)              {}
! friend GenPtr Copy(const LEDA_SIMPLE& y)    { return y.PTR; }
! friend GenPtr Convert(const LEDA_SIMPLE& y) { return y.PTR; }
  
- };
  
  
  //------------------------------------------------------------------------------
--- 90,119 ----
  
  GenPtr PTR;
  
! friend int  compare(const LEDA_SIMPLE& x, const LEDA_SIMPLE& y);
! 
! friend void Print(const LEDA_SIMPLE& x, ostream& out = cout) ;
! 
! friend void Read(LEDA_SIMPLE&, istream& = cin);
! friend void Clear(LEDA_SIMPLE&);
! friend void Init(LEDA_SIMPLE&);
! friend GenPtr Copy(const LEDA_SIMPLE& y);
! friend GenPtr Convert(const LEDA_SIMPLE& y);
! 
! };
! 
! inline int  compare(const LEDA_SIMPLE& x, const LEDA_SIMPLE& y) 
                                        { return int(x.PTR) - int(y.PTR);}
  
! inline void Print(const LEDA_SIMPLE& x, ostream& out = cout) 
                                        { out << "L" << int(x.PTR); }
  
! inline void Read(LEDA_SIMPLE&, istream& = cin) {}
! inline void Clear(LEDA_SIMPLE&)             {}
! inline void Init(LEDA_SIMPLE&)              {}
! inline GenPtr Copy(const LEDA_SIMPLE& y)    { return y.PTR; }
! inline GenPtr Convert(const LEDA_SIMPLE& y) { return y.PTR; }
  
  
  
  //------------------------------------------------------------------------------
***************
*** 494,511 ****
  friend istream& operator>>(istream&, string&); 
  friend ostream& operator<<(ostream&, const string&) ;
  
! friend void Print(const string& x, ostream& out = cout) { out << x; }
! friend void Read(string&  x, istream& in = cin)   { in  >> x; }
! 
  
! friend GenPtr  Copy(const string& x) { x.ptr()->count++;  return x.PTR; }
! friend void    Clear(string& x)      { x.clear(); }
! friend string& Access(const string&, const GenPtr& p){ return *(string*)&p; }
  
  friend int  compare(const string& x, const string& y);
  
- 
  };
  
  //------------------------------------------------------------------------------
  // STRING(cmp): string with user defined linear order cmp
--- 505,527 ----
  friend istream& operator>>(istream&, string&); 
  friend ostream& operator<<(ostream&, const string&) ;
  
! friend void Print(const string& x, ostream& out = cout);
! friend void Read(string&  x, istream& in = cin);
  
! friend GenPtr  Copy(const string& x);
! friend void    Clear(string& x);
! friend string& Access(const string&, const GenPtr& p);
  
  friend int  compare(const string& x, const string& y);
  
  };
+ 
+ inline void Print(const string& x, ostream& out = cout) { out << x; }
+ inline void Read(string&  x, istream& in = cin)   { in  >> x; }
+ inline GenPtr  Copy(const string& x) { x.ptr()->count++;  return x.PTR; }
+ inline  void    Clear(string& x)      { x.clear(); }
+ inline  string& Access(const string&, const GenPtr& p){ return *(string*)&p; }
+ 
  
  //------------------------------------------------------------------------------
  // STRING(cmp): string with user defined linear order cmp


Newsgroups: gnu.g++.bug