[comp.lang.c++] Possible cfront 1.1 bugs, general observations

tjt@styx.UUCP (Tim Tessin) (11/18/86)

I missed the postings in this newsgroup from about March to August of 
this year.  I don't know if these bugs have been posted before.  
If anyone who archives news can get me the March-August postings I would 
appreciate it.

I have come across the following anomalies in C++ cfront 1.1 (These were 
present in 1.0 also).
All examples have been compiled on a VAX/780 running BSD4.2.
(Side note, one C++ module I created, caused an expression tree overflow
 in my 4.2 compiler.  I had to increase the expression tree size of ccom
 to get the stuff to compile. A few less parenthesis please! :-) )

----- Example 1 ------
xx.c:
	class T
		{
	public:
		T(){}
		int operator() (int i, int j = -1) { return i==j; }
--->		operator char () { return 'a'; }
		};
	main ()
		{
		T s;
		s(0,10);
		s(10);
		}

This program produces a warning from cfront upon compilation as follows:

	CC  xx.c:
	"xx.c", line 13: warning: overloaded function call may be ambiguous.
			 function with type int T::(int , int ) used

When the conversion operator 'char' (as indicated by the arrow above)
is removed there is no ambiguity.  I don't see how this can be "normal".
Overloading of the '()' operator should not conflict with the 'char' conversion
member.  Note that the 'char' operator could be anything: long, float,
char* etc.; it still draws the warning.

----- Example 2 ------
yy.c:
	class T 
		{
	public:
		T(){}  
		int f()
			{
			int i = 4; 
			i += 10;    // "use" i in some inane way
			T p;	    // new declaration
			return i;
			}
		};

	main () 
		{ 
		T s; 
		s.f();
		}

Produces error as follows:
	CC  yy.c:
	cc  -c  yy..c
	"yy.c", line 17: _auto_p undefined

To see why, look at yy..c (condensed version):
yy..c:
	struct T 
		{
		char _dummy; 
		} ;

	int main ()
	{ _main(); 
		{ 
		struct T _auto_s ;
		int _auto__Xi_f_T;
		(((struct T *)(&_auto_s)));
		((_auto__Xi_f_T = 4),
		((_auto__Xi_f_T += 10 ),
		((((struct T *)(& _auto_p))),      <--- _auto_p not declared
		_auto__Xi_f_T)));
		}
	};

This happens only in member functions defined in the class body or
"inline" functions.  It is not hard to understand why this is happening.
The output from cfront is missing the declaration of 'p' because all
declarations must be at the beginning of a block (a cc requirement, not CC).
The two obvious solutions are to either declare the 'p' object at the
beginning of the region of scope or add an extra level of scope by
injecting more {} pairs.  I don't have the foggiest as which is the better
solution.  Since this is "inline", the compiler may not have enough
information to properly resolve this when the "inline" is encountered.

----- Example 3 -----

This is not a actual bug but just a anomaly I ran across. The idea was
to benchmark a class by delaring a "statistics" class and making it 
a friend to the class I wanted to benchmark.  I then added code
to increment counters in the desired class.  The "statistics" class
had a ctor to initialize counters, member functions to increment counters,
and a dtor to dump statistics using stream cout.  The ctor,dtor,and members
for "statistics" was implemented in a stat.c file.  The declarations are
in a stat.h file.  Now, main looks like this:

zz.c:
	#include <stream>     // try to cause ctor/dtor cout first/last
	#include "stat.h"
	static stats st;
	main ()
		{
		/* do something with desired class */
		}

The compile line is as follows: CC -o zz zz.c stat.c

The desired action was to print statistics at program termination.
What actually happens is that since "cout" is not used in "main" but
only in stat.c the declaration for the static stream cout is in the
stat.o file.  The "munch" program sees the static "stats" declaration
first and causes the static ctor functions and dtor functions to be
executed in the wrong order!  Stream cout is closed before the
dtor for stats can output the stuff.  If I declare the stats ctor and dtor
within the class body it is ok.
I understand the cfront can't really be expected to be able to handle this,
but I would prefer to be able to completely separate member declarations
and implementations from the class definitions.  It bothers me to have
half my code in a .h file and the other half in the .c file.  You also can't
guarantee that "inline" will always be applied, so including member functions
in the .h file may some day cause multiple define errors from your loader if
you include a .h file in more than one file.
Food for thought y'all.

------ General Comments -------
C++ is great!  What is the scoop from ATT on debuggers, libraries etc?
Can we look forward to any neat things comming down the pipe(2)?
I was, however, dismayed at finding more links to stdio in the stream
library in V1.1.  I was considering writing my own exit() just to get rid
of the external reference to _cleanup but there is still the use of 
sprintf which causes a good portion of the stdio library to be brought in.  
With the power of C++ to express startup and exit behaviour through 
static constructors and destructors, it seems to me that we can now do
better than this.

Tim Tessin  -  Lawrence Livermore National Laboratory 
Phone: 415-463-6850 / 415-423-3992 
ARPA:  tjt@lll-tis-b.ARPA       UUCP: {ihnp4,dual,sun}!lll-lcc!styx!tjt