wescott@sauron.UUCP (Mike Wescott) (11/16/86)
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) {
karl@haddock.UUCP (11/22/86)
In article <757@sauron.UUCP> wescott@sauron.UUCP (Mike Wescott) writes: >While masked on the VAX, the bug can be demonstrated by the following: >typedef int (* S)(float); extern S s; >void x() { (*s)(4); s(4); } >[...] >Note first, that both methods of invoking the function pointers are >legitimate C and C++. They are? I don't recall seeing this feature described in C++ (but I don't have any recent documentation). And it is *not* legitimate oldC -- some compilers will accept it, but not all. (It has, alas, been blessed by ANSI, but the C++ compiler isn't supposed to generate ANSI C output, so the C++ compiler is broken if it silently generates "s((float)4);". Right?) Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
wescott@sauron.UUCP (Mike Wescott) (11/25/86)
In article <175@haddock.UUCP> karl@haddock.UUCP (Karl Heuer) writes: > In article <757@sauron.UUCP> wescott@sauron.UUCP (Mike Wescott) writes: > >While masked on the VAX, the bug can be demonstrated by the following: > >typedef int (* S)(float); extern S s; > >void x() { (*s)(4); s(4); } > >[...] > >Note first, that both methods of invoking the function pointers are > >legitimate C and C++. > > They are? I don't recall seeing this feature described in C++ (but I don't > have any recent documentation). And it is *not* legitimate oldC -- some > compilers will accept it, but not all. (It has, alas, been blessed by ANSI, > but the C++ compiler isn't supposed to generate ANSI C output, so the C++ > compiler is broken if it silently generates "s((float)4);". Right?) Within a day of posting this article, I cancelled it. For a more complete description of the probllem and a better fix, see <765@sauron.UUCP> and <766@sauron.UUCP>. And yes, it is C++ (see sect r7.1 of The C++ Programming Language, p. 256). And no it's not in K&R. As for the exact flavor of C that C++ ought to generate, I don't know. By the way, the fix posted in <766@sauron> produces "(*s)((float)4);" -- -Mike Wescott ncrcae!wescott