Release Notes For Cfront 3.0.1
February 1992


This is the USL C++ Language System, Release 3.0.1 (beta).  This
README describes the changes made since release 3.0.

If you are a new user of release 3.0 you should read the release 3.0
README before continuing with this README.  The 3.0 README is not on
the 3.0.1 beta distribution tape but will be included on the final
3.0.1 tape.

Release 3.0.1 addresses problems found in the original 3.0 release.
Most of the changes are improvements in the template implementation
and the template instantiation mechanisms.  In addition, 3.0.1
corrects a few regressions that have been found.

3.0.1 HIGHLIGHTS

Instantiation improvements: A new dependency checking mechanism has
been implemented that dramatically improves the speed of the
instantiation mechanism.

Regressions from 2.1: As its name implies, release 3.0 represents a
major change from 2.1.  Consequently a few regressions have been found
and corrected.

Template improvements: 3.0.1 corrects significant template problems
that have been identified in 3.0.

Demangler compatibility: The new demangler has been updated to provide
improved compatibility with the old demangler (e.g., local variable
support).

SORRIES

Some uses of the template feature have been sorried in the 3.0.1
release.  The fact that the features are sorried is not a comment on
the language feature, but rather an implementation difficulty.  Most
of these will be resolved in the next release.

	- Local classes cannot be used as template arguments

	- Nested classes within templates are not supported

	- Variant nested enums and typedefs in templates

	- Enums and typedefs in class specializations

The rest of this README describes 3.0.1 changes in detail.


========================= CC =========================

1. Force on +s option to directed mode. This will defer more type
checking of templates until instantiation time but will allow certain
programs to be accepted that were not previously.  For example:

	struct A {
		A();
		A(char*);
	};
	
	template <class T>
	class B {
	public:
		T	next();
	};
	
	template <class T>
	T B<T>::next()
	{
		return T((double*)0); //error here "no match for call"
	}
	
	class C { 
		B<A> mnemonic_names();
	};

2. Fix template bug with use of "$x" instead of "$pti" just before
ptlink call.

========================= cfront nontemplate =========================

1. Fix crash with goto used in inline function:

	class A {
	public:
		int i;
		A(int j) {
			if (j) goto xxx;
			j = 5;
		xxx:
			i = j;
		}
	};

2. Increase various cfront buffer sizes to accommodate larger
programs.

3. Change the way cfront handles initializations of array references.
Pre-3.0.1 those initialized at global scope were flagged as an error,
but those done at a local scope were not. In this release, neither
will result in an error.

	typedef int B[2];
	typedef int U[];
 
	typedef B &BR;		// Bounded array reference type
	typedef U &UR;		// Unbounded array reference type

	B Bx;			// Bounded array object
	extern U Ux;		// Unbounded array object

	BR brx = Bx;		// OK
	UR urx = Ux;		// OK
	const BR cbrx2 = Bx;    // error in 3.0, o.k. in 3.0.1
	const UR curx2 = Ux;    // error in 3.0, o.k. in 3.0.1

	B Ux;			// Complete declaration of object Ux

	void main()
	{

        	const BR cbr = Bx;  // o.k. in 3.0 and 3.0.1
        	const UR cur = Ux;  // o.k. in 3.0 and 3.0.1
	}

4. In release 3.0 some uses of explicit casts were wrongly disallowed.

	class B { int b; };
	class DB : private B { int d; };
	
	main(){
        	DB *pd = new DB;
        	B  *pb = (B*)pd;  // error in 3.0, legal in 3.0.1
	}

5. Ambiguous constructor calls should produce errors both for objects
and for arrays of objects. In 3.0 this was not the case.

	class A {
        	int j;
	public:
        	A() { }
        	A(int i = 0): j(i) { }
	};
	
	main() {
        	A a;		// error in 3.0 and 3.0.1
        	A b[2];		// no error in 3.0, error in 3.0.1
	}

6. Fix return value optimization bug:

	class Type_info;

	class typeid
	{
	public:

		typeid();
		typeid( const typeid& );
		typeid( const Type_info* );
	private:
		const Type_info* id;
	};

	typeid
	info()
	{
		static typeid id ( 0 );
		return id;
	}

7. Code generated by cfront for the following class assignment 
        b1 = d1;
    is
        ( (((struct B *)(& __1b1 )))) ;

which is wrong.

	struct B {
	        virtual int f();
	        int b;
	};
	int B::f() { return 0; }
	
	struct D : B{
	        int f();
	        int d;
	};
	int D::f() { return 0; }
	
	main() {
	        D d1;
	        d1.b = 42;
	        d1.d = 62;
	
	        B b1(d1);
	
	        b1 = d1;
	}

8. Fix bad C on:

           class X
            {
              public:
               void operator delete (void *);
               static void f(X *x);
            };
   
           class Y
            {
              public:
               static void f(Y *y);
            };
   
           void X::operator delete(void *obj) {}
   
           void X::f(X *x) { ::delete x; }
           void Y::f(Y *y) { ::delete y; } 

9. Fix for bad ANSI C (+a1 option) generated for:

	const int &r = 5;
	main()
	{
		const int *p = &r;
		if (r == 5 && *p == 5 && p == &r)
			return 0;
		return 1;
	}

10. Sorry the following case:

	inline void f()
	{
		return;
	}

	main()
	{
		f();
	}

This was a sorry in 2.1.  In 3.0 the 'return' was literally expanded
in the caller's function.

11. Fixed bug with failure to call copy constructor in some cases:

	extern "C" void exit(int);

	int Stringcount = 0;
	
	struct String {
		String();
		String(const String &);
		~String();
	};
	
	String::String() { ++Stringcount; }
	
	String::String(const String&) { ++Stringcount; }
	
	String::~String() { --Stringcount; }
	
	struct Name {
		Name();
		operator const String & () const;
	};
	
	Name::Name() { }
	
	String foo;
	
	Name::operator const String&() const {
		return foo;
	}
	
	void f()
	{
		Name n;
		String s = String(n);
		String t(n);
	}
	
	main()
	{
		f();
		if (Stringcount != 1)
			exit(1);
		exit(0);
	}

12. As a consequence of fixing #11, fix a bug where extra copy
constructors were called:

	extern "C" void exit(int);

	int ctor = 0;
	int dtor = 0;
	int cctor = 0;
	
	struct A {
		A(int) {ctor++;}
		A(const A&) {ctor++; cctor++;}
		~A() {dtor++;}
	};
	
	void f(A) {}
	
	void f()
	{
		f(A(3));
		f(A(A(4)));
		f(A(A(A(5))));
	}
	
	main()
	{
		f();
	
		if (!ctor)
			exit(1);
	
		if (ctor != dtor)
			exit(2);
	
		if (cctor != 3)
			exit(3);
	
		exit(0);
	}

13. Fix for rejection of:

	class N {
	public:
		operator long () const;
		inline N(const N&);
		~N();
	};

	int foo()
	{
		extern N f();   
		return ((long)f() == 0) ? 0 : 1;	// error here
	}

14. Fix for unnecessary use of a temporary in N::get():

	class N {
		int d;
	public:
		N(const int &_d) : d(_d) {}
		const int& get() const;
	};

	const int& N::get() const { return d; }

15. Fix parsing bug with:

	void f(void (func)())
	{
	}

i.e. the case where the function does not have '*' or '&'.

16. Fix regression where the following was rejected:

	class foo {
	public:
		operator!=(int);
		operator int();
	};
	
	enum color {red, blue};
	
	main()
	{
		foo f;
		if (f != red)
			;
	}

See also the 3.0 release notes for a discussion of changes to operator
overloading.

========================= cfront template =========================

1. Add support for classnames > 99 characters; important for mangled
template class names.

2. Fix bug with parsing of:

	A<void (*)(int)>

as a type argument.

3. Fix several bugs where "infinite instantiation" errors were coming
out:

	template <int i, class T> class A {
	public:
		A<62,int>* foo(A<47,double>*);
	};
	
	A<83,long> a;

4. Fix parsing of:

	A<void (*fp)(int)>

as a non-type template argument.

5. Fix pointer to member template arguments that lack a preceding &:

	template <class T> struct A {};

	struct B {void f();}

	A<B::f> a;

6. Fix N**3 compile performance problem when many (> 100) template
classes are present in one cfront input stream.

7. Fix for crash on:

	template <class T, class U> void f(T t, T<U>& u) {}

8. Fix for crash on:

	template <int i> struct S {
		friend S<i> *f(S<i>&);
	};

9. Fix for crash on:

	template <class T> struct {};

which is illegal.

10. Fix directed mode bug of the form:

	# 1 "appl.c"
	# 1 "appl.h"
	template <class T> struct A {};
	template <class T> struct B {};
	A<int> a;
	B<long> b;
	# 23 "appl.h"
	# 47 "appl.c"
	typedef A<int> dummy;

11. Fix crash on:

	class X {template <class T> X& X::copy();};

which is illegal usage.

12. Fix cfront infinite loop on:

	template <class T> class A {};
	template <class T> class B {
		void f();
	};
	template <class T> class C : public B<T> {};

	template <class T> void B<T>::f() {
		C<A<T>*> m;
	}
	B<int> foo;

This code is illegal.

13. Fix crash on:

	class A {
	    int a;
	  public:
	    A(int i) : a(i) {;}
	    void print();
	};
	
	class B {
	    int b;
	  public:
	    B(int i) : b(i) {;}
	    void print();
	};
	
	template <class T>
	class C : public A, public B {
	    T t;   // dummy variable
	  public:
	    C(int i, int j) : A(i), B(j) {;}
	    void print(C<T>&);
	};
	
	main ()
	{
	    C<int> c(3,4);
	    c.print(c);
	}
	
	void A :: print() { }
	
	void B :: print() { }
	
	template <class T>
	void C<T> :: print(C<T>& c) {
	    A::print();
	    B::print();
	    c.B::print();
	    c.A::print();
	}

14. Fix crash on:

	template <class T> int f1(T);
	template <class T> int f2(T);
	template <class T> int f3(T);
	template <class T> int f4(T);
	template <class T> int f5(T);
	template <class T> int f6(T);
	template <class T> int f7(T);
	template <class T> int f8(T);
	template <class T> int f9(T);
	
	template <class T> struct X {
		int mf();
		X();
		~X();
	};
	
	template <class T> int X<T>::mf() { return f1('x'); }
	
	template <class T> int f1(T t) { return f2(t); }
	template <class T> int f2(T t) { return f3(t); }
	template <class T> int f3(T t) { return f4(t); }
	template <class T> int f4(T t) { return f5(t); }
	template <class T> int f5(T t) { return f6(t); }
	template <class T> int f6(T t) { return f7(t); }
	template <class T> int f7(T t) { return f8(t); }
	template <class T> int f8(T t) { return f9(t); }
	template <class T> int f9(T t) { return (int)t; }
	
	X<int> x;

15. Sorry local class types as template arguments:

	template <class T> class A {};

	void f()
	{
		class B {};
		A<B> a;
	}

16. Disallow casts of function template names, which by definition are
overloaded. See the ARM 5.4 and 13.3.

	template <class T> void f(T) {}

	typedef void (*fp)(int);

	fp p = fp(f);

17. Fix to support template array arguments:

	template <class T> struct A {};

	A<int[12][13]> a;

The first array dimension does not count when distinguishing template
classes;  this may change in the future.

18. Sorry nested classes within templates:

	template <class T> struct A {
		struct B {};
	};

19. Fix parsing bug with:

	template <class T> struct A {};

	typedef A<int> (&X)();

20. Fix name mangling bug with:

	template <class T> struct A {};

	A< A<int> > a;

21. Sorry variant nested enums/typedefs in templates and all
enums/typedefs in class specializations:

	template <class T> struct A {
		enum E {ee = sizeof(T)};
		typedef T T2;
	};

	struct A<int> {
		enum E {ee = 47};
		typedef int T2;
	};

22. Fix friend scoping crash:
	
	template<class T> class X { 
		void f(int);
	}; 
	
	template <class T> class Y { 
		friend void X<double*>::f(int) {};
		friend X<double*>::f(int) {};
		friend void X<double*>::f(int) {}
		friend X<double*>::f(int) {}
		friend void X<double*>::f(int);
		friend X<double*>::f(int);
		friend void g(int);
	};

23. Fix for crash during error processing of:
	
	struct ZZZ37 {};
	
	template <class T, long n, class V> class A { 
	public : 
		A(int) ; 
	} ; 
	
	typedef class A<double*,12345L,ZZZ37> T ; 
	
	template<class T, long n, class V>
	class B : public A<double*,12345L,ZZZ37> { 
	public : 
		B() : T (5) { } 
	}; 
	
	main() 
	{ 
		B<double*,12345L,ZZZ37> b ; 
	} 

24. Fix for crash on trailing underscores in template names:

	template<class T> class _A { 
	public : 
		virtual int abc(); 
	} ; 
	
	template<class T> class B_ { 
	public: 
		virtual int def(); 
	};
	
	class C : public _A<double*> , public B_ <double*> { 
	public : 
		C() ; 
		int abc() ; 
	}; 
	
	C::C() {} 

25. Support complicated constant expressions as template arguments:

	template <int min, int max>
	class Subrange {
	public:
	      void f();
	};
	typedef Subrange <0,(~(1 << (8 * (int)sizeof(int)) - 1))> uint;
	template <int min, int max> void Subrange<min,max>::f() {}

26. Fix many "generated template instantiation name was not unique"
crashes, including:

	struct B {
		int x;
	};
	template <int B::*x> struct D6 {void f();};
	D6<&B::x> d6;
	typedef D6<(int B::*const)1> _dummy_;

27. Fix for parsing of:

	template <class T> struct J {
		static void func() {}
		static void (*fp)();
	};

	template <class T> void (*J<T>::fp)() = &J<T>::func;

28. Fix for parsing of:

	template <class T> struct D {
		friend int func(D<T>*) { return 1; }
		D(int i) { val = i; }
		int val;
	};

29. Fix for function template matching:

	struct B { };
	struct D : B { };

	template <class T> void oof(B&, T) { }

	void foo(D &rD)
	{
		oof(rD, 9);	// 3.0 does not match
	}

30. Fix for multiple instantiations of same template function:

	template <class T> class N { };

	struct B { };
	struct D : B { };

	template <class T> void oof(B&, N<T>&) { }

	void foo(D &rD, B &rB)
	{
		N<int> n;

		oof(rD, n);	// 3.0 instantiates `oof(B&, N<int>)' here
		oof(rB, n);	// and here
	}

31. Fix for invalid reuse of template function instantiations:

	template <class T> void F(const int&, T) { }

	void foo()
	{
		int i;
		const int &rci=i;
		F(rci, i);

		short s;
		F(i, s);	// 3.0 calls `F(const int&, int)' here
	}

32. Fix for spurious "too complicated" bail-out on:

	#include <iostream.h>

	template <class T> struct A
	{
		T re;
		char *s;
		A() { re = 0; s = "elementary!"; }
	};

	template <class T> ostream& operator<<(ostream& s, A<T>& a)
	{
		s << a.s; 
		return s;
	};

	main()
	{
		A<int> a;
		cout << "not too complicated -- " << a << "\n";

		return 0;
	}

33. Fix for assignment of function template name to pointer-to-function:

	template <class S, class T> int F(S s, T)
	{
		return sizeof s;
	}

	template <class S, class T> int G(S s, T t)
	{
		int (*pf)(T,S) = F;	// 3.0 rejects
		return (*pf)(t,s);
	}

	main()
	{
		if (G('x', 55) != sizeof (int))
			return 1;
		return 0;
	}

34. Fix for access of parameterized friends to template classes:

	template <class T> class B {
		friend void f(T);
		int i;
	};

	void f(double)
	{
		B<double> b;
		int j = b.i;	// 3.0 denies access
	}

35. Fix for specializations of template class member functions:

	template<class T, int *pi> class X {
		T* v;
	public:
		X();
		T& operator[](int);
	};

	template<class T, int *pi> T& X<T, pi>::operator[](int i)
	{
		return v[i];
	}

	int i;

	X<int, &i> iv;

	int &X<int, &i>::operator[](int i)	// 3.0 rejects
	{
		return v[i];
	}

36. Fix for bad C generated for:

	template <class T> struct A {
		int a;
	};

	template <class T> struct B : A<double*> {
		int b;
	};

	void f()
	{
		B<double*> b;
		b.a = 1;
		b.b = 2;
		A<double*> a = b;	// 3.0 generates bad C here
	}

37. Fix for assignments of pointers to template class members:

	template <class T> class Q {
	public:
		int i;
	};

	template <class T> class Z {
	public:
		int Q<int>::*p;
		Z();
	};

	template <class T> Z<T>::Z()
	{
		p = &Q<int>::i;		// 3.0 rejects
	}

	Z<int> z;

38. Fix for MI where derivation is from template classes:

	template <int i, class T> class A {
	public:
		T a;
		A(T j) : a(j) {}
	};

	class C : public A<1,int>, public A<5,long> {
	public:
		C() : A<5,long>(19L), A<1,int>(83) {}
	};

	main()
	{
		C c;

		if (c.A<1,int>::a != 83)
			return 1;
		return 0;
	}

39. Fix for crash on:

	template <class T, class U> void operator&&(T t, const U& u) { }

	struct A { };

	static void _dummy(A a1, A *const&a2)
	{
		operator&&(a1, a2);
	}

40. Fix for crash on:

	template <class T> class A {
	public:
		enum E { a = 33 };
		typedef E TD;
		int f() { return TD(); }
	};

	void g()
	{
		A<double*> Ao;
		int i = Ao.f();
	}

41. Fix for crash on:

	template <class T> class Q {
	public:
		int j;
	};

	template <class T> class Z {
	public:
		enum E { a = 7 } e;
		int Q<int>::*p;
		Z() : e(a), p(&Q<int>::i) { }
	};

	Z<int> z;

which should get a diagnostic.

42. Fix for crash on:

	template <class T> void T::foo() { }

which should get a diagnostic.

43. Fix for crash on:

	template <unsigned int ui> class C {
		char ac[ui-4];
	};

	C<sizeof'x'-1> c;

which should get a diagnostic.

44. Fix for crash on:

	template <class T> void swap(T&, T&);

	void f()
	{
		short is=10, js=20;
		swap(is, js);
	}

	template <class T> void swap(T& a, T& b)
	{
		T temp = a;
		a = b;
		b = temp;
	}

========================= demangler =========================

1. Add support for local variables:

	__2xxx --> xxx

2. Fix bug with trailing underscores on template class names:

	A___pt__2_i --> A_<int>

3. Add type field to DEM structure to tell what type of name was
demangled.

========================= ptcomp/ptlink =========================

1. New dependency checking scheme in ptlink that is much faster than
the old checksum scheme. This requires a one-time rebuilding of
repositories. See tools/pt/README.ptenv for full details.

2. Make Sun3 repository locking the same as other Sun types.

3. Add ARC_EXT and HE_EXT to pt.h.

4. Add CHECKSUM option to pt.h to get back the old checksum scheme
(see tools/pt/README.ptenv).

5. Make many variables static to their files to reduce their
visibility.

6. Fix ptcomp bug where one -I path was a prefix of another.

7. Fix ptcomp bug with use of the same type name in different
applications in one directory.

8. is_archive() function added to ptlink.c to better determine
whether a file is an archive.

9. Fix ptlink bug so that an instantiation done with -pta later
satisfies non-pta builds.

10. Fix ptlink bug so that instantiation objects are prepended rather
than appended to CC link line.

11. Fix internal ptlink bug where instantiation objects were appearing
twice in internal list with slight performance loss.

12. Fix ptlink bug with -pts redoing some instantiations.

13. Fix ptlink bug with not picking up arguments inside function
pointer arguments as template arguments.

========================= libraries =========================

1. Increase buffer sizes in stream/flt.c.

2. Fix bug in lib/task/task/sched.c where wait() instead of pause()
was called.

========================= miscellaneous =========================

1. Increase buffer sizes in munch.
