[gnu.g++.bug] bug

rfg@MCC.COM (Ron Guilmette) (01/26/89)

The following three files show that G++ (1.32.0) handles the
case of a call to an un-declared constructor differently in
different contexts.  If the call to the undeclared constructor
occurs for a static or an auto object, then warnings are issued.
If however the constructor call is made for a heap (new) object
then an error is issued.

I believe that all three cases demand that an error be issued.
After all, you are supposed to declare things before you use
them right?  At the very least, all three cases should be handled
the same way.


====================================================================
/*
Description - check that a constructor with a given parameter profile
		cannot be called for a global (static) object unless
		the constructor has already been explicitly declared.
*/

struct node {
  int f1;
};

node global_node(7);	// ERROR: node(int) not declared
====================================================================
/*
Description - check that a constructor with a given parameter profile
		cannot be called for a local (auto) object unless the
		constructor has already been explicitly declared.
*/

struct node {
  int f1;
};

main ()
{
	node local_node(9);	// ERROR: node(int) not declared
}
=====================================================================
/*
Description - check that a constructor with a given parameter profile
		cannot be called for a heap (new) object unless the
		constructor has already been explicitly declared.
*/

struct node {
  int f1;
};

main ()
{
	node& node_ref = new node(9);	// ERROR: node(int) not declared
}
=========================================================================

rfg@MCC.COM (Ron Guilmette) (02/23/89)

The following short fragment of code demonstrates three independent
problems with g++ 1.33.0 (on a Sun 3).

a)	Errors do not prevent a .s or a .o file from being generated.
	They should.  Otherwise some (bad) Makefiles can do bad things.

b)	Errors in processing global level declarations cause strange
	looking error messages to be generated.  Specifically, in the
	example below, prior to one of the errors, I get:

	In function void _GLOBAL_$I$x02_cc ():

	I think that this function-identification stuff which generally
	preceeds error message groups for a given function is (obviously)
	nonsense at the global level and should be suppressed.

c)	The error messages issued for the case when a default constructor
	is needed but the one that exists is non-public are misleading
	and confusing.  They just say that there is no default constructor.
	In fact, there is one!  It's just not "visible" at the points where
	it needed to be.  The error messages should say that instead.

The code follows below.  After the code is a log showing the results of
compilation.

// Ron Guilmette  -  MCC  -  Experimental (parallel) Systems Kit Project
// 3500 West Balcones Center Drive,  Austin, TX  78759  -  (512)338-3740
// ARPA: rfg@mcc.com
// UUCP: {rutgers,uunet,gatech,ames,pyramid}!cs.utexas.edu!pp!rfg

Cut here
----------------------------------------------------------------------
/*
Description - check that if a default constructor is need (e.g. at the point
		of an object declaration) and that if there is a constructor
		which takes zero arguments but which is non-public, a
		reasonable error message is issued.
*/

class base
{
    base();
    virtual ~base();
};
  
inline base::base() {}
inline base::~base() {}

class derived : base
{
public:
    derived();
    ~derived();
};
 
base base_object;

inline derived::derived() : ()
{
}
------------------------------------------------------------------------
/usr/local/src/src/g++/build/1.33.0.0/sun3/g++ -B/usr/local/src/src/g++/build/1.33.0.0/sun3/ -S -v x02.cc
g++ version 1.33.0
 /usr/local/lib/gcc-cpp -+ -v -undef -D__GNU__ -D__GNUG__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -D__HAVE_68881__ -Dmc68020 x02.cc /tmp/cca16143.cpp
GNU CPP version 1.32
 /usr/local/src/src/g++/build/1.33.0.0/sun3/c++ /tmp/cca16143.cpp -quiet -dumpbase x02.cc -noreg -version -o x02.s
GNU C++ version 1.33.0 (68k, MIT syntax) compiled by GNU C version 1.33.
In method struct derived *derived::derived ():
x02.cc:28: no default constructor defined for type `base'
In function void _GLOBAL_$I$x02_cc ():
x02.cc:24: no default constructor defined for type `base'
*** Error code 1 (ignored)

rfg@MCC.COM (Ron Guilmette) (03/10/89)

The following short program demonstrates two bugs in g++ 1.34.0 on a Sun3.
First, it gets a compile time error (I think that it shouldn't).  Second,
even after the error, a .s output file is left on disk (it should not be).

Following the program is a log of the compilation, assembly, linking,
and execution.  Note that the error goes away if the first declaration
of a virtual function called foo (i.e. the one in class c1) is made
non-virtual (e.g. by commenting out the word virtual).

Cut here
--------------------------------------------------------------------------
/*
Description - check that calls to the correct overloaded virtual
	function are generated even where the type of the formal
	arguments for the overloadings are very similar or related.
*/

class c1 {
public:
	virtual void foo (char)
	{
		printf ("FAILED - wrong overloaded virtual function called\n");
		exit (0);
	}
};

class c2 : c1 {
public:

	virtual void foo (char)
	{
		printf ("FAILED - wrong overloaded virtual function called\n");
		exit (0);
	}

	virtual void foo (char *)
	{
		printf ("PASSED\n");
	}
};

void test ();

void main ()
{
	test ();
	exit (0);
}

char *message = "hello, world!";

void test ()
{
	c2 c2_object;

	c2_object.foo (message);
}
---------------------------------------------------------------------------
g++  -S -v x13.cc
g++ version 1.34.0.1
 /usr/local/src/lib/1.34.0.1/sun3/gcc-cpp -+ -v -undef -D__GNU__ -D__GNUG__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -D__HAVE_68881__ -Dmc68020 x13.cc /tmp/cca03715.cpp
GNU CPP version 1.34.0.1
 /usr/local/src/lib/1.34.0.1/sun3/gcc-c++ /tmp/cca03715.cpp -quiet -dumpbase x13.cc -noreg -version -o x13.s
GNU C++ version 1.34.0.1 (68k, MIT syntax) compiled by GNU C version 1.33.
x13.cc:26: conficting specification deriving virtual function `void c2::foo (char *)'
*** Error code 1 (ignored)
as  x13.s -o x13.o
g++  x13.o -o x13
./x13
PASSED

rfg@MCC.COM (Ron Guilmette) (03/11/89)

I'm not sure what the precise rules are regarding the required visibility
of constructors at points where they are invoked, but the following code
indicates that G++ (1.34.0/Sun3) does *not* issue errors at those points
where a given constructor is called even though it is "private" (and therefore
invisible?) at these points.

I believe that all of the lines marked with // ERROR in the code below should
be flagged by the compiler as containing errors.  The basis of this belief
comes from Stroustrup's article in the 1987 SantaFe proceedings (page 11)
where he notes that you can effectively make a given operation (i.e. assignment)
illegal (for objects of the class, in areas outside of the class) simply by
explicitly declaring the given operation within the private part of the class
declaration.  If this is also true for the "construction" operation, then
g++ should be issuing errors for all the // ERROR lines below.

Following the code is the compilation log.  Note that no errors or warnings are
issued.

Cut here.
-------------------------------------------------------------------------------
/*
Description - check that if a default constructor is needed (e.g. at the point
		where an object is created) and that if there is a constructor
		which takes zero arguments but which is private, a reasonable
		error message is issued.

		Cases: objects which are: (1) static (2) auto (3) heap.

		Cases: objects of (1) a type which has a private default
		    constructor, and (2) objects of a type derived from a type
		    which has a private default constructor.
*/

class base
{
    base();
    friend class friendly;
};

static base static_base_object_1;		// ERROR
base static_base_object_2;			// ERROR

void f1 ()
{
	base local_base_object;			// ERROR
	base *base_ptr = new base;		// ERROR
}
 
class derived : base
{
public:
    derived();
};

static derived static_derived_object_1;		// ERROR
derived static_derived_object_2;		// ERROR

void f2()
{
	derived local_derived_object;		// ERROR
	derived *derived_ptr = new derived;	// ERROR
}
----------------------------------------------------------------------------------
g++  -S -v x02.cc
g++ version 1.34.0.0
 /usr/local/src/lib/1.34.0.0/sun3/gcc-cpp -+ -v -undef -D__GNU__ -D__GNUG__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -D__HAVE_68881__ -Dmc68020 x02.cc /tmp/cca07700.cpp
GNU CPP version 1.34.0.0
 /usr/local/src/lib/1.34.0.0/sun3/gcc-c++ /tmp/cca07700.cpp -quiet -dumpbase x02.cc -noreg -version -o x02.s
GNU C++ version 1.34.0.0 (68k, MIT syntax) compiled by GNU C version 1.33.

rfg@MCC.COM (Ron Guilmette) (03/11/89)

This bug report (for G++ 1.34.0/Sun3) is very much like my previous one about
private constructors, except this one is about private destructors.

In either case, the programmer should be allowed to make certain operations
of a given class (such as assignment, construction, and destruction) illegal
outside of the class just by declaring these operations within the private
part of the class declaration.

Unfortunately, g++ doesn't (currently) let you control the visibility of
constructors or destructors this way.  These operations remain accessable
anywhere regardless of their public or private status.

The following code demonstrates this.  I believe that all of the lines
marked with // ERROR should have errors messages issued for them because
these are the places where base::~base() gets (implicitly) called.

Following the code is a compilation log.

Cut here
------------------------------------------------------------------------------
/*
Description - check that if a destructor is needed (e.g. at the point
		where an object is destroyed) and that if there is a destructor
		for the class of the object, but it is private, a reasonable
		error message is issued.

		Cases: objects which are: (1) static (2) auto (3) heap.

		Cases: objects of (1) a type which has a private default
		    constructor, and (2) objects of a type derived from a type
		    which has a private default constructor.
*/

class base
{
    ~base();
    friend class friendly;
};

static base static_base_object_1;		// ERROR
base static_base_object_2;			// ERROR

void f1 ()
{
	base local_base_object;
	base *base_ptr = new base;

	return;					// ERROR, ERROR
}
 
class derived : base
{
public:
    ~derived();
};

static derived static_derived_object_1;		// ERROR
derived static_derived_object_2;		// ERROR

void f2()
{
	derived local_derived_object;
	derived *derived_ptr = new derived;

	return;					// ERROR, ERROR
}
----------------------------------------------------------------------------------
g++  -S -v x03.cc
g++ version 1.34.0.0
 /usr/local/src/lib/1.34.0.0/sun3/gcc-cpp -+ -v -undef -D__GNU__ -D__GNUG__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -D__HAVE_68881__ -Dmc68020 x03.cc /tmp/cca07729.cpp
GNU CPP version 1.34.0.0
 /usr/local/src/lib/1.34.0.0/sun3/gcc-c++ /tmp/cca07729.cpp -quiet -dumpbase x03.cc -noreg -version -o x03.s
GNU C++ version 1.34.0.0 (68k, MIT syntax) compiled by GNU C version 1.33.

rfg@MCC.COM (Ron Guilmette) (03/11/89)

The following code causes G++ 1.34.0 to correctly issue an error
(actually two errors) for the ambigous declaration(s).  Unfortunately,
it then also issues two bogus warnings.  The compiler messages follow
the code below:

Cut here
----------------------------------------------------------------------
/*
Description - check that if two overloaded functions are declared within the
		same scope, and if these two functions are essentially
		identical in their names and in their number, order,
		and type of parameters except that one of the two has
		more parameters than the other, but these additional
		parameters all have defaults, an appropriate error is
		issued for the (ambiguous) declaration(s).
*/

overload function1;

void function1 (int arg1, int arg2);
void function1 (int arg1, int arg2, int arg3 = 88);

main ()
{
	function1 (3,4);
}
------------------------------------------------------------------------
g++  -S -v x02.cc
g++ version 1.34.0.0
 /usr/local/src/lib/1.34.0.0/sun3/gcc-cpp -+ -v -undef -D__GNU__ -D__GNUG__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -D__HAVE_68881__ -Dmc68020 x02.cc /tmp/cca08777.cpp
GNU CPP version 1.34.0.0
 /usr/local/src/lib/1.34.0.0/sun3/gcc-c++ /tmp/cca08777.cpp -quiet -dumpbase x02.cc -noreg -version -o x02.s
GNU C++ version 1.34.0.0 (68k, MIT syntax) compiled by GNU C version 1.33.
x02.cc:14: conflicting types for `void function1 (int, int, int (=  88 ))'
x02.cc:13: previous declaration of `void function1 (int, int)'
x02.cc:14: warning: `function1_SI_SI' was declared `extern' and later `static'
x02.cc:13: warning: previous declaration of `function1_SI_SI'


// Ron Guilmette  -  MCC  -  Experimental (parallel) Systems Kit Project
// 3500 West Balcones Center Drive,  Austin, TX  78759  -  (512)338-3740
// ARPA: rfg@mcc.com
// UUCP: {rutgers,uunet,gatech,ames,pyramid}!cs.utexas.edu!pp!rfg

rfg@MCC.COM (Ron Guilmette) (04/22/89)

When the following code is compiled with g++ 1.34.1 (Sun3) it misses the
error on line 39 where the function member called "base_member_7" is
redeclared (within the same class) to be a data member.

When this code is compiled with G++ 1.35.0 (pre-release from yahi, April 20th)
the compiler SegFaults.  I would say off-hand that this is worse than the
response given by 1.34.1 :-) Progress? :-)

--------------------------------------------------------------------------
// Check that that it is an error to declare a variable within a given
// scope and then to redeclare that variable within the same scope.
// Check that this is true whether or not the latter declaration has
// the same type.
//
// Also check that it is an error to try to overload a class data member
// as a class function member (or vise versa) within a given class.
//
// Cases:
//	global
//	within a function
//	within a method
//	within a struct
//	within a class
//	across visibility sections of a single class

int global_var;
int global_var;				// ERROR
float global_var;			// ERROR

struct structure {
	int field;
	int field;			// ERROR
	float field;			// ERROR
};

class base {
	int base_member_1;
	int base_member_1;		// ERROR
	float base_member_1;		// ERROR
	int base_member_2;
	int base_member_3;
	int base_member_4;
	int base_member_5 ();
	int base_member_6;
	int base_member_7 ();
public:
	int base_member_6;		// ERROR
	int base_member_7;		// ERROR - data member can't be overloaded
	base ();
};

class derived : private base {
	int base_member_2;		// OK - can overload inherited data members
	double base_member_3;		// OK - can even be a different type
	int base_member_4 ();		// OK
	int base_member_5;		// OK
public:
	derived ();
};

int test ()
{
	int local_var;
	int local_var;			// ERROR
	float local_var;		// ERROR

	local_var = 1;
	return 0;
}

base::base ()
{
	int local_var;
	int local_var;			// ERROR
	float local_var;		// ERROR

	local_var = 1;
}

rfg@MCC.COM (Ron Guilmette) (04/22/89)

The following source file causes G++ 1.34.1 (Sun3) and G++ 1.35.0 (Sun3,
pre-release from yahi April 20th) to abort.

----------------------------------------------------------------------- 
// Check that default arguments may be non constant expressions

// #include "Testinc.h"

int global_variable;
const int global_const = 99;

int func1 (int i);
int func2 (int j);

int function (int k = func2 (func1 (global_variable + global_const)));

class base {
	int field;
public:
	int function (int k = func2 (func1 (global_variable + global_const)));
};

int test ()
{
	base b;

	global_variable = 99;
	function ();
	b.function ();
	return 0;
}

int function (int k = func2 (func1 (global_variable + global_const)))
{
	return 0;
}

int base::function (int k = func2 (func1 (global_variable + global_const)))
{
	return 0;
}

int func1 (int i)
{
	return 1+i;
}

int func2 (int j)
{
	return 2+j;
}

rfg@MCC.COM (Ron Guilmette) (04/22/89)

The following code caused G++ 1.34.1 (Sun3) to go into an infinite loop.

This code now causes G++ 1.35.0 (pre-release) to SegFault.  The compilation
log is shown below the code.

------------------------------------------------------------------------
// Check that it is illegal to have more than one *definition*
// for a given function with a given formal parameter profile
// in any one scope.

overload function;

void function (int i, float f)
{
	f = i;
}

void function (int j, float g)		// ERROR - previous definition
{
	g = j;
}

class base {
public:
	int member (int i)
	{
		return i;
	};

	int member (int j)		// ERROR - previous definition
	{
		return j;
	};
};
------------------------------------------------------------------------
/usr/local/src/src/g++/build/sun3/1.35-.0-.0/g++ -B/usr/local/src/src/g++/build/sun3/1.35-.0-.0/ -Wall -Wwrite-strings -S -v b035.C
g++ version 1.35.0-
 /usr/local/src/src/g++/build/sun3/1.35-.0-.0/cpp -+ -v -undef -D__GNU__ -D__GNUG__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -Wall -D__HAVE_68881__ -Dmc68020 b035.C /tmp/cca14767.cpp
GNU CPP version 1.35.0-
 /usr/local/src/src/g++/build/sun3/1.35-.0-.0/c++ /tmp/cca14767.cpp -quiet -dumpbase b035.C -Wall -Wwrite-strings -noreg -version -o b035.s
/usr/local/src/src/g++/build/sun3/1.35-.0-.0/g++: Program c++ got fatal signal 11.

rfg@MCC.COM (Ron Guilmette) (04/22/89)

The following source file checks that it is always illegal to
specify the return type for a constructor or a destructor.

When compiled with G++ 1.35.0 (pre-release, Apr. 20th), it is
apparent that the compiler does (incorrectly) allow you to:

	a) specify the return type of a destructor as void, and
	b) specify the return type of a destructor as void*, and
	c) specify the return type of a constructor as class_name*,
	   where "class_name" is the name of the containing class.

I believe that (a), (b), and (c) should all causes errors.

Another thing to note (in the compile log shown below the code) is that
the errors and warnings which *are* issued for explicit return type
specifications on constructors/destructors are inconsistant.  Shouldn't
there be one single message like:

	illegal return type spec for constructor or destructor

which is issued for all such cases?

Here is a list of the missed errors in the code below:

b036 had missed error(s) as follows:
	18: 	void ~class1 ();	// ERROR
	28: 	void* ~class3 ();	// ERROR
	37: 	class5* class5 ();	// ERROR
	44: 	void ~class6 () {	// ERROR
	58: 	void* ~class8 () {	// ERROR
	70: 	class10* class10 () {	// ERROR

------------------------------------------------------------------------
// Check that it is illegal to specify a return type in a
// declaration or a definition of either a constructor or
// a destructor.
//
// Cases:
//	void type
//	int type
//	void* type
//	class type
//	class* type
//
//	declarations & definitions
//
//	constructors & destructors

struct class1 {
	void class1 ();		// ERROR
	void ~class1 ();	// ERROR
};

struct class2 {
	int class2 ();		// ERROR
	int ~class2 ();		// ERROR
};

struct class3 {
	void* class3 ();	// ERROR
	void* ~class3 ();	// ERROR
};

struct class4 {
	class4 class4 ();	// ERROR
	class4 ~class4 ();	// ERROR
};

struct class5 {
	class5* class5 ();	// ERROR
	class5* ~class5 ();	// ERROR
};

struct class6 {
	void class6 () {	// ERROR
	};
	void ~class6 () {	// ERROR
	};
};

struct class7 {
	int class7 () {		// ERROR
	};
	int ~class7 () {	// ERROR
	};
};

struct class8 {
	void* class8 () {	// ERROR
	};
	void* ~class8 () {	// ERROR
	};
};

struct class9 {
	class9 class9 () {	// ERROR
	};
	class9 ~class9 () {	// ERROR
	};
};

struct class10 {
	class10* class10 () {	// ERROR
	};
	class10* ~class10 () {	// ERROR
	};
};
---------------------------------------------------------------------------
/usr/local/src/src/g++/build/sun3/1.35-.0-.0/g++ -B/usr/local/src/src/g++/build/sun3/1.35-.0-.0/ -Wall -Wwrite-strings -S -v b036.C
g++ version 1.35.0-
 /usr/local/src/src/g++/build/sun3/1.35-.0-.0/cpp -+ -v -undef -D__GNU__ -D__GNUG__ -Dmc68000 -Dsun -Dunix -D__mc68000__ -D__sun__ -D__unix__ -Wall -D__HAVE_68881__ -Dmc68020 b036.C /tmp/cca15886.cpp
GNU CPP version 1.35.0-
 /usr/local/src/src/g++/build/sun3/1.35-.0-.0/c++ /tmp/cca15886.cpp -quiet -dumpbase b036.C -Wall -Wwrite-strings -noreg -version -o b036.s
GNU C++ version 1.35.0- (68k, MIT syntax) compiled by GNU C version 1.34.1.
b036.C:17: invalid return type given for constructor
b036.C:22: invalid return type given for constructor
b036.C:23: non-void return type specified for destructor
b036.C:27: constructor declared with invalid return type
b036.C:32: invalid return type given for constructor
b036.C:33: non-void return type specified for destructor
b036.C:37: warning: declaration of return type for constructor redundant
b036.C:38: non-void return type specified for destructor
b036.C:42: invalid return type given for constructor
b036.C:49: invalid return type given for constructor
b036.C:51: non-void return type specified for destructor
b036.C:56: constructor declared with invalid return type
b036.C:63: invalid return type given for constructor
b036.C:65: non-void return type specified for destructor
b036.C:70: warning: declaration of return type for constructor redundant
b036.C:72: non-void return type specified for destructor

rfg@MCC.COM (Ron Guilmette) (04/28/89)

The following code, if compiled with G++ 1.35.0- on a Sun3 will
fail compilation even though (I believe) that it is perfectly
legal code.

-------------------------------------------------------------------
// Check that it is legal to convert an object of a derived class
// to an object of a base class.

struct base {
	base () {}
	base (float x, float y) {}	// Conversion tries to call this
					// Who knows why?
};

struct derived : public base
{
};

base	base_object;
derived derived_object;

int main ()
{
	base_object = (base) derived_object;
	return 0;
}
--------------------------------------------------------------------
/usr/local/src/src/g++/build/sun3/1.35-.0-.0/g++ -B/usr/local/src/src/g++/build/sun3/1.35-.0-.0/ -Wall -Wwrite-strings -S -v a027.C
In function int main ():
a027.C:19: aggregate value used where a float was expected
a027.C:19: too few arguments to function


// Ron Guilmette  -  MCC  -  Experimental Systems Kit Project
// 3500 West Balcones Center Drive,  Austin, TX  78759  -  (512)338-3740
// ARPA: rfg@mcc.com
// UUCP: {rutgers,uunet,gatech,ames,pyramid}!cs.utexas.edu!pp!rfg

rfg@MCC.COM (Ron Guilmette) (04/28/89)

Should the scope of a typedef'd name extend to the typedef itself?

How (if at all) can you use ANSI function prototypes to declare
a pointer-to-function type where the function can take a pointer
to itself as an argument?

The following code is rejected with errors on each of the two typedefs
by both GCC and G++ (1.34 and 1.34.1 respectively).  The specific
errors issued are radically different however.

Are the errors legitimate?  Are these errors due to bugs in the
compilers or bugs in the ANSI C standard?  Both?  Neither?

--------------------------------------------------------------------
typedef void (*recursive_func) (int i, recursive_func f);

typedef struct {
		recursive_struct* f1;
	} recursive_struct;

void my_recursive_func (int i, recursive_func f)
{
}

void test ()
{
	my_recursive_func (99, my_recursive_func);
}
---------------------------------------------------------------------

// Ron Guilmette  -  MCC  -  Experimental Systems Kit Project
// 3500 West Balcones Center Drive,  Austin, TX  78759  -  (512)338-3740
// ARPA: rfg@mcc.com
// UUCP: {rutgers,uunet,gatech,ames,pyramid}!cs.utexas.edu!pp!rfg

shin@sgtp.apple.juice (Shinichirou Sugou) (06/14/89)

Hello.

My system is Sun-3/60 with OS3.4, g++-1.34.

According to "C++ Programming language" by B.S. page 164, 'this' has the value
zero at entry when its object is created by new operator.  But, in g++-1.34
(and g++-1.32), 'this' already has the heap address at entry.

CAUTION: Reply-command supplied by your mail system may NOT generate
         my address correctly.
         Please use the following address instead.

         shin%sgtp.apple.juice%lkbreth.foretune.junet@uunet.uu.net

---
  Shinichirou Sugou   shin%sgtp.apple.juice%lkbreth.foretune.junet@uunet.uu.net