[comp.lang.c++] Bug in C++ 1.2 involving the :: operator

lomow@calgary.UUCP (04/04/87)

I have found a bug in release 1.2 of C++. Could you please look
at the following description of the problem and either confirm
or clear up the problem. I'm sorry if this problem has been
previously reported, but it is new to me.

The following program

	//////////
	#include <stdio.h>
	#define NULL 0
	
	class q_el {
	  q_el *Next;
	public:
	  q_el *next() { return Next;}
	  q_el(q_el *n) { Next=n; }
	};
	
	class d_q_el : public q_el {
	  int Count;
	public:
	  int count() { return Count;}
	  d_q_el(q_el *n, int c) : (n) { Count = c; }
	};
	
	main()
	{ q_el *q;
	  q = new d_q_el(NULL, 2);	// will be at the end of the list
	  q = new d_q_el(q, 1);		// will be at the head of the list
	
	  if ( ((d_q_el*)q) ->count() == 1) printf("ok\n");
	  if ( ((d_q_el*)q->next()) ->count() == 2) printf("ok\n");
	
	  if (q->d_q_el::count() == 1) printf("ok\n");
	
	// *** the following line causes an internal error ****
	  if (q->next()->d_q_el::count() == 2) printf("ok\n");
	}
	//////////

causes the compiler to issue the following messages:

	% CC c.err.c
	CC  c.err.c:
	"c.err.c", line 31: internal <<cfront 05/20/86>> error:
		bus error (or something nasty like that)
	1 error
	% 

The problem seems to be the use of the scope resolution operator
(i.e., '::') with a result returned from a function (or maybe it
has to do with the way inline functions are expanded).

The error can be eliminated by:

	1) Commenting out line 30 (the line before the
		closing curly bracket of main()).

or

	2) Making Next a public data member of q_el and changing
		the calls to next() in main() to references to the 
		variable Next - as shown in the following program.

	//////////
	#include <stdio.h>
	#define NULL 0
	
	class q_el {
	public:
	  q_el *Next;						// MOVED
	  q_el *next() { return Next;}
	  q_el(q_el *n) { Next=n; }
	};
	
	class d_q_el : public q_el {
	  int Count;
	public:
	  int count() { return Count;}
	  d_q_el(q_el *n, int c) : (n) { Count = c; }
	};
	
	main()
	{ q_el *q;
	  q = new d_q_el(NULL, 2);
	  q = new d_q_el(q, 1);
	
	  if (((d_q_el*)q)->count() == 1) printf("ok\n");
	  if (((d_q_el*)q->Next)->count() == 2) printf("ok\n");	// CHANGED
	
	  if (q->d_q_el::count() == 1) printf("ok\n");
	
	  if (q->Next->d_q_el::count() == 2) printf("ok\n");	// CHANGED
	}
	//////////

I prefer the following style
	  if (q->next()->d_q_el::count() == 2) printf("ok\n");
to
	  if ( ((d_q_el*)q->next()) ->count() == 2) printf("ok\n");
because the cast in the second if statement is hard to read.
Would anyone care to comment? are there other alternatives?

Thank You,

Greg Lomow.

Usenet:    ....![ubc-vision,ihnp4]!alberta!calgary!lomow

bs@alice.UUCP (04/08/87)

lomow@calgary.UUCP (lomow @ U. of Calgary, Calgary, Ab.) writes:

 > I have found a bug in release 1.2 of C++. Could you please look
 > at the following description of the problem and either confirm
 > or clear up the problem. I'm sorry if this problem has been
 > previously reported, but it is new to me.
 > 
 > The following program
 > 
 > 	#include <stdio.h>
 > 	#define NULL 0
 > 	
 > 	class q_el {
 > 	  q_el *Next;
 > 	public:
 > 	  q_el *next() { return Next;}
 > 	  q_el(q_el *n) { Next=n; }
 > 	};
 > 	
 > 	class d_q_el : public q_el {
 > 	  int Count;
 > 	public:
 > 	  int count() { return Count;}
 > 	  d_q_el(q_el *n, int c) : (n) { Count = c; }
 > 	};
 > 	
 > 	main()
 > 	{ q_el *q;
 > 	  q = new d_q_el(NULL, 2);	// will be at the end of the list
 > 	  q = new d_q_el(q, 1);		// will be at the head of the list
 > 	
 > 	  if ( ((d_q_el*)q) ->count() == 1) printf("ok\n");
 > 	  if ( ((d_q_el*)q->next()) ->count() == 2) printf("ok\n");

The following line contains an error:

 > 	  if (q->d_q_el::count() == 1) printf("ok\n");

"q" is a pointer to a "q_el" and a "q_el" does not have a base class
called "d_q_el". The member qualification syntax "class_name::member_name"
is a mechanism for disambiguation and not a mechanism for breaking the type
system.
 > 	// *** the following line causes an internal error ****
 > 	  if (q->next()->d_q_el::count() == 2) printf("ok\n");

same bug, sorry about the poor error message. My latest cfront says:
"", line 25: error: d_q_el  is not a base class of  q_el
"", line 32: error: d_q_el  is not a base class of  q_el

 > 	}

 > causes the compiler to issue the following messages:

 > 	"c.err.c", line 31: internal <<cfront 05/20/86>> error:
		bus error (or something nasty like that)

 > I prefer the following style
 > 	  if (q->next()->d_q_el::count() == 2) printf("ok\n");
 > to
 > 	  if ( ((d_q_el*)q->next()) ->count() == 2) printf("ok\n");
 > because the cast in the second if statement is hard to read.
 > Would anyone care to comment? are there other alternatives?

The cast notation is ugly because you are doing something ugly.
Please don't misunderstand me: casts can be necessary, but I see
no point in going out of my way to make them pleasing to the eye.

There is a ``proper way'' of ``raising'' the type of a base class to
that of the appropriate derived class: a virtual function call.

Thank you for reporting the bug/problem.

I have a point about style too: Don't use ``#define NULL 0''; it is redundant
and classical C variations such as ``#define NULL ((char*)0)'' are potentially
harmful.