[gnu.g++.bug] Is "class x" legal?

gordon%stats.ucl.ac.uk@NSS.CS.UCL.AC.UK (Gordon Joly Statistics UCL) (02/04/89)

I have submitted this example before and was confident that the fix
was OK. But I still cannot compile any of the code unless I change
"class x" to "class z" throughout. Even then, the test fails. I am 
prepared to admit that the fault may lie at this end. But is it odd.

I am using g++ and libg++.a version 1.32.0, under two configurations,
a SUN-3/160 under 3.4 and SUN-3/50 under 4.0.1. Links on 3.4 OS are

Linked `config.h' to `xm-m68k.h'.
Linked `tm.h' to `tm-sun3+.h'.
Linked `md' to `m68k.md'.
Linked `aux-output.c' to `output-m68k.c'.

Here is the error in the compilation.

karl:/stats/staff/karl/gordon/c++/otto/workspace[85] make -n
g++  -c x.cc
g++  -c testing_prog.cc
g++  -o testing_prog testing_prog.o x.o
testing_prog 2> errors-prob_bitwise_copying > calling_sequence
if [ -s errors-prob_bitwise_copying ]; then cat errors-prob_bitwise_copying; exit 1; else rm errors-prob_bitwise_copying; fi
# calling seq check is only valid if previous check was OK
awk -f check.awk calling_sequence > errors-sequencing
if [ -s errors-sequencing ]; then cat errors-sequencing; exit 1; else rm errors-sequencing; fi
# rm calling_sequence
echo " - Passed test OK"
karl:/stats/staff/karl/gordon/c++/otto/workspace[86] make
g++  -c x.cc
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/builtin.h:71: parse error before `x'
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/builtin.h:72: parse error before `x'
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/builtin.h:73: parse error before `x'
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/builtin.h:74: parse error before `x'
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:133: parse error before `x'
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:134: parse error before `x'
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:247: parse error before `x'
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:248: warning: inline declaration ignored for function with `...'
In function struct File &File::read (...):
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:249: parse error before `,'
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:249: `n' was not declared (first use this function)
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:249: (Each undeclared identifier is reported only once
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:249: for each function it appears in.)
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:249: parse error before `)'
At top level:
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:252: parse error before `x'
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:253: warning: inline declaration ignored for function with `...'
In function struct File &File::write (...):
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:254: parse error before `,'
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:254: `n' was not declared (first use this function)
/stats/staff/karl/gordon/GNU/usr/ucl/lib/g++-include/File.h:254: parse error before `)'
*** Error code 1

Stop.
karl:/stats/staff/karl/gordon/c++/otto/workspace[87] 

Gordon Joly.

Surface mail: Dr. G.C.Joly, Department of Statistical Science,
      University College London, Gower Street, LONDON WC1E 6BT, U.K.
E-mail:  					   | Tel: +44 1 387 7050
 JANET (U.K. network) gordon@uk.ac.ucl.stats       |      extension 3636
       (Arpa/Internet form: gordon@stats.ucl.ac.uk)| FAX: +44 1 387 8057
Relays: ARPA @nss.cs.ucl.ac.uk                     |
        EAN: @ean-relay.ac.uk                      |
	CSNET: %nss.cs.ucl.ac.uk@relay.cs.net      |
        BITNET: %ukacrl.bitnet@cunyvm.cuny.edu, @ac.uk
        EARN: @ukacrl.bitnet, @AC.UK, @uk.ac.earn-relay
By uucp/Usenet: ....!uunet!mcvax!ukc!stats.ucl.ac.uk!gordon

-- Makefile start --
# to create & run "constructor/destructor" test for C++
#
# To run test, just utter "make" in this directory.
#

# filenames for errors
EBC=errors-prob_bitwise_copying
ESEQ=errors-sequencing

CC=g++

tests:	testing_prog check.awk
	testing_prog 2> $(EBC) > calling_sequence
	if [ -s $(EBC) ]; then cat $(EBC); exit 1; else rm $(EBC); fi
	# calling seq check is only valid if previous check was OK
	awk -f check.awk calling_sequence > $(ESEQ)
	if [ -s $(ESEQ) ]; then cat $(ESEQ); exit 1; else rm $(ESEQ); fi
	# rm calling_sequence
	echo " - Passed test OK"
	
testing_prog: x.h x.o testing_prog.o
	$(CC) $(CFLAGS) -o testing_prog testing_prog.o x.o

testing_prog.o: x.h testing_prog.cc
	$(CC) $(CFLAGS) -c testing_prog.cc

x.o:	x.h x.cc
	$(CC) $(CFLAGS) -c x.cc

clean:
	rm -f *.o *..c core calling_sequence $(EBC) $(ESEQ)

clobber:	clean
	rm -f testing_prog
-- Makefile end --

# This is a shell archive, shar, format file.
# To unarchive, feed this text into /bin/sh in the directory
# you wish the files to be in.

echo x - check.awk 1>&2
sed 's/^X//' > check.awk << 'End of check.awk'
X# Check output from ctor/dtor test prog.
X#
X# Input is assumed to be a sequence of lines of the form:
X#	<routine-name> called; "this" = <address>
X#	
X# An error is reported if, for any given address, the routine calls do not
X# occur as in the following BNF:
X#		{ ctor-call other-call* dtor-call }*
X# (Constructor call includes initializers.)
X#
X# NB This awk script is relatively fragile - it does not validate its
X# input, or do any other such checks for errors in the testing programs
X# themselves.
X#						GPO 16/11/87
X#	Minor mod (to tidy up prog slightly)	GPO 24/11/87
X
X	{	if (($1 == "x::x()") || ($1 == "x::x(x&)")){	# ctor
X			if (status[$5] == "defined"){
X				print "ERROR: multiple use of address " $5 " on line " NR
X			} else {
X				status[$5] = "defined"
X			}
X		} else if ($1 == "x::~x()"){			# dtor
X			if (status[$5] != "defined"){
X				print "ERROR: dtor called for unit'ed address " $5 " on line " NR
X			} else {
X				status[$5] = "undefined"
X			}
X		} else {					# other
X			if (status[$5] != "defined"){
X				print "ERROR: routine using unit'ed address " $5 " on line " NR
X			}
X		}
X	}
XEND	{	for (a in status){	# check that all dtors have been called
X			if (status[a] == "defined"){
X				print "ERROR: address " a " has not been dtor'ed by end of prog"
X			}
X		}
X	}
End of check.awk
chmod 755 check.awk
echo x - testing_prog.cc 1>&2
sed 's/^X//' > testing_prog.cc << 'End of testing_prog.cc'
X#include "x.h"
X
X// first some routines to play with ...
X
Xx
Xf(x arg1, x arg2)
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
Xint
Xintf(x arg1, x arg2)
X{
X	x local1, local2, local3;
X
X	return 0;
X}
X
Xx
Xg()
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
Xx
Xh()
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
Xx
Xi(x arg)
X{
X	x local1, local2, local3;
X
X	return local2;
X}
X
X#ifndef pyr
Xx
Xdoubly_recursive(int depth_to_go)
X{
X	if (depth_to_go > 0){
X		return(f(doubly_recursive(depth_to_go-1),
X				doubly_recursive(depth_to_go-1)));
X	} else {
X		x local;
X		return(local);
X	}
X}
X#endif
X
X// Now call the routines & see what happens ...
Xint
Xmain()
X{
X	// test for calling of ctors & dtors on nested calls ...
X	{
X		x local;
X
X		local = f(g(),h());
X	}
X#ifndef pyr
X	// test for calling of ctors & dtors in recursive calls ...
X	doubly_recursive(3);
X#endif
X	// test for calling of ctors & dtors in nested calls occurring in
X	//  an expression
X	{
X		x a;
X		if (intf(i(g()),a))
X			7;
X	}
X	return 0;	// ought to return true status, but .....
X}
End of testing_prog.cc
chmod 755 testing_prog.cc
echo x - x.cc 1>&2
sed 's/^X//' > x.cc << 'End of x.cc'
X// noddy class for testing purposes
X//
X// BEWARE: This file relies on being able to coerce a class pointer into
X// a long so that it can be printed.
X
X#include "x.h"
X#include <stream.h>
X
Xinline static void
Xtell_world(char * who, x* address)
X{
X	cout << who << " called; \"this\" = " << (long) address << "\n";
X	// Might be more convenient when debugging to use stderr, so that
X	//  stays in sync with error messages - but test makefile assumes
X	//  stdout.
X}
X
Xinline static void
Xerror_address_mismatch(char* routine, x* says, x* actual)
X{
X	cerr << "ERROR: address mismatch in call of " << routine
X		<< "; class instance thought address was " << (long) says
X		<< ", but it was actually " << (long) actual << "\n";
X}
X
Xx::x()
X{
X	tell_world("x::x()",this);
X	self = this;
X}
X
Xx::x(x& xref)
X{
X	tell_world("x::x(x&)",this);
X	self = this;
X	if (xref.self != &xref)
X		error_address_mismatch("x::x(x&)",xref.self,&xref);
X}
X
Xx&
Xx::operator=(x& rhs)
X{
X	tell_world("x::operator=(x&)",this);
X	if (rhs.self != &rhs)
X		error_address_mismatch("x::operator=(x&)",rhs.self,&rhs);
X	if (self != this)
X		error_address_mismatch("x::operator=(x&)",self,this);
X	return(*this);
X}
X
Xx::~x()
X{
X	tell_world("x::~x()",this);
X	if (self != this)
X		error_address_mismatch("x::~x()",self,this);
X}
End of x.cc
chmod 755 x.cc
echo x - x.h 1>&2
sed 's/^X//' > x.h << 'End of x.h'
X// simplest class which completely avoids bitwise copying.
X// good for testing calling of constructors and destructors.
X
Xclass x {
X	class x* self;	// Note own address for testing/debugging purposes
Xpublic:
X	x();
X	x(x&);
X	x& operator=(x&);
X	~x();
X};
End of x.h
chmod 755 x.h