Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!lll-crg!mordor!sri-spam!sri-unix!hplabs!hp-sdd!ncr-sd!ncrcae!sauron!wescott From: wescott@sauron.UUCP (Mike Wescott) Newsgroups: comp.lang.c++ Subject: Bug in C++ cfont with possible fix (C++ v1.1) Message-ID: <757@sauron.UUCP> Date: Sun, 16-Nov-86 04:28:09 EST Article-I.D.: sauron.757 Posted: Sun Nov 16 04:28:09 1986 Date-Received: Mon, 17-Nov-86 04:58:56 EST Reply-To: wescott@sauron.UUCP (Mike Wescott) Organization: NCR Corp., Advanced System Development, Columbia, SC Lines: 123 Paraphrase of a recent comment in net.lang.c: "Everyone knows that the first test of a compiler is to compile itself." Well in porting C++ (1.1 and 1.0) to the NCR Tower (MC680x0) machines, C++ wouldn't compile itself. It got a bus error when cfront was working on main.c. The bug is masked in most architectures by the way alignments of the 'basetype' and 'fct' derived classes line up. The bug occurs in print.c when a reference is assumed to be to the 'fct' class but in fact is to the 'basetype' class. On machines with VAX alignments and sizes, a NULL pointer is fetched, recognized and processing continues. On my machine, the top half of another pointer is fetched, and used to try to access low memory. While masked on the VAX, the bug can be demonstrated by the following function typedef int (* S)(float); extern S s; void x() { (*s)(4); s(4); } from which cfront produces (stripped of line numbers and comments) int *_new (); int _delete (); int *_vec_new (); int _vec_delete (); typedef int (*S )(); extern S s ; int x () { (*s )( (float )4 ) ; s ( 4 ) ; } ; Note first, that both methods of invoking the function *s are legitimate C and C++. Note as well, that the second invocation does not get its argument preceeded by the (float) cast. This is the bug. Since both C++ statements are equivalent, both should produce that same construct for the argument list. As mentioned above, the problem is in print.c. As the second statement is printed, the assumtion is made that since the statement is a "CALL" then "s" is a function name. Under that assumtion, print.c tries to determine the type of the arguments to "s" using the wrong structure. On the VAX it gives up because it gets a NULL, on other machines it can go off into never-never land. A patch follows. Perhaps Dr. Stroustup will bless or (better yet) improve upon this. -Mike Wescott ncrcae!wescott *** print.c.orig Sat Nov 15 21:06:04 1986 --- print.c Sun Nov 16 03:03:31 1986 *************** *** 1372,1377 else { //error('d',"e1%k e1->tp %d %d%t",e1->base,e1->tp,e1->tp->base,e1->tp); eprint(e1); if (e1->tp) // pointer to fct at = Pfct(e1->tp)->argtype; else // virtual: argtype encoded --- 1372,1378 ----- else { //error('d',"e1%k e1->tp %d %d%t",e1->base,e1->tp,e1->tp->base,e1->tp); eprint(e1); + #ifdef BUG if (e1->tp) // pointer to fct at = Pfct(e1->tp)->argtype; else // virtual: argtype encoded *************** *** 1376,1381 at = Pfct(e1->tp)->argtype; else // virtual: argtype encoded at = (Pname)e1->e1->tp; } puttok(LP); if (e2) { --- 1377,1412 ----- at = Pfct(e1->tp)->argtype; else // virtual: argtype encoded at = (Pname)e1->e1->tp; + #else + if (!(e1->tp)) // virtual: argtype encoded + at = (Pname)e1->e1->tp; + else // look for pointer to fct + for (at = (Pname)(e1->tp); at ; ) { + switch (at->base) { + case FCT: + at = Pfct(at)->argtype; + break; + case ZTYPE: // is this possible ?? + case ANY: // is this possible ?? + case TYPE: // this is !! + at = Pbase(at)->b_name; + continue; + case RPTR: // is this possible?? + case PTR: // this is !! + at = (Pname)(Pptr(at)->typ); + continue; + case NAME: // is this possible?? + case TNAME: // this is !! + at = (Pname)(at->tp); + continue; + default: // what else ?? + error('i',"can't find arglist types"); + at = (Pname) 0; + break; + } + break; + } + #endif } puttok(LP); if (e2) {