Return-Path: <benson@odi.com> Received: from indirect.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA08711; Tue, 16 May 89 09:31:32 EDT Received: by indirect.odi.com (4.0/SMI-4.0/ODI-C2) id AA17362; Tue, 16 May 89 09:31:48 EDT Message-Id: <8905161331.AA17362@indirect.odi.com> To: c++-bugs Subject: void return types and void * types as printed into C Date: Tue, 16 May 89 09:31:47 EDT From: Benson I. Margulies <benson@odi.com> Pretty much all C compilers these days support void. Sun's certainly does. The mapping of void to char in cfront makes some debuggers print junk. Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA08826; Tue, 16 May 89 10:33:10 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA02086; Tue, 16 May 89 10:33:14 EDT Date: Tue, 16 May 89 10:33:14 EDT From: sam@odi.com Message-Id: <8905161433.AA02086@joplin.odi.com> To: c++-bugs Subject: lexer is confused during :: processing The following is a bug report that will be forwarded to AT&T. It is in a template form designed by AT&T to help them speed up the disposition of bug reports; you may feel inclined to dispute this claim. who: sam@odi.com file: date: 5/12/89 state: not fixed sum: A reference at top level to a member of the form x::y provokes an error message if y also happens to be the name of a class with a constructor. release filed under: beta 6 MR: priority: category: teststate: name of changed files: release agent: related MRs: description of bug with output now and expected output: Output: CC -I/usr1/sam/2.0/test/ +e0 -F /tmp/lalex-bug.C -c > /dev/null "/usr1/sam/2.0/test/lalex-bug.C", line 23: error: foo redefined: both a class name with constructor and an identifier "/usr1/sam/2.0/test/lalex-bug.C", line 25: error: foo1 redefined: both a class name with constructor and an identifier Compilation exited abnormally with code 1 at Mon May 15 19:06:18 Expected Output: The test should compile without any error messages. description of analysis and changes: The problem appears to be localized to the lexer's ability to deal with names of the form x::y at the top level, when y also happens to be the name of a class. It does does not account for the fact that y is in the scope of x and is consequently not a top level definition. Example below if available- */ /* test exhibiting bug goes below */ class foo { foo() ; } ; class foo1 { foo1() ; } ; class bar { public: static int foo1 ; void foo() ; } ; class bar1 { public: void foo() {} ; // No problem with foo being an inline } ; void bar::foo() {} // Redefinition error for foo int bar::foo1 = 0 ; // Similar redefinition error main () { bar::foo1 = 5 ; // This is ok } Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA08913; Tue, 16 May 89 10:43:55 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA02104; Tue, 16 May 89 10:44:00 EDT Date: Tue, 16 May 89 10:44:00 EDT From: sam@odi.com Message-Id: <8905161444.AA02104@joplin.odi.com> To: c++-bugs Subject: typedef enum foo{} ; core dumps This is a bug report that will be submitted to AT&T. It has been fixed at ODI. /*ident "@(#)ctrans:bug.header 1.1" */ /* who: sam@odi.com file: date: 5/15/89 state: not fixed sum: An enumeration typedef of the form: typedef bool {true, false} bool ; provokes a core dump. release filed under: beta 6 MR: priority: category: teststate: name of changed files: release agent: related MRs: description of bug with output now and expected output: The core dump is due to a null pointer being dereferenced at line 454 in the function: bit type::check(Ptype t, TOK oper) The backtrace is: #0 0x41b42 in check__4typeFP4typeUc (__0this=(Ptype) 0x76594, __0t=(Ptype) 0x765d8, __0oper=0) (typ.c line 454) #1 0x2b820 in hide__4nameFv (__0this=(Pname) 0x6db6a) (norm.c line 579) #2 0x2b1bc in aggr__8basetypeFv (__0this=(Pbase) 0x76594) (norm.c line 415) #3 0x447cc in yyparse__Fv () (gram.y line 652) #4 0x43b86 in syn__Fv () (gram.y line 253) #5 0x294e4 in run__Fv () (main.c line 83) #6 0x2a264 in main (__0argc=1, __0argv=(char **) 0xefffe68) (main.c line 477) OUTPUT: CC temp.C: "temp.C", line 2: internal <<C++ Translator 2.0 Beta 6 04/12/89>> error: bus error (or something nasty like that) 1 error The test should have compiled without any errors. description of analysis and changes: The error appears to be due to check for EOBJ in the following code fragment: b1 = t1->base; switch (b1) { case TYPE: if (Pbase(t1)->b_const) cnst1++; t1 = Pbase(t1)->b_name->tp; goto top; * case EOBJ: * t1 = Penum(Pbase(t1)->b_name->tp)->e_type; * goto top; } b2 = t2->base; switch (b2) { case TYPE: if (Pbase(t2)->b_const) cnst2++; t2 = Pbase(t2)->b_name->tp; goto top; * case EOBJ: * t2 = Penum(Pbase(t2)->b_name->tp)->e_type; * goto top; } The "goto top" statement bypasses the check for null pointers that guards the enclosing while loop. There seem to be two possible fixes: 1) Change the goto top into a continue, so that the while expression is evaluated. This provokes a redefinition error message, which may be the correct thing to do, but the Reference manual is unclear on this point. The Evolution of C++:1985 to 1989 paper seems to favor the notion of separate name spaces for structure tags, and possibly for enum tags. The second fix is in keeping with this trend. 2) The second alternative is to permit such a declaration. The EOBJ case blocks the processing of EOBJ types later in the body of the same function, at the enum_check label. Removing the lines marked with asterisks, permits control to reach the enum_check code, and consequently permit such declarations. Example below if available- */ /* test exhibiting bug goes below */ typedef enum bool {true, false} bool ; Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA09075; Tue, 16 May 89 11:22:14 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA02122; Tue, 16 May 89 11:22:18 EDT Date: Tue, 16 May 89 11:22:18 EDT From: sam@odi.com Message-Id: <8905161522.AA02122@joplin.odi.com> To: c++-bugs Subject: BD in patch step Another candidate for AT&T. /*ident "@(#)ctrans:bug.header 1.1" */ /* who: sam@odi.com file: date: ?/?/89 state: not fixed sum: The patch step, ie. the step following the link step to ensure that constructors are run on static varaibles, takes a very long time when the a.out file contains debug symbols. "patching" cfront takes approximately 4 minutes on a Sun 3/60. The enclosed fix speeds up the "patch step", it reduces the time taken to patch "cfront" to approximately 5 seconds. release filed under: beta 6 MR: priority: category: teststate: name of changed files: release agent: related MRs: description of bug with output now and expected output: compile (with the -g option) and link cfront or any substantial C++ program and observe the time taken by the patch step. description of analysis and changes: The excessive time was due to the random i/o being done to obtain the string for every symbol in a.out file. The enclosed fix uses a faster test that eliminates the random i/o associated with debug symbols. The diff for BSDpatch.c is enclosed below: diff patch.c /odi/C++/install/att_2_0b6/Patch/BSDpatch.c 106,110d104 < < < /* a symbol table entry, ignore it */ < if (sym.n_type & (unsigned char) N_STAB) continue ; < Example below if available- Use cfront as a candidate. */ /* test exhibiting bug goes below */ Return-Path: <dlw@odi.com> Received: from valens.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA10875; Tue, 16 May 89 17:21:34 EDT Received: by valens.odi.com (4.0/SMI-4.0/ODI-C2) id AA03492; Tue, 16 May 89 17:21:52 EDT Date: Tue, 16 May 89 17:21:52 EDT From: dlw@odi.com Message-Id: <8905162121.AA03492@valens.odi.com> To: c++-bugs Subject: Overloading the new operator If you provide an overloaded "operator new" with extra arguments, and do not provide an "operator new" with no extra arguments, you get an incomprehensible error message, whose line number is the last line of the constructor function. I don't think it should be an error at all. Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA13763; Wed, 17 May 89 17:55:45 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA04487; Wed, 17 May 89 17:55:51 EDT Date: Wed, 17 May 89 17:55:51 EDT From: sam@odi.com Message-Id: <8905172155.AA04487@joplin.odi.com> To: c++-bugs Subject: data members of the form "struct x {} x;" are broken /*ident "@(#)ctrans:bug.header 1.1" */ /* who: sam@odi.com file: date: 5/17/89 state: not fixed sum: Data members of the form: struct x {} x ; are incorrectly translated. They are omitted completely from the C struct generated as a translation of the enclosing class. release filed under: beta 6 MR: priority: category: teststate: name of changed files: release agent: related MRs: description of bug with output now and expected output: Consider a class declaration of the form: class s { class x1 { int i ; } x1; // Does not emit this field in the generated c struct }; Class s is translated by cfront into: #line 1 "2.0/test/struct-bug.c" struct s { /* sizeof s == 4 */ }; Note the missing reference to the field x1. The correct translation after applying the enclosed fix is: #line 1 "struct-bug.c" struct s { /* sizeof s == 4 */ #line 4 "struct-bug.c" struct x1 x1__1s ; }; description of analysis and changes: The problem is that the type name x1, hides the member name x1, in the member table for the class "s". The function classdef::print_members does not allow for such hiding. The fix provided below accounts for this hiding. 1374,1378c1371,1372 < // Sam: A class or an enum type declared within a class can hide a < // member with the same name, so make sure that it gets printed by < // traversing the n_tbl_list to get at these names. < for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i)) < do if (nn->base==NAME --- > for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i)) { > if (nn->base==NAME 1389,1392c1383,1384 < } < while ((nn->base == NAME) && < ((nn->tp->base!=CLASS) || (nn->tp->base!=ENUM)) && < (nn = nn->n_tbl_list)) ; --- > } > } Example below if available- */ /* test exhibiting bug goes below */ class s { class x1 { int i ; } x1; // Does not emit this field in the generated c struct }; s v ; Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA15049; Thu, 18 May 89 10:44:36 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA04745; Thu, 18 May 89 10:44:41 EDT Date: Thu, 18 May 89 10:44:41 EDT From: sam@odi.com Message-Id: <8905181444.AA04745@joplin.odi.com> To: c++-bugs Subject: linkage specification is incorrectly processed /*ident "@(#)ctrans:bug.header 1.1" */ /* who: sam@odi.com file: date: 5/18/89 state: not fixed sum: The linkage specification sometimes produces unwarranted error messages. release filed under: beta 6 MR: priority: category: teststate: name of changed files: release agent: related MRs: description of bug with output now and expected output: Compiling the program below provokes an error message when it shouldn't CC 2.0/test/linkage-bug.C: "2.0/test/linkage-bug.C", line 6: error: inconsistent linkage specifications for malloc() 1 error description of analysis and changes: The test to determine whether two linkages are consistent is incorrect in the function Pname name::dofct(Ptable tbl, TOK scope) The fix is provided below as output from diff: file: dcl3.c 1667,1669c1667 < if (linkage && nf->f_signature && < *nf->f_signature // the signature is not "" < ) --- > if (linkage && nf->f_signature) Example below if available- */ /* test exhibiting bug goes below */ extern "C" char *malloc(unsigned); extern "C" { char *malloc(unsigned); } ; Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA17783; Fri, 19 May 89 10:45:39 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA05539; Fri, 19 May 89 10:45:47 EDT Date: Fri, 19 May 89 10:45:47 EDT From: sam@odi.com Message-Id: <8905191445.AA05539@joplin.odi.com> To: c++-bugs Cc: benson Subject: A missing ";" after a function declaration provokes a core dump /*ident "@(#)ctrans:bug.header 1.1" */ /* who: sam@odi.com file: date: 5/19/89 state: not fixed sum: A missing semi colon after a function declaration causes a core dump. release filed under: beta 6 MR: priority: category: teststate: name of changed files: release agent: related MRs: description of bug with output now and expected output: A missing semi after a function declaration is detected as an error, but the cfront core dumps trying to issue the error message since the format effector used for the error message is a %t(for type) rather than a %k for token. Erroneous Output ---------------- CC 2.0/test/syntax-bug.c: "2.0/test/syntax-bug.c", line 2: error: syntax error: unexpected "2.0/test/syntax-bug.c", line 2: "2.0/test/syntax-bug.c", line 2: internal <<C++ Translator 2.0 Beta 6 04/12/89>> error: bus error (or something nasty like that) 1 error Correct Output ------------- CC syntax-bug.c: "syntax-bug.c", line 2: error: syntax error: unexpected char "syntax-bug.c", line 2: error: syntax error description of analysis and changes: Fixing the call to error in the production (in file gram.y) arg_list : arg_lp arg_type_list ellipsis_opt RP TYPE to use the %k format effector fixes the problem. Example below if available- */ /* test exhibiting bug goes below */ int foo(int i) char i ; Return-Path: <dlw@odi.com> Received: from valens.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA06592; Wed, 24 May 89 17:49:46 EDT Received: by valens.odi.com (4.0/SMI-4.0/ODI-C2) id AA01476; Wed, 24 May 89 17:49:36 EDT Date: Wed, 24 May 89 17:49:36 EDT From: dlw@odi.com Message-Id: <8905242149.AA01476@valens.odi.com> To: c++bugs Subject: socketpair Reply-To: dlw@odi.com The BSD system call "socketpair" is not defined in any of the include files. Return-Path: <dlw@odi.com> Received: from valens.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA08331; Thu, 25 May 89 11:12:25 EDT Received: by valens.odi.com (4.0/SMI-4.0/ODI-C2) id AA02117; Thu, 25 May 89 11:12:17 EDT Date: Thu, 25 May 89 11:12:17 EDT From: dlw@odi.com Message-Id: <8905251512.AA02117@valens.odi.com> To: c++bugs Subject: more standard declarations Reply-To: dlw@odi.com C++'s libc.h does declare mktemp, but does not have a declaration for mkstemp. These are both library routines from the "(3)" part of the documentation. Return-Path: <tompkins@odi.com> Received: from moon.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA04276; Tue, 20 Jun 89 12:34:12 EDT Received: by moon.odi.com (4.0/SMI-4.0/ODI-C2) id AA00792; Tue, 20 Jun 89 12:34:12 EDT Date: Tue, 20 Jun 89 12:34:12 EDT From: tompkins@odi.com Message-Id: <8906201634.AA00792@moon.odi.com> To: c++-bugs Subject: anonymous union bug /*ident "@(#)ctrans:bug.header 1.1" */ /* who: Rick Tompkins, Object Design, Inc. file: print2.c:658 default: // encode with lexicallevel UNLESS ``special'' // e.g. __builtin if (string[0]!='_' || string[1]!='_') { if (i) 658: fprintf(out_file,"__%d__O%d.",lex_level-1,i,i); else fprintf(out_file,"__%d",lex_level); } } break; date: 6/20/89 state: not fixed sum: Anonymous unions within functions result in undefined unions. release filed under: beta 6 MR: priority: category: teststate: name of changed files: release agent: related MRs: description of bug with output now and expected output: Anonymous unions within functions result in undefined unions. This is due to the inconsistency in outputing the lexical level of such a union when generating its C name. In an expression the union name generated for a anonymous union at the function level has the lexical level part while the corresponding declaration does not. EXAMPLE: main () { union { char u_c; int u_i; float u_f; }; u_c = 'a'; /* These result in an undefined union name. */ u_i = 9; u_f = 3.5; } OUTPUT: #line 1 "e.out.C" /* <<C++ Translator 2.0 Beta 6 04/12/89 ODI version 1.2.1.18 of 89/06/06 16:24:40 by benson. Compiled by tompkins at 89-06-08 14:48:22 in /usr1/tompkins/C++_2.0_bugs/src>> */ /* < e.out.C > */ #line 3 "e.out.C" char *_vec_new (); #line 3 "e.out.C" char _vec_delete (); typedef int (*__vptp)(); struct __mptr {short d; short i; __vptp f; }; #line 3 "e.out.C" #line 6 "e.out.C" union __C1 { /* sizeof __C1 == 4 */ #line 7 "e.out.C" char u_c ; int u_i ; float u_f ; }; #line 3 "e.out.C" int main (){ _main(); #line 4 "e.out.C" { #line 6 "e.out.C" #line 10 "e.out.C" union __C1 __O1 ; /* Declaration of generated union. */ #line 12 "e.out.C" __1__O1.u_c = 'a' ; /* Use of generated union has different name.*/ __1__O1.u_i = 9 ; __1__O1.u_f = 3.5 ; } } #line 18 "e.out.C" /* the end */ ERRORS: moon:tompkins(34)> /usr/local/bin/CC -g -o e.out e.out.C e.out.C: cc -o e.out -g e.out..c -l/usr/local/lib/libC.1.2.a "e.out.C", line 12: __1__O1 undefined description of analysis and changes: The simplest change is to delete the lexical level part of the generated union name. And of course, the extra "i" argument to fprintf can be deleted as well. Given that any generated union name is guaranteed to be unique within a file, the lexical level isn't needed. print2.c:658> fprintf(out_file,"__O%d.",,i); Example below if available- */ /* test exhibiting bug goes below */ Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA14961; Wed, 28 Jun 89 19:35:57 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA07403; Wed, 28 Jun 89 19:35:58 EDT Date: Wed, 28 Jun 89 19:35:58 EDT From: sam@odi.com Message-Id: <8906282335.AA07403@joplin.odi.com> To: c++-bugs Subject: name hiding lossage in real 2.0 Rather than fixing the bugs associated with conflicting type and member names, 2.0 has made things worse. You now have to ensure that even formal parmeter member names don't conflict with an existing type. Thus the following example that compiled under 2.0 beta, fails in the real 2.0 Changing the name of the formal for y::foo permits compilation to proceed. class x{ public: x() ;} ; class y { foo (int x ) ; gotcha() ; } ; y::gotcha() { new x() ; // Syntax error in real 2.0, ok in beta 2.0 } Return-Path: <benson> Received: by odi.com (4.0/SMI-4.0/ODI-4) id AA28498; Sun, 2 Jul 89 08:02:50 EDT Date: Sun, 2 Jul 89 08:02:50 EDT From: Benson Margulies <benson> Message-Id: <8907021202.AA28498@odi.com> To: c++bugs Subject: exit.c shadows important functionality of sun's exit(3) exit(3) has various responsabilities other than calling _exit. The copy of exit in libC.a busts profiling, in that the call to _mcount is lost. It probably also busts sun's on_exit stuff, and possibly other things. Return-Path: <benson> Received: by odi.com (4.0/SMI-4.0/ODI-4) id AA02052; Mon, 3 Jul 89 20:07:23 EDT Message-Id: <8907040007.AA02052@odi.com> To: dlw@odi.com Cc: c++-bugs Subject: Re: stdargs.h In-Reply-To: Your message of Mon, 03 Jul 89 17:22:21 -0400. <8907032122.AA04350@valens.odi.com> Date: Mon, 03 Jul 89 20:07:22 EDT From: Benson I. Margulies <benson> The file /odi/C++/install/bugs/include/stdargs.h is missing an #endif. (The att2.0 version of the file is also broken.) stdargs.h is full of non-working code. stdarg.h is correct. stdargs.h should be deleted. Return-Path: <tompkins@odi.com> Received: from moon.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA07601; Wed, 12 Jul 89 15:54:48 EDT Received: by moon.odi.com (4.0/SMI-4.0/ODI-C2) id AA03177; Wed, 12 Jul 89 15:55:19 EDT Date: Wed, 12 Jul 89 15:55:19 EDT From: tompkins@odi.com Message-Id: <8907121955.AA03177@moon.odi.com> To: c++-bugs Subject: [aml: trivial spelling bug] Return-Path: <aml> Date: Wed, 12 Jul 89 15:32:51 EDT From: Al Leisinger <aml> To: rick Subject: trivial spelling bug Cfront error message: warning: negative retured from function returning unsigned ^^^^^^^ returned ?? I know it's trivial but why not report it ? Return-Path: <dlw@odi.com> Received: from valens.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA09657; Wed, 12 Jul 89 18:50:48 EDT Received: by valens.odi.com (4.0/SMI-4.0/ODI-C2) id AA16557; Wed, 12 Jul 89 18:51:05 EDT Date: Wed, 12 Jul 89 18:51:05 EDT From: dlw@odi.com Message-Id: <8907122251.AA16557@valens.odi.com> To: c++bugs Subject: mman.h Reply-To: dlw@odi.com mman.h has been changed from the beta release to the 2.0 release. It now no longer provides a declaration for the "mprotect" system call. Return-Path: <benson@odi.com> Received: from cass.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA02846; Fri, 14 Jul 89 08:35:48 EDT Received: by cass.odi.com (4.0/SMI-4.0/ODI-C2) id AA00287; Fri, 14 Jul 89 08:36:10 EDT Message-Id: <8907141236.AA00287@cass.odi.com> To: sam, c++bugs Subject: void versus ansi mode Date: Fri, 14 Jul 89 08:36:06 EDT From: Benson I. Margulies <benson@odi.com> Cfront translates void types to char types, in apparent support of really ancient K&R c compilers. This is supposedly turned off by +a1. However, (1) the code in print2.c that conditions on ansi_opt fails to print the string "void" when ansi mode is turned on. It just prints nothing. (2) the code in simpl.c referred to by print2.c dosen't even check ansi mode, it just emits a cast. I've changed print2 and simple to leave void be when running on a sun, since the sun compiler is quite content with void. I also fixed it to print "void" when in ansi mode. Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA03158; Fri, 14 Jul 89 11:44:01 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA00819; Fri, 14 Jul 89 11:44:00 EDT Date: Fri, 14 Jul 89 11:44:00 EDT From: sam@odi.com Message-Id: <8907141544.AA00819@joplin.odi.com> To: c++-bugs Subject: problem with reference initialization A reference initialized by a function returning a reference generates bad c code which provokes an error message from cc of the form: "/usr1/sam/2.0/test/cast.C", line 3: unacceptable operand of & for the example provided below: int &foo () ; int &i = foo() ; Return-Path: <benson@odi.com> Received: from cass.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA17585; Wed, 19 Jul 89 07:46:52 EDT Received: by cass.odi.com (4.0/SMI-4.0/ODI-C2) id AA01219; Wed, 19 Jul 89 07:47:19 EDT Message-Id: <8907191147.AA01219@cass.odi.com> To: c++bugs Subject: confusion over placement options Date: Wed, 19 Jul 89 07:47:17 EDT From: Benson I. Margulies <benson@odi.com> Please explain the following message: "foo.C", line 7: error: argument 2 of type void * expected for T::operator new() #include <sys/types.h> #include <malloc.h> void * operator new (size_t, void *); class T { public: char * s; void * operator new (size_t, void *); T(int x, void * v) { s = new (v)(char[x]); }; }; void * T::operator new (size_t s, void * v) { return (void *)malloc(s); } T* Q() { int z = 1; void * v = 0; T* t = new (v)T(z, v); return t; } Return-Path: <benson@odi.com> Received: from cass.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA17849; Wed, 19 Jul 89 09:58:24 EDT Received: by cass.odi.com (4.0/SMI-4.0/ODI-C2) id AA01533; Wed, 19 Jul 89 09:58:52 EDT Message-Id: <8907191358.AA01533@cass.odi.com> To: c++bugs Subject: don't put names on typedef param list params Date: Wed, 19 Jul 89 09:58:49 EDT From: Benson I. Margulies <benson@odi.com> The followings gets an entirely spurious error. class node { }; typedef (* gruz) (node * node); class bn : public node { int y; }; Return-Path: <landis@odi.com> Received: from pigpen.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA18574; Wed, 19 Jul 89 12:39:44 EDT Received: by pigpen.odi.com (4.0/SMI-4.0/ODI-C2) id AA11032; Wed, 19 Jul 89 12:40:26 EDT Date: Wed, 19 Jul 89 12:40:26 EDT From: landis@odi.com Message-Id: <8907191640.AA11032@pigpen.odi.com> To: C++-bugs Subject: static members of nested classes Static members of nested class definitions don't work. The following code: main() { class T { public: static int count; }; T::count++; // "int T::count;" also causes failure } results in a link error: ld: Undefined symbol T__main__Fv__L1::count Now, the C++ 2.0 reference manual says that (1) The declaration of a static member in its class declaration is NOT a definition. (2) Static members of a class declared local to some function ... cannot be initialized [and must therefore accept the default "all zeros" initialization]. The current behavior, though, is worse than that: static members of a nested class cannot be referred to at all, because they are declared but never defined. Return-Path: <dlw@odi.com> Received: from valens.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA18753; Wed, 19 Jul 89 15:12:40 EDT Received: by valens.odi.com (4.0/SMI-4.0/ODI-C2) id AA24717; Wed, 19 Jul 89 15:13:09 EDT Date: Wed, 19 Jul 89 15:13:09 EDT From: dlw@odi.com Message-Id: <8907191913.AA24717@valens.odi.com> To: landis@odi.com Cc: C++-bugs In-Reply-To: landis@odi.com's message of Wed, 19 Jul 89 12:40:26 EDT <8907191640.AA11032@pigpen.odi.com> Subject: static members of nested classes Reply-To: dlw@odi.com Date: Wed, 19 Jul 89 12:40:26 EDT From: landis@odi.com The current behavior, though, is worse than that: static members of a nested class cannot be referred to at all, because they are declared but never defined. You know, it's conceivable that this works properly with the C compiler that they use at AT&T, because C compilers are inconsistent about how they handle this. Harbison & Steele goes into great detail about the four different sets of behavior that they've seen in various C compilers. However, that's not much of an excuse, because if that's why the bug exists, then it's only because they are depending on non-ANSI-like behavior. Return-Path: <benson@odi.com> Received: from cass.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA26387; Fri, 21 Jul 89 08:57:51 EDT Received: by cass.odi.com (4.0/SMI-4.0/ODI-C2) id AA06686; Fri, 21 Jul 89 08:58:23 EDT Date: Fri, 21 Jul 89 08:58:23 EDT From: benson@odi.com Message-Id: <8907211258.AA06686@cass.odi.com> To: c++bugs Subject: malloc.h malloc.h is broken. First of all, the correct prototype for mallinfo on a sun is to take no arguments. Second of all, the attempt to deal with the identically named structure and function fails, since the function of no args gets C++ linkage. I kludged around it by removing the declaration from the extern "C", and surrounding the cc/malloc.h include with #pragma linkage C #pragma linkage Return-Path: <benson@odi.com> Received: from cass.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA06715; Thu, 27 Jul 89 11:51:19 EDT Received: by cass.odi.com (4.0/SMI-4.0/ODI-C2) id AA00607; Thu, 27 Jul 89 11:51:57 EDT Message-Id: <8907271551.AA00607@cass.odi.com> To: c++bugs Subject: local typedefs and references are broken Date: Thu, 27 Jul 89 11:51:54 EDT From: Benson I. Margulies <benson@odi.com> the following emits a reference to type "z" in the C code for the declaration of ZZ. int qq(); int q(int a) { typedef int z; z Z; z& ZZ = Z; int b; Z = qq(); b= (int)(a + ZZ); return b; } Return-Path: <landis@odi.com> Received: from pigpen.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA07632; Thu, 27 Jul 89 18:22:56 EDT Received: by pigpen.odi.com (4.0/SMI-4.0/ODI-C2) id AA14970; Thu, 27 Jul 89 18:23:52 EDT Date: Thu, 27 Jul 89 18:23:52 EDT From: landis@odi.com Message-Id: <8907272223.AA14970@pigpen.odi.com> To: c++-bugs Subject: global ref variable init broken? The following file: int theint; int& intref(){return theint;}; int& bar = intref(); main() { } gives the message (from cc): "foo.C", line 4: unacceptable operand of & while int theint; int& intref(){return theint;}; int bar = intref(); main() { } and int theint; int& intref(){return theint;}; main() { int& bar = intref(); } both compile correctly. Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA11374; Fri, 28 Jul 89 18:22:27 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA11900; Fri, 28 Jul 89 18:22:37 EDT Date: Fri, 28 Jul 89 18:22:37 EDT From: sam@odi.com Message-Id: <8907282222.AA11900@joplin.odi.com> To: jack@odi.com In-Reply-To: jack@odi.com's message of Fri, 28 Jul 89 15:13:15 EDT <8907281913.AA08729@indirect.odi.com> Subject: initialization of local static variables Cc: c++bugs Date: Fri, 28 Jul 89 15:13:15 EDT From: jack@odi.com Are you aware of problems with the handling of static local variables? I created a static path object (which encapsulates a linked list) inside a function: person::person(string n, person* f, person* m) : name(n), age(-1), father(NULL), mother(NULL) { // Without cast to person*, cfront complains about "&this". set_father(f); set_mother(m); if (father) father->children.insert((person*) this); if (mother) mother->children.insert((person*) this); static path f_index = arrow(person, father); children.add_index(f_index); } The first time person::person runs, f_index is created, and temporary path_step objects (used to initialize permanent path_steps comprising the path) get deleted. I verified this by watching ~path_step run. On the second invocation of person::person, the path isn't created, but dtors are called anyway, sometimes with a zero address, sometimes not. If the f_index declaration is moved outside the function, so that it is static global, the program runs. I don't need a fix for this - I'm just wondering if I am misunderstanding something about when dtors should be run, or whether I'm running into a known bug. Jack (The code above is from /odi/aggs/src/person.C) The code generation for local static variables initialized with an expression that requires the use of compiler temporaries is busted. The constructor code for initializing the temporaries is run conditionally, since local static variables must be initialized just once, when control first passes through the declaration. Unfortunately, the destructor is run unconditionally in the generated code, each time control passes through the block containing the local static declaration. You may wish to avoid the use of local static variables with non-trivial initializations for now. Return-Path: <benson@odi.com> Received: from cass.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA20107; Wed, 2 Aug 89 13:11:40 EDT Received: by cass.odi.com (4.0/SMI-4.0/ODI-C2) id AA00545; Wed, 2 Aug 89 13:12:25 EDT Date: Wed, 2 Aug 89 13:12:25 EDT From: benson@odi.com Message-Id: <8908021712.AA00545@cass.odi.com> To: c++bugs Subject: complex initializations bungled for consts. when a complex expr initialization of a const is evaluated to an integer, dcl.c DEL's the variable init but neither zero's it nor skips the code that looks at it. Depending on accidents of storage, this can cause the compiler to core-dump shortly thereafter trying to run need_sti over it. Return-Path: <dlw@odi.com> Received: from valens.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA28108; Fri, 25 Aug 89 10:42:08 EDT Received: by valens.odi.com (4.0/SMI-4.0/ODI-C2) id AA04592; Fri, 25 Aug 89 10:42:08 EDT Date: Fri, 25 Aug 89 10:42:08 EDT From: dlw@odi.com Message-Id: <8908251442.AA04592@valens.odi.com> To: c++-bugs Subject: Computed pointer-to-function values Reply-To: dlw@odi.com In the following program, the last line, but only the last line, gets an error, namely "illegal indirection", whatever that means. I don't understand how the last line could not be legal C++ code. int twice(int x) { return x + x; } main() { int dummy; int (*fn)(int); int (*fn2)(int); int (*fn3)(int); fn = twice; fn2 = twice; dummy = (*fn)(30); dummy = fn(30); dummy = (fn)(3); fn3 = (dummy > 30 ? fn : fn2); dummy = (dummy > 30 ? fn : fn2)(30); /* line 22: illegal indirection */ } Return-Path: <benson@odi.com> Received: from cass.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA28339; Fri, 25 Aug 89 11:30:08 EDT Received: by cass.odi.com (4.0/SMI-4.0/ODI-C2) id AA06818; Fri, 25 Aug 89 11:30:13 EDT Date: Fri, 25 Aug 89 11:30:13 EDT From: benson@odi.com Message-Id: <8908251530.AA06818@cass.odi.com> To: c++bugs, sam, stryker, tompkins Subject: Installation in /usr2/odi/c++/versions/odi2/src/ Installation version odi2_34 in /usr2/odi/c++/versions/odi2/src/ at 89:7:25:11:26:44. Version odi2_34(1.34) from /usr1/benson/work/cfront/ cfront croaked for class x : public y { public: x (a, b, c) : y(z(a), Cast(b)) {}; because it tried to detect the entry to the initialization list only by seeing ) :, and to exit it at any ). So the close of the z(a) turned off the global that indicated that the current state was within a base init list, and then got confused by the cast. The fix is to use grammar actions to control the state. gram.y: revision 1.12 date: 89/08/25 11:23:09; author: benson; state: Exp; lines added/del: 21/7 set must_be_expr for base_init processing and for nothing else. Don't leave in_arg_list on in the base_init list. lalex.c: revision 1.6 date: 89/08/25 11:22:33; author: benson; state: Exp; lines added/del: 20/18 Remove code to try to set the must_be_expr code by detecting ) : and const : in the token stream. Depend on the grammar. Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA04677; Tue, 29 Aug 89 12:31:06 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA02179; Tue, 29 Aug 89 12:31:03 EDT Date: Tue, 29 Aug 89 12:31:03 EDT From: sam@odi.com Message-Id: <8908291631.AA02179@joplin.odi.com> To: c++-bugs Subject: missing error message The following example is in error, since the class "b" has effectively been defined twice in the global scope. Cfront fails to detect this error, and generates a bad translation that evokes complaints from the C compiler. Removing the member x::mb does result in an appropriate error message ! class a { class b { int mb ; double r ; } cb ; } ; class x { int ma ; /* provokes the bug ? */ class b { int mb ; } cb ; } ; Return-Path: <dlw@odi.com> Received: from valens.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA02798; Fri, 8 Sep 89 17:48:28 EDT Received: by valens.odi.com (4.0/SMI-4.0/ODI-C2) id AA05949; Fri, 8 Sep 89 17:51:07 EDT Date: Fri, 8 Sep 89 17:51:07 EDT From: dlw@odi.com Message-Id: <8909082151.AA05949@valens.odi.com> To: c++-bugs Subject: base type expected for init_fn Reply-To: dlw@odi.com Compiling the file /usr2/odi/storage/client/bug.C, I get the weird error message "base type expected for init_fn". Look at this file, and search for #define bug. If you remove this line, the file compiles. This is extremely strange since the thing that "bug" controls has nothing to do with the part of the code that causes the error message. valens:dlw(89)> pwd /usr2/odi/storage/client valens:dlw(90)> CC -v bug.C -o bug.o CC $Revision: 1.8 $ of $Date: 89/08/22 13:25:28 $ by $Author: tompkins $ /lib/cpp -B -C -Dc_plusplus=1 -D__cplusplus=1 -DBSD -I/usr2/odi/C++/install/odi2/include bug.C > /usr/tmp/CC.5939/cpptmp /usr2/odi/C++/install/odi2/cfront +v +fbug.C </usr/tmp/CC.5939/cpptmp > /usr/tmp/CC.5939/bug.i <<C++ Translator 2.00 06/30/89 ODI version 1.42 of 89/09/07 15:05:58 by benson. Compiled by benson at 89-09-07 15:43:00 in /usr2/odi/C++/versions/odi2/src>> "bug.C", line 2916: error: base type expected for init_fn 1 error Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA15018; Wed, 13 Sep 89 10:25:59 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA02436; Wed, 13 Sep 89 10:25:57 EDT Date: Wed, 13 Sep 89 10:25:57 EDT From: sam@odi.com Message-Id: <8909131425.AA02436@joplin.odi.com> To: c++-bugs Subject: typedefs nested within a class definition Definition of a typedef nested within a class with the same name as a class definition, is not detected as an error, and may provoke subsequent confusing error messages, since the class definition is effectively blocked. An example: class t {double d ;} ; class c { typedef int t ; // Bug: this should be flagged as an error, but isn't. } ; // It appears that "t" is an int from this point forth ! t i = 0 ; Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA18635; Thu, 14 Sep 89 17:03:45 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA04200; Thu, 14 Sep 89 17:03:42 EDT Date: Thu, 14 Sep 89 17:03:42 EDT From: sam@odi.com Message-Id: <8909142103.AA04200@joplin.odi.com> To: jack Cc: c++-bugs Subject: pure virtual operator functions are broken Compiling the following example: class c { virtual operator int() = 0 ; }; provokes the internal error message: "/usr1/sam/2.0/test/z.C", line 5: internal /usr2/odi/C++/install/odi2/cfront error: signature of 0 Cfront appears to be one field short; it uses name::n_initializer both to hold the type of the operator, however, the remarkable abstract class declaration syntax uses this field to store what looks like an initializer, thereby overwriting the operator type information. Just deserts for the abstract class kludge ! Will save this one for the bugfest. Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA14391; Tue, 19 Sep 89 18:21:56 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA11736; Tue, 19 Sep 89 18:21:54 EDT Date: Tue, 19 Sep 89 18:21:54 EDT From: sam@odi.com Message-Id: <8909192221.AA11736@joplin.odi.com> To: c++-bugs, dlw Subject: name hiding lossage odi2_51 fixes the pernicious name hiding bug, where a formal argument name in a function member declaration would hide the name of an outer class definition, as in the example below: class x ; class c { foo(int x) ; bar(x *v) ; // invalid error message, x should be visible here } ; "hide.C", line 6: error: argument type expected for bar() Return-Path: <benson@odi.com> Received: from cass.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA28358; Tue, 26 Sep 89 10:08:38 EDT Received: by cass.odi.com (4.0/SMI-4.0/ODI-C2) id AA03843; Tue, 26 Sep 89 10:08:37 EDT Date: Tue, 26 Sep 89 10:08:37 EDT From: benson@odi.com Message-Id: <8909261408.AA03843@cass.odi.com> To: c++bugs Subject: static member functions treated like ordinary member functions class foo { public: static int x (int y) { return y; }; int (*xx) (int); foo () { xx = x;}; }; foo FOO; compiling this gets: "bug.C", line 6: warning: address of bound function (try using ``foo ::*'' for po inter type and ``&foo ::x '' for address) which is wrong. Since x is a static function, it ought to be usuable like any other function. Return-Path: <landis@odi.com> Received: from pigpen.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA14840; Wed, 4 Oct 89 13:19:17 EDT Received: by pigpen.odi.com (4.0/SMI-4.0/ODI-C2) id AA13854; Wed, 4 Oct 89 13:19:14 EDT Date: Wed, 4 Oct 89 13:19:14 EDT From: landis@odi.com Message-Id: <8910041719.AA13854@pigpen.odi.com> To: c++-bugs Subject: members of const objects not const The following incorrectly compiles without error. This bug is documented in the 2.0 release notes, page A-9. class embedded { public: int value; void update() {value++;}; }; class C { public: embedded strct; }; main() { const C p; p.strct.update(); p.strct.value = 23; } Return-Path: <dysak@odi.com> Received: from mojo.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA14856; Wed, 4 Oct 89 13:42:12 EDT Received: by mojo.odi.com (4.0/SMI-4.0/ODI-C2) id AA18996; Wed, 4 Oct 89 13:42:10 EDT Date: Wed, 4 Oct 89 13:42:10 EDT From: dysak@odi.com Message-Id: <8910041742.AA18996@mojo.odi.com> To: c++-bugs Subject: Can't Type Cast New Placement Arguments Compiling the following 3 lines provokes syntax errors for line 3. typedef unsigned int size_t; extern void * operator new(size_t,size_t,size_t); char *fund_01_xc_01 = new(size_t(1),size_t(2)) char('a'); Return-Path: <landis@odi.com> Received: from pigpen.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA15538; Wed, 4 Oct 89 16:49:48 EDT Received: by pigpen.odi.com (4.0/SMI-4.0/ODI-C2) id AA14895; Wed, 4 Oct 89 16:49:43 EDT Date: Wed, 4 Oct 89 16:49:43 EDT From: landis@odi.com Message-Id: <8910042049.AA14895@pigpen.odi.com> To: c++-bugs Subject: coercion ops order-dependent class test { public: void dummy() {}; operator const test*() { return this; }; // the order of these ops ... operator test*() { return this; }; // ... is significant (??) }; main() { test t; ((test*)t) -> dummy(); // both of these casts use operator test*() ((const test*)t) -> dummy(); // rather than operator const test*() }; // however, if the ops appear in the opposite order in the class defn, // then they are called correctly -- // BUT it is only a warning (not an error) that a const test* is used // as the this for the non-const member function dummy() Return-Path: <landis@odi.com> Received: from pigpen.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA18054; Thu, 5 Oct 89 16:36:38 EDT Received: by pigpen.odi.com (4.0/SMI-4.0/ODI-C2) id AA16379; Thu, 5 Oct 89 16:36:35 EDT Date: Thu, 5 Oct 89 16:36:35 EDT From: landis@odi.com Message-Id: <8910052036.AA16379@pigpen.odi.com> To: c++-bugs Subject: CAST is not a permitted struct/union operation /* The following code goes through CC ok, but gets errors from cc: line 31: CAST is not a permitted struct/union operation line 31: operands of = have incompatible types */ template<class vtype> class vpointer { public: int foo; vpointer(){}; vpointer(vpointer<vtype>& v) {foo = v.foo;}; int operator==(vpointer<vtype> const&v) const { return (foo == v.foo); }; }; template<class t> class attribute { public: t rep; operator t() {return rep;}; attribute(){}; // if these constructors are removed attribute(attribute& v) {rep = v.rep;}; // then the 2nd error dissappears }; class c { public: attribute<vpointer<int> > foo; }; main() { c a, b; if (a.foo == b.foo); } Return-Path: <landis@odi.com> Received: from pigpen.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA18060; Thu, 5 Oct 89 16:40:22 EDT Received: by pigpen.odi.com (4.0/SMI-4.0/ODI-C2) id AA16396; Thu, 5 Oct 89 16:40:19 EDT Date: Thu, 5 Oct 89 16:40:19 EDT From: landis@odi.com Message-Id: <8910052040.AA16396@pigpen.odi.com> To: c++-bugs Subject: CAST still not permitted /* whoops -- I just realized that the templates were a red herring; the same error occurs without templates: */ /* The following code goes through CC ok, but gets errors from cc: line 29: CAST is not a permitted struct/union operation line 29: operands of = have incompatible types */ class vpointer { public: int foo; vpointer(){}; vpointer(vpointer& v) {foo = v.foo;}; int operator==(vpointer const&v) const { return (foo == v.foo); }; }; class attribute { public: vpointer rep; operator vpointer() {return rep;}; attribute(){}; // if these constructors are removed attribute(attribute& v) {rep = v.rep;}; // then the 2nd error dissappears }; class c { public: attribute foo; }; main() { c a, b; if (a.foo == b.foo); } Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA19948; Fri, 6 Oct 89 14:34:59 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA00311; Fri, 6 Oct 89 14:34:57 EDT Date: Fri, 6 Oct 89 14:34:57 EDT From: sam@odi.com Message-Id: <8910061834.AA00311@joplin.odi.com> To: c++-bugs Subject: compile time checking of pure virtual functions is suspect The following compiles without error, even though it should according to section 10.3. class b1 { virtual foo() ; } ; class b2 { virtual foo() = 0 ; } ; class d : public b1, public b2 { } ; Note that modifying the derivation order so that b2 precedes b1 in the definition of the class "d", results in an appropriate error message, reproduced at the end of this message. According to section 10.1 order of derivation is not supposed to be significant except for default initialization, cleanup, and storage layout. CC -I/usr1/sam/2.0/test/ -I /odi/include +e0 -F /tmp/x.C -c > /dev/null "/usr1/sam/2.0/test/x.C", line 12: error: cannot inherit pure virtual function b2::foo() Compilation finished at Fri Oct 6 14:27:23 Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA26627; Tue, 10 Oct 89 11:56:10 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA02816; Tue, 10 Oct 89 11:56:09 EDT Date: Tue, 10 Oct 89 11:56:09 EDT From: sam@odi.com Message-Id: <8910101556.AA02816@joplin.odi.com> To: c++-bugs Cc: bob Subject: pure virtual destructors Pure virtual destructors appear to be broken in two ways: a) The derived class buit from the abstract class is not checked to ensure that it defines a virtual destructor. b) Section 10.3 of the PRM states that a pure virtual function must be defined if it is called explicitly. In the example below, the destructor is called "explicitly" by the compiler as part of the code generated for the destructors of the derived type. I think it is just the documentation that is remiss here. The moral of the story seems to be that if you have defined a pure virtual destructor you must define a body for it. The hack (= 0) syntax prevents you from defining the body at the same time that you define it "pure", so you must do it outside the class declaration. class base { protected: int a; public: base( int anA); virtual ~base() = 0; }; class derived : public base { protected: int b; public: derived( int anA, int aB); virtual ~derived(); // commenting out this line doesn't provoke an error // message }; base::base( int anA) { } derived::derived( int anA, int aB) : base( anA) { } derived::~derived() { } base::~base(){} main(){} Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA27198; Tue, 10 Oct 89 16:29:51 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA02918; Tue, 10 Oct 89 16:29:47 EDT Date: Tue, 10 Oct 89 16:29:47 EDT From: sam@odi.com Message-Id: <8910102029.AA02918@joplin.odi.com> To: c++-bugs Subject: default arguments It would seem that the default arguments for a virtual function should have the same initialization expression in the base and derived types. Otherwise, since the evaluation of the default argument is performed at the point of call, the expression used for the default initialization may not correspond to the virtual function that is actually run for the object ! This may be a language bug rather than a cfront bug, since I can't find any such strictures on default arguments in the PRM. class b { public: virtual foo(int i = 5) ; } ; class d : public b { public: virtual foo(int i = 6) ; // different initialization } ; foo(d *dp) { b *bp = d ; bp->foo() ; // uses i = 5, even though the "most derived type" of // bp * is a d, and d::foo is the function that would // actually be invoked. dp->foo() ; // uses i = 6 } Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA27291; Tue, 10 Oct 89 16:56:56 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA03101; Tue, 10 Oct 89 16:56:54 EDT Date: Tue, 10 Oct 89 16:56:54 EDT From: sam@odi.com Message-Id: <8910102056.AA03101@joplin.odi.com> To: c++-bugs Subject: incorrect error message A missing destructor member declaration, derived::~derived in this case results in a very misleading error message. class base { public: base(); virtual ~base() ; }; class derived : public base { public: derived(); }; derived::~derived() { } CC -I/usr1/sam/2.0/test/ -I /odi/include +e0 -F /tmp/vd.C -c > /dev/null "/usr1/sam/2.0/test/vd.C", line 13: error: two definitions of derived::~derived() Compilation finished at Tue Oct 10 16:52:59 Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA27460; Tue, 10 Oct 89 18:54:22 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA03209; Tue, 10 Oct 89 18:54:21 EDT Date: Tue, 10 Oct 89 18:54:21 EDT From: sam@odi.com Message-Id: <8910102254.AA03209@joplin.odi.com> To: c++-bugs Subject: more name visibility lossage (how bankrupt can a symbol table be) Members defined in a base class but accessed from within a derived class provoke syntax errors when the member name is shadowed by a global type name. Note that it is ok to access a a member in the immediate class even if it is shadowed as above. typedef unsigned char t ; typedef unsigned char t1 ; class b { public: int t ; } ; class d : public b { int t1 ; foo() { t1 = 0 ; // t1 is ok since it is local t = 0 ; // incorrect error by cfront here } bar() ; } ; d::bar() { t = 0 ; } // incorrect error by cfront here Return-Path: <landis@odi.com> Received: from pigpen.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA28825; Wed, 11 Oct 89 09:12:07 EDT Received: by pigpen.odi.com (4.0/SMI-4.0/ODI-C2) id AA19362; Wed, 11 Oct 89 09:12:05 EDT Date: Wed, 11 Oct 89 09:12:05 EDT From: landis@odi.com Message-Id: <8910111312.AA19362@pigpen.odi.com> To: c++-bugs@odi.com, sam@odi.com Subject: Re: default arguments Date: Tue, 10 Oct 89 16:29:47 EDT From: sam@odi.com It would seem that the default arguments for a virtual function should have the same initialization expression in the base and derived types. Otherwise, since the evaluation of the default argument is performed at the point of call, the expression used for the default initialization may not correspond to the virtual function that is actually run for the object ! This may be a language bug rather than a cfront bug, since I can't find any such strictures on default arguments in the PRM. class b { public: virtual foo(int i = 5) ; } ; class d : public b { public: virtual foo(int i = 6) ; // different initialization } ; foo(d *dp) { b *bp = d ; bp->foo() ; // uses i = 5, even though the "most derived type" of // bp * is a d, and d::foo is the function that would // actually be invoked. dp->foo() ; // uses i = 6 } I am not even completely convinced that this is a language bug (on the other hand I am hesitant to call it exactly a feature either -- it's firmly in that grey area in between). Since default arg selection happens at compile time, of course it cannot use the actual type of the object, it can only use the declared type. But what's so wrong with that? Sure, it might be confusing to some users, but that seems like a scant motivation for labelling it a "bug", since it might actually be useful in some cases: class person { public: virtual void hire(char* job_title, int starting_salary = MINIMUM_WAGE); }; class college_graduate : public person { public: virtual void hire(char* job_title, int starting_salary = 30000); }; main() { college_graduate *g = new college_graduate; person *p = g; p->hire("box packer"); /* minimum wage, who cares if she went to college */ g->hire("CEO"); /* for a job like this, she better be a grad, * and she should get paid accoringly */ } I'm not sure if this is a convincing argument that this isn't a bug; but on the other hand, I don't see a strong argument that it is a bug either. Users just have to get their heads around a slightly complicated rule: for virtual functions, the function body chosen depends on the actual type of the object, but the default args depend on its declared type. $.02 -Gordon Return-Path: <benson@odi.com> Received: from cass.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA02033; Thu, 12 Oct 89 14:13:37 EDT Received: by cass.odi.com (4.0/SMI-4.0/ODI-C2) id AA23840; Thu, 12 Oct 89 14:13:35 EDT Date: Thu, 12 Oct 89 14:13:35 EDT From: benson@odi.com Message-Id: <8910121813.AA23840@cass.odi.com> To: c++bugs Subject: multiple uses of constr consider: class foo {} ; typedef foo * FOO; typedef FOO const FOOc; typedef FOOc const FOOcc; if c++ was like ansi C, the last typedef would be invalid. Instead, it is permitted, but a FOOcc cannot be passed as a FOOc. The code in type::check adds 1 to cnst1 or cnst2 for each const that it sees, and then makes various arithmetic comparisons. Whatever this means, it can't be true that two const's is more const than one const. Either type::check should use |=, or the grammar should catch and yell about the last typedef above. Return-Path: <benson@odi.com> Received: from cass.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA17710; Thu, 19 Oct 89 15:06:19 EDT Received: by cass.odi.com (4.0/SMI-4.0/ODI-C2) id AA01604; Thu, 19 Oct 89 15:06:17 EDT Date: Thu, 19 Oct 89 15:06:17 EDT From: benson@odi.com Message-Id: <8910191906.AA01604@cass.odi.com> To: c++bugs Subject: warnings? ! ^!%#% Consider this program: class C { int x; int y; }; class D : public C { public: D (D &); D(); int r; int s; }; void x (C &); D makec(D&); void y () { D q; int z; /* Warning */ x(makec(q)); /* No Warning */ x((z = 0, makec(q))); } In both cases, the code generates has no temporary. (to be precise, the code generated has a temporary passed in as a result argument, but no copies are made. that temporary is passed directly to the function X.) In call_fct, a G_CM and a temp are built if f_result is non-0, and that is non-0 because there is a D(D&) constructor. (see make_res). In the second case, the presence of the comma hides the so-called temporary from the sight of the code in call_fct that produces the warning. Since the generated code is AOK, its hard to be too upset about this. but it sure is mystifying. Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA26697; Mon, 23 Oct 89 19:38:29 EDT Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA11165; Mon, 23 Oct 89 19:38:26 EDT Date: Mon, 23 Oct 89 19:38:26 EDT From: sam@odi.com Message-Id: <8910232338.AA11165@joplin.odi.com> To: c++-bugs Subject: coercions within the operands of a conditional operator are broken The first operand of a condition operator is not coerced to the result type, the second operator matches the result type, as in the example below. class b0 { int i ; } ; class b { int i ; virtual f() ; } ; class d : public b0, public b { public: int i ; d (int i) ; virtual f() ; } ; int f() ; b *lose(d *dp, b* bp) { bp = (f() ? dp : bp) ; // incorrect code, no coercion of dp return (f() ? dp : bp) ; // same bug } Return-Path: <dysak@odi.com> Received: from mojo.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA01763; Wed, 25 Oct 89 13:25:14 EDT Received: by mojo.odi.com (4.0/SMI-4.0/ODI-C2) id AA04012; Wed, 25 Oct 89 13:25:11 EDT Date: Wed, 25 Oct 89 13:25:11 EDT From: dysak@odi.com Message-Id: <8910251725.AA04012@mojo.odi.com> To: c++-bugs Subject: You can't new a pointer to member function Compiling the following program /* This may look like C code, but it is really -*- C++ -*- */ struct MF_01_tk_01 { char char_00, char_01, char_02, char_03; char fun_00(); }; struct MF_01_tk_02 : public MF_01_tk_01 { char fun_01(); }; void *MF_new_01() { typedef char (MF_01_tk_01::*MFp)(); return (void *)(new MFp(MF_01_tk_02::fun_00)); } produces the not immediately comprehensible error messages "MF_new_01.C", line 15: syntax error at or near symbol { "MF_new_01.C", line 14: syntax error at or near symbol } "MF_new_01.C", line 17: syntax error from cc (not CC). Return-Path: <tompkins@odi.com> Received: from moon.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA04140; Thu, 26 Oct 89 11:08:45 EDT Received: by moon.odi.com (4.0/SMI-4.0/ODI-C2) id AA16204; Thu, 26 Oct 89 11:08:42 EDT Date: Thu, 26 Oct 89 11:08:42 EDT From: tompkins@odi.com Message-Id: <8910261508.AA16204@moon.odi.com> To: c++-bugs Subject: bit field packing cfront incorrectly estimates the size of classes containing bit fields. Consequently, when casting a derived class pointer to a pointer to one of its base classes which contains a bit field, the wrong offset may be added to the derived class pointer. The field basecl::obj_offset is getting the wrong value as cfront assumes each bit fields to be aligned on a byte boundary. The places to look. Allocating base class objects: probably the culprit, but given cfront's method of code reuse (cut and paste) the other places probably need to be checked. dcl4.c:1349: l->obj_offset = boff; Allocating virtual base classes dcl4.c:1764: if (b->obj_offset = has_allocated_base(bcl)) continue; dcl4.c:1771: b->obj_offset = byte_offset; // offset in this Generating destructors for both non-virtual and virtual base classes. simpl.c:555: x->obj_offset = l->obj_offset; simpl.c:562: b->obj_offset = l->obj_offset; Test Code --------- #include <iostream.h> typedef unsigned int uint ; class A { public: char c; A () { c = 0; } }; class bit_fields_1 { public: uint file_index : 10; uint line_no : 22; bit_fields_1 () { file_index = 0; line_no = 0; }; }; class bit_fields_2 { public: uint file_index : 10, line_no : 22; bit_fields_2 () { file_index = 0; line_no = 0; }; }; class B { public: int v; B () { v = 0xaaaa; }; }; class D1 : public A, public bit_fields_1, public B { }; class D2 : public A, public bit_fields_2, public B { }; int works_as_B (B *b) { if (b->v == 5) return 1; else return 0; } int main () { int passed = 1; D1 d1; if ( ! works_as_B(&d1)) { cout << "FAILED: d1 doesn't work as B" << endl; cout << "\tsizeof(D1) = " << sizeof(D1) << endl; passed = 0; } D2 d2; if ( ! works_as_B(&d2)) { cout << "FAILED: d2 doesn't work as B" << endl; cout << "\tsizeof(D2) = " << sizeof(D2) << endl; passed = 0; } if (passed) cout << "PASSED" << endl; } -Rick Return-Path: <landis@odi.com> Received: from pigpen.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA03326; Tue, 31 Oct 89 15:28:12 EST Received: by pigpen.odi.com (4.0/SMI-4.0/ODI-C2) id AA01538; Tue, 31 Oct 89 15:28:08 EST Date: Tue, 31 Oct 89 15:28:08 EST From: landis@odi.com Message-Id: <8910312028.AA01538@pigpen.odi.com> To: c++-bugs Subject: bad template ref member inits not caught The following file appropriately fails to compile: struct A { int& i; A() : i() {}; }; generating the errors: "t.C", line 1: error: empty initializer for reference A::i "t.C", line 1: error: reference member A::i needs initializer But if you hide the ref member inside a template parameter, cfront dies with a core dump: template<class T> struct A { T i; A() : i() {}; }; static A<int&> a; Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA02618; Wed, 1 Nov 89 13:44:45 EST Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA04946; Wed, 1 Nov 89 13:44:37 EST Date: Wed, 1 Nov 89 13:44:37 EST From: sam@odi.com Message-Id: <8911011844.AA04946@joplin.odi.com> To: landis@odi.com Cc: c++-bugs In-Reply-To: landis@odi.com's message of Tue, 31 Oct 89 15:28:08 EST <8910312028.AA01538@pigpen.odi.com> Subject: bad template ref member inits not caught(actually bad typedefed ref member inits not caught) Date: Tue, 31 Oct 89 15:28:08 EST From: landis@odi.com The following file appropriately fails to compile: struct A { int& i; A() : i() {}; }; generating the errors: "t.C", line 1: error: empty initializer for reference A::i "t.C", line 1: error: reference member A::i needs initializer But if you hide the ref member inside a template parameter, cfront dies with a core dump: template<class T> struct A { T i; A() : i() {}; }; static A<int&> a; The problem is template independent. The case below will blow up in the same way, a fix is on the way. typedef int & x ; struct A { x i; A() : i() {}; }; Return-Path: <benson@odi.com> Received: from cass.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA13420; Mon, 6 Nov 89 10:35:39 EST Received: by cass.odi.com (4.0/SMI-4.0/ODI-C2) id AA04499; Mon, 6 Nov 89 10:35:37 EST Date: Mon, 6 Nov 89 10:35:37 EST From: benson@odi.com Message-Id: <8911061535.AA04499@cass.odi.com> To: c++bugs Subject: how to confuse const checking The following program: /* -*- Mode:C++ -*- */ int gruz (char *, char *); int gruz (char const *, char const *); void plugh (char const * x, char * y) { gruz(x,y); } gets the following error: CC foo.C: "foo.C", line 8: error: two exact matches for gruz(): int (const char *, const c har *) and int (char *, char *) 1 error Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA13457; Mon, 6 Nov 89 10:46:49 EST Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA09132; Mon, 6 Nov 89 10:46:47 EST Date: Mon, 6 Nov 89 10:46:47 EST From: sam@odi.com Message-Id: <8911061546.AA09132@joplin.odi.com> To: benson@odi.com Cc: c++bugs In-Reply-To: benson@odi.com's message of Mon, 6 Nov 89 10:35:37 EST <8911061535.AA04499@cass.odi.com> Subject: how to confuse const checking Date: Mon, 6 Nov 89 10:35:37 EST From: benson@odi.com The following program: /* -*- Mode:C++ -*- */ int gruz (char *, char *); int gruz (char const *, char const *); void plugh (char const * x, char * y) { gruz(x,y); } gets the following error: CC foo.C: "foo.C", line 8: error: two exact matches for gruz(): int (const char *, const c har *) and int (char *, char *) 1 error Unfortunately, according to Section 13 of the PRM this error message is legitimate. Return-Path: <sam@odi.com> Received: from joplin.odi.com by odi.com (4.0/SMI-4.0/ODI-4) id AA13519; Mon, 6 Nov 89 11:01:50 EST Received: by joplin.odi.com (4.0/SMI-4.0/ODI-C2) id AA09163; Mon, 6 Nov 89 11:01:47 EST Date: Mon, 6 Nov 89 11:01:47 EST From: sam@odi.com Message-Id: <8911061601.AA09163@joplin.odi.com> To: benson@odi.com Cc: c++bugs In-Reply-To: benson@odi.com's message of Mon, 6 Nov 89 10:35:37 EST <8911061535.AA04499@cass.odi.com> Subject: how to confuse const checking Upon further reflection there is a bug here. It shouldn't have been possible to define the second gruz, ie. the following abbreviated test should fail, but doesn't. --------- int gruz (char *, char *); int gruz (const char *, const char *); ---------- Date: Mon, 6 Nov 89 10:35:37 EST From: benson@odi.com The following program: /* -*- Mode:C++ -*- */ int gruz (char *, char *); int gruz (char const *, char const *); void plugh (char const * x, char * y) { gruz(x,y); } gets the following error: CC foo.C: "foo.C", line 8: error: two exact matches for gruz(): int (const char *, const c har *) and int (char *, char *) 1 error Unfortunately, according to Section 13 of the PRM this error message is legitimate.