📄 cctype.c
字号:
PTRREP_WD, /* (double *) */
PTRREP_WD, /* (long double *) */
PTRREP_CH, /* (bitfield *) */
PTRREP_CH, /* (char *) */
PTRREP_WD, /* (short *) */
PTRREP_WD, /* (int *) */
PTRREP_WD, /* (long *) */
PTRREP_CH, /* (unsigned bitfield *) */
PTRREP_CH, /* (unsigned char *) */
PTRREP_WD, /* (unsigned short *) */
PTRREP_WD, /* (unsigned int *) */
PTRREP_WD, /* (unsigned long *) */
};
/* Pointer conversion table, [to][from] */
static pconvtab[PTRREP_MAX][PTRREP_MAX] = {
/* To word ptr */
CAST_NONE, /* From word ptr */
CAST_PC_PI, /* From char ptr */
/* To char ptr */
CAST_PI_PC, /* From word ptr */
CAST_NONE, /* From char ptr */
};
#endif
/* CAST_OP Find CAST_ conversion type to use. [H&S 6.2 - 6.9 incl]
** This is the only routine that references the conversion table.
** The returned operation is based purely on the top type of
** each type, ignoring qualifiers. Minimal checking is done.
*/
static int
cast_op(to, frm)
TYPE *to, *frm;
{
int cop;
switch (cop = convtab[castidx(frm->Tspec,to->Tspec)]) {
case CAST_TRIV: /* Verify that types are identical */
if (to == frm /* This should have been caught before call */
|| cmputype(to, frm)) /* Ignore type-qualifiers */
return CAST_NONE;
cop = CAST_ILL; /* Otherwise drop through to complain */
case CAST_ILL:
error("Illegal conversion - %s to %s",
tsnames[frm->Tspec], tsnames[to->Tspec]);
break;
case CAST_VOID: /* Discard -- converting to void */
case CAST_NONE: /* No actual conversion operation needed */
break;
/* These two conversions should have been caught before this.
*/
case CAST_AR_PA: /* Array to T should be ptr to T */
case CAST_FN_PF: /* Function should be ptr to function */
int_error("cast_op: bad cast - %s to %s",
tsnames[frm->Tspec], tsnames[to->Tspec]);
cop = CAST_ILL;
break;
case CAST_PT_PT: /* OK as is. Someday convert into more */
break; /* specific type of conversion? */
/* Integer to integer conversion.
** May be able to detect that no actual conversion is needed.
** This code assumes that signed and unsigned types occupy the
** same amount of space, and that there is no representation
** change when converting between the two! This will be true
** for just about all computers.
*/
case CAST_IT_IT:
if ((tbitsize(frm) == tbitsize(to)) /* If same size */
/* && tisunsigned(frm) == tisunsigned(to) *//* & signedness? */
)
return CAST_NONE;
break;
default:
; /* do nothing */
}
return cop;
}
/* CONVCAST - Apply "cast conversions" to an expression. [H&S 6.10]
** This is called for explicit casts by the user, and by
** some implicit conversions elsewhere in CCTYPE.
** Any type qualifiers are removed from the target type.
**
** For easier debugging, this almost always forces a cast to the indicated
** type, even if it may not be necessary. Optimization can clean up
** such no-ops farther on.
*/
NODE *
convcast(t,n)
NODE *n;
TYPE *t;
{
int op;
if (n->Ntype->Tspec == TS_FUNCT || n->Ntype->Tspec == TS_ARRAY)
n = convarrfn(n); /* Pre-convert funct/arrays here */
if (t == n->Ntype) /* May now be a trivial cast */
return n;
if (tisqualif(t))
t = findutype(t); /* Use unqualified type as target */
op = cast_op(t, n->Ntype); /* find out which cast to use */
if (op == CAST_PT_PT && clevkcc /* Special hack for KCC extension */
&& n->Nop == N_SCONST /* If casting string literal */
&& tischar(t->Tsubt)) { /* to another kind of char ptr */
n->Ntype = t; /* then just change type of const! */
return n; /* And code gen will win. */
}
return ndefcast(op, t, n); /* Make cast using that cast op */
}
/* CONVASGN - Apply "assignment conversions" to an expression. [H&S 6.11]
** [dpANS 3.3.16.1]
** Takes two args, a pointer to the type of the left-hand op
** (destination type) and a node pointer to the right-hand expression
** which needs to have its type checked and perhaps fixed up.
*/
NODE *
convasgn(lt,n)
TYPE *lt; /* Left (destination) type */
NODE *n;
{
TYPE *rt; /* Right (source) type */
NODE *cn; /* New cast node if any */
/* If same type, OK */
if (lt == n->Ntype) return n;
rt = n->Ntype;
/* Not same type. Check to see if it's OK to silently convert the
** right-hand type to left-hand type. If so, call convcast() to do it.
*/
if (tisarith(lt) && tisarith(rt)) /* Any arith type to any arith type */
return convcast(lt, n); /* OK, do the specified conversion */
switch (lt->Tspec) {
case TS_PTR:
if (nisnull(&n)) /* Integer 0 to any ptr type */
return convcast(lt, n); /* OK, do the specified conversion */
rt = n->Ntype; /* n may have changed */
if (rt->Tspec != TS_PTR) /* Ensure all ptr-to-ptr after here */
break;
/* Ensure left subtype has all qualifiers that right subtype does */
if (((~lt->Tsubt->Tflag) & rt->Tsubt->Tflag)&TF_QUALS)
break; /* R has qual that L doesnt */
if (cmputype(lt->Tsubt, rt->Tsubt)
|| (lt->Tsubt->Tspec == TS_VOID && rt->Tsubt->Tspec != TS_FUNCT)
|| (rt->Tsubt->Tspec == TS_VOID && lt->Tsubt->Tspec != TS_FUNCT) )
return convcast(lt, n); /* OK, do the specified conversion */
break;
case TS_STRUCT:
case TS_UNION:
if (lt->Tspec == rt->Tspec /* Ignore qualifiers, check tag */
&& lt->Tsmtag == rt->Tsmtag)
return convcast(lt, n); /* OK, do the specified conversion */
break;
default:
; /* do nothing */
}
/* Last-resort attempt */
if (rt->Tspec == TS_FUNCT || rt->Tspec == TS_ARRAY)
return convasgn(lt, convarrfn(n));
/* Technically nothing else is OK. But we try to do it anyway
** and print a warning message. If the attempted conversion is illegal
** then cast_op will complain.
*/
cn = convcast(lt, n); /* Attempt to force the cast */
if (cn != n && cn->Nop == N_CAST /* If cast was done, print warning */
&& cn->Ncast != CAST_ILL) /* unless cast_op already barfed. */
if (clevel >= CLEV_STRICT)
error("Illegal conversion - %s to %s",
tsnames[rt->Tspec], tsnames[lt->Tspec]);
else
warn("Implicit conversion - %s to %s",
tsnames[rt->Tspec], tsnames[lt->Tspec]);
return cn;
}
/* CONVARRFN - Apply array/function conversions to an expression node.
** Returns pointer to a converted expression (usually the same node)
*/
NODE *
convarrfn(n)
NODE *n;
{
switch (n->Ntype->Tspec) {
default: break; /* Not array or function */
case TS_ARRAY: /* Convert "array of T" to "pointer to T" */
if (!(n->Nflag & NF_LVALUE)) { /* Can only convert lvalues */
error("Array ref must be lvalue");
} /* Do it anyway after complaint */
if (!(n->Nflag & NF_GLOBAL)) { /* If obj has local extent */
stackrefs++; /* then count it as a */
n->Nflag |= NF_STKREF; /* stack reference */
}
/* For array name, or array subscripting, just set the type.
** Anything else requires using & to get the address.
** That can only be N_PTR, Q_DOT, or Q_MEMBER.
*/
if (n->Nop == Q_IDENT || n->Nop == Q_PLUS) {
n->Ntype = findtype(TS_PTR, n->Ntype->Tsubt);
n->Nflag &= ~NF_LVALUE; /* Ensure not an lvalue */
} else
return ndef(N_ADDR, findtype(TS_PTR, n->Ntype->Tsubt),
n->Nflag & ~NF_LVALUE,
n, (NODE *)NULL);
break;
case TS_FUNCT: /* Convert "function of T" to "pointer to fun of T" */
if (n->Nop == Q_IDENT) /* For function name, just set type */
n->Ntype = findtype(TS_PTR, n->Ntype);
else
return ndeftl(N_ADDR, findtype(TS_PTR, n->Ntype), n);
}
return n;
}
/* CONVUNARY - Apply "usual unary conversions" to a node. [H&S 6.12]
** Returns pointer to a converted expression (usually the same node)
** Note that for ANSI there are two differences:
** (1) the float -> double conversion is suppressed!
** (2) integer promotions preserve value, not unsignedness.
** For the PDP-10 this means chars/shorts always
** are converted to "int", as are bitfields less
** than the length of an int.
** The new type, if any, is always the unqualified type. This may
** cause a "trivial conversion" merely to get rid of any qualifiers.
*/
NODE *
convunary(n)
NODE *n;
{
TYPE *newtype;
switch (n->Ntype->Tspec) {
case TS_FLOAT: /* If ANSI, leave float alone */
if (clevel < CLEV_ANSI) {
newtype = dbltype; /* Float to double */
break;
}
/* Not converting, drop thru to default */
default: /* Usual case, no conversion needed unless qualified */
if (tisqualif(n->Ntype))
n = convcast(findutype(n->Ntype), n);
return n;
case TS_BITF:
case TS_CHAR:
case TS_SHORT: /* Signed bitfield, char and short */
newtype = inttype; /* always become signed int */
break;
case TS_UBITF:
case TS_UCHAR:
case TS_USHORT: /* But if unsigned, depends on ANSIness */
if ((clevel >= CLEV_ANSI) /* If ANSI, */
&& (TGSIZ_INT > tbitsize(n->Ntype))) /* check size */
newtype = inttype; /* ANSI and int is big enough */
else newtype = uinttype; /* Not ANSI, or not big enough */
break;
case TS_ARRAY: /* Convert "array of T" to "pointer to T" */
case TS_FUNCT: /* Convert "function of T" to "pointer to fun of T" */
return convarrfn(n);
}
/* Apply some simple cast operation and return result */
return ndefcast(cast_op(newtype, n->Ntype), newtype, n);
}
/* CONVBINARY - Apply "usual binary conversions" to a node. [H&S 6.13]
** Takes pointer to a binary operator node, with the operands
** pointed to by the left and right links.
** Returns pointer to a converted expression (usually the same node)
** The type will always be unqualified.
** Note that normally a float-float rule exists ("2a" in H&S 6.13),
** as ANSI requires this.
** Also note the check in convboth() to avoid doing a double implicit
** conversion (once by convunary and again by convboth); this makes things
** more efficient and avoids confusing the assignment-op code generation,
** which expects only a single implicit cast.
*/
NODE *
convbinary(n)
NODE *n;
{
TYPE *lt, *rt;
n->Nleft = convunary(n->Nleft); /* First do unary convs on both */
n->Nright = convunary(n->Nright); /* Note this removes qualifiers! */
n->Ntype = n->Nleft->Ntype; /* Set type in case of quick return */
if (n->Nleft->Ntype == n->Nright->Ntype) return n;
lt = n->Nleft->Ntype;
rt = n->Nright->Ntype;
/* 1. If either operand is not arith type, do no additional conversion */
if (!tisarith(lt) || !tisarith(rt)) return n;
/* 2x. If one operand is "long double", make both "long double". */
if (lt == lngdbltype || rt == lngdbltype)
convboth(n, lngdbltype);
/* 2. If one operand is "double", make both "double". */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -