4bsd-f77@utah-cs.UUCP (4.2 BSD f77 bug reports) (08/01/84)
From: Donn Seeley <donn@utah-cs.arpa> Subject: F77 doesn't calculate the lengths of concatenations properly Index: usr.bin/f77/src/f77pass1/put.c 4.2BSD Description: There are at least a couple errors in the f77 compiler in the way it handles the lengths of concatenated strings. One of them is a clear error in the code dealing with finding the length of a concatenation of two CHARACTER variables; the other is a failure to propagate the length of a CHARACTER variable through parentheses. The first problem was found and fixed by Conrad Huang at UC San Francisco. Repeat-By: I don't have a handy example of how the first problem breaks some code, but the error is quite obvious from just looking at the source. The other bug can be shown by attempting to compile the following program with the optimizer on: ---------------------------------------------------------------- program chcat character*4 hi character*6 there character*1 excl character*15 out data hi/'hi'/ data there/'there'/ data excl/'!'/ out = (hi // there) // excl print *, out stop end ---------------------------------------------------------------- The compiler bombs out with the following edifying messages: ---------------------------------------------------------------- chcat.f: MAIN chcat: Error on line 12 of chcat.f: nonarithmetic operand of arithmetic operator Error on line 12 of chcat.f: impossible element in concatenation Error. No assembly. ---------------------------------------------------------------- Fix: The first bug is easy to identify and to fix. The problem is that the code in lencat() implies that the 'varleng' field in an 'Addrblock' stucture is at the same offset as the 'varleng' field in a 'Tempblock' structure, which, alas, it is not. The fix is in lencat(), in put.c: ---------------------------------------------------------------- *** /tmp/,RCSt1028292 Thu Jul 19 17:27:25 1984 --- put.c Thu Jul 19 12:04:26 1984 *************** *** 173,179 return( lencat(p->exprblock.leftp) + lencat(p->exprblock.rightp) ); else if( p->headblock.vleng!=NULL && ISICON(p->headblock.vleng) ) return(p->headblock.vleng->constblock.const.ci); ! else if((p->tag==TADDR || p->tag==TTEMP) && p->addrblock.varleng!=0) return(p->addrblock.varleng); else { --- 186,192 ----- return( lencat(p->exprblock.leftp) + lencat(p->exprblock.rightp) ); else if( p->headblock.vleng!=NULL && ISICON(p->headblock.vleng) ) return(p->headblock.vleng->constblock.const.ci); ! else if(p->tag==TADDR && p->addrblock.varleng!=0) return(p->addrblock.varleng); else if(p->tag==TTEMP && p->tempblock.varleng!=0) return(p->tempblock.varleng); *************** *** 175,180 return(p->headblock.vleng->constblock.const.ci); else if((p->tag==TADDR || p->tag==TTEMP) && p->addrblock.varleng!=0) return(p->addrblock.varleng); else { err("impossible element in concatenation"); --- 188,195 ----- return(p->headblock.vleng->constblock.const.ci); else if(p->tag==TADDR && p->addrblock.varleng!=0) return(p->addrblock.varleng); + else if(p->tag==TTEMP && p->tempblock.varleng!=0) + return(p->tempblock.varleng); else { err("impossible element in concatenation"); ---------------------------------------------------------------- The second bug is due to the fact that for some obscure reason, parentheses are treated as an operator in f77 (only when the optimizer is enabled, by the way -- even so, none of the optimization code appears to use the parenthesis operator for anything). A parenthesis expression has the type of its operand; unfortunately it does not propagate the length of its operand when that operand is a CHARACTER expression, leading to indirection through a null pointer (which explains the first error message in the example) and a complaint from lencat() because it can't get a length for one operand of a concatenation operator (which explains the second error message). Yet another bug is concealed behind this one, which is that the intermediate code emitting routine putch1() does not know what to do with a parenthesis expression anyway, length or no length. Here is the fix to fixexpr() in expr.c to force the length to be passed through parentheses: ---------------------------------------------------------------- *** /tmp/,RCSt1028422 Thu Jul 19 17:48:21 1984 --- expr.c Thu Jul 19 17:21:27 1984 *************** *** 666,671 case OPCOMMA: case OPQUEST: case OPCOLON: break; case OPMIN: --- 670,679 ----- case OPCOMMA: case OPQUEST: case OPCOLON: + break; + + case OPPAREN: + p->vleng = cpexpr( lp->headblock.vleng ); break; case OPMIN: ---------------------------------------------------------------- And here is the fix to putch1() in putpcc.c: ---------------------------------------------------------------- *** /tmp/,RCSt1028466 Thu Jul 19 17:54:01 1984 --- putpcc.c Thu Jul 19 17:23:05 1984 *************** *** 929,934 case OPCALL: case OPCCALL: t = putcall(p); break; case OPCONCAT: --- 932,942 ----- case OPCALL: case OPCCALL: t = putcall(p); + break; + + case OPPAREN: + --*ncommap; + t = putch1(p->exprblock.leftp, ncommap); break; case OPCONCAT: ---------------------------------------------------------------- Character manipulation in FORTRAN?!? -- You gotta be kidding, Donn Seeley University of Utah CS Dept donn@utah-cs.arpa 40 46' 6"N 111 50' 34"W (801) 581-5668 decvax!utah-cs!donn