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