[net.bugs.4bsd] PCC param processing: the whole sorid story. "bad arg temp" bug.

steve@sdcc3.UUCP (Steve Serocki) (09/04/84)

Subject: PCC's Indefensible Argument Processing -- "bad arg temp" bug
Index:  lib/mip/pftn.c 4.2BSD

Description:
	Error checking in the portable C compiler's semantic analysis
	phase has always been less than rigorous, to the point now of
	being the butt of cruel jokes comparing the pcc in robustness
	to the C shell.  Recent ridicule (*) has been directed
	especially at the comic handling of irregular parameter 
	declarations.

	The pcc will disdain catching parameters described as "static",
	or "extern" storage class in semantic analysis, ultimately
	falling on its nose in codegen, or worse.  A catch is described
	in a companion bug report.

	The pcc will often respond to missing parameters with a "bad
	arg temp" warning, and then go on to generate incorrect code.
	If the missing parameter is in addition (improperly) declared 
	"static" or "external" no warning will be given and the result
	will be even more bizarre.  A catch for the "bad arg temp" bug is 
	described here.

	[(*) Refs: 3015@utah-cs.UUCP, 8180-8181@ucmp-cs.UUCP]


Repeat-By:
	"bad arg temp":

	Give the following C program to the pcc and compile
	with the -S option.  The compiler will give the "bad arg temp"
	warning and display a ridiculous stack offset for
	the parameter.

	-------the program:------
	int imp;

	main(perverse )
		int imp;	/* "imp" missing from param list */
	{
		imp = 6969;
	}
	-------the .s file:-------

	LL0:
		.data
		.comm	_imp,4
		.text
		.align	1
		.globl	_main
	_main:
		.word	L13
		jbr 	L15
	L16:
	"foo.c", line 6: warning: bad arg temp
		cvtwl	$6969,-1275(ap)
		ret
		.set	L13,0x0
	L15:
	jbr 	L16
	.data


	Even more bizarre:

	Give the following C program to the pcc and compile
	with the -S option.  The compile will complete 
	normally and silently.  L13 will be undefined in the
	output.

	int imp;

	main(perverse )
		static int imp;	/* "imp" missing from param list */
	{
		imp = 6969;
	}

Fix:
	The problem seems to be an errant "if" statement sifting out
	(incorrectly)  cases that should be caught as errors
	in the first "switch" [if...switch(class)] in defid().  
	The case of (blevel == 1 && { ident type not FunctionArg }
			    && { ident defined somewhere though})
	was not being caught.  Moving the switch up and
	out of the if statement solves the problem, catching 
	the extra cases without side effects.  The changed compiler
	clones itself.


*** pftn.c	Sun Jul 17 13:37:05 1983
--- jess.pftn.c	Tue Sep  4 04:09:07 1984
***************
*** 79,85
  
  	if( stp == FTN && p->sclass == SNULL )goto enter;
  		/* name encountered as function, not yet defined */
- 	if( stp == UNDEF|| stp == FARG ){
  		if( blevel==1 && stp!=FARG ) switch( class ){
  
  		default:

--- 79,84 -----
  
  	if( stp == FTN && p->sclass == SNULL )goto enter;
  		/* name encountered as function, not yet defined */
  		if( blevel==1 && stp!=FARG ) switch( class ){
  
  		default:
***************
*** 97,102
  		case TYPEDEF:
  			;
  			}
  		goto enter;
  		}
  

--- 96,103 -----
  		case TYPEDEF:
  			;
  			}
+ 
+ 	if( stp == UNDEF|| stp == FARG )
  		goto enter;
  
  	if( type != stp ) goto mismatch;
***************
*** 98,104
  			;
  			}
  		goto enter;
- 		}
  
  	if( type != stp ) goto mismatch;
  	/* test (and possibly adjust) dimensions */

--- 99,104 -----
  
  	if( stp == UNDEF|| stp == FARG )
  		goto enter;
  
  	if( type != stp ) goto mismatch;
  	/* test (and possibly adjust) dimensions */