some minor fixes, renamed ch7 stuff to ch3
This commit is contained in:
		
							parent
							
								
									fa4e6eecb4
								
							
						
					
					
						commit
						00027d3893
					
				
					 15 changed files with 1281 additions and 92 deletions
				
			
		| 
						 | 
				
			
			@ -71,20 +71,20 @@ LOBJ =	tokenfile.o declar.o statement.o expression.o program.o Lpars.o ival.o
 | 
			
		|||
 | 
			
		||||
# Objects of hand-written C files
 | 
			
		||||
CSRC =	main.c idf.c declarator.c decspecs.c struct.c \
 | 
			
		||||
	expr.c ch7.c ch7bin.c cstoper.c fltcstoper.c arith.c \
 | 
			
		||||
	expr.c ch3.c ch3bin.c cstoper.c fltcstoper.c arith.c \
 | 
			
		||||
	code.c dumpidf.c error.c field.c\
 | 
			
		||||
	tokenname.c LLlex.c LLmessage.c \
 | 
			
		||||
	input.c domacro.c replace.c init.c options.c \
 | 
			
		||||
	skip.c stack.c type.c ch7mon.c label.c eval.c \
 | 
			
		||||
	skip.c stack.c type.c ch3mon.c label.c eval.c \
 | 
			
		||||
	switch.c conversion.c util.c proto.c \
 | 
			
		||||
	pragma.c blocks.c dataflow.c Version.c \
 | 
			
		||||
	l_lint.c l_states.c l_misc.c l_ev_ord.c l_outdef.c l_comment.c l_dummy.c
 | 
			
		||||
COBJ =	main.o idf.o declarator.o decspecs.o struct.o \
 | 
			
		||||
	expr.o ch7.o ch7bin.o cstoper.o fltcstoper.o arith.o \
 | 
			
		||||
	expr.o ch3.o ch3bin.o cstoper.o fltcstoper.o arith.o \
 | 
			
		||||
	code.o dumpidf.o error.o field.o\
 | 
			
		||||
	tokenname.o LLlex.o LLmessage.o \
 | 
			
		||||
	input.o domacro.o replace.o init.o options.o \
 | 
			
		||||
	skip.o stack.o type.o ch7mon.o label.o eval.o \
 | 
			
		||||
	skip.o stack.o type.o ch3mon.o label.o eval.o \
 | 
			
		||||
	switch.o conversion.o util.o proto.o \
 | 
			
		||||
	pragma.o blocks.o dataflow.o Version.o \
 | 
			
		||||
	l_lint.o l_states.o l_misc.o l_ev_ord.o l_outdef.o l_comment.o l_dummy.o
 | 
			
		||||
| 
						 | 
				
			
			@ -405,34 +405,34 @@ expr.o: sizes.h
 | 
			
		|||
expr.o: spec_arith.h
 | 
			
		||||
expr.o: target_sizes.h
 | 
			
		||||
expr.o: type.h
 | 
			
		||||
ch7.o: Lpars.h
 | 
			
		||||
ch7.o: arith.h
 | 
			
		||||
ch7.o: assert.h
 | 
			
		||||
ch7.o: debug.h
 | 
			
		||||
ch7.o: def.h
 | 
			
		||||
ch7.o: expr.h
 | 
			
		||||
ch7.o: file_info.h
 | 
			
		||||
ch7.o: idf.h
 | 
			
		||||
ch7.o: label.h
 | 
			
		||||
ch7.o: lint.h
 | 
			
		||||
ch7.o: nobitfield.h
 | 
			
		||||
ch7.o: nopp.h
 | 
			
		||||
ch7.o: proto.h
 | 
			
		||||
ch7.o: spec_arith.h
 | 
			
		||||
ch7.o: struct.h
 | 
			
		||||
ch7.o: type.h
 | 
			
		||||
ch7bin.o: Lpars.h
 | 
			
		||||
ch7bin.o: arith.h
 | 
			
		||||
ch7bin.o: botch_free.h
 | 
			
		||||
ch7bin.o: expr.h
 | 
			
		||||
ch7bin.o: idf.h
 | 
			
		||||
ch7bin.o: label.h
 | 
			
		||||
ch7bin.o: lint.h
 | 
			
		||||
ch7bin.o: nobitfield.h
 | 
			
		||||
ch7bin.o: nopp.h
 | 
			
		||||
ch7bin.o: spec_arith.h
 | 
			
		||||
ch7bin.o: struct.h
 | 
			
		||||
ch7bin.o: type.h
 | 
			
		||||
ch3.o: Lpars.h
 | 
			
		||||
ch3.o: arith.h
 | 
			
		||||
ch3.o: assert.h
 | 
			
		||||
ch3.o: debug.h
 | 
			
		||||
ch3.o: def.h
 | 
			
		||||
ch3.o: expr.h
 | 
			
		||||
ch3.o: file_info.h
 | 
			
		||||
ch3.o: idf.h
 | 
			
		||||
ch3.o: label.h
 | 
			
		||||
ch3.o: lint.h
 | 
			
		||||
ch3.o: nobitfield.h
 | 
			
		||||
ch3.o: nopp.h
 | 
			
		||||
ch3.o: proto.h
 | 
			
		||||
ch3.o: spec_arith.h
 | 
			
		||||
ch3.o: struct.h
 | 
			
		||||
ch3.o: type.h
 | 
			
		||||
ch3bin.o: Lpars.h
 | 
			
		||||
ch3bin.o: arith.h
 | 
			
		||||
ch3bin.o: botch_free.h
 | 
			
		||||
ch3bin.o: expr.h
 | 
			
		||||
ch3bin.o: idf.h
 | 
			
		||||
ch3bin.o: label.h
 | 
			
		||||
ch3bin.o: lint.h
 | 
			
		||||
ch3bin.o: nobitfield.h
 | 
			
		||||
ch3bin.o: nopp.h
 | 
			
		||||
ch3bin.o: spec_arith.h
 | 
			
		||||
ch3bin.o: struct.h
 | 
			
		||||
ch3bin.o: type.h
 | 
			
		||||
cstoper.o: Lpars.h
 | 
			
		||||
cstoper.o: arith.h
 | 
			
		||||
cstoper.o: assert.h
 | 
			
		||||
| 
						 | 
				
			
			@ -691,18 +691,18 @@ type.o: sizes.h
 | 
			
		|||
type.o: spec_arith.h
 | 
			
		||||
type.o: target_sizes.h
 | 
			
		||||
type.o: type.h
 | 
			
		||||
ch7mon.o: Lpars.h
 | 
			
		||||
ch7mon.o: arith.h
 | 
			
		||||
ch7mon.o: botch_free.h
 | 
			
		||||
ch7mon.o: def.h
 | 
			
		||||
ch7mon.o: expr.h
 | 
			
		||||
ch7mon.o: idf.h
 | 
			
		||||
ch7mon.o: label.h
 | 
			
		||||
ch7mon.o: lint.h
 | 
			
		||||
ch7mon.o: nobitfield.h
 | 
			
		||||
ch7mon.o: nopp.h
 | 
			
		||||
ch7mon.o: spec_arith.h
 | 
			
		||||
ch7mon.o: type.h
 | 
			
		||||
ch3mon.o: Lpars.h
 | 
			
		||||
ch3mon.o: arith.h
 | 
			
		||||
ch3mon.o: botch_free.h
 | 
			
		||||
ch3mon.o: def.h
 | 
			
		||||
ch3mon.o: expr.h
 | 
			
		||||
ch3mon.o: idf.h
 | 
			
		||||
ch3mon.o: label.h
 | 
			
		||||
ch3mon.o: lint.h
 | 
			
		||||
ch3mon.o: nobitfield.h
 | 
			
		||||
ch3mon.o: nopp.h
 | 
			
		||||
ch3mon.o: spec_arith.h
 | 
			
		||||
ch3mon.o: type.h
 | 
			
		||||
label.o: Lpars.h
 | 
			
		||||
label.o: arith.h
 | 
			
		||||
label.o: def.h
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -142,10 +142,10 @@ relbalance(e1p, oper, e2p)
 | 
			
		|||
	if ((*e2p)->ex_type->tp_fund == FUNCTION)
 | 
			
		||||
		function2pointer(*e2p);
 | 
			
		||||
	if ((*e1p)->ex_type->tp_fund == POINTER)
 | 
			
		||||
		ch76pointer(e2p, oper, (*e1p)->ex_type);
 | 
			
		||||
		ch3pointer(e2p, oper, (*e1p)->ex_type);
 | 
			
		||||
	else
 | 
			
		||||
	if ((*e2p)->ex_type->tp_fund == POINTER)
 | 
			
		||||
		ch76pointer(e1p, oper, (*e2p)->ex_type);
 | 
			
		||||
		ch3pointer(e1p, oper, (*e2p)->ex_type);
 | 
			
		||||
	else
 | 
			
		||||
	if (	(*e1p)->ex_type == (*e2p)->ex_type &&
 | 
			
		||||
		(*e1p)->ex_type->tp_fund == ENUM
 | 
			
		||||
| 
						 | 
				
			
			@ -155,7 +155,7 @@ relbalance(e1p, oper, e2p)
 | 
			
		|||
		arithbalance(e1p, oper, e2p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ch76pointer(expp, oper, tp)
 | 
			
		||||
ch3pointer(expp, oper, tp)
 | 
			
		||||
	struct expr **expp;
 | 
			
		||||
	register struct type *tp;
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -167,7 +167,7 @@ ch76pointer(expp, oper, tp)
 | 
			
		|||
 | 
			
		||||
	if (exp->ex_type->tp_fund == POINTER)	{
 | 
			
		||||
		if (exp->ex_type != tp)
 | 
			
		||||
			ch7cast(expp, oper, tp);
 | 
			
		||||
			ch3cast(expp, oper, tp);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	if (is_integral_type(exp->ex_type)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -177,14 +177,14 @@ ch76pointer(expp, oper, tp)
 | 
			
		|||
					symbol2str(oper),
 | 
			
		||||
					symbol2str(exp->ex_type->tp_fund));
 | 
			
		||||
		}
 | 
			
		||||
		ch7cast(expp, CAST, tp);
 | 
			
		||||
		ch3cast(expp, CAST, tp);
 | 
			
		||||
	}
 | 
			
		||||
	else	{
 | 
			
		||||
		expr_error(exp, "%s on %s and pointer",
 | 
			
		||||
				symbol2str(oper),
 | 
			
		||||
				symbol2str(exp->ex_type->tp_fund)
 | 
			
		||||
			);
 | 
			
		||||
		ch7cast(expp, oper, tp);
 | 
			
		||||
		ch3cast(expp, oper, tp);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -468,7 +468,7 @@ opnd2test(expp, oper)
 | 
			
		|||
	if ((*expp)->ex_class == Oper && is_test_op((*expp)->OP_OPER))
 | 
			
		||||
		{ /* It is already a test */ }
 | 
			
		||||
	else
 | 
			
		||||
		ch7bin(expp, NOTEQUAL, intexpr((arith)0, INT));
 | 
			
		||||
		ch3bin(expp, NOTEQUAL, intexpr((arith)0, INT));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
| 
						 | 
				
			
			@ -542,19 +542,19 @@ field2arith(expp)
 | 
			
		|||
	(*expp)->ex_type = atype;
 | 
			
		||||
 | 
			
		||||
	if (atype->tp_unsigned)	{	/* don't worry about the sign bit */
 | 
			
		||||
		ch7bin(expp, RIGHT, intexpr((arith)fd->fd_shift, INT));
 | 
			
		||||
		ch7bin(expp, '&', intexpr(fd->fd_mask, INT));
 | 
			
		||||
		ch3bin(expp, RIGHT, intexpr((arith)fd->fd_shift, INT));
 | 
			
		||||
		ch3bin(expp, '&', intexpr(fd->fd_mask, INT));
 | 
			
		||||
	}
 | 
			
		||||
	else	{	/* take care of the sign bit: sign extend if needed */
 | 
			
		||||
		arith bits_in_type = atype->tp_size * 8;
 | 
			
		||||
 | 
			
		||||
		ch7bin(expp, LEFT,
 | 
			
		||||
		ch3bin(expp, LEFT,
 | 
			
		||||
			intexpr(bits_in_type - fd->fd_width - fd->fd_shift,
 | 
			
		||||
						INT)
 | 
			
		||||
		);
 | 
			
		||||
		ch7bin(expp, RIGHT, intexpr(bits_in_type - fd->fd_width, INT));
 | 
			
		||||
		ch3bin(expp, RIGHT, intexpr(bits_in_type - fd->fd_width, INT));
 | 
			
		||||
	}
 | 
			
		||||
	ch7cast(expp, CAST, tp);	/* restore its original type */
 | 
			
		||||
	ch3cast(expp, CAST, tp);	/* restore its original type */
 | 
			
		||||
}
 | 
			
		||||
#endif NOBITFIELD
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										660
									
								
								lang/cem/cemcom.ansi/ch3.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										660
									
								
								lang/cem/cemcom.ansi/ch3.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,660 @@
 | 
			
		|||
/*
 | 
			
		||||
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
			
		||||
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
			
		||||
 */
 | 
			
		||||
/* $Header$ */
 | 
			
		||||
/*	S E M A N T I C   A N A L Y S I S -- C H A P T E R  3.3		*/
 | 
			
		||||
 | 
			
		||||
#include	"lint.h"
 | 
			
		||||
#include	"debug.h"
 | 
			
		||||
#include	"nobitfield.h"
 | 
			
		||||
#include	"idf.h"
 | 
			
		||||
#include	<flt_arith.h>
 | 
			
		||||
#include	"arith.h"
 | 
			
		||||
#include	"proto.h"
 | 
			
		||||
#include	"type.h"
 | 
			
		||||
#include	"struct.h"
 | 
			
		||||
#include	"label.h"
 | 
			
		||||
#include	"expr.h"
 | 
			
		||||
#include	"def.h"
 | 
			
		||||
#include	"Lpars.h"
 | 
			
		||||
#include	"assert.h"
 | 
			
		||||
#include	"file_info.h"
 | 
			
		||||
 | 
			
		||||
extern char options[];
 | 
			
		||||
extern char *symbol2str();
 | 
			
		||||
extern struct type *qualifier_type();
 | 
			
		||||
 | 
			
		||||
/*	Most expression-handling routines have a pointer to a
 | 
			
		||||
	(struct type *) as first parameter. The object under the pointer
 | 
			
		||||
	gets updated in the process.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
ch3sel(expp, oper, idf)
 | 
			
		||||
	struct expr **expp;
 | 
			
		||||
	struct idf *idf;
 | 
			
		||||
{
 | 
			
		||||
	/*	The selector idf is applied to *expp; oper may be '.' or
 | 
			
		||||
		ARROW.
 | 
			
		||||
	*/
 | 
			
		||||
	register struct expr *exp;
 | 
			
		||||
	register struct type *tp;
 | 
			
		||||
	register struct sdef *sd;
 | 
			
		||||
 | 
			
		||||
	any2opnd(expp, oper);
 | 
			
		||||
	exp = *expp;
 | 
			
		||||
	tp = exp->ex_type;
 | 
			
		||||
	if (oper == ARROW)	{
 | 
			
		||||
		if (tp->tp_fund == POINTER &&
 | 
			
		||||
		    ( tp->tp_up->tp_fund == STRUCT ||
 | 
			
		||||
		      tp->tp_up->tp_fund == UNION))	/* normal case */
 | 
			
		||||
			tp = tp->tp_up;
 | 
			
		||||
		else {	/* constructions like "12->selector" and
 | 
			
		||||
				"char c; c->selector"
 | 
			
		||||
			*/
 | 
			
		||||
			switch (tp->tp_fund)	{
 | 
			
		||||
			case POINTER:
 | 
			
		||||
				break;
 | 
			
		||||
			case INT:
 | 
			
		||||
			case LONG:
 | 
			
		||||
				/* An error is given in idf2sdef() */
 | 
			
		||||
				ch3cast(expp, CAST, pa_type);
 | 
			
		||||
				sd = idf2sdef(idf, tp);
 | 
			
		||||
				tp = sd->sd_stype;
 | 
			
		||||
				break;
 | 
			
		||||
			default:
 | 
			
		||||
				expr_error(exp, "-> applied to %s",
 | 
			
		||||
					symbol2str(tp->tp_fund));
 | 
			
		||||
			case ERRONEOUS:
 | 
			
		||||
				exp->ex_type = error_type;
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {		/* oper == '.' */
 | 
			
		||||
		/* nothing */
 | 
			
		||||
	}
 | 
			
		||||
	exp = *expp;
 | 
			
		||||
	switch (tp->tp_fund)	{
 | 
			
		||||
	case POINTER:	/* for int *p;	p->next = ...	*/
 | 
			
		||||
	case STRUCT:
 | 
			
		||||
	case UNION:
 | 
			
		||||
		break;
 | 
			
		||||
	case INT:
 | 
			
		||||
	case LONG:
 | 
			
		||||
		/* warning will be given by idf2sdef() */
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		if (!is_anon_idf(idf))
 | 
			
		||||
			expr_error(exp, "selector %s applied to %s",
 | 
			
		||||
				idf->id_text, symbol2str(tp->tp_fund));
 | 
			
		||||
	case ERRONEOUS:
 | 
			
		||||
		exp->ex_type = error_type;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	sd = idf2sdef(idf, tp);
 | 
			
		||||
	if (oper == '.')	{
 | 
			
		||||
		/*	there are 3 cases in which the selection can be
 | 
			
		||||
			performed compile-time: 
 | 
			
		||||
			I:	n.sel (n either an identifier or a constant)
 | 
			
		||||
			II:	(e.s1).s2 (transformed into (e.(s1+s2)))
 | 
			
		||||
			III:	(e->s1).s2 (transformed into (e->(s1+s2)))
 | 
			
		||||
				The code performing these conversions is
 | 
			
		||||
				extremely obscure.
 | 
			
		||||
		*/
 | 
			
		||||
		if (exp->ex_class == Value)	{
 | 
			
		||||
			/*	It is an object we know the address of; so
 | 
			
		||||
				we can calculate the address of the
 | 
			
		||||
				selected member 
 | 
			
		||||
			*/
 | 
			
		||||
			exp->VL_VALUE += sd->sd_offset;
 | 
			
		||||
			exp->ex_type = sd->sd_type;
 | 
			
		||||
			exp->ex_lvalue = exp->ex_type->tp_fund != ARRAY;
 | 
			
		||||
			if (exp->ex_type == error_type) {
 | 
			
		||||
				exp->ex_flags |= EX_ERROR;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		if (exp->ex_class == Oper)	{
 | 
			
		||||
			struct oper *op = &(exp->ex_object.ex_oper);
 | 
			
		||||
			
 | 
			
		||||
			if (op->op_oper == '.' || op->op_oper == ARROW)	{
 | 
			
		||||
				ASSERT(is_cp_cst(op->op_right));
 | 
			
		||||
				op->op_right->VL_VALUE += sd->sd_offset;
 | 
			
		||||
				exp->ex_type = sd->sd_type;
 | 
			
		||||
				exp->ex_lvalue = exp->ex_type->tp_fund != ARRAY;
 | 
			
		||||
				if (exp->ex_type == error_type) {
 | 
			
		||||
					exp->ex_flags |= EX_ERROR;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				exp = new_oper(sd->sd_type, exp, '.',
 | 
			
		||||
						intexpr(sd->sd_offset, INT));
 | 
			
		||||
				exp->ex_lvalue = sd->sd_type->tp_fund != ARRAY;
 | 
			
		||||
				if (!exp->OP_LEFT->ex_lvalue)
 | 
			
		||||
					exp->ex_flags |= EX_ILVALUE;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else { /* oper == ARROW */
 | 
			
		||||
		exp = new_oper(sd->sd_type,
 | 
			
		||||
			exp, oper, intexpr(sd->sd_offset, INT));
 | 
			
		||||
		exp->ex_lvalue = (sd->sd_type->tp_fund != ARRAY);
 | 
			
		||||
		exp->ex_flags &= ~EX_ILVALUE;
 | 
			
		||||
	}
 | 
			
		||||
	if (sd->sd_type->tp_typequal & TQ_CONST)
 | 
			
		||||
		exp->ex_flags |= EX_READONLY;
 | 
			
		||||
	if (sd->sd_type->tp_typequal & TQ_VOLATILE)
 | 
			
		||||
		exp->ex_flags |= EX_VOLATILE;
 | 
			
		||||
	if (oper == '.' && exp->ex_flags & EX_READONLY)  {
 | 
			
		||||
		exp->ex_type = qualifier_type(exp->ex_type, TQ_CONST);
 | 
			
		||||
	}
 | 
			
		||||
	*expp = exp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ch3incr(expp, oper)
 | 
			
		||||
	struct expr **expp;
 | 
			
		||||
{
 | 
			
		||||
	/*	The monadic prefix/postfix incr/decr operator oper is
 | 
			
		||||
		applied to *expp.
 | 
			
		||||
	*/
 | 
			
		||||
	ch3asgn(expp, oper, intexpr((arith)1, INT));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ch3cast(expp, oper, tp)
 | 
			
		||||
	register struct expr **expp;
 | 
			
		||||
	register struct type *tp;
 | 
			
		||||
{
 | 
			
		||||
	/*	The expression *expp is cast to type tp; the cast is
 | 
			
		||||
		caused by the operator oper.  If the cast has
 | 
			
		||||
		to be passed on to run time, its left operand will be an
 | 
			
		||||
		expression of class Type.
 | 
			
		||||
	*/
 | 
			
		||||
	register struct type *oldtp;
 | 
			
		||||
 | 
			
		||||
	if (oper == RETURN && tp->tp_fund == VOID) {
 | 
			
		||||
		strict("return <expression> in function returning void");
 | 
			
		||||
		(*expp)->ex_type = void_type;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if ((*expp)->ex_type->tp_fund == FUNCTION)
 | 
			
		||||
		function2pointer(*expp);
 | 
			
		||||
	if ((*expp)->ex_type->tp_fund == ARRAY)
 | 
			
		||||
		array2pointer(*expp);
 | 
			
		||||
	if ((*expp)->ex_class == String)
 | 
			
		||||
		string2pointer(*expp);
 | 
			
		||||
	oldtp = (*expp)->ex_type;
 | 
			
		||||
 | 
			
		||||
#ifndef NOBITFIELD
 | 
			
		||||
	if (oldtp->tp_fund == FIELD)	{
 | 
			
		||||
		field2arith(expp);
 | 
			
		||||
		ch3cast(expp, oper, tp);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	if (tp->tp_fund == FIELD) {
 | 
			
		||||
		ch3cast(expp, oper, tp->tp_up);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
#endif NOBITFIELD
 | 
			
		||||
	if (equal_type(tp, oldtp, 0)) {
 | 
			
		||||
		/* life is easy */
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	if (tp->tp_fund == VOID) {
 | 
			
		||||
		/* easy again */
 | 
			
		||||
		(*expp)->ex_type = void_type;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	if (is_arith_type(oldtp) && is_arith_type(tp))	{
 | 
			
		||||
		int oldi = is_integral_type(oldtp);
 | 
			
		||||
		int i = is_integral_type(tp);
 | 
			
		||||
 | 
			
		||||
		if (oldi && i)	{
 | 
			
		||||
#ifdef	LINT
 | 
			
		||||
			if (oper == CAST)
 | 
			
		||||
				(*expp)->ex_type = tp;
 | 
			
		||||
			else
 | 
			
		||||
				int2int(expp, tp);
 | 
			
		||||
#else	LINT
 | 
			
		||||
			int2int(expp, tp);
 | 
			
		||||
#endif	LINT
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		if (oldi && !i)	{
 | 
			
		||||
#ifdef	LINT
 | 
			
		||||
			if (oper == CAST)
 | 
			
		||||
				(*expp)->ex_type = tp;
 | 
			
		||||
			else
 | 
			
		||||
				int2float(expp, tp);
 | 
			
		||||
#else	LINT
 | 
			
		||||
			int2float(expp, tp);
 | 
			
		||||
#endif	LINT
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		if (!oldi && i) {
 | 
			
		||||
#ifdef	LINT
 | 
			
		||||
			if (oper == CAST)
 | 
			
		||||
				(*expp)->ex_type = tp;
 | 
			
		||||
			else
 | 
			
		||||
				float2int(expp, tp);
 | 
			
		||||
#else	LINT
 | 
			
		||||
			float2int(expp, tp);
 | 
			
		||||
#endif	LINT
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			/* !oldi && !i */
 | 
			
		||||
#ifdef	LINT
 | 
			
		||||
			if (oper == CAST)
 | 
			
		||||
				(*expp)->ex_type = tp;
 | 
			
		||||
			else
 | 
			
		||||
				float2float(expp, tp);
 | 
			
		||||
#else	LINT
 | 
			
		||||
			float2float(expp, tp);
 | 
			
		||||
#endif	LINT
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	if (oldtp->tp_fund == POINTER && tp->tp_fund == POINTER)	{
 | 
			
		||||
		if (oper == CASTAB)
 | 
			
		||||
			expr_warning(*expp, "incompatible pointers");
 | 
			
		||||
		else
 | 
			
		||||
		if (oper != CAST)
 | 
			
		||||
			expr_warning(*expp, "incompatible pointers in %s",
 | 
			
		||||
							symbol2str(oper));
 | 
			
		||||
#ifdef	LINT
 | 
			
		||||
		if (oper != CAST)
 | 
			
		||||
			lint_ptr_conv(oldtp->tp_up->tp_fund, tp->tp_up->tp_fund);
 | 
			
		||||
#endif	LINT
 | 
			
		||||
		(*expp)->ex_type = tp;	/* free conversion */
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	if (oldtp->tp_fund == POINTER && is_integral_type(tp))	{
 | 
			
		||||
		/* from pointer to integral */
 | 
			
		||||
		if (oper != CAST)
 | 
			
		||||
			expr_warning(*expp,
 | 
			
		||||
				"illegal conversion of pointer to %s",
 | 
			
		||||
				symbol2str(tp->tp_fund));
 | 
			
		||||
		if (oldtp->tp_size > tp->tp_size)
 | 
			
		||||
			expr_warning(*expp,
 | 
			
		||||
				"conversion of pointer to %s loses accuracy",
 | 
			
		||||
				symbol2str(tp->tp_fund));
 | 
			
		||||
		if (oldtp->tp_size != tp->tp_size)
 | 
			
		||||
			int2int(expp, tp);
 | 
			
		||||
		else
 | 
			
		||||
			(*expp)->ex_type = tp;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	if (tp->tp_fund == POINTER && is_integral_type(oldtp))	{
 | 
			
		||||
		/* from integral to pointer */
 | 
			
		||||
		switch (oper)	{
 | 
			
		||||
		case CAST:
 | 
			
		||||
			break;
 | 
			
		||||
		case CASTAB:
 | 
			
		||||
		case EQUAL:
 | 
			
		||||
		case NOTEQUAL:
 | 
			
		||||
		case '=':
 | 
			
		||||
		case RETURN:
 | 
			
		||||
			if (is_cp_cst(*expp) && (*expp)->VL_VALUE == (arith)0)
 | 
			
		||||
				break;
 | 
			
		||||
		default:
 | 
			
		||||
			expr_warning(*expp,
 | 
			
		||||
				"illegal conversion of %s to pointer",
 | 
			
		||||
				symbol2str(oldtp->tp_fund));
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if (oldtp->tp_size > tp->tp_size)
 | 
			
		||||
			expr_warning(*expp,
 | 
			
		||||
				"conversion of %s to pointer loses accuracy",
 | 
			
		||||
				symbol2str(oldtp->tp_fund));
 | 
			
		||||
		if (oldtp->tp_size != tp->tp_size)
 | 
			
		||||
			int2int(expp, tp);
 | 
			
		||||
		else
 | 
			
		||||
			(*expp)->ex_type = tp;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	if (oldtp->tp_fund == ERRONEOUS) {
 | 
			
		||||
		/* we just won't look */
 | 
			
		||||
		(*expp)->ex_type = tp;	/* brute force */
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	if (oldtp->tp_size == tp->tp_size && oper == CAST)	{
 | 
			
		||||
		expr_warning(*expp, "dubious conversion based on equal size");
 | 
			
		||||
		(*expp)->ex_type = tp;		/* brute force */
 | 
			
		||||
	}
 | 
			
		||||
	else	{
 | 
			
		||||
		if (oldtp->tp_fund != ERRONEOUS && tp->tp_fund != ERRONEOUS)
 | 
			
		||||
			expr_error(*expp, "cannot convert %s to %s",
 | 
			
		||||
				symbol2str(oldtp->tp_fund),
 | 
			
		||||
				symbol2str(tp->tp_fund)
 | 
			
		||||
			);
 | 
			
		||||
		(*expp)->ex_type = tp;		/* brute force */
 | 
			
		||||
	}
 | 
			
		||||
	if (oper == CAST) {
 | 
			
		||||
		(*expp)->ex_flags |= EX_ILVALUE;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*	Determine whether two types are equal.
 | 
			
		||||
*/
 | 
			
		||||
equal_type(tp, otp, check_qual)
 | 
			
		||||
	register struct type *tp, *otp;
 | 
			
		||||
	int check_qual;
 | 
			
		||||
{
 | 
			
		||||
	if (tp == otp)
 | 
			
		||||
		return 1;
 | 
			
		||||
	if (!tp || !otp)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	if (tp->tp_fund != otp->tp_fund)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (tp->tp_unsigned != otp->tp_unsigned)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (tp->tp_align != otp->tp_align)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (tp->tp_fund != ARRAY /* && tp->tp_fund != STRUCT */ ) {	/* UNION ??? */
 | 
			
		||||
		if (tp->tp_size != otp->tp_size)
 | 
			
		||||
			return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (tp->tp_fund) {
 | 
			
		||||
 | 
			
		||||
	case FUNCTION:
 | 
			
		||||
		/*	If both types have parameter type lists, the type of
 | 
			
		||||
			each parameter in the composite parameter type list
 | 
			
		||||
			is the composite type of the corresponding paramaters.
 | 
			
		||||
		*/
 | 
			
		||||
		if (tp->tp_proto && otp->tp_proto) {
 | 
			
		||||
			if (!equal_proto(tp->tp_proto, otp->tp_proto))
 | 
			
		||||
				return 0;
 | 
			
		||||
		} else if (tp->tp_proto || otp->tp_proto) {
 | 
			
		||||
			if (!legal_mixture(tp, otp))
 | 
			
		||||
				return 0;
 | 
			
		||||
		}
 | 
			
		||||
		return equal_type(tp->tp_up, otp->tp_up, 0);
 | 
			
		||||
 | 
			
		||||
	case ARRAY:
 | 
			
		||||
		/*	If one type is an array of known size, the composite
 | 
			
		||||
			type is an array of that size
 | 
			
		||||
		*/
 | 
			
		||||
		if (tp->tp_size != otp->tp_size &&
 | 
			
		||||
		     (tp->tp_size != -1 && otp->tp_size != -1))
 | 
			
		||||
			return 0;
 | 
			
		||||
		return equal_type(tp->tp_up, otp->tp_up, check_qual);
 | 
			
		||||
 | 
			
		||||
	case POINTER:
 | 
			
		||||
		if (equal_type(tp->tp_up, otp->tp_up, check_qual)) {
 | 
			
		||||
		    if (otp->tp_up->tp_typequal & TQ_CONST) {
 | 
			
		||||
			if (!(tp->tp_up->tp_typequal & TQ_CONST)) {
 | 
			
		||||
			    strict("illegal use of pointer to const object");
 | 
			
		||||
			}
 | 
			
		||||
		    }
 | 
			
		||||
		    if (otp->tp_up->tp_typequal & TQ_VOLATILE) {
 | 
			
		||||
			if (!(tp->tp_up->tp_typequal & TQ_VOLATILE)) {
 | 
			
		||||
			    strict("illegal use of pointer to volatile object");
 | 
			
		||||
			}
 | 
			
		||||
		    }
 | 
			
		||||
		    return 1;
 | 
			
		||||
		}
 | 
			
		||||
		else return 0;
 | 
			
		||||
 | 
			
		||||
	case FIELD:
 | 
			
		||||
		return equal_type(tp->tp_up, otp->tp_up, check_qual);
 | 
			
		||||
 | 
			
		||||
	case STRUCT:
 | 
			
		||||
	case UNION:
 | 
			
		||||
	case ENUM:
 | 
			
		||||
		return tp->tp_idf == otp->tp_idf && tp->tp_sdef == otp->tp_sdef;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
check_pseudoproto(pl, opl)
 | 
			
		||||
	register struct proto *pl, *opl;
 | 
			
		||||
{
 | 
			
		||||
	int retval = 1;
 | 
			
		||||
 | 
			
		||||
	if (pl->pl_flag & PL_ELLIPSIS) {
 | 
			
		||||
		error("illegal ellipsis terminator");
 | 
			
		||||
		return 2;
 | 
			
		||||
	}
 | 
			
		||||
	if (opl->pl_flag & PL_VOID) {
 | 
			
		||||
		if (!(pl->pl_flag & PL_VOID))
 | 
			
		||||
			error("function is defined without parameters");
 | 
			
		||||
		pl->pl_flag |= PL_ERRGIVEN;
 | 
			
		||||
		opl->pl_flag |= PL_ERRGIVEN;
 | 
			
		||||
		return 2;
 | 
			
		||||
	}
 | 
			
		||||
	while (pl && opl) {
 | 
			
		||||
	    if (!equal_type(pl->pl_type, opl->pl_type, 0)) {
 | 
			
		||||
		if (!(pl->pl_flag & PL_ERRGIVEN)
 | 
			
		||||
		    && !(opl->pl_flag & PL_ERRGIVEN))
 | 
			
		||||
			error("incorrect type for parameter %s of definition",
 | 
			
		||||
				opl->pl_idf->id_text);
 | 
			
		||||
		pl->pl_flag |= PL_ERRGIVEN;
 | 
			
		||||
		opl->pl_flag |= PL_ERRGIVEN;
 | 
			
		||||
		retval = 2;
 | 
			
		||||
	    }
 | 
			
		||||
	    pl = pl->next;
 | 
			
		||||
	    opl = opl->next;
 | 
			
		||||
	}
 | 
			
		||||
	if (pl || opl) {
 | 
			
		||||
		error("incorrect number of parameters");
 | 
			
		||||
		retval = 2;
 | 
			
		||||
	}
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
legal_mixture(tp, otp)
 | 
			
		||||
	struct type *tp, *otp;
 | 
			
		||||
{
 | 
			
		||||
	register struct proto *pl = tp->tp_proto, *opl = otp->tp_proto;
 | 
			
		||||
	int retval = 1;
 | 
			
		||||
	struct proto *prot;
 | 
			
		||||
	int fund;
 | 
			
		||||
 | 
			
		||||
	ASSERT( (pl != 0) ^ (opl != 0));
 | 
			
		||||
	if (pl)  {
 | 
			
		||||
		prot = pl;
 | 
			
		||||
	} else  {
 | 
			
		||||
		prot = opl;
 | 
			
		||||
	}
 | 
			
		||||
	if (!opl && otp->tp_pseudoproto) {
 | 
			
		||||
		return check_pseudoproto(tp->tp_proto, otp->tp_pseudoproto);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (prot->pl_flag & PL_ELLIPSIS) {
 | 
			
		||||
		if (!(prot->pl_flag & PL_ERRGIVEN)) {
 | 
			
		||||
			if (pl)
 | 
			
		||||
				error("illegal ellipsis terminator");
 | 
			
		||||
			else	error("ellipsis terminator in previous (prototype) declaration");
 | 
			
		||||
		}
 | 
			
		||||
		prot->pl_flag |= PL_ERRGIVEN;
 | 
			
		||||
		prot = prot->next;
 | 
			
		||||
		return 2;
 | 
			
		||||
	}
 | 
			
		||||
	while (prot) {
 | 
			
		||||
				/* if (!(prot->pl_flag & PL_ELLIPSIS)) {} */
 | 
			
		||||
		fund = prot->pl_type->tp_fund;
 | 
			
		||||
		if (fund == CHAR || fund == SHORT || fund == FLOAT) {
 | 
			
		||||
			if (!(prot->pl_flag & PL_ERRGIVEN))
 | 
			
		||||
			    error("illegal %s parameter in %sdeclaration",
 | 
			
		||||
				symbol2str(fund), (opl ? "previous (prototype) " : "" ));
 | 
			
		||||
			prot->pl_flag |= PL_ERRGIVEN;
 | 
			
		||||
			retval = 2;
 | 
			
		||||
		}
 | 
			
		||||
		prot = prot->next;
 | 
			
		||||
	}
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
equal_proto(pl, opl)
 | 
			
		||||
	register struct proto *pl, *opl;
 | 
			
		||||
{
 | 
			
		||||
	if (pl == opl)
 | 
			
		||||
		return 1;
 | 
			
		||||
 | 
			
		||||
	/*	If only one type is a function type with a parameter type list
 | 
			
		||||
		(a function prototype), the composite type is a function
 | 
			
		||||
		prototype with parameter type list.
 | 
			
		||||
	*/
 | 
			
		||||
	while ( pl && opl) {
 | 
			
		||||
 | 
			
		||||
	    if ((pl->pl_flag & ~PL_ERRGIVEN) != (opl->pl_flag & ~PL_ERRGIVEN))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	    if (!equal_type(pl->pl_type, opl->pl_type, 0))
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	    pl = pl->next;
 | 
			
		||||
	    opl = opl->next;
 | 
			
		||||
	}
 | 
			
		||||
	return !(pl || opl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* check if a type has a const declared member */
 | 
			
		||||
recurconst(tp)
 | 
			
		||||
struct type *tp;
 | 
			
		||||
{
 | 
			
		||||
	register struct sdef *sdf;
 | 
			
		||||
 | 
			
		||||
	ASSERT(tp);
 | 
			
		||||
	if (!tp) return 0;
 | 
			
		||||
	if (tp->tp_typequal & TQ_CONST) return 1;
 | 
			
		||||
	sdf = tp->tp_sdef;
 | 
			
		||||
	while (sdf) {
 | 
			
		||||
		if (recurconst(sdf->sd_type))
 | 
			
		||||
			return 1;
 | 
			
		||||
		sdf = sdf->sd_sdef;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ch3asgn(expp, oper, expr)
 | 
			
		||||
	struct expr **expp;
 | 
			
		||||
	struct expr *expr;
 | 
			
		||||
{
 | 
			
		||||
	/*	The assignment operators.
 | 
			
		||||
		"f op= e" should be interpreted as
 | 
			
		||||
		"f = (typeof f)((typeof (f op e))f op (typeof (f op e))e)"
 | 
			
		||||
		and not as "f = f op (typeof f)e".
 | 
			
		||||
		Consider, for example, (i == 10) i *= 0.9; (i == 9), where
 | 
			
		||||
		typeof i == int.
 | 
			
		||||
		The resulting expression tree becomes:
 | 
			
		||||
				op=
 | 
			
		||||
				/ \
 | 
			
		||||
			       /   \
 | 
			
		||||
			      f     (typeof (f op e))e
 | 
			
		||||
		EVAL should however take care of evaluating (typeof (f op e))f
 | 
			
		||||
	*/
 | 
			
		||||
	register struct expr *exp = *expp;
 | 
			
		||||
	int fund = exp->ex_type->tp_fund;
 | 
			
		||||
	int vol = 0;
 | 
			
		||||
	struct type *tp;
 | 
			
		||||
 | 
			
		||||
	/* We expect an lvalue */
 | 
			
		||||
	if (!exp->ex_lvalue) {
 | 
			
		||||
		expr_error(exp, "no lvalue in operand of %s", symbol2str(oper));
 | 
			
		||||
	} else if (exp->ex_flags & EX_ILVALUE)	{
 | 
			
		||||
		strict("incorrect lvalue in operand of %s", symbol2str(oper));
 | 
			
		||||
	} else if (exp->ex_flags & EX_READONLY) {
 | 
			
		||||
		expr_error(exp, "operand of %s is read-only", symbol2str(oper));
 | 
			
		||||
	} else if (fund == STRUCT || fund == UNION) {
 | 
			
		||||
		if (recurconst(exp->ex_type))
 | 
			
		||||
			expr_error(expr,"operand of %s contains a const-qualified member",
 | 
			
		||||
					    symbol2str(oper));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*	Preserve volatile markers across the tree.
 | 
			
		||||
		This is questionable, depending on the way the optimizer
 | 
			
		||||
		wants this information.
 | 
			
		||||
	vol = (exp->ex_flags & EX_VOLATILE) || (expr->ex_flags & EX_VOLATILE);
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
	if (oper == '=') {
 | 
			
		||||
		ch3cast(&expr, oper, exp->ex_type);
 | 
			
		||||
		tp = expr->ex_type;
 | 
			
		||||
	}
 | 
			
		||||
	else {	/* turn e into e' where typeof(e') = typeof (f op e) */
 | 
			
		||||
		struct expr *extmp = intexpr((arith)0, INT);
 | 
			
		||||
 | 
			
		||||
		/* this is really $#@&*%$# ! */
 | 
			
		||||
		/* if you correct this, please correct lint_new_oper() too */
 | 
			
		||||
		extmp->ex_lvalue = 1;
 | 
			
		||||
		extmp->ex_type = exp->ex_type;
 | 
			
		||||
		ch3bin(&extmp, oper, expr);
 | 
			
		||||
		/* Note that ch3bin creates a tree of the expression
 | 
			
		||||
			((typeof (f op e))f op (typeof (f op e))e),
 | 
			
		||||
		   where f ~ extmp and e ~ expr.
 | 
			
		||||
		   We want to use (typeof (f op e))e.
 | 
			
		||||
		   Ch7bin does not create a tree if both operands
 | 
			
		||||
		   were illegal or constants!
 | 
			
		||||
		*/
 | 
			
		||||
		tp = extmp->ex_type;	/* perform the arithmetic in type tp */
 | 
			
		||||
		if (extmp->ex_class == Oper) {
 | 
			
		||||
			expr = extmp->OP_RIGHT;
 | 
			
		||||
			extmp->OP_RIGHT = NILEXPR;
 | 
			
		||||
			free_expression(extmp);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			expr = extmp;
 | 
			
		||||
	}
 | 
			
		||||
#ifndef NOBITFIELD
 | 
			
		||||
	if (fund == FIELD)
 | 
			
		||||
		exp = new_oper(exp->ex_type->tp_up, exp, oper, expr);
 | 
			
		||||
	else
 | 
			
		||||
		exp = new_oper(exp->ex_type, exp, oper, expr);
 | 
			
		||||
#else NOBITFIELD
 | 
			
		||||
	exp = new_oper(exp->ex_type, exp, oper, expr);
 | 
			
		||||
#endif NOBITFIELD
 | 
			
		||||
	exp->OP_TYPE = tp;	/* for EVAL() */
 | 
			
		||||
	exp->ex_flags |= vol ? (EX_SIDEEFFECTS|EX_VOLATILE) : EX_SIDEEFFECTS;
 | 
			
		||||
	*expp = exp;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*	Some interesting (?) questions answered.
 | 
			
		||||
*/
 | 
			
		||||
int
 | 
			
		||||
is_integral_type(tp)
 | 
			
		||||
	register struct type *tp;
 | 
			
		||||
{
 | 
			
		||||
	switch (tp->tp_fund)	{
 | 
			
		||||
	case GENERIC:
 | 
			
		||||
	case CHAR:
 | 
			
		||||
	case SHORT:
 | 
			
		||||
	case INT:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case ENUM:
 | 
			
		||||
		return 1;
 | 
			
		||||
#ifndef NOBITFIELD
 | 
			
		||||
	case FIELD:
 | 
			
		||||
		return is_integral_type(tp->tp_up);
 | 
			
		||||
#endif NOBITFIELD
 | 
			
		||||
	default:
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
is_arith_type(tp)
 | 
			
		||||
	register struct type *tp;
 | 
			
		||||
{
 | 
			
		||||
	switch (tp->tp_fund)	{
 | 
			
		||||
	case GENERIC:
 | 
			
		||||
	case CHAR:
 | 
			
		||||
	case SHORT:
 | 
			
		||||
	case INT:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case ENUM:
 | 
			
		||||
	case FLOAT:
 | 
			
		||||
	case DOUBLE:
 | 
			
		||||
	case LNGDBL:
 | 
			
		||||
		return 1;
 | 
			
		||||
#ifndef NOBITFIELD
 | 
			
		||||
	case FIELD:
 | 
			
		||||
		return is_arith_type(tp->tp_up);
 | 
			
		||||
#endif NOBITFIELD
 | 
			
		||||
	default:
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										352
									
								
								lang/cem/cemcom.ansi/ch3bin.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								lang/cem/cemcom.ansi/ch3bin.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,352 @@
 | 
			
		|||
/*
 | 
			
		||||
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
			
		||||
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
			
		||||
 */
 | 
			
		||||
/* $Header$ */
 | 
			
		||||
/* SEMANTIC ANALYSIS (CHAPTER 3.3)  --  BINARY OPERATORS */
 | 
			
		||||
 | 
			
		||||
#include	"botch_free.h"
 | 
			
		||||
#include	<alloc.h>
 | 
			
		||||
#include	"lint.h"
 | 
			
		||||
#include	"idf.h"
 | 
			
		||||
#include	<flt_arith.h>
 | 
			
		||||
#include	"arith.h"
 | 
			
		||||
#include	"type.h"
 | 
			
		||||
#include	"struct.h"
 | 
			
		||||
#include	"label.h"
 | 
			
		||||
#include	"expr.h"
 | 
			
		||||
#include	"Lpars.h"
 | 
			
		||||
 | 
			
		||||
extern char options[];
 | 
			
		||||
extern char *symbol2str();
 | 
			
		||||
 | 
			
		||||
/*	This chapter asks for the repeated application of code to handle
 | 
			
		||||
	an operation that may be executed at compile time or at run time,
 | 
			
		||||
	depending on the constancy of the operands.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#define commutative_binop(expp, oper, expr)	mk_binop(expp, oper, expr, 1)
 | 
			
		||||
#define non_commutative_binop(expp, oper, expr)	mk_binop(expp, oper, expr, 0)
 | 
			
		||||
 | 
			
		||||
ch3bin(expp, oper, expr)
 | 
			
		||||
	register struct expr **expp;
 | 
			
		||||
	struct expr *expr;
 | 
			
		||||
{
 | 
			
		||||
	/*	apply binary operator oper between *expp and expr.
 | 
			
		||||
		NB: don't swap operands if op is one of the op= operators!!!
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
	any2opnd(expp, oper);
 | 
			
		||||
	any2opnd(&expr, oper);
 | 
			
		||||
	switch (oper)	{
 | 
			
		||||
	case '[':				/* 3.3.2.1 */
 | 
			
		||||
		/* indexing follows the commutative laws */
 | 
			
		||||
		switch ((*expp)->ex_type->tp_fund)	{
 | 
			
		||||
		case POINTER:
 | 
			
		||||
		case ARRAY:
 | 
			
		||||
			break;
 | 
			
		||||
		case ERRONEOUS:
 | 
			
		||||
			return;
 | 
			
		||||
		default:		/* unindexable */
 | 
			
		||||
			switch (expr->ex_type->tp_fund)	{
 | 
			
		||||
			case POINTER:
 | 
			
		||||
			case ARRAY:
 | 
			
		||||
				break;
 | 
			
		||||
			case ERRONEOUS:
 | 
			
		||||
				return;
 | 
			
		||||
			default:
 | 
			
		||||
				expr_error(*expp,
 | 
			
		||||
					"indexing an object of type %s",
 | 
			
		||||
					symbol2str((*expp)->ex_type->tp_fund));
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		ch3bin(expp, '+', expr);
 | 
			
		||||
		ch3mon('*', expp);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case '(':				/* 3.3.2.2 */
 | 
			
		||||
		if (	(*expp)->ex_type->tp_fund == POINTER &&
 | 
			
		||||
			(*expp)->ex_type->tp_up->tp_fund == FUNCTION
 | 
			
		||||
		)	{
 | 
			
		||||
			ch3mon('*', expp);
 | 
			
		||||
		}
 | 
			
		||||
		if ((*expp)->ex_type->tp_fund != FUNCTION)	{
 | 
			
		||||
			expr_error(*expp, "call of non-function (%s)",
 | 
			
		||||
				symbol2str((*expp)->ex_type->tp_fund));
 | 
			
		||||
			/* leave the expression; it may still serve */
 | 
			
		||||
			free_expression(expr);	/* there go the parameters */
 | 
			
		||||
			*expp = new_oper(error_type,
 | 
			
		||||
					*expp, '(', (struct expr *)0);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			*expp = new_oper((*expp)->ex_type->tp_up,
 | 
			
		||||
					*expp, '(', expr);
 | 
			
		||||
		(*expp)->ex_flags |= EX_SIDEEFFECTS;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case PARCOMMA:				/* 3.3.2.2 */
 | 
			
		||||
		if ((*expp)->ex_type->tp_fund == FUNCTION)
 | 
			
		||||
			function2pointer(*expp);
 | 
			
		||||
		*expp = new_oper(expr->ex_type, *expp, PARCOMMA, expr);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case '%':
 | 
			
		||||
	case MODAB:
 | 
			
		||||
	case ANDAB:
 | 
			
		||||
	case XORAB:
 | 
			
		||||
	case ORAB:
 | 
			
		||||
		opnd2integral(expp, oper);
 | 
			
		||||
		opnd2integral(&expr, oper);
 | 
			
		||||
		/* fallthrough */
 | 
			
		||||
	case '/':
 | 
			
		||||
	case DIVAB:
 | 
			
		||||
	case TIMESAB:
 | 
			
		||||
		arithbalance(expp, oper, &expr);
 | 
			
		||||
		non_commutative_binop(expp, oper, expr);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case '&':
 | 
			
		||||
	case '^':
 | 
			
		||||
	case '|':
 | 
			
		||||
		opnd2integral(expp, oper);
 | 
			
		||||
		opnd2integral(&expr, oper);
 | 
			
		||||
		/* fallthrough */
 | 
			
		||||
	case '*':
 | 
			
		||||
		arithbalance(expp, oper, &expr);
 | 
			
		||||
		commutative_binop(expp, oper, expr);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case '+':
 | 
			
		||||
		if (expr->ex_type->tp_fund == POINTER)	{ /* swap operands */
 | 
			
		||||
			struct expr *etmp = expr;
 | 
			
		||||
			expr = *expp;
 | 
			
		||||
			*expp = etmp;
 | 
			
		||||
		}
 | 
			
		||||
		/* fallthrough */
 | 
			
		||||
	case PLUSAB:
 | 
			
		||||
	case POSTINCR:
 | 
			
		||||
	case PLUSPLUS:
 | 
			
		||||
		if ((*expp)->ex_type->tp_fund == POINTER)	{
 | 
			
		||||
			pointer_arithmetic(expp, oper, &expr);
 | 
			
		||||
			if (expr->ex_type->tp_size != (*expp)->ex_type->tp_size)
 | 
			
		||||
				ch3cast(&expr, CAST, (*expp)->ex_type);
 | 
			
		||||
			pointer_binary(expp, oper, expr);
 | 
			
		||||
		}
 | 
			
		||||
		else	{
 | 
			
		||||
			arithbalance(expp, oper, &expr);
 | 
			
		||||
			if (oper == '+')
 | 
			
		||||
				commutative_binop(expp, oper, expr);
 | 
			
		||||
			else
 | 
			
		||||
				non_commutative_binop(expp, oper, expr);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case '-':
 | 
			
		||||
	case MINAB:
 | 
			
		||||
	case POSTDECR:
 | 
			
		||||
	case MINMIN:
 | 
			
		||||
		if ((*expp)->ex_type->tp_fund == POINTER)	{
 | 
			
		||||
			if (expr->ex_type->tp_fund == POINTER)
 | 
			
		||||
				pntminuspnt(expp, oper, expr);
 | 
			
		||||
			else {
 | 
			
		||||
				pointer_arithmetic(expp, oper, &expr);
 | 
			
		||||
				pointer_binary(expp, oper, expr);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else	{
 | 
			
		||||
			arithbalance(expp, oper, &expr);
 | 
			
		||||
			non_commutative_binop(expp, oper, expr);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case LEFT:
 | 
			
		||||
	case RIGHT:
 | 
			
		||||
	case LEFTAB:
 | 
			
		||||
	case RIGHTAB:
 | 
			
		||||
		opnd2integral(expp, oper);
 | 
			
		||||
		opnd2integral(&expr, oper);
 | 
			
		||||
		arithbalance(expp, oper, &expr); /* ch. 7.5 */
 | 
			
		||||
		ch3cast(&expr, oper, int_type); /* cvt. rightop to int */
 | 
			
		||||
		non_commutative_binop(expp, oper, expr);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case '<':
 | 
			
		||||
	case '>':
 | 
			
		||||
	case LESSEQ:
 | 
			
		||||
	case GREATEREQ:
 | 
			
		||||
	case EQUAL:
 | 
			
		||||
	case NOTEQUAL:
 | 
			
		||||
		relbalance(expp, oper, &expr);
 | 
			
		||||
		non_commutative_binop(expp, oper, expr);
 | 
			
		||||
		(*expp)->ex_type = int_type;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case AND:
 | 
			
		||||
	case OR:
 | 
			
		||||
		opnd2test(expp, oper);
 | 
			
		||||
		opnd2test(&expr, oper);
 | 
			
		||||
		if (is_cp_cst(*expp))	{
 | 
			
		||||
			register struct expr *ex = *expp;
 | 
			
		||||
 | 
			
		||||
			/* the following condition is a short-hand for
 | 
			
		||||
				((oper == AND) && o1) || ((oper == OR) && !o1)
 | 
			
		||||
				where o1 == (*expp)->VL_VALUE;
 | 
			
		||||
				and ((oper == AND) || (oper == OR))
 | 
			
		||||
			*/
 | 
			
		||||
			if ((oper == AND) == (ex->VL_VALUE != (arith)0))
 | 
			
		||||
				*expp = expr;
 | 
			
		||||
			else {
 | 
			
		||||
				ex->ex_flags |= expr->ex_flags;
 | 
			
		||||
				free_expression(expr);
 | 
			
		||||
				*expp = intexpr((arith)((oper == AND) ? 0 : 1),
 | 
			
		||||
						INT);
 | 
			
		||||
			}
 | 
			
		||||
			(*expp)->ex_flags |= ex->ex_flags;
 | 
			
		||||
			free_expression(ex);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		if (is_cp_cst(expr))	{
 | 
			
		||||
			/* Note!!!: the following condition is a short-hand for
 | 
			
		||||
				((oper == AND) && o2) || ((oper == OR) && !o2)
 | 
			
		||||
				where o2 == expr->VL_VALUE
 | 
			
		||||
				and ((oper == AND) || (oper == OR))
 | 
			
		||||
			*/
 | 
			
		||||
			if ((oper == AND) == (expr->VL_VALUE != (arith)0)) {
 | 
			
		||||
				(*expp)->ex_flags |= expr->ex_flags;
 | 
			
		||||
				free_expression(expr);
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				if (oper == OR)
 | 
			
		||||
					expr->VL_VALUE = (arith)1;
 | 
			
		||||
				ch3bin(expp, ',', expr);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			*expp = new_oper(int_type, *expp, oper, expr);
 | 
			
		||||
		}
 | 
			
		||||
		(*expp)->ex_flags |= EX_LOGICAL;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case ':':
 | 
			
		||||
		if (	is_struct_or_union((*expp)->ex_type->tp_fund)
 | 
			
		||||
		||	is_struct_or_union(expr->ex_type->tp_fund)
 | 
			
		||||
		)	{
 | 
			
		||||
			if (!equal_type((*expp)->ex_type, expr->ex_type, 0))
 | 
			
		||||
				expr_error(*expp, "illegal balance");
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			relbalance(expp, oper, &expr);
 | 
			
		||||
#ifdef	LINT
 | 
			
		||||
		if (	(is_cp_cst(*expp) && is_cp_cst(expr))
 | 
			
		||||
		&&	(*expp)->VL_VALUE == expr->VL_VALUE
 | 
			
		||||
		) {
 | 
			
		||||
			hwarning("operands of : are constant and equal");
 | 
			
		||||
		}
 | 
			
		||||
#endif	LINT
 | 
			
		||||
		*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case '?':
 | 
			
		||||
		opnd2logical(expp, oper);
 | 
			
		||||
		if (is_cp_cst(*expp)) {
 | 
			
		||||
#ifdef	LINT
 | 
			
		||||
			hwarning("condition in ?: expression is constant");
 | 
			
		||||
#endif	LINT
 | 
			
		||||
			*expp = (*expp)->VL_VALUE ?
 | 
			
		||||
				expr->OP_LEFT : expr->OP_RIGHT;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			*expp = new_oper(expr->ex_type, *expp, oper, expr);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case ',':
 | 
			
		||||
		if (is_cp_cst(*expp))
 | 
			
		||||
			*expp = expr;
 | 
			
		||||
		else
 | 
			
		||||
			*expp = new_oper(expr->ex_type, *expp, oper, expr);
 | 
			
		||||
		(*expp)->ex_flags |= EX_COMMA;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pntminuspnt(expp, oper, expr)
 | 
			
		||||
	register struct expr **expp, *expr;
 | 
			
		||||
{
 | 
			
		||||
	/*	Subtracting two pointers is so complicated it merits a
 | 
			
		||||
		routine of its own.
 | 
			
		||||
	*/
 | 
			
		||||
	struct type *up_type = (*expp)->ex_type->tp_up;
 | 
			
		||||
 | 
			
		||||
	if (!equal_type(up_type, expr->ex_type->tp_up, 0)) {
 | 
			
		||||
		expr_error(*expp, "subtracting incompatible pointers");
 | 
			
		||||
		free_expression(expr);
 | 
			
		||||
		erroneous2int(expp);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	/*	we hope the optimizer will eliminate the load-time
 | 
			
		||||
		pointer subtraction
 | 
			
		||||
	*/
 | 
			
		||||
	*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
 | 
			
		||||
	ch3cast(expp, CAST, pa_type);	/* ptr-ptr: result has pa_type	*/
 | 
			
		||||
	ch3bin(expp, '/',
 | 
			
		||||
		intexpr(size_of_type(up_type, "object"), pa_type->tp_fund));
 | 
			
		||||
	ch3cast(expp, CAST, int_type);	/* result will be an integer expr */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
mk_binop(expp, oper, expr, commutative)
 | 
			
		||||
	struct expr **expp;
 | 
			
		||||
	register struct expr *expr;
 | 
			
		||||
{
 | 
			
		||||
	/*	Constructs in *expp the operation indicated by the operands.
 | 
			
		||||
		"commutative" indicates whether "oper" is a commutative
 | 
			
		||||
		operator.
 | 
			
		||||
	*/
 | 
			
		||||
	register struct expr *ex = *expp;
 | 
			
		||||
 | 
			
		||||
	if (is_cp_cst(expr) && is_cp_cst(ex))
 | 
			
		||||
		cstbin(expp, oper, expr);
 | 
			
		||||
	else if (is_fp_cst(expr) && is_fp_cst(ex))
 | 
			
		||||
		fltcstbin(expp, oper, expr);
 | 
			
		||||
	else	{
 | 
			
		||||
		*expp = (commutative && expr->ex_depth >= ex->ex_depth) ?
 | 
			
		||||
				new_oper(ex->ex_type, expr, oper, ex) :
 | 
			
		||||
				new_oper(ex->ex_type, ex, oper, expr);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pointer_arithmetic(expp1, oper, expp2)
 | 
			
		||||
	register struct expr **expp1, **expp2;
 | 
			
		||||
{
 | 
			
		||||
	int typ;
 | 
			
		||||
	/*	prepares the integral expression expp2 in order to
 | 
			
		||||
		apply it to the pointer expression expp1
 | 
			
		||||
	*/
 | 
			
		||||
	if ((typ = any2arith(expp2, oper)) == FLOAT
 | 
			
		||||
	    || typ == DOUBLE
 | 
			
		||||
	    || typ == LNGDBL)	{
 | 
			
		||||
		expr_error(*expp2,
 | 
			
		||||
			"illegal combination of %s and pointer",
 | 
			
		||||
			symbol2str(typ));
 | 
			
		||||
		erroneous2int(expp2);
 | 
			
		||||
	}
 | 
			
		||||
	ch3bin( expp2, '*',
 | 
			
		||||
		intexpr(size_of_type((*expp1)->ex_type->tp_up, "object"),
 | 
			
		||||
			pa_type->tp_fund)
 | 
			
		||||
	);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pointer_binary(expp, oper, expr)
 | 
			
		||||
	register struct expr **expp, *expr;
 | 
			
		||||
{
 | 
			
		||||
	/*	constructs the pointer arithmetic expression out of
 | 
			
		||||
		a pointer expression, a binary operator and an integral
 | 
			
		||||
		expression.
 | 
			
		||||
	*/
 | 
			
		||||
	if (is_ld_cst(expr) && is_ld_cst(*expp))
 | 
			
		||||
		cstbin(expp, oper, expr);
 | 
			
		||||
	else
 | 
			
		||||
		*expp = new_oper((*expp)->ex_type, *expp, oper, expr);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										168
									
								
								lang/cem/cemcom.ansi/ch3mon.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								lang/cem/cemcom.ansi/ch3mon.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,168 @@
 | 
			
		|||
/*
 | 
			
		||||
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
			
		||||
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
			
		||||
 */
 | 
			
		||||
/* $Header$ */
 | 
			
		||||
/* SEMANTIC ANALYSIS (CHAPTER 3.3) -- MONADIC OPERATORS */
 | 
			
		||||
 | 
			
		||||
#include	"botch_free.h"
 | 
			
		||||
#include	<alloc.h>
 | 
			
		||||
#include	"nobitfield.h"
 | 
			
		||||
#include	"Lpars.h"
 | 
			
		||||
#include	<flt_arith.h>
 | 
			
		||||
#include	"arith.h"
 | 
			
		||||
#include	"type.h"
 | 
			
		||||
#include	"label.h"
 | 
			
		||||
#include	"expr.h"
 | 
			
		||||
#include	"idf.h"
 | 
			
		||||
#include	"def.h"
 | 
			
		||||
 | 
			
		||||
extern char options[];
 | 
			
		||||
extern arith full_mask[/*MAXSIZE*/];	/* cstoper.c */
 | 
			
		||||
char *symbol2str();
 | 
			
		||||
 | 
			
		||||
ch3mon(oper, expp)
 | 
			
		||||
	register struct expr **expp;
 | 
			
		||||
{
 | 
			
		||||
	/*	The monadic prefix operator oper is applied to *expp.
 | 
			
		||||
	*/
 | 
			
		||||
	register struct expr *expr;
 | 
			
		||||
 | 
			
		||||
	switch (oper)	{
 | 
			
		||||
	case '*':			/* 3.3.3.2 */
 | 
			
		||||
		/* no FIELD type allowed	*/
 | 
			
		||||
		if ((*expp)->ex_type->tp_fund == ARRAY)
 | 
			
		||||
			array2pointer(*expp);
 | 
			
		||||
		if ((*expp)->ex_type->tp_fund != POINTER) {
 | 
			
		||||
		    if ((*expp)->ex_type->tp_fund != FUNCTION) {
 | 
			
		||||
			    expr_error(*expp,
 | 
			
		||||
				    "* applied to non-pointer (%s)",
 | 
			
		||||
				    symbol2str((*expp)->ex_type->tp_fund));
 | 
			
		||||
		    } else {
 | 
			
		||||
			    warning("superfluous use of * on function");
 | 
			
		||||
			    /* ignore indirection (yegh) */
 | 
			
		||||
		    }
 | 
			
		||||
		} else {
 | 
			
		||||
			expr = *expp;
 | 
			
		||||
			if (expr->ex_lvalue == 0 && expr->ex_class != String)
 | 
			
		||||
				/* dereference in administration only */
 | 
			
		||||
				expr->ex_type = expr->ex_type->tp_up;
 | 
			
		||||
			else	/* runtime code */
 | 
			
		||||
				*expp = new_oper(expr->ex_type->tp_up, NILEXPR,
 | 
			
		||||
							'*', expr);
 | 
			
		||||
			(*expp)->ex_lvalue = (
 | 
			
		||||
				(*expp)->ex_type->tp_fund != ARRAY &&
 | 
			
		||||
				(*expp)->ex_type->tp_fund != FUNCTION
 | 
			
		||||
				);
 | 
			
		||||
			if ((*expp)->ex_type->tp_typequal & TQ_CONST)
 | 
			
		||||
				(*expp)->ex_flags |= EX_READONLY;
 | 
			
		||||
			if ((*expp)->ex_type->tp_typequal & TQ_VOLATILE)
 | 
			
		||||
				(*expp)->ex_flags |= EX_VOLATILE;
 | 
			
		||||
			(*expp)->ex_flags &= ~EX_ILVALUE;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case '&':
 | 
			
		||||
		if ((*expp)->ex_type->tp_fund == ARRAY) {
 | 
			
		||||
			expr_warning(*expp, "& before array ignored");
 | 
			
		||||
			array2pointer(*expp);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		if ((*expp)->ex_type->tp_fund == FUNCTION) {
 | 
			
		||||
			expr_warning(*expp, "& before function ignored");
 | 
			
		||||
			function2pointer(*expp);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
#ifndef NOBITFIELD
 | 
			
		||||
		if ((*expp)->ex_type->tp_fund == FIELD)
 | 
			
		||||
			expr_error(*expp, "& applied to field variable");
 | 
			
		||||
		else
 | 
			
		||||
#endif NOBITFIELD
 | 
			
		||||
		if (!(*expp)->ex_lvalue)
 | 
			
		||||
			expr_error(*expp, "& applied to non-lvalue");
 | 
			
		||||
		else if ((*expp)->ex_flags & EX_ILVALUE)
 | 
			
		||||
			expr_error(*expp, "& applied to illegal lvalue");
 | 
			
		||||
		else {
 | 
			
		||||
			/* assume that enums are already filtered out	*/
 | 
			
		||||
			if (ISNAME(*expp)) {
 | 
			
		||||
				register struct def *def =
 | 
			
		||||
					(*expp)->VL_IDF->id_def;
 | 
			
		||||
 | 
			
		||||
				/*	&<var> indicates that <var>
 | 
			
		||||
					cannot be used as register
 | 
			
		||||
					anymore
 | 
			
		||||
				*/
 | 
			
		||||
				if (def->df_sc == REGISTER) {
 | 
			
		||||
					expr_error(*expp,
 | 
			
		||||
					"& on register variable not allowed");
 | 
			
		||||
					break;	/* break case '&' */
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			(*expp)->ex_type = pointer_to((*expp)->ex_type,
 | 
			
		||||
						(*expp)->ex_type->tp_typequal);
 | 
			
		||||
			(*expp)->ex_lvalue = 0;
 | 
			
		||||
			(*expp)->ex_flags &= ~EX_READONLY;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case '~':
 | 
			
		||||
	{
 | 
			
		||||
		int fund = (*expp)->ex_type->tp_fund;
 | 
			
		||||
 | 
			
		||||
		if (fund == FLOAT || fund == DOUBLE || fund == LNGDBL)	{
 | 
			
		||||
			expr_error( *expp,
 | 
			
		||||
				    "~ not allowed on %s operands",
 | 
			
		||||
				    symbol2str(fund));
 | 
			
		||||
			erroneous2int(expp);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		/* FALLTHROUGH */
 | 
			
		||||
	}
 | 
			
		||||
	case '-':
 | 
			
		||||
		any2arith(expp, oper);
 | 
			
		||||
		if (is_cp_cst(*expp))	{
 | 
			
		||||
			arith o1 = (*expp)->VL_VALUE;
 | 
			
		||||
 | 
			
		||||
			(*expp)->VL_VALUE = (oper == '-') ? -o1 :
 | 
			
		||||
			  ((*expp)->ex_type->tp_unsigned ?
 | 
			
		||||
				(~o1) & full_mask[(*expp)->ex_type->tp_size] :
 | 
			
		||||
				~o1
 | 
			
		||||
			  );
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		if (is_fp_cst(*expp))
 | 
			
		||||
			switch_sign_fp(*expp);
 | 
			
		||||
		else
 | 
			
		||||
			*expp = new_oper((*expp)->ex_type,
 | 
			
		||||
					NILEXPR, oper, *expp);
 | 
			
		||||
		break;
 | 
			
		||||
	case '!':
 | 
			
		||||
		if ((*expp)->ex_type->tp_fund == FUNCTION)
 | 
			
		||||
			function2pointer(*expp);
 | 
			
		||||
		if ((*expp)->ex_type->tp_fund != POINTER)
 | 
			
		||||
			any2arith(expp, oper);
 | 
			
		||||
		opnd2test(expp, '!');
 | 
			
		||||
		if (is_cp_cst(*expp))	{
 | 
			
		||||
			(*expp)->VL_VALUE = !((*expp)->VL_VALUE);
 | 
			
		||||
			(*expp)->ex_type = int_type;	/* a cast ???(EB) */
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			*expp = new_oper(int_type, NILEXPR, oper, *expp);
 | 
			
		||||
		(*expp)->ex_flags |= EX_LOGICAL;
 | 
			
		||||
		break;
 | 
			
		||||
	case PLUSPLUS:
 | 
			
		||||
	case MINMIN:
 | 
			
		||||
		ch3incr(expp, oper);
 | 
			
		||||
		break;
 | 
			
		||||
	case SIZEOF:
 | 
			
		||||
		if (ISNAME(*expp) && (*expp)->VL_IDF->id_def->df_formal_array)
 | 
			
		||||
			expr_warning(*expp, "sizeof formal array %s is sizeof pointer!",
 | 
			
		||||
				(*expp)->VL_IDF->id_text);
 | 
			
		||||
		expr = intexpr((*expp)->ex_class == String ?
 | 
			
		||||
				   (arith)((*expp)->SG_LEN) :
 | 
			
		||||
				   size_of_type((*expp)->ex_type, "object"),
 | 
			
		||||
				INT);
 | 
			
		||||
		expr->ex_flags |= EX_SIZEOF;
 | 
			
		||||
		free_expression(*expp);
 | 
			
		||||
		*expp = expr;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -337,7 +337,7 @@ do_return_expr(expr)
 | 
			
		|||
	/*	do_return_expr() generates the expression and the jump for
 | 
			
		||||
		a return statement with an expression.
 | 
			
		||||
	*/
 | 
			
		||||
	ch7cast(&expr, RETURN, func_type);
 | 
			
		||||
	ch3cast(&expr, RETURN, func_type);
 | 
			
		||||
	code_expr(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
 | 
			
		||||
	C_bra(return_label);
 | 
			
		||||
	return_expr_occurred = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -504,7 +504,7 @@ loc_init(expr, id)
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else	{	/* not embraced	*/
 | 
			
		||||
		ch7cast(&expr, '=', tp);	/* may modify expr */
 | 
			
		||||
		ch3cast(&expr, '=', tp);	/* may modify expr */
 | 
			
		||||
#ifndef	LINT
 | 
			
		||||
		{
 | 
			
		||||
			struct value vl;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -641,7 +641,14 @@ parameter_declarator(register struct declarator *dc;)
 | 
			
		|||
			parameter_type_list(&pl)
 | 
			
		||||
		|
 | 
			
		||||
			formal_list(&fm)
 | 
			
		||||
		]?
 | 
			
		||||
		|
 | 
			
		||||
			/* empty */
 | 
			
		||||
			{
 | 
			
		||||
				pl = new_proto();
 | 
			
		||||
				pl->pl_type = void_type;
 | 
			
		||||
				pl->pl_flag = PL_VOID;
 | 
			
		||||
			}
 | 
			
		||||
		]
 | 
			
		||||
		')'
 | 
			
		||||
		{   add_decl_unary(dc, FUNCTION, 0, (arith)0, fm, pl);
 | 
			
		||||
		    reject_params(dc);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -395,7 +395,7 @@ new_oper(tp, e1, oper, e2)
 | 
			
		|||
		expr->ex_depth =
 | 
			
		||||
			(e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) + 1;
 | 
			
		||||
		expr->ex_flags = (e1_flags | e2->ex_flags)
 | 
			
		||||
			& ~(EX_PARENS | EX_READONLY /* ??? | EX_VOLATILE */ );
 | 
			
		||||
			& ~(EX_PARENS | EX_READONLY | EX_VOLATILE );
 | 
			
		||||
	}
 | 
			
		||||
	op = &expr->ex_object.ex_oper;
 | 
			
		||||
	op->op_type = tp;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,13 +85,13 @@ postfix_expression(register struct expr **expp;)
 | 
			
		|||
	primary(expp)
 | 
			
		||||
	[
 | 
			
		||||
		'[' expression(&e1) ']'
 | 
			
		||||
			{ ch7bin(expp, '[', e1); e1 = 0; }
 | 
			
		||||
			{ ch3bin(expp, '[', e1); e1 = 0; }
 | 
			
		||||
	|
 | 
			
		||||
		'(' parameter_list(&e1)? ')'
 | 
			
		||||
			{ ch7bin(expp, '(', e1); call_proto(expp); e1 = 0; }
 | 
			
		||||
			{ ch3bin(expp, '(', e1); call_proto(expp); e1 = 0; }
 | 
			
		||||
	|
 | 
			
		||||
		[ '.' | ARROW ]			{ oper = DOT; }
 | 
			
		||||
		identifier(&idf)		{ ch7sel(expp, oper, idf); }
 | 
			
		||||
		identifier(&idf)		{ ch3sel(expp, oper, idf); }
 | 
			
		||||
	]*
 | 
			
		||||
	[
 | 
			
		||||
		[
 | 
			
		||||
| 
						 | 
				
			
			@ -99,7 +99,7 @@ postfix_expression(register struct expr **expp;)
 | 
			
		|||
		|
 | 
			
		||||
			MINMIN		{ oper = POSTDECR; }
 | 
			
		||||
		]
 | 
			
		||||
		    { ch7incr(expp, oper); }
 | 
			
		||||
		    { ch3incr(expp, oper); }
 | 
			
		||||
	]?
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -112,7 +112,7 @@ parameter_list(struct expr **expp;)
 | 
			
		|||
		','
 | 
			
		||||
		assignment_expression(&e1)
 | 
			
		||||
		{any2opnd(&e1, PARCOMMA);}
 | 
			
		||||
		{ch7bin(expp, PARCOMMA, e1);}
 | 
			
		||||
		{ch3bin(expp, PARCOMMA, e1);}
 | 
			
		||||
	]*
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -124,14 +124,14 @@ unary(register struct expr **expp;)
 | 
			
		|||
:
 | 
			
		||||
%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
 | 
			
		||||
	cast(&tp) unary(expp)
 | 
			
		||||
	{	ch7cast(expp, CAST, tp);
 | 
			
		||||
	{	ch3cast(expp, CAST, tp);
 | 
			
		||||
		(*expp)->ex_flags |= EX_CAST;
 | 
			
		||||
	}
 | 
			
		||||
|
 | 
			
		||||
	postfix_expression(expp)
 | 
			
		||||
|
 | 
			
		||||
	unop(&oper) unary(expp)
 | 
			
		||||
	{ch7mon(oper, expp);}
 | 
			
		||||
	{ch3mon(oper, expp);}
 | 
			
		||||
|
 | 
			
		||||
	size_of(expp)
 | 
			
		||||
;
 | 
			
		||||
| 
						 | 
				
			
			@ -152,7 +152,7 @@ size_of(register struct expr **expp;)
 | 
			
		|||
		}
 | 
			
		||||
	|
 | 
			
		||||
		unary(expp)
 | 
			
		||||
		{ch7mon(SIZEOF, expp);}
 | 
			
		||||
		{ch3mon(SIZEOF, expp);}
 | 
			
		||||
	]
 | 
			
		||||
	{ InSizeof--; }
 | 
			
		||||
;
 | 
			
		||||
| 
						 | 
				
			
			@ -216,7 +216,7 @@ binary_expression(int maxrank; struct expr **expp;)
 | 
			
		|||
		}
 | 
			
		||||
		binary_expression(rank_of(oper)-1, &e1)
 | 
			
		||||
		{
 | 
			
		||||
			ch7bin(expp, oper, e1);
 | 
			
		||||
			ch3bin(expp, oper, e1);
 | 
			
		||||
			ResultKnown = OldResultKnown;
 | 
			
		||||
		}
 | 
			
		||||
	]*
 | 
			
		||||
| 
						 | 
				
			
			@ -249,9 +249,9 @@ conditional_expression(struct expr **expp;)
 | 
			
		|||
		{	
 | 
			
		||||
			check_conditional(e2, '=', "not allowed after :");
 | 
			
		||||
			ResultKnown = OldResultKnown;
 | 
			
		||||
			ch7bin(&e1, ':', e2);
 | 
			
		||||
			ch3bin(&e1, ':', e2);
 | 
			
		||||
			opnd2test(expp, '?');
 | 
			
		||||
			ch7bin(expp, '?', e1);
 | 
			
		||||
			ch3bin(expp, '?', e1);
 | 
			
		||||
		}
 | 
			
		||||
	]?
 | 
			
		||||
;
 | 
			
		||||
| 
						 | 
				
			
			@ -266,7 +266,7 @@ assignment_expression(struct expr **expp;)
 | 
			
		|||
	[%prefer	/* (rank_of(DOT) <= maxrank) for any asgnop */
 | 
			
		||||
		asgnop(&oper)
 | 
			
		||||
		assignment_expression(&e1)
 | 
			
		||||
		{ch7asgn(expp, oper, e1);}
 | 
			
		||||
		{ch3asgn(expp, oper, e1);}
 | 
			
		||||
	|
 | 
			
		||||
		empty		/* LLgen artefact ??? */
 | 
			
		||||
	]
 | 
			
		||||
| 
						 | 
				
			
			@ -280,7 +280,7 @@ expression(struct expr **expp;)
 | 
			
		|||
	[	','
 | 
			
		||||
		assignment_expression(&e1)
 | 
			
		||||
		{
 | 
			
		||||
			ch7bin(expp, ',', e1);
 | 
			
		||||
			ch3bin(expp, ',', e1);
 | 
			
		||||
		}
 | 
			
		||||
	]*
 | 
			
		||||
;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -414,7 +414,7 @@ global_redecl(idf, new_sc, tp)
 | 
			
		|||
	register struct def *def = idf->id_def;
 | 
			
		||||
	int retval;
 | 
			
		||||
 | 
			
		||||
	if (!(retval = equal_type(tp, def->df_type)))
 | 
			
		||||
	if (!(retval = equal_type(tp, def->df_type, 0)))
 | 
			
		||||
		error("redeclaration of %s with different type", idf->id_text);
 | 
			
		||||
	else if (retval == 1)
 | 
			
		||||
		update_proto(tp, def->df_type);
 | 
			
		||||
| 
						 | 
				
			
			@ -609,7 +609,7 @@ check_formals(idf, dc)
 | 
			
		|||
		}
 | 
			
		||||
		while(fm && pl) {
 | 
			
		||||
		    if (!equal_type(promoted_type(fm->fm_idf->id_def->df_type)
 | 
			
		||||
					, pl->pl_type)) {
 | 
			
		||||
					, pl->pl_type, 0)) {
 | 
			
		||||
			if (!(pl->pl_flag & PL_ERRGIVEN))
 | 
			
		||||
			    error("incorrect type for parameter %s"
 | 
			
		||||
						, fm->fm_idf->id_text);
 | 
			
		||||
| 
						 | 
				
			
			@ -638,6 +638,7 @@ check_formals(idf, dc)
 | 
			
		|||
		}
 | 
			
		||||
		if (pl == 0) {		/* make func(void) */
 | 
			
		||||
			pl = new_proto();
 | 
			
		||||
			pl->pl_type = void_type;
 | 
			
		||||
			pl->pl_flag = PL_VOID;
 | 
			
		||||
		}
 | 
			
		||||
		idf->id_def->df_type->tp_pseudoproto = pl;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -447,7 +447,7 @@ check_ival(expp, tp)
 | 
			
		|||
	register struct type *tp;
 | 
			
		||||
	struct expr **expp;
 | 
			
		||||
{
 | 
			
		||||
	/*	The philosophy here is that ch7cast puts an explicit
 | 
			
		||||
	/*	The philosophy here is that ch3cast puts an explicit
 | 
			
		||||
		conversion node in front of the expression if the types
 | 
			
		||||
		are not compatible.  In this case, the initialisation
 | 
			
		||||
		expression is no longer a constant.
 | 
			
		||||
| 
						 | 
				
			
			@ -461,7 +461,7 @@ check_ival(expp, tp)
 | 
			
		|||
	case LONG:
 | 
			
		||||
	case ENUM:
 | 
			
		||||
	case POINTER:
 | 
			
		||||
		ch7cast(expp, '=', tp);
 | 
			
		||||
		ch3cast(expp, '=', tp);
 | 
			
		||||
		expr = *expp;
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
		print_expr("init-expr after cast", expr);
 | 
			
		||||
| 
						 | 
				
			
			@ -491,7 +491,7 @@ check_ival(expp, tp)
 | 
			
		|||
	case FLOAT:
 | 
			
		||||
	case DOUBLE:
 | 
			
		||||
	case LNGDBL:
 | 
			
		||||
		ch7cast(expp, '=', tp);
 | 
			
		||||
		ch3cast(expp, '=', tp);
 | 
			
		||||
		expr = *expp;
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
		print_expr("init-expr after cast", expr);
 | 
			
		||||
| 
						 | 
				
			
			@ -527,7 +527,7 @@ and also to prevent runtime coercions for compile-time constants.
 | 
			
		|||
 | 
			
		||||
#ifndef NOBITFIELD
 | 
			
		||||
	case FIELD:
 | 
			
		||||
		ch7cast(expp, '=', tp->tp_up);
 | 
			
		||||
		ch3cast(expp, '=', tp->tp_up);
 | 
			
		||||
		expr = *expp;
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
		print_expr("init-expr after cast", expr);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,14 +52,14 @@ lint_new_oper(expr)
 | 
			
		|||
		right == 0 ? 0 :		/* for ( without parameters */
 | 
			
		||||
		right->ex_type->tp_fund;
 | 
			
		||||
 | 
			
		||||
	/*	In ch7.c, in ch7asgn(), a combined operator/assignment
 | 
			
		||||
	/*	In ch3.c, in ch3asgn(), a combined operator/assignment
 | 
			
		||||
		is hammered into correctness by repeated application of
 | 
			
		||||
		ch7bin(), which calls new_oper(), which calls lint_new_oper().
 | 
			
		||||
		ch3bin(), which calls new_oper(), which calls lint_new_oper().
 | 
			
		||||
		These spurious calls understandably cause spurious error
 | 
			
		||||
		messages, which we don't like.  So we try to suppress these
 | 
			
		||||
		wierd calls here.  This refers to the code marked
 | 
			
		||||
			this is really $#@&*%$# !
 | 
			
		||||
		in ch7asgn().
 | 
			
		||||
		in ch3asgn().
 | 
			
		||||
	*/
 | 
			
		||||
	switch (oper) {
 | 
			
		||||
	case PLUSAB:
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +103,7 @@ lint_new_oper(expr)
 | 
			
		|||
		else {
 | 
			
		||||
			/* binary */
 | 
			
		||||
			if (l_fund == ENUM && r_fund == ENUM) {
 | 
			
		||||
				if (!equal_type(left->ex_type, right->ex_type))
 | 
			
		||||
				if (!equal_type(left->ex_type, right->ex_type, 0))
 | 
			
		||||
					warning("subtracting enums of different type");
 | 
			
		||||
				/* update the type, cem does not do it */
 | 
			
		||||
				expr->ex_type = int_type;
 | 
			
		||||
| 
						 | 
				
			
			@ -164,7 +164,7 @@ lint_new_oper(expr)
 | 
			
		|||
	case EQUAL:
 | 
			
		||||
	case NOTEQUAL:
 | 
			
		||||
		if (	(l_fund == ENUM || r_fund == ENUM)
 | 
			
		||||
		&&	!equal_type(left->ex_type, right->ex_type)
 | 
			
		||||
		&&	!equal_type(left->ex_type, right->ex_type, 0)
 | 
			
		||||
		) {
 | 
			
		||||
			warning("comparing enum with non-enum");
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -482,7 +482,7 @@ call_proto(expp)
 | 
			
		|||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			else if (!(pstack[pcnt]->pl_flag & PL_ELLIPSIS)) {
 | 
			
		||||
				ch7cast(estack[ecnt],CASTAB,pstack[pcnt]->pl_type);
 | 
			
		||||
				ch3cast(estack[ecnt],CASTAB,pstack[pcnt]->pl_type);
 | 
			
		||||
				pcnt--;
 | 
			
		||||
			} else
 | 
			
		||||
				any2parameter(estack[ecnt]);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -252,22 +252,23 @@ idf2sdef(idf, tp)
 | 
			
		|||
	register struct idf *idf;
 | 
			
		||||
	struct type *tp;
 | 
			
		||||
{
 | 
			
		||||
	/*	The identifier idf is identified as a selector, preferably
 | 
			
		||||
		in the struct tp, but we will settle for any unique
 | 
			
		||||
		identification.
 | 
			
		||||
		If the attempt fails, a selector of type error_type is
 | 
			
		||||
	/*	The identifier idf is identified as a selector
 | 
			
		||||
		in the struct tp.
 | 
			
		||||
		If there is no such member, give a member with the same
 | 
			
		||||
		name.
 | 
			
		||||
		If this fails too, a selector of type error_type is
 | 
			
		||||
		created.
 | 
			
		||||
	*/
 | 
			
		||||
	register struct sdef **sdefp = &idf->id_sdef, *sdef;
 | 
			
		||||
	
 | 
			
		||||
	/* Follow chain from idf, to meet tp. */
 | 
			
		||||
	while ((sdef = *sdefp))	{
 | 
			
		||||
		if (equal_type(sdef->sd_stype, tp))
 | 
			
		||||
		if (equal_type(sdef->sd_stype, tp, 0))
 | 
			
		||||
			return sdef;
 | 
			
		||||
		sdefp = &(*sdefp)->next;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/* Tp not met; any unique identification will do. */
 | 
			
		||||
	/* Tp not met; take an identification. */
 | 
			
		||||
	if (sdef = idf->id_sdef)	{
 | 
			
		||||
		/* There is an identification */
 | 
			
		||||
		error("illegal use of selector %s", idf->id_text);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -156,7 +156,7 @@ code_case(expr)
 | 
			
		|||
	}
 | 
			
		||||
	if (expr->ex_flags & EX_ERROR) /* is probably 0 anyway */
 | 
			
		||||
		return;
 | 
			
		||||
	ch7cast(&expr, CASE, sh->sh_type);
 | 
			
		||||
	ch3cast(&expr, CASE, sh->sh_type);
 | 
			
		||||
	ce = new_case_entry();
 | 
			
		||||
	C_df_ilb(ce->ce_label = text_label());
 | 
			
		||||
	ce->ce_value = val = expr->VL_VALUE;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue