Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/old/kcc/cctype.c
There are 8 other files named cctype.c in the archive. Click here to see a list.
/* <KCC.CC>CCTYPE.C.38, 30-Jun-85 14:52:06, Edit by KRONJ */
/*  Set type of LNOT, backwards int+ptr addition */
/* <KCC.CC>CCTYPE.C.34, 19-Jun-85 13:34:16, Edit by KRONJ */
/*  Fix old typo causing spurious DF_INT coercions with new type nos */
/* <KCC.CC>CCTYPE.C.33, 20-May-85 17:21:45, Edit by KRONJ */
/*  Fix typechecking of comparisons */
/* <KCC.CC>CCTYPE.C.23, 13-Mar-85 12:38:22, Edit by KRONJ */
/*  Coerce float function args to double */
/* <KCC.CC>CCTYPE.C.18, 12-Mar-85 14:43:32, Edit by KRONJ */
/*  Typecheck return values */
/* <KCC.CC>CCTYPE.C.16, 12-Mar-85 08:25:06, Edit by KRONJ */
/*  Check for implicit (char *) / (int *) coercions */
/* <KCC.CC>CCTYPE.C.11,  2-Jan-85 14:04:00, Edit by KRONJ */
/*  divide down struct pointer subtraction */
/* <KCC.CC>CCTYPE.C.9, 29-Dec-84 18:20:03, Edit by KRONJ */
/*  Fix for multiple-diml char array indexing */
/* SCORE:<KCC.CC>CCTYPE.C.8, 17-Aug-84 12:44:51, Edit by KRONJ */
/*  Type of multiplied array index is still integer */
/* SCORE:<KCC.CC>CCTYPE.C.6, 13-Jul-84 18:07:38, Edit by KRONJ */
/*  This time for sure!  ptr - ptr was returning type ptr not int, fix. */
/* SCORE:<KCC.CC>CCTYPE.C.2, 13-Jul-84 15:20:43, Edit by KRONJ */
/*  Fix up data type of pointer-int arithmetic */
/* SCORE:<KCC.CC>CC53.C.2, 12-May-84 15:57:58, Edit by KRONJ */
/*  Make type checking work correctly for functions */

/* cc53.c -- Type checking and automatic coercions. */
/*		(C) 1981   K. Chen		    */

#include "cc.h"

extern node defnode();

void pcoerce();
node checktype(), checkfloat(), rightcoerce(), leftcoerce();

node typecheck(n)
struct NODE *n;
{
    int    compare;
    struct TY   *t;
    struct NODE *l;

    switch (n->nop) {
    case RETURN:
	return checkfloat (n, 2);	/* check return value */

    case QUERY:
	n->right = checkfloat(n->right, -1); /* make both halves match */
	n->ntype = n->right->left->ntype; /* type is that of true case */
	return n;

    case ASGN:
	return checkfloat(n,1);

    case LEQ:
    case GEQ:
    case LESS:
    case GREAT:
	t = n->ntype;
	if ((t->ttype == PTR || t->ttype == ARRAY) && t->tptr->ttype == CHAR)
	    pcoerce (n);
	/* fall through */
    case NEQ:
    case EQUAL:
	n = checkfloat (n, 0);		/* coerce floats around */
	n->ntype = deftype;		/* result of boolean is int */
	return n;

    case FNCALL:
	t = n->left->ntype;
	if (t->ttype == PTR && t->tptr->ttype == FUNCTION) {
	    t = t->tptr;		/* call to (*)(), dereference both */
	    n->left = defnode (N2, PTR, t, 0, n->left);	/* ..type and node */
	}
	if (t->ttype != FUNCTION) error(EFNCALL);
	else n->ntype = t->tptr;
	l = n->right;
	if (l->nop == EXPRESS) while (l != NULL) {
	    switch (l->right->ntype->ttype) {
	    case VOID:
		error (EVOID, "function argument");
		break;
	    case FLOAT:
		l->right = defnode (N3,COERCE,dbltype,0,l->right,FL_DF);
	    }
	    l = l->left;
	} else switch (l->ntype->ttype) {
	case VOID:
	    error (EVOID, "function argument");
	    break;
	case FLOAT:
	    n->right = defnode (N3, COERCE, dbltype, 0, l, FL_DF);
	}
	return n;

    case NOT:
	if (tsize (n->left->ntype) != 1) error (EINT, "logical not operand");
	n->ntype = deftype;		/* result is int */
	return n;

    case COMPL:
	if (!integral (n->ntype)) error (EINT, "bitwise complement operand");
	n->ntype = deftype;
	return n;

    case LAND:
    case LOR:
	if (tsize (n->left->ntype) != 1 || tsize (n->right->ntype) != 1)
	    error (EINT, "boolean operand");
	n->ntype = deftype;		/* result is int */
	return n;			/* always succeed */
    }

    switch (n->left->ntype->ttype) {
    case PTR:
    case ARRAY:
    case STRUCT:
	return checktype(n, 0);
    default:
	return checktype(n, 1);
    }
}
static node
checktype (n, lr)
node n;
{
    struct TY *ltype, *rtype;
    node c;
    int lscalar, rscalar, ptrptr, size;
  
    if (lr == 0) {
	ltype = n->left->ntype;
	rtype = n->right->ntype;
    } else {
	rtype = n->left->ntype;
	ltype = n->right->ntype;
    }

    lscalar = ltype->ttype;
    rscalar = rtype->ttype;

    /* first order checking of pointer/array/struct arithmetic */

    ptrptr = 0;
    switch (lscalar) {
    case PTR:
    case ARRAY:
    case STRUCT:
	switch (rscalar) {
	case FLOAT:
	case DOUBLE:
	    error(EPARITH);
	    return n;
	case ARRAY:
	case PTR:
	case STRUCT:
	    ptrptr = 1;
	}
	break;

    default:
	switch(n->nop) {
	case ASPLUS:
	case ASMINUS:
	case ASMPLY:
	case ASDIV:
	    checkfloat(n,1);
	    break;
	default:
	    checkfloat(n,0);
	}
	return n;
    }

    /* pointer/array/struct arithmetic */
    switch (n->nop) {
    case ASPLUS:
    case ASMINUS:
    case PLUS:
	if (ptrptr) {
	    error(EPARITH);	/* pointer-pointer adds not allowed */
	    return n;
	}
	/* fall through */
    case MINUS:
	/* fix up pointer-int arith to multiply int to ptr size */
	n = checkfloat (n, 0);		/* make sure ok */
	if (ptrptr) {
	    n->ntype = deftype;
	    size = tsize (ltype->tptr);	/* get size of obj in words */
	    if (size != tsize (rtype->tptr)) error(EPARITH); /* must be same */
	    if (size > 1) {		/* need to divide down? */
		c = defnode(N3, MINUS, n->ntype, n->nflag, n->left, n->right);
		n->nop = DIV;		/* copy node, replace with division */
		n->left = c;		/* use copy as dividend */
		n->right = defnode(N2, ICONST, deftype, 0, NULL);
		n->right->niconst = size; /* divisor is size of struct */
	    }
	} else {
	    n->ntype = ltype;
	    size = tsize (ltype->tptr);	/* get size of obj in words */
	    if (charpointer(ltype) && ltype->tptr->ttype != CHAR)
		size *= NBYTES;		/* make size in bytes if char ptr */
	    if (size > 1) {
		c = defnode(N2, ICONST, deftype, 0, NULL);
		c->niconst = size;
		c = defnode(N3, MPLY, deftype, 0, NULL, c);
		if (lr == 0) {
		    c->left = n->right;
		    n->right = c;
		}
		else {
		    c->left = n->left;
		    n->left = c;
		}
	    }
	}
	break;

    default:
	error(EPARITH);
    }
    return n;
}
/* ----------------------------------------------------- */
/*	coerce char pointers to be an ordered index      */
/* ----------------------------------------------------- */

static void
pcoerce (n)
node n;
{
    struct TY *ty;
    int tt;

    ty = n->left->ntype;
    if (charpointer(ty)) {
	tt = ty->ttype;
	if (tt == PTR || tt == ARRAY) leftcoerce(n,PC_PC);
    }

    ty = n->right->ntype;
    if (charpointer(ty)) {
	tt = ty->ttype;
	if (tt == PTR || tt == ARRAY) rightcoerce(n,PC_PC);
    }
}
/*
** Perform automatic coercions, possibly with warnings
**
** mem =
**   -1  for (?:)
**    0  for binary operations
**    1  for stores
**    2  for return values
*/

static node
checkfloat (n,mem)
node n;
{
    struct TY *t;
    if (mem == 2) t = curfn->sptr->tptr; /* return statement */
    else t = n->left->ntype;		/* normal assignment or binop */

    switch(t->ttype) {
    case VOID:				/* void function can't have retval */
	error (ERETVOID);
	return n;

    case STRUCT:
    case UNION:
	if (mem <= 0) error (EPARITH);
	else switch (n->right->ntype->ttype) {
	case PTR:
	case ARRAY:
	    switch (n->right->ntype->tptr->ttype) {
	    case STRUCT:
	    case UNION:
		warn (EIMPCOER, "struct pointer to struct");
		n->right = defnode(N2,PTR,n->right->ntype->tptr,0,n->right);
		break;
	    default:
		error (ECOER);
		return n;
	    }
	case STRUCT:
	case UNION:
	    if (t == n->right->ntype) break;
	    else if (tsize (t) == tsize (n->right->ntype)) {
		warn (EIMPCOER, "struct to struct");
		break;
	    }
	default:
	    error(ECOER);
	}
	return n;

    case FUNCTION:
	error (EFNARITH);		/* can't do anything but call fn */
	return n;

    case ARRAY:
    case PTR:
	switch (n->right->ntype->ttype) {
	case FLOAT:
	case DOUBLE:
	    error (EPARITH);

	case FUNCTION:
	    error (EFNARITH);
	    break;

	case STRUCT:
	case UNION:
	    warn (EIMPCOER, "struct to struct pointer");
	    if (!(n->right->nflag & LVALUE))
		error (ELVALUE, "struct assumed to be used as pointer");
	    if (!(n->right->nflag & GLOBAL)) stackrefs++;
	    n->right = defnode (N2, ADDR,
				findtype (PTR, PTRSIZE, n->right->ntype),
				LVALUE, n->right);
	case ARRAY:
	case PTR:
	    switch (charpointer (t) - charpointer (n->right->ntype)) {
	    case -1:			/* left (int *), right (char *) */
		if (mem > 0) {
		    warn (EIMPCOER, "char pointer to word pointer");
		    return rightcoerce (n, PC_PI);
		} else {
		    warn (EIMPCOER, "word pointer to char pointer");
		    return leftcoerce (n, PI_PC);
		}
	    case 1:			/* left (char *), right (int *) */
		warn (EIMPCOER, "word pointer to char pointer");
		return rightcoerce (n, PI_PC);
	    case 0:
		if (t->tptr != n->right->ntype->tptr) /* careful w/PTR tsize */
		    warn (EIMPCOER, "pointer to pointer");
	    }
	    break;
	default:			/* integer types */
	    if (mem == 0) break;	/* pointer/pointer arith */
	    if (n->right->nop != ICONST || n->right->niconst != 0) {
		if (charpointer (t)) warn (EIMPCOER, "int to char pointer");
		else warn (EIMPCOER, "int to word pointer");
	    }
	    n->right->ntype = t;
	}
	return n;

    case FLOAT:
	switch(n->right->ntype->ttype) {
	case FUNCTION:
	    error (EFNARITH);
	    return n;

	case ARRAY:
	case PTR:
	case STRUCT:
	case UNION:
	    error(EPARITH);
	    return n;

	case FLOAT:
	    return n;

	case DOUBLE:
	    if (mem > 0) return rightcoerce(n,DF_FL);
	    else return leftcoerce(n,FL_DF);

	default:			/* int, short, unsigned, char */
	    return rightcoerce(n,INT_FL);
	}

    case DOUBLE:
	switch(n->right->ntype->ttype) {
	case FUNCTION:
	    error (EFNARITH);
	    return n;

	case ARRAY:
	case PTR:
	case STRUCT:
	case UNION:
	    error(EPARITH);
	    return n;

	case FLOAT:
	    return rightcoerce(n,FL_DF);

	case DOUBLE:
	    return n;

	default:			/* int, short, unsigned, char */
	    return rightcoerce(n,INT_DF);
	}

    default:				/* int, short, unsigned, char */
	switch(n->right->ntype->ttype) {
	case FLOAT:
	    if (mem > 0) return rightcoerce(n,FL_INT);
	    else return leftcoerce(n,INT_FL);

	case DOUBLE:
	    if (mem > 0) return rightcoerce(n,DF_INT);
	    else return leftcoerce(n,INT_DF);

	case STRUCT:
	case UNION:
	    error (ECOER);
	    return n;

	case FUNCTION:
	    error (EFNARITH);
	    return n;

	case ARRAY:
	case PTR:
	    switch (mem) {
	    case 0:
		break;
	    case -1:
		if (n->left->nop != ICONST || n->left->niconst != 0) {
		    if (charpointer (n->right->ntype))
			warn (EIMPCOER, "int to char pointer");
		    else warn (EIMPCOER, "int to word pointer");
		}
		n->left->ntype = n->right->ntype;
		break;
	    case 1:
	    case 2:
		if (charpointer (n->right->ntype))
		    warn (EIMPCOER, "char pointer to int");
		else warn (EIMPCOER, "word pointer to int");
		n->right->ntype = deftype;
	    }
	}
    }
    return n;
}
/* ------------------------------------------- */
/*      install coercion on right operand      */
/* ------------------------------------------- */

static node
rightcoerce (n,coercion)
node n;
{
    n->right =
      defnode(N3,COERCE,n->left->ntype,n->right->nflag,n->right,coercion);
    if (n->nop == RETURN) n->right->ntype = curfn->sptr->tptr;
    else n->ntype = n->left->ntype;
    return n;
}
/* ------------------------------------------ */
/*      install coercion on left operand      */
/* ------------------------------------------ */

static node
leftcoerce (n,coercion)
node n;
{
    n->left =
      defnode(N3,COERCE,n->right->ntype,n->left->nflag,n->left,coercion);
    n->ntype = n->right->ntype;
    return n;
}