[net.lang.c++] Bugs in C++ Release 1.0

keith@cecil.UUCP (keith gorlen) (03/04/86)

Attached is a list of bugs we've found in Release 1.0 of the C++
translator.  These have been reported to AT&T, so maybe you can save
yourself the trouble if they bite you!  I'd like to hear of others
anyone has found.

---
	Keith Gorlen
	Computer Systems Laboratory
	Division of Computer Research and Technology
	National Institutes of Health
	Bethesda, MD 20892
	phone:	(301) 496-5363
	uucp:	{decvax!}seismo!elsie!cecil!keith

-----
CC#1

Following declaration causes syntax error:

	extern void seterrtrap(int(*)(),int);

Work-around:

	typedef int(*error_handler)();
	extern void seterrtrap(error_handler,int);

[new in cfront 8/20/85]
[not fixed in Release 1.0]

-----
CC#2

Following program produces C code containing an error:

//structbug.c
#include <stream.h>

class Object {
public:
	virtual printOn(ostream& strm);
	Object() {}
};

class Point : public Object {
	int x,y;
public:
	Point(int X=0, int Y=0) { x=X; y=Y; }
	virtual printOn(ostream& strm);
	Point operator+(Point& p)	{ return Point(x+p.x, y+p.y); }
	Point operator-(Point& p);
};

inline ostream& operator<<(ostream& strm, Object& ob)
{
	ob.printOn(strm);
	return strm;
}

main()
{
	Point a,b;
	cout << (a+b);	/* OK because operator+ inline */
	cout << (a-b);	/* cc error: "structbug.c", line 28: assignment of different structures */
}

[not fixed in Release 1.0]

-----
CC#3

Following program produces C code containing errors:

/*
##F-cc (100):"redec.c", line 33: redeclaration of _String__call
*/

#include <string.h>

class String;

class SubString {
	char* sp;	/* substring pointer */
	int sl;		/* substring length */
	SubString(String& s, unsigned pos, unsigned lgt);
	friend String;
public:
	void operator=(SubString& from);
	void operator=(String& from);
};

class String {
	char* v;
	int sz;
	String(char* cs, unsigned lgt);
	friend SubString;
public:
	String(char* cs="");
	String(String& s);
	String(SubString& ss);
	SubString operator()(unsigned pos, unsigned lgt);
	void operator=(String& s);
};

inline SubString String::operator()(unsigned pos, unsigned lgt)
{
	return SubString(*this, pos, lgt);
}
	
main()
{
	String a("abcdef");
	String b = "012345";
	a(0,2) = b(0,3);
}


CC  +L redec.c:
"redec.c", line 34: warning: bitwise copy: SubString has a member with operator=()
cc  -c  redec..c -lC
##F-cc (100):"redec.c", line 33: redeclaration of _String__call
##F-cc (100):"redec.c", line 34: operands of CAST have incompatible types

[not fixed in Release 1.0]

-----
CC#4

Compiler aborts, see subdirectory abort1.
	CC  +L Object.c:
	/usr/bin/CC: 14652 Memory fault - core dumped
	139 errors

[The example program has been omitted because of its size.]

-----
CC#5

Compiler aborts, see subdirectory abort2.  Interchanging last two
functions corrects problem.
[Actually a problem with cpp caused by long #define's like those in
vector.h]

----
CC#6

Compiler aborts with "input buffer overflow" error.  See abort2.
[can't duplicate]

-----
CC#7

Following program will not compile:

//ctor.c
#include <stream.h>

class Object {
	int* isa;
public:
	Object() {}
	Object(istream&,Object&);
	virtual int size();
};

class Point : public Object {
	short x,y;
public:
	Point(int X=0,int Y=0);
	Point(istream&,Object&);
};

main() { Point p; }

CC  +L ctor.c:
"ctor.c", line 17: error:  initializer makes overloaded _ctor() ambiguous
1 error

[not fixed in Release 1.0]

-----
CC#8

Messages such as:

	"amb.c", line 8: warning: overloaded != may be ambiguous

should provide more information by indicating what the ambiguous
interpretations are specifically.  These can be very difficult
to determine otherwise.

-----
CC#9

Constructor/destructor for variable declared within switch statement not called
at proper times:

#include "stream.h"
struct foo {
	int x;
	foo()  { cerr << "constructed\n"; }
	~foo() { cerr << "destructed\n"; }
};

main()
{
	for (int i=1; i<=3; i++) {
		switch(i) {
			case 1:
				foo j;
				cerr << "case 1\n";
				break;
			case 2:
				cerr << "case 2\n";
				break;
		}
	}
}

Running this program produces the output:

constructed
case 1
destructed
case 2
destructed

Workaround:  place {} around statements after each case.

-----
CC#10

Following program produces C code containing an error:

//cast.c
inline int BIT(int i)	{ return 1<<i; }

class Bitset {
	int m;
	Bitset(int i, float)	{ m = i; }
public:
	Bitset()			{ m = 0; }
	Bitset(int i1)			{ m = BIT(i1); }
	Bitset(Bitset& n)		{ m = n.m; }
	Bitset operator|(Bitset n)	{ return Bitset(m | n.m, 0.0); }
};

main()
{
	Bitset a(1),b(2);
	b = b | a | 3;
}

CC  +L cast.c:
cc  -c  cast..c -lC
##F-cc (100):"cast.c", line 11: operands of CAST have incompatible types

[NEW BUG in Release 1.0]

-----
LIB#1

From the file /usr/include/CC/vector.h:

vector(type).vector(type)(vector(type)& a)
{
	register i = a.sz;
	v = new type[i];
	register type* vv = &v[i];
	register type* av = &a.v[i];
	while (i--) *--vv = *--av;
}

The assignment "sz = a.sz" should be added.
[not fixed in Release 1.0]

-----
LIB#2

Problem with stream.h:

tied_to stream not flushed when istream::get() called.

-----
LIB#3

Problem with stream.h:

There seems to be no way to read a single line of characters from an
interactive input stream such as a terminal.  Something like:

	char line[512];
	char term;
	cin.get(line,512);	/* read to '\n' */
	cin.get(term);		/* skip the '\n' */

doesn't work because the second get tries to read another line of input.
Tricks such as reversing the order of the gets have other problems, like
not working for the first line or not working for empty lines.  It seems
that there should be an easy way provided to do something as common as
this.

-----
LIB#4

stream functions oct, dec, and hex don't work for negative numbers:

#include <stream.h>
main()
{
	cout << dec(-1) << "\n";
	cout << oct(-1) << "\n";
	cout << hex(-1) << "\n";
}

-----
LIB#5

"munch" does not work under Masscomp UNIX V2.2A unless compiled with
-DBSD

-----
INC#1

problems in osfcn.h:

Syntax error caused by:

	extern int      acct (const har*);

Declaration:

	extern int      create (const char*, int);

should be:

	extern int      creat (const char*, int);

Declaration:

	extern int      open (char*, int);

should be:

	extern int      open (char*, int ...);

so that O_CREAT can be given a mode argument.

-----
DOC#1

Result of log((complex(1,2.718)/3) = (-0.035240,1.218249) not
(0.706107,1.10715) as given in article "Complex Arithmetic in C++".

-----
-- 
---
	Keith Gorlen
	Computer Systems Laboratory
	Division of Computer Research and Technology
	National Institutes of Health
	Bethesda, MD 20892
	phone:	(301) 496-5363
	uucp:	{decvax!}seismo!elsie!cecil!keith