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