📄 com.c
字号:
if(tcompat(n, T, l->type, tindir)) goto bad; n->type = l->type->link; n->addable = 1; break; case OSTRUCT: if(tcomx(n)) goto bad; break; } t = n->type; if(t == T) goto bad; if(t->width < 0) { snap(t); if(t->width < 0) { if(typesu[t->etype] && t->tag) diag(n, "structure not fully declared %s", t->tag->name); else diag(n, "structure not fully declared"); goto bad; } } if(typeaf[t->etype]) { if(f & ADDROF) goto addaddr; if(f & ADDROP) warn(n, "address of array/func ignored"); } return 0;addaddr: if(tlvalue(n)) goto bad; l = new1(OXXX, Z, Z); *l = *n; n->op = OADDR; if(l->type->etype == TARRAY) l->type = l->type->link; n->left = l; n->right = Z; n->addable = 0; n->type = typ(TIND, l->type); n->type->width = types[TIND]->width; return 0;bad: n->type = T; return 1;}inttcoma(Node *l, Node *n, Type *t, int f){ Node *n1; int o; if(t != T) if(t->etype == TOLD || t->etype == TDOT) /* .../old in prototype */ t = T; if(n == Z) { if(t != T && !sametype(t, types[TVOID])) { diag(n, "not enough function arguments: %F", l); return 1; } return 0; } if(n->op == OLIST) { o = tcoma(l, n->left, t, 0); if(t != T) { t = t->down; if(t == T) t = types[TVOID]; } return o | tcoma(l, n->right, t, 1); } if(f && t != T) tcoma(l, Z, t->down, 0); if(tcom(n) || tcompat(n, T, n->type, targ)) return 1; if(sametype(t, types[TVOID])) { diag(n, "too many function arguments: %F", l); return 1; } if(t != T) { typeext(t, n); if(stcompat(nodproto, t, n->type, tasign)) { diag(l, "argument prototype mismatch \"%T\" for \"%T\": %F", n->type, t, l); return 1; } switch(t->etype) { case TCHAR: case TSHORT: t = types[TINT]; break; case TUCHAR: case TUSHORT: t = types[TUINT]; break; } } else switch(n->type->etype) { case TCHAR: case TSHORT: t = types[TINT]; break; case TUCHAR: case TUSHORT: t = types[TUINT]; break; case TFLOAT: t = types[TDOUBLE]; } if(t != T && !sametype(t, n->type)) { n1 = new1(OXXX, Z, Z); *n1 = *n; n->op = OCAST; n->left = n1; n->right = Z; n->type = t; n->addable = 0; } return 0;}inttcomd(Node *n){ Type *t; long o; o = 0; t = dotsearch(n->sym, n->left->type->link, n, &o); if(t == T) { diag(n, "not a member of struct/union: %F", n); return 1; } makedot(n, t, o); return 0;}inttcomx(Node *n){ Type *t; Node *l, *r, **ar, **al; int e; e = 0; if(n->type->etype != TSTRUCT) { diag(n, "constructor must be a structure"); return 1; } l = invert(n->left); n->left = l; al = &n->left; for(t = n->type->link; t != T; t = t->down) { if(l == Z) { diag(n, "constructor list too short"); return 1; } if(l->op == OLIST) { r = l->left; ar = &l->left; al = &l->right; l = l->right; } else { r = l; ar = al; l = Z; } if(tcom(r)) e++; typeext(t, r); if(tcompat(n, t, r->type, tasign)) e++; constas(n, t, r->type); if(!e && !sametype(t, r->type)) { r = new1(OCAST, r, Z); r->type = t; *ar = r; } } if(l != Z) { diag(n, "constructor list too long"); return 1; } return e;}inttlvalue(Node *n){ if(!n->addable) { diag(n, "not an l-value"); return 1; } return 0;}/* * general rewrite * (IND(ADDR x)) ==> x * (ADDR(IND x)) ==> x * remove some zero operands * remove no op casts * evaluate constants */voidccom(Node *n){ Node *l, *r; int t;loop: if(n == Z) return; l = n->left; r = n->right; switch(n->op) { case OAS: case OASXOR: case OASAND: case OASOR: case OASMOD: case OASLMOD: case OASLSHR: case OASASHR: case OASASHL: case OASDIV: case OASLDIV: case OASMUL: case OASLMUL: case OASSUB: case OASADD: ccom(l); ccom(r); if(n->op == OASLSHR || n->op == OASASHR || n->op == OASASHL) if(r->op == OCONST) { t = n->type->width * 8; /* bits per byte */ if(r->vconst >= t || r->vconst < 0) warn(n, "stupid shift: %lld", r->vconst); } break; case OCAST: ccom(l); if(l->op == OCONST) { evconst(n); if(n->op == OCONST) break; } if(nocast(l->type, n->type)) { l->type = n->type; *n = *l; } break; case OCOND: ccom(l); ccom(r); if(l->op == OCONST) if(vconst(l) == 0) *n = *r->right; else *n = *r->left; break; case OREGISTER: case OINDREG: case OCONST: case ONAME: break; case OADDR: ccom(l); l->etype = TVOID; if(l->op == OIND) { l->left->type = n->type; *n = *l->left; break; } goto common; case OIND: ccom(l); if(l->op == OADDR) { l->left->type = n->type; *n = *l->left; break; } goto common; case OEQ: case ONE: case OLE: case OGE: case OLT: case OGT: case OLS: case OHS: case OLO: case OHI: ccom(l); ccom(r); if(compar(n, 0) || compar(n, 1)) break; relcon(l, r); relcon(r, l); goto common; case OASHR: case OASHL: case OLSHR: ccom(l); if(vconst(l) == 0 && !side(r)) { *n = *l; break; } ccom(r); if(vconst(r) == 0) { *n = *l; break; } if(r->op == OCONST) { t = n->type->width * 8; /* bits per byte */ if(r->vconst >= t || r->vconst <= -t) warn(n, "stupid shift: %lld", r->vconst); } goto common; case OMUL: case OLMUL: ccom(l); t = vconst(l); if(t == 0 && !side(r)) { *n = *l; break; } if(t == 1) { *n = *r; goto loop; } ccom(r); t = vconst(r); if(t == 0 && !side(l)) { *n = *r; break; } if(t == 1) { *n = *l; break; } goto common; case ODIV: case OLDIV: ccom(l); if(vconst(l) == 0 && !side(r)) { *n = *l; break; } ccom(r); t = vconst(r); if(t == 0) { diag(n, "divide check"); *n = *r; break; } if(t == 1) { *n = *l; break; } goto common; case OSUB: ccom(r); if(r->op == OCONST) { if(typefd[r->type->etype]) { n->op = OADD; r->fconst = -r->fconst; goto loop; } else { n->op = OADD; r->vconst = -r->vconst; goto loop; } } ccom(l); goto common; case OXOR: case OOR: case OADD: ccom(l); if(vconst(l) == 0) { *n = *r; goto loop; } ccom(r); if(vconst(r) == 0) { *n = *l; break; } goto commute; case OAND: ccom(l); ccom(r); if(vconst(l) == 0 && !side(r)) { *n = *l; break; } if(vconst(r) == 0 && !side(l)) { *n = *r; break; } commute: /* look for commutative constant */ if(r->op == OCONST) { if(l->op == n->op) { if(l->left->op == OCONST) { n->right = l->right; l->right = r; goto loop; } if(l->right->op == OCONST) { n->right = l->left; l->left = r; goto loop; } } } if(l->op == OCONST) { if(r->op == n->op) { if(r->left->op == OCONST) { n->left = r->right; r->right = l; goto loop; } if(r->right->op == OCONST) { n->left = r->left; r->left = l; goto loop; } } } goto common; case OANDAND: ccom(l); if(vconst(l) == 0) { *n = *l; break; } ccom(r); goto common; case OOROR: ccom(l); if(l->op == OCONST && l->vconst != 0) { *n = *l; n->vconst = 1; break; } ccom(r); goto common; default: if(l != Z) ccom(l); if(r != Z) ccom(r); common: if(l != Z) if(l->op != OCONST) break; if(r != Z) if(r->op != OCONST) break; evconst(n); }}/* OEQ, ONE, OLE, OLS, OLT, OLO, OGE, OHS, OGT, OHI */static char *cmps[12] = { "==", "!=", "<=", "<=", "<", "<", ">=", ">=", ">", ">",};/* 128-bit numbers */typedef struct Big Big;struct Big{ vlong a; uvlong b;};static intcmp(Big x, Big y){ if(x.a != y.a){ if(x.a < y.a) return -1; return 1; } if(x.b != y.b){ if(x.b < y.b) return -1; return 1; } return 0;}static Bigadd(Big x, int y){ uvlong ob; ob = x.b; x.b += y; if(y > 0 && x.b < ob) x.a++; if(y < 0 && x.b > ob) x.a--; return x;} Bigbig(vlong a, uvlong b){ Big x; x.a = a; x.b = b; return x;}intcompar(Node *n, int reverse){ Big lo, hi, x; int op; char xbuf[40], cmpbuf[50]; Node *l, *r; Type *lt, *rt; /* * The point of this function is to diagnose comparisons * that can never be true or that look misleading because * of the `usual arithmetic conversions'. As an example * of the latter, if x is a ulong, then if(x <= -1) really means * if(x <= 0xFFFFFFFF), while if(x <= -1LL) really means * what it says (but 8c compiles it wrong anyway). */ if(reverse){ r = n->left; l = n->right; op = comrel[relindex(n->op)]; }else{ l = n->left; r = n->right; op = n->op; } /* * Skip over left casts to find out the original expression range. */ while(l->op == OCAST) l = l->left; if(l->op == OCONST) return 0; lt = l->type; if(l->op == ONAME){ lt = l->sym->type; if(lt && lt->etype == TARRAY) lt = lt->link; } if(lt == T) return 0; if(lt->etype == TXXX || lt->etype > TUVLONG) return 0; /* * Skip over the right casts to find the on-screen value. */ if(r->op != OCONST) return 0; while(r->oldop == OCAST && !r->xcast) r = r->left; rt = r->type; if(rt == T) return 0; x.b = r->vconst; x.a = 0; if((rt->etype&1) && r->vconst < 0) /* signed negative */ x.a = ~0ULL; if((lt->etype&1)==0){ /* unsigned */ lo = big(0, 0); if(lt->width == 8) hi = big(0, ~0ULL); else hi = big(0, (1LL<<(l->type->width*8))-1); }else{ lo = big(~0ULL, -(1LL<<(l->type->width*8-1))); hi = big(0, (1LL<<(l->type->width*8-1))-1); } switch(op){ case OLT: case OLO: case OGE: case OHS: if(cmp(x, lo) <= 0) goto useless; if(cmp(x, add(hi, 1)) >= 0) goto useless; break; case OLE: case OLS: case OGT: case OHI: if(cmp(x, add(lo, -1)) <= 0) goto useless; if(cmp(x, hi) >= 0) goto useless; break; case OEQ: case ONE: /* * Don't warn about comparisons if the expression * is as wide as the value: the compiler-supplied casts * will make both outcomes possible. */ if(lt->width >= rt->width && debug['w'] < 2) return 0; if(cmp(x, lo) < 0 || cmp(x, hi) > 0) goto useless; break; } return 0;useless: if((x.a==0 && x.b<=9) || (x.a==~0LL && x.b >= -9ULL)) snprint(xbuf, sizeof xbuf, "%lld", x.b); else if(x.a == 0) snprint(xbuf, sizeof xbuf, "%#llux", x.b); else snprint(xbuf, sizeof xbuf, "%#llx", x.b); if(reverse) snprint(cmpbuf, sizeof cmpbuf, "%s %s %T", xbuf, cmps[relindex(n->op)], lt); else snprint(cmpbuf, sizeof cmpbuf, "%T %s %s", lt, cmps[relindex(n->op)], xbuf); warn(n, "useless or misleading comparison: %s", cmpbuf); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -