📄 expr.c
字号:
#include "c.h"
static char prec[] = {
#define xx(a,b,c,d,e,f,g) c,
#define yy(a,b,c,d,e,f,g) c,
#include "token.h"
};
static int oper[] = {
#define xx(a,b,c,d,e,f,g) d,
#define yy(a,b,c,d,e,f,g) d,
#include "token.h"
};
float refinc = (float)1.0;
static Tree expr2 ARGS((void));
static Tree expr3 ARGS((int));
static Tree nullcheck ARGS((Tree));
static Tree postfix ARGS((Tree));
static Tree unary ARGS((void));
static Tree primary ARGS((void));
static Type super ARGS((Type ty));
Tree expr(int tok)
{
static char stop[] = { IF, ID, '}', 0 };
Tree p = expr1(0);
while (t == ',') {
Tree q;
t = gettok();
q = pointer(expr1(0));
p = tree(RIGHT, q->type, root(value(p)), q);
}
if (tok)
test(tok, stop);
return p;
}
Tree expr0(int tok)
{
return root(expr(tok));
}
Tree expr1(int tok)
{
static char stop[] = { IF, ID, 0 };
Tree p = expr2();
if (t == '='
|| (prec[t] >= 6 && prec[t] <= 8)
|| (prec[t] >= 11 && prec[t] <= 13)) {
int op = t;
Tree lhs = p;
t = gettok();
if (oper[op] == ASGN) {
p = asgntree(ASGN, p, value(expr1(0)));
if ((p->type->op == POINTER || generic(lhs->op) == INDIR) &&
p->kids[0] && p->kids[0]->u.sym) {
Symbol sym;
sym = p->kids[0]->u.sym;
if (sym->scope == LOCAL &&
(sym->sclass == AUTO || sym->sclass == REGISTER))
sym->assigned = 1;
}
}
else
{
expect('=');
p = incr(op, p, expr1(0));
}
}
if (tok)
test(tok, stop);
return p;
}
Tree incr(int op,Tree v,Tree e)
{
if (v->kids[0] && v->kids[0]->u.sym) {
v->kids[0]->u.sym->ref += 1.0;
v->kids[0]->u.sym->lastuse = StatementCount;
}
return asgntree(ASGN, v, (*optree[op])(oper[op], v, e));
}
static Tree expr2(void)
{
Tree p = expr3(4);
if (t == '?') {
Tree l, r;
Coordinate pts[2];
if (Aflag > 1 && isfunc(p->type))
warning(StrTab[247],// <%s used in a conditional expression\n>
funcname(p));
p = pointer(p);
t = gettok();
pts[0] = src;
l = pointer(expr(':'));
pts[1] = src;
r = pointer(expr2());
p = condtree(p, l, r);
#if 0
if (OptimizeFlag && p->op == COND &&
p->kids[1] && p->kids[1]->op == RIGHT &&
p->kids[1]->kids[0]->op == ASGNI && p->kids[1]->kids[1]->op == ASGNI) {
/*
Try to optimize the constructs of nested ?:
a = (cond) ? (cond ? expr1 : expr2) : expr3;
*/
Tree tmp10 = p->kids[1]->kids[0];
Tree tmp11 = p->kids[1]->kids[1];
// printtree(tmp10,2);
// printtree(tmp11,2);
if (tmp10->kids[1] && tmp10->kids[1]->op == COND) {
Tree tmp101 = tmp10->kids[1];
if (tmp101->kids[1] && tmp101->kids[1]->op == RIGHT) {
Tree tmp1010 = tmp101->kids[1]->kids[0];
Tree tmp1011 = tmp101->kids[1]->kids[1];
Symbol s1 = tmp10->kids[0]->u.sym;
Symbol s2 = tmp11->kids[0]->u.sym;
if (s1 == s2 && s1->temporary && s1->generated) {
tmp1010->kids[0]->u.sym = tmp10->kids[0]->u.sym;
tmp1011->kids[0]->u.sym = tmp11->kids[0]->u.sym;
tmp101->u.sym = tmp10->kids[0]->u.sym;
printf("toto\n");
}
}
}
else if (tmp11->kids[1] && tmp11->kids[1]->op == COND) {
Tree tmp101 = tmp11->kids[1];
if (tmp101->kids[1] && tmp101->kids[1]->op == RIGHT) {
Tree tmp1010 = tmp101->kids[1]->kids[0];
Tree tmp1011 = tmp101->kids[1]->kids[1];
Symbol s1 = tmp10->kids[0]->u.sym;
Symbol s2 = tmp11->kids[0]->u.sym;
if (s1 == s2 && s1->temporary && s1->generated) {
tmp1010->kids[0]->u.sym = tmp10->kids[0]->u.sym;
tmp1011->kids[0]->u.sym = tmp11->kids[0]->u.sym;
tmp101->u.sym = tmp10->kids[0]->u.sym;
printf("toto *1*\n");
}
}
}
}
#endif
if (events.points)
if (p->op == COND) {
Symbol t1 = p->u.sym;
assert(p->kids[1]);
assert(p->kids[1]->op == RIGHT);
apply(events.points, &pts[0], &p->kids[1]->kids[0]);
apply(events.points, &pts[1], &p->kids[1]->kids[1]);
p = tree(COND, p->type, p->kids[0],
tree(RIGHT, p->type,
p->kids[1]->kids[0],
p->kids[1]->kids[1]));
p->u.sym = t1;
}
}
return p;
}
Tree value(Tree p)
{
int op = generic(rightkid(p)->op);
if (op==AND || op==OR || op==NOT || op==EQ || op==NE
|| op== LE || op==LT || op== GE || op==GT) {
p = condtree(p, consttree(1, inttype),
consttree(0, inttype));
}
return p;
}
static Tree expr3(int k)
{
int k1;
Tree p = unary();
for (k1 = prec[t]; k1 >= k; k1--)
while (prec[t] == k1 && *cp != '=') {
Tree r;
Coordinate pt;
int op = t;
t = gettok();
pt = src;
p = pointer(p);
if (op == ANDAND || op == OROR) {
r = pointer(expr3(k1));
if (events.points)
apply(events.points, &pt, &r);
} else
r = pointer(expr3(k1 + 1));
p = (*optree[op])(oper[op], p, r);
}
return p;
}
static Tree unary(void)
{
Tree p;
switch (t) {
case '*': t = gettok(); p = unary(); p = pointer(p);
if (isptr(p->type)
&& (isfunc(p->type->type) || isarray(p->type->type)))
p = retype(p, p->type->type);
else {
if (YYnull)
p = nullcheck(p);
p = rvalue(p);
} break;
case '&': t = gettok();
p = unary();
if (p->kids[0] &&
p->kids[0]->op != (CNST+P) &&
p->kids[0]->u.sym)
p->kids[0]->u.sym->assigned = 1;
if (isarray(p->type) || isfunc(p->type))
p = retype(p, ptr(p->type));
else
p = lvalue(p);
if (isaddrop(p->op) && p->u.sym->sclass == REGISTER)
error(StrTab[248], p->u.sym->name);// <invalid operand of unary &; `%s' is declared register\n>
else if (isaddrop(p->op))
p->u.sym->addressed = 1;
break;
case '+': t = gettok();
p = unary();
p = pointer(p);
if (isarith(p->type))
p = cast(p, promote(p->type));
else
typeerror(ADD, p, NULL);
break;
case '-': t = gettok(); p = unary(); p = pointer(p);
if (isarith(p->type)) {
p = cast(p, promote(p->type));
if (isunsigned(p->type)) {
warning(StrTab[249]);// <unsigned operand of unary -\n>
p = simplify(NEG, inttype, cast(p, inttype), NULL);
p = cast(p, unsignedtype);
} else
p = simplify(NEG, p->type, p, NULL);
} else
typeerror(SUB, p, NULL); break;
case '~': t = gettok(); p = unary(); p = pointer(p);
if (isint(p->type)
|| (p->type == longlongtype || p->type == ulonglongtype)) {
Type ty = promote(p->type);
p = simplify(BCOM, ty, cast(p, ty), NULL);
} else
typeerror(BCOM, p, NULL); break;
case '!': t = gettok(); p = unary(); p = pointer(p);
if (isscalar(p->type))
p = simplify(NOT, inttype, cond(p), NULL);
else
typeerror(NOT, p, NULL); break;
case INCR: t = gettok(); p = unary(); p = incr(INCR, pointer(p), consttree(1, inttype)); break;
case DECR: t = gettok(); p = unary(); p = incr(DECR, pointer(p), consttree(1, inttype)); break;
case SIZEOF: t = gettok(); { Type ty;
p = NULL;
if (t == '(') {
t = gettok();
if (istypename(t, tsym)) {
ty = typename();
expect(')');
} else {
p = postfix(expr(')'));
ty = p->type;
}
} else {
p = unary();
ty = p->type;
}
assert(ty);
if (isfunc(ty) || ty->size == 0)
error(StrTab[250], ty);// <invalid type argument `%t' to `sizeof'\n>
else if (p && rightkid(p)->op == FIELD)
error(StrTab[251]);// <`sizeof' applied to a bit field\n>
p = consttree(ty->size, unsignedtype); } break;
case '(':
t = gettok();
if (istypename(t, tsym)) {
Type ty, ty1 = typename(), pty;
expect(')');
ty = unqual(ty1);
if (isenum(ty)) {
Type ty2 = ty->type;
if (isconst(ty1))
ty2 = qual(CONST, ty2);
if (isvolatile(ty1))
ty2 = qual(VOLATILE, ty2);
ty1 = ty2;
ty = ty->type;
}
#if 0
if (Xflag && isstruct(ty) && t == '{') {
Symbol t1 = temporary(AUTO, ty, level);
if (Aflag >= 2)
warning(StrTab[252], ty);// <non-ANSI constructor for `%t'\n>
p = tree(RIGHT, ty1, structexp(ty, t1), idtree(t1));
break;
}
#endif
p = pointer(unary());
pty = p->type;
if (isenum(pty))
pty = pty->type;
if (isarith(pty) && isarith(ty)
|| isptr(pty) && isptr(ty))
p = cast(p, ty);
else if (isptr(pty) && isint(ty)
|| isint(pty) && isptr(ty)) {
if (Aflag >= 1 && ty->size < pty->size)
warning(StrTab[253], p->type, ty);// <conversion from `%t' to `%t' is compiler dependent\n>
p = cast(p, ty);
} else if (ty != voidtype) {
error(StrTab[254],// <cast from `%t' to `%t' is illegal\n>
p->type, ty1);
ty1 = inttype;
}
p = retype(p, ty1);
if (generic(p->op) == INDIR)
p = tree(RIGHT, ty, NULL, p);
} else
p = postfix(expr(')'));
break;
default:
p = postfix(primary());
}
return p;
}
static Tree postfix(Tree p)
{
for (;;)
switch (t) {
case INCR: p = tree(RIGHT, p->type,
tree(RIGHT, p->type,
p,
incr(t, p, consttree(1, inttype))),
p);
t = gettok(); break;
case DECR: p = tree(RIGHT, p->type,
tree(RIGHT, p->type,
p,
incr(t, p, consttree(1, inttype))),
p);
t = gettok(); break;
case '[': {
Tree q;
t = gettok();
q = expr(']');
if (q->op == (CNST+I) &&
p->op != (CNST+P) &&
p->type && p->type->op == ARRAY) {
char *n;
int bidx,d;
if (p->u.sym && p->type->size) {
n = p->u.sym->name;
bidx = 1+q->u.v.i;
assert(p->type->type);
bidx *= p->type->type->size;
d = p->type->type->size;
if (d <= 0) d = 1;
if (bidx > p->type->size)
warning(StrTab[255],n,// <indexing array %s[%d] out of bounds (%d)\n>
q->u.v.i,
p->type->size/d);
}
}
if (YYnull)
if (isptr(p->type))
p = nullcheck(p);
else if (isptr(q->type))
q = nullcheck(q);
p = (*optree['+'])(ADD, pointer(p), pointer(q));
if (isptr(p->type) && isarray(p->type->type))
p = retype(p, p->type->type);
else
p = rvalue(p);
} break;
case '(': {
Type ty;
Coordinate pt;
p = pointer(p);
if (isptr(p->type) && isfunc(p->type->type))
ty = p->type->type;
else {
error(StrTab[256], p->type);// <found `%t' expected a function\n>
ty = func(voidtype, NULL, 1);
}
pt = src;
t = gettok();
p = call(p, ty, pt);
} break;
case '.': t = gettok();
if (t == ID) {
if (isstruct(p->type)) {
Tree q = addrof(p);
p = field(q, token);
q = rightkid(q);
if (isaddrop(q->op) && q->u.sym->temporary) {
p = tree(RIGHT, p->type, p, NULL);
p->u.sym = q->u.sym;
}
} else
error(StrTab[257],// <left operand of . has incompatible type `%t'\n>
p->type);
t = gettok();
} else
error(StrTab[258]); break;// <field name expected\n>
case DEREF: t = gettok();
p = pointer(p);
if (t == ID) {
if (isptr(p->type) && isstruct(p->type->type)) {
if (YYnull)
p = nullcheck(p);
p = field(p, token);
} else
error(StrTab[259], p->type);// <left operand of -> has incompatible type `%t'\n>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -