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