From: jimc@pic.ucla.edu
Subject: ___ls ( operator << ) not mangled in template
Organization: GNUs Not Usenet
Distribution: gnu
Date: Thu, 17 Dec 1992 02:43:02 GMT

// BUG13.C -- ___ls ( operator << ) not mangled in template

/* Gnu g++ v2.3.2 for SPARC-SunOS v4.1.1

A compilation unit contains two template classes each of which has a
non-friend operator << template function to print it out.  Both of
these are given the unmangled name ___ls.  The assembler (not to
mention the linker, were the compilations separate) doesn't like this. 
The names ___ls are used appropriately both at the point of call and
the point of definition, such that if the second one is commented out,
the code will compile and execute correctly.  

If the operator <<'s are declared in the template classes to be friends,
the names are generated correctly.  99.9% of operator <<'s are friends,
and it was only chance and laziness that led me to omit the friend
declaration thereby happening to discover this bug.  

James F. Carter        Voice 310 825 2897	FAX 310 206 6673
UCLA-Mathnet;  6221 MSA; 405 Hilgard Ave.; Los Angeles, CA, USA  90024-1555
Internet: jimc@math.ucla.edu            BITNET: jimc%math.ucla.edu@INTERBIT
UUCP:...!{ucsd,ames,ncar,gatech,purdue,rutgers,decvax,uunet}!math.ucla.edu!jimc

*/

#include <stdlib.h>
#include <iostream.h>

template <class T> struct list {	//Also acts as a list node and as root
  public:
    list* forw;
    T* data;

    list(T* d = NULL) : forw(NULL), data(d) { }
    void operator += (list& n)
	{ n.forw = forw; forw = &n; }
    list* next() const
	{ return forw; }
		//Fails only if operator << is non-friendly
//    friend ostream& operator << (ostream& f, const list& s);
};

template<class X, class Y> struct pair{ 
	typedef X pX;			//Add typedefs
	typedef Y pY;
	X x;
	Y y;
	pair(const X& xi, const Y& yi) : x(xi), y(yi) { }
		//Fails only if operator << is non-friendly
//	friend ostream& operator << (ostream& f, const pair& s);
};

template <class P> struct list_of_pairs {
	list<P> data;
	list_of_pairs(P* pi = NULL) : data(pi) { }
	void operator += (P& pi) {
	    data += *(new list<P>(&pi));
	}
};

// Fails with this template in place.  To see it work, comment this out.
template<class X, class Y> 
ostream& operator << (ostream& f, const pair<X,Y>& p) {
    return f << '(' << p.x << ' ' << p.y << ')';
}

template <class T> ostream& operator << (ostream& f, const list<T>& s) {
    for (const list<T>* p = &s; p; p = p->next()) {
	T* dp = p->data;
	if (dp) 
		f << *dp;	//Use this to see it fail
//		f << '(' << dp->x << ' ' << dp->y << ')'; //Use to see it work
	else f << "NULL";
    }
    return f;
}

typedef int X;		//The purpose of all this is to do something
typedef double Y;	//complicated with typedefs of template classes.

typedef pair<X,Y> PXY;
list_of_pairs<PXY> lp;

int main() {
    int x;
    double y;
    for (x = 0; x < 4; ++x) {
	lp += *(new pair<int,double>(x, x+0.5));
	cout << lp.data << '\n';
    }
}

/*
-------- Assembly code output -- annotated

gcc2_compiled.:
typedef pair<X,Y> PXY;
list_of_pairs<PXY> lp;

	double LC0(0.5)
LC0:	.double 0r0.5

int main() {
    int x;		%fp-20
    double y;		%fp-40 (?)
    for (x = 0; x < 4; ++x) {	(to L229)
        lp += *(new pair<int,double>(x, x+0.5));
	___t4pair2ZiZdRCiRCd(x, x+0.5)	//pair<int,double>(con int&, con dbl&)
	___apl__t13list_of_pairs1Zt4pair2ZiZdRt4pair2ZiZd,0
			// list_of_pairs<pair<int,dbl>>::op+= (pair<int,dbl>&)

        cout << lp.data << '\n';
	___ls__FR7ostreamc(___ls (cout, lp.data) , '\n')
			// ___ls__FR7ostreamc = ::op << (ostream&, char)
			// ___ls, what the hell is this?	==========
    }
}
	
// First instance of ___ls:					==========
	(ostream& f,		// in %fp+68
	const list<T>& s) {	// in %fp+72, 
    for (const list<T>* p = &s; p; p = p->next()) {
				// p in %fp-20, end of loop at L233
	T* dp = p->data; 	// dp in %fp-24
        if (dp)			// Zero code at L235
	    ___ls(f, *dp)	// Which ___ls is this supposed to be? =======
	else
	___ls__FR7ostreamPCc(f, "NULL")
			// ___ls__FR7ostreamPCc = ::op << (ostream, const char*)

    }
}

___apl__t13list_of_pairs1Zt4pair2ZiZdRt4pair2ZiZd:
(analysis omitted; it seems to work)
___t13list_of_pairs1Zt4pair2ZiZdPt4pair2ZiZd:
(analysis omitted; it seems to work)
_next__Ct4list1Zt4pair2ZiZd:
(analysis omitted; it seems to work)
___apl__t4list1Zt4pair2ZiZdRT0:
(analysis omitted; it seems to work)
___t4list1Zt4pair2ZiZdPt4pair2ZiZd:
(analysis omitted; it seems to work)
___t4pair2ZiZdRCiRCd:
(analysis omitted; it seems to work)

Second instance of ___ls:					===========
	(ostream& f,		// in %fp+68
	const pair<X,Y>& p) {	// in %fp+72, 
	call ___ls__FR7ostreamc,0 (f, '(')
	call ___ls__FR7ostreami,0 (previous, p.x)  x is int
	call ___ls__FR7ostreamc,0 (previous, ' ')
	call ___ls__FR7ostreamd,0 (previous, p.y)  y is double
	call ___ls__FR7ostreamc,0 (previous, ')')
}

__GLOBAL_$I$lp:	(constructor of global object lp)
	call ___t13list_of_pairs1Zt4pair2ZiZdPt4pair2ZiZd,0


--------------------- Actual assembly code

gcc2_compiled.:
	.global _lp
.data
	.align 4
_lp:
	.skip 8
	.align 8
LC0:
	.double 0r0.5
.text
	.align 4
	.global _main
	.proc	04
_main:
	!#PROLOGUE# 0
	save %sp,-160,%sp
	!#PROLOGUE# 1
	call ___main,0
	nop
	st %g0,[%fp-20]
L228:
	ld [%fp-20],%o0
	cmp %o0,3
	bg L229
	nop
	mov 16,%o0
	call ___builtin_new,0
	nop
	add %fp,-20,%o1
	ld [%fp-20],%f2
	fitod %f2,%f0
	sethi %hi(LC0),%o2
	ldd [%o2+%lo(LC0)],%f2
	faddd %f0,%f2,%f0
	std %f0,[%fp-40]
	add %fp,-40,%o2
	call ___t4pair2ZiZdRCiRCd,0
	nop
	mov %o0,%l0
	sethi %hi(_lp),%o1
	or %o1,%lo(_lp),%o0
	mov %l0,%o1
	call ___apl__t13list_of_pairs1Zt4pair2ZiZdRt4pair2ZiZd,0
	nop
	sethi %hi(_cout),%o1
	or %o1,%lo(_cout),%o0
	sethi %hi(_lp),%o2
	or %o2,%lo(_lp),%o1
	call ___ls,0
	nop
	mov %o0,%o1
	mov %o1,%o0
	mov 10,%o1
	call ___ls__FR7ostreamc,0
	nop
L230:
	ld [%fp-20],%o0
	add %o0,1,%o1
	st %o1,[%fp-20]
	b L228
	nop
L229:
	mov 0,%i0
	b L227
	nop
	b L227
	nop
L227:
	ret
	restore
	.align 8
LC1:
	.ascii "NULL\0"
	.align 4
	.proc	0110
___ls:
	!#PROLOGUE# 0
	save %sp,-120,%sp
	!#PROLOGUE# 1
	st %i0,[%fp+68]
	st %i1,[%fp+72]
	ld [%fp+72],%o0
	st %o0,[%fp-20]
L232:
	ld [%fp-20],%o0
	cmp %o0,0
	be L233
	nop
	ld [%fp-20],%o0
	ld [%o0+4],%o1
	st %o1,[%fp-24]
	ld [%fp-24],%o0
	cmp %o0,0
	be L235
	nop
	ld [%fp+68],%o0
	ld [%fp-24],%o1
	call ___ls,0
	nop
	b L234
	nop
L235:
	ld [%fp+68],%o0
	sethi %hi(LC1),%o2
	or %o2,%lo(LC1),%o1
	call ___ls__FR7ostreamPCc,0
	nop
L236:
L234:
	ld [%fp-20],%o0
	call _next__Ct4list1Zt4pair2ZiZd,0
	nop
	st %o0,[%fp-20]
	b L232
	nop
L233:
	ld [%fp+68],%i0
	b L231
	nop
	b L231
	nop
L231:
	ret
	restore
	.align 4
	.proc	020
___apl__t13list_of_pairs1Zt4pair2ZiZdRt4pair2ZiZd:
	!#PROLOGUE# 0
	save %sp,-112,%sp
	!#PROLOGUE# 1
	mov %i0,%l0
	st %i1,[%fp+72]
	mov 8,%o0
	call ___builtin_new,0
	nop
	mov %o0,%o1
	mov %o1,%o0
	ld [%fp+72],%o1
	call ___t4list1Zt4pair2ZiZdPt4pair2ZiZd,0
	nop
	mov %o0,%l1
	mov %l0,%o0
	mov %l1,%o1
	call ___apl__t4list1Zt4pair2ZiZdRT0,0
	nop
L237:
	ret
	restore
	.align 4
	.proc	0110
___t13list_of_pairs1Zt4pair2ZiZdPt4pair2ZiZd:
	!#PROLOGUE# 0
	save %sp,-112,%sp
	!#PROLOGUE# 1
	mov %i0,%l0
	st %i1,[%fp+72]
	mov %l0,%o0
	ld [%fp+72],%o1
	call ___t4list1Zt4pair2ZiZdPt4pair2ZiZd,0
	nop
L239:
	mov %l0,%i0
	b L238
	nop
	b L238
	nop
L238:
	ret
	restore
	.align 4
	.proc	0110
_next__Ct4list1Zt4pair2ZiZd:
	!#PROLOGUE# 0
	save %sp,-112,%sp
	!#PROLOGUE# 1
	mov %i0,%o0
	ld [%o0],%i0
	b L240
	nop
	b L240
	nop
L240:
	ret
	restore
	.align 4
	.proc	020
___apl__t4list1Zt4pair2ZiZdRT0:
	!#PROLOGUE# 0
	save %sp,-112,%sp
	!#PROLOGUE# 1
	mov %i0,%o0
	st %i1,[%fp+72]
	ld [%fp+72],%o1
	ld [%o0],%o2
	st %o2,[%o1]
	ld [%fp+72],%o1
	st %o1,[%o0]
L241:
	ret
	restore
	.align 4
	.proc	0110
___t4list1Zt4pair2ZiZdPt4pair2ZiZd:
	!#PROLOGUE# 0
	save %sp,-112,%sp
	!#PROLOGUE# 1
	mov %i0,%o0
	st %i1,[%fp+72]
	st %g0,[%o0]
	ld [%fp+72],%o1
	st %o1,[%o0+4]
L243:
	mov %o0,%i0
	b L242
	nop
	b L242
	nop
L242:
	ret
	restore
	.align 4
	.proc	0110
___t4pair2ZiZdRCiRCd:
	!#PROLOGUE# 0
	save %sp,-112,%sp
	!#PROLOGUE# 1
	mov %i0,%o0
	st %i1,[%fp+72]
	st %i2,[%fp+76]
	ld [%fp+72],%o1
	ld [%o1],%o2
	st %o2,[%o0]
	ld [%fp+76],%o1
	ldd [%o1],%o2
	std %o2,[%o0+8]
L245:
	mov %o0,%i0
	b L244
	nop
	b L244
	nop
L244:
	ret
	restore
	.align 4
	.proc	0110
___ls:
	!#PROLOGUE# 0
	save %sp,-120,%sp
	!#PROLOGUE# 1
	st %i0,[%fp+68]
	st %i1,[%fp+72]
	ld [%fp+68],%o0
	mov 40,%o1
	call ___ls__FR7ostreamc,0
	nop
	ld [%fp+72],%o1
	ld [%o1],%o1
	call ___ls__FR7ostreami,0
	nop
	mov %o0,%o1
	mov %o1,%o0
	mov 32,%o1
	call ___ls__FR7ostreamc,0
	nop
	ld [%fp+72],%o1
	ldd [%o1+8],%f0
	std %f0,[%fp-24]
	ld [%fp-24],%o1
	ld [%fp-20],%o2
	call ___ls__FR7ostreamd,0
	nop
	mov %o0,%o1
	mov %o1,%o0
	mov 41,%o1
	call ___ls__FR7ostreamc,0
	nop
	mov %o0,%i0
	b L246
	nop
	b L246
	nop
L246:
	ret
	restore
	.align 4
	.global __GLOBAL_$I$lp
	.proc	020
__GLOBAL_$I$lp:
	!#PROLOGUE# 0
	save %sp,-112,%sp
	!#PROLOGUE# 1
	sethi %hi(_lp),%o1
	or %o1,%lo(_lp),%o0
	mov 0,%o1
	call ___t13list_of_pairs1Zt4pair2ZiZdPt4pair2ZiZd,0
	nop
L247:
	ret
	restore

*/

Newsgroups: gnu.g++.bug