📄 uno_lts.c
字号:
safe_stack = d; return any_added;}static voiddfs_pop(void){ DfStack *d; SymRef *r, *n; uno_assert((int) (dfstack && safe_stack), "no dfstack or safe_stack"); for (r = dfstack->symrefs; r; r = n) /* free stack items */ { n = r->nxt; r->nxt = dfs_free; dfs_free = r; } for (r = dfstack->globrefs; r; r = n) { n = r->nxt; r->nxt = dfs_free; dfs_free = r; } d = dfstack; dfstack = dfstack->nxt; d->nxt = dfs_frame; /* free stackframe */ dfs_frame = d; for (r = safe_stack->symrefs; r; r = n) /* free sym refs */ { n = r->nxt; r->nxt = dfs_free; dfs_free = r; } d = safe_stack; safe_stack = safe_stack->nxt; d->nxt = dfs_frame; /* free stackframe */ dfs_frame = d;}static voidglobal_var(SymList *s, treenode *n) /* track global, default-initialized, pointers */{ leafnode *l; int extra = 0; if (s->mark & DECL) { l = leftmost(n); extra = (s->mark & (DEF|ARRAY_DECL))? 8 : 0; if ((s->mark & PARAM) && (s->mark & USE)) /* it came from a prototype decl or an enum */ extra |= 1; /* suppress complaints */ if (s->mark & UNO_CONST) /* enum constant */ extra |= 8; /* suppress complaints about lack of def */ if (l) { if (l->hdr.tok == STATIC) mark_guse(s->sm, n, 2|extra); /* static global */ else if (l->hdr.tok == EXTRN) mark_guse(s->sm, n, 4|extra); /* extern global */ else mark_guse(s->sm, n, extra); /* normal global */ } else mark_guse(s->sm, n, extra); /* global declared - see if used */ if ((s->mark & DEREF) /* pointer */ && !(s->mark & ARRAY_DECL)) /* not an array */ { if (!(s->mark & DEF)) /* uninitialized */ add_glob(s->sm, n, 0); /* an interesting global */ else add_defs(s->sm, n); /* def_b4_use of global ptr */ } } else /* not a declaration */ { if ((s->mark & USE) && is_constant(s->sm->nme->str)) s->mark |= UNO_CONST; /* was s->mark |= DEF; */ if ((s->mark & (USE|USEafterdef|REF0|REF1)) || (s->mark & DEREF)) { mark_guse(s->sm, n, 1); /* at least one USE */ add_gstack(s->sm, n, USE); /* global used in this procedure */ } if (s->mark & ALIAS) /* address taken - def could happen via ptr */ { mark_guse(s->sm, n, 32); /* flag to void global checks on this var */ add_gstack(s->sm, n, ALIAS); /* mark it as aliased */ } if ((s->mark & (DEF|UNO_CONST)) && !(s->mark & DEREF)) { mark_guse(s->sm, n, 8); /* at least one DEF */ add_gstack(s->sm, n, DEF); /* global set in this procedure */ } if (on_glob(s->sm) /* of interest: an uninitialized global ptr */ && !on_safe(s->sm)) /* not already declared moot on this path */ { if (((s->mark & (DEF|UNO_CONST)) /* defined */ && !(s->mark & REF0) && !(s->mark & DEREF)) || (s->mark & ALIAS)) /* or address taken */ { add_defs(s->sm, n); /* record def of global ptr */ add_safe(s->sm, n); /* moot in remainder of path */ } if (s->mark & USE) /* direct use */ { if (checkpathcond(s->sm, n, 1)) /* unless value known */ add_uses(s->sm, n); /* use_b4_def in fct */ } if ((s->mark & REF0) /* ref0->x */ || ((s->mark & DEREF) && (s->mark & (USE|DEF|FCALL)))) /* ptr deref */ { if (checkpathcond(s->sm, n, 2)) /* unless known value */ add_derefs(s->sm, n); /* use_b4_def in fct */ else if (0) printf("check %s - %d - <%s>\n", s->sm->nme->str, checkpathcond(s->sm, n, 3), x_stmnt(n)); } } }}static voidlocal_var(SymList *s, treenode *n) /* track local, uninitialized non-array objects */{ leafnode *l; if (s->mark & DECL) /* declaration */ { l = leftmost(n); if (l && l->hdr.tok == EXTRN) /* extern declared locally */ { s->sm->decl_level = FILE_SCOPE; /* fix */ global_var(s, n); /* global in disguise */ return; } if (!(s->mark & (USE | USEafterdef))) { add_locs(s->sm, n); /* check if this local can remain un-used */ if (s->mark & PARAM) mark_locs(s->sm, n, PARAM|(s->mark&FCALL)); if (s->mark & DEREF) /* it's a local pointer variable */ mark_locs(s->sm, n, DEREF); /* remember that */ } if ((!l || l->hdr.tok != STATIC || (s->mark & DEREF)) /* not static, unless ptr */ && !(s->mark & DEF) /* not initialized in decl */ && !(s->mark & ARRAY_DECL) /* arraynames are initialized ptrs */ && !(s->mark & USEafterdef)) /* a USEafterdef implies a DEF */ add_stack(s->sm, n); /* track this local */ } else { if (s->mark & PARAM) mark_locs(s->sm, n, PARAM); /* means: used in sizeof operation */ if (s->mark & ALIAS) /* address taken - def could happen via ptr */ { mark_locs(s->sm, n, ALIAS|(s->mark&FCALL)); del_stack(s->sm); /* no point in keeping track */ } if ((s->mark & (USE|USEafterdef|REF0|REF1)) || (s->mark & DEREF)) /* deref counts as use */ mark_locs(s->sm, n, USE|(s->mark&FCALL)); /* no longer un-used */ if (n && n->hdr.tok == RETURN) { extern int err_path; int x = is_local(s->sm); x = (x & ~DEREF); if (x != 0 && !(x&PARAM) && !(s->mark & DEREF|REF0) && (s->mark & ALIAS) /* taking address */ && !has_fctcalls(n->hdr.defuse)) { err_path++; /* print fct args as well */ fprintf(stdout, "uno: %s:%d: fct %s, returning address of local '%s' in <%s>\n", n->hdr.fnm, n->hdr.line, curgraph?curgraph->fctnm:"-", s->sm->nme->str, x_stmnt(n)); err_path--; if (debug || Verbose) { fprintf(stdout, "s\t"); dflow_mark(stdout, s->mark); fprintf(stdout, "\n"); fprintf(stdout, "x\t"); dflow_mark(stdout, x); fprintf(stdout, "\n"); fprintf(stdout, "d\t"); dump_defuse(n->hdr.defuse, stdout); fprintf(stdout, "\n"); } } /* should also complain about basnames of arrays */ } } if (on_stack(s->sm)) /* seen local decl */ { if (!(s->mark & USEafterdef) && (((s->mark & (USE|REF0)) || ((s->mark & DEREF) && !(s->mark & DECL))))) { mark_locs(s->sm, n, USEbeforedef|(s->mark&FCALL)); del_stack(s->sm); } else if (s->mark & (DEF|UNO_CONST)) { mark_locs(s->sm, n, DEF|(s->mark&FCALL)); /* def before use */ del_stack(s->sm); } }}static voidana_work(DefUse *d, SymList *s, treenode *n){ if (debug) { printf("\tanawork: %s: ", s->sm->nme->str); dump_defuse(d, stdout); printf("\n"); } if (0) { printf("%s:%d: %s here: %d <<%s>>\t<%u>\n\t", n->hdr.fnm, n->hdr.line, s->sm->nme->str, s->mark, x_stmnt(n), s->sm); dump_defuse(d, stdout); printf("\n"); } if (uno_ignore(s->sm) /* symbol declared in "/usr/include/*" */ || (s->mark & REF2)) /* x->ref2 or x.ref2 -- compounds not yet */ return; if (uno == 4) /* -local */ uno_bounds(s, d->aio, n); /* array bounds */ if (s->mark & FCALL) { if (debug) printf("anawork->add_fcall\n"); add_fcall(s->sm, n, (s->mark&USE)?USE:DEF);#if 1 /* collect all places where a fct is called thru a ptr */ /* and remember in which fct this happens... */ if (s->mark & DEREF) { Gst *g; if (Verbose) printf("%s:%d fct %s calls another fct via a ptr: %s...\n", n->hdr.fnm, n->hdr.line, curgraph->fctnm, s->sm->nme->str); g = (Gst *) emalloc(sizeof(Gst)); g->gnm = curgraph; g->nxt = grst; grst = g; }#endif return; } else if (debug) printf("\tnot a fcall...\n"); if (s->sm->decl_level < FUNCTION_SCOPE) global_var(s, n); else local_var(s, n);}static voidana_reversed(DefUse *d, SymList *s, treenode *n){ if (!s) return; ana_reversed(d, s->nxt, n); ana_work(d, s, n); /* last entry checked first */}static voidana_defuse(treenode *n){ DefUse *d; SymList *e; if (!n) return; if (n->hdr.type == TN_IF) { d = ((if_node *)n)->cond->hdr.defuse; if (lintlike && d) { if (has_node_type(((if_node *)n)->cond, TN_ASSIGN) && !v_reported(n)) fprintf(stdout, "uno: warning, %s:%d: assignment in condition <%s>\n", n->hdr.fnm, n->hdr.line, x_stmnt(((if_node *)n)->cond)); else for (e = d->other; e; e = e->nxt) if ((e->mark & DEF) && !(e->mark & UNO_CONST) && !v_reported(n)) fprintf(stdout, "uno: warning, %s:%d: condition has side effect on '%s'\n", n->hdr.fnm, n->hdr.line, e->sm->nme->str); } } else d = n->hdr.defuse; if (debug && d) { printf("uno: ==> "); dump_defuse(d, stdout); printf("\n"); } if (d) ana_reversed(d, d->other, n);}static PathCond *getpathframe(void){ PathCond *np; if (pathfree) { np = pathfree; pathfree = pathfree->nxt; } else np = (PathCond *) emalloc(sizeof(PathCond)); return np;}static voidnewpathcond(treenode *exp, treenode *val){ PathCond *np; if (debug) printf("New Pathcondition <%s>\n", x_stmnt(exp)); np = getpathframe(); np->exp = exp; np->val = val; np->nxt = pathcond; pathcond = np;}static voidprevpathcond(void){ PathCond *np; np = pathcond; pathcond = pathcond->nxt; /* uno cannot exclude nill-deref here */ np->nxt = pathfree; pathfree = np;}static inthas_symbol(symentry_t *s, treenode *n){ if (!n) return 0; if (n->syment == s) return 1; if (n->hdr.which == LEAF_T) return 0; return has_symbol(s, n->lnode) || has_symbol(s, n->rnode);}intinfeasible(treenode *e, treenode *v){ int w; char *s; if (!e || !v) return 0; if (e->hdr.type == TN_INT && v->hdr.tok == IDENT) { w = ((leafnode *)e)->data.ival; /* could use const_expr evaluator here */ s = ((leafnode *)v)->data.sval->str; if ((w != 0 && strcmp(s, "_false_") == 0) || (w == 0 && strcmp(s, "_true_") == 0)) return 1; } return 0;}static intis_zero_val(treenode *n){ if (!n) return 0; if (n->hdr.type == TN_CAST) return is_zero_val(n->rnode); return (n->hdr.type == TN_INT && ((leafnode *)n)->data.ival == 0);}static intsimple_zero(symentry_t *s, treenode *ex){ if (!ex) return 0; if (debug) printf("SZ %s, %s <%s>\n", s->nme->str, name_of_node(ex->hdr.type), x_stmnt(ex)); if (ex->hdr.type == TN_IDENT && ex->syment == s) return 0; /* s */ if (ex->hdr.type != TN_EXPR) return 0; if (ex->hdr.tok == AND) return simple_zero(s, ex->lnode) || simple_zero(s, ex->rnode); if (ex->hdr.tok == OR) return simple_zero(s, ex->lnode) && simple_zero(s, ex->rnode); if (ex->hdr.tok == NOT && ex->lnode == ZT && ex->rnode->hdr.type == TN_IDENT && ex->rnode->syment == s) return 1; /* !s */ if (ex->hdr.tok == NOT && ex->lnode == ZT && ex->rnode->hdr.type == TN_EXPR && ex->rnode->hdr.tok == NOT_EQ && ex->rnode->lnode->hdr.type == TN_IDENT && ex->rnode->lnode->syment == s && is_zero_val(ex->rnode->rnode)) return 1; /* !(s != 0) */ if (ex->hdr.tok == EQUAL && ex->lnode->hdr.type == TN_IDENT && ex->lnode->syment == s && is_zero_val(ex->rnode)) return 1; /* (s == 0) */ return 0;}static intsimple_nonzero(symentry_t *s, treenode *ex){ if (!ex) return 0; if (debug) printf("SNZ %s, %s <%s>\n", s->nme->str, name_of_node(ex->hdr.type), x_stmnt(ex)); if (ex->hdr.type == TN_IDENT && ex->syment == s) { if (debug) printf(" s -- pattern matches\n"); return 1; /* s */ } if (ex->hdr.type != TN_EXPR) return 0; if (ex->hdr.tok == AND) return simple_nonzero(s, ex->lnode) || simple_nonzero(s, ex->rnode); if (ex->hdr.tok == OR) return simple_nonzero(s, ex->lnode) && simple_nonzero(s, ex->rnode); if (ex->hdr.tok == NOT && ex->lnode == ZT && ex->rnode->hdr.type == TN_EXPR && ex->rnode->hdr.tok == EQUAL && ex->rnode->lnode->hdr.type == TN_IDENT && ex->rnode->lnode->syment == s && is_zero_val(ex->rnode->rnode)) { if (debug) printf(" !(s == 0) -- pattern matches\n"); return 1; /* !(s == 0) */ } if (ex->hdr.tok == NOT_EQ && ex->lnode->hdr.type == TN_IDENT && ex->lnode->syment == s && is_zero_val(ex->rnode)) { if (debug) printf(" (s != 0) -- pattern matches\n"); return 1; /* (s != 0) */ } if (debug) printf(" nonoftheabove (%d %u)\n", ex->hdr.tok, ex->lnode); return 0;}static intsimple_form(symentry_t *s, PathCond *np) /* can we deduce that s is nonzero from np */{ treenode *ex = np->exp; if (!((leafnode *)np->val)->data.sval) return 0; if (debug) printf("\t\tsimpleform: %s\n", ((leafnode *)np->val)->data.sval->str); if (strcmp(((leafnode *)np->val)->data.sval->str, "_true_") == 0) return simple_nonzero(s, ex); if (strcmp(((leafnode *)np->val)->data.sval->str, "_false_") == 0) return simple_zero(s, ex); return 0;}static intcheckpathcond(symentry_t *s, treenode *n, int callpt){ PathCond *np; if (debug) printf("%s:%d, CPC: symbol %s %s -- callpt %d\n", n->hdr.fnm, n->hdr.line, s->nme->str, name_of_node(n->hdr.type), callpt); if (n && n->hdr.type == TN_IF /* current statement is conditional */ && simple_nonzero(s, ((if_node *)n)->cond)) { if (debug) printf("CPC: symbol %s in cond, known nonzero <%s>\n", s->nme->str, x_stmnt(n)); return 0; } else { if (debug) printf("CPC: not known nonzero <%s>\n", x_stmnt(n)); } for (np = pathcond; np; np = np->nxt) { if (debug) { printf("\tcheckpathcond: val=%s exp=%s (%s)", toksym(np->val->hdr.tok, 1), x_stmnt(np->exp), name_of_node(np->exp->hdr.type)); printf("\tval=%s\n", x_stmnt(np->val)); } if (has_symbol(s, np->exp)) { if (debug) printf(" 1\n"); if (np->val->hdr.tok == IDENT && simple_form(s, np)) { if (debug) printf(" 2\n"); return 0; /* voids insertion */ } if (debug) printf(" 3\n"); continue; /* can't tell from this condition */ } if (has_symbol(s, np->val)) { if (debug) printf(" 4\n"); break; /* can't tell -- and this may change the value */ } } if (debug) printf(" 5\n"); return 1;}#if 0voiddebug_node(treenode *n, int tabs, char *p){ int i; if (!n) return; printf(p); for (i = 0; i < tabs; i++) fprintf(stdout, " "); printf("%s\n", name_of_node(n->hdr.type)); if (n->hdr.which == NODE_T) { debug_node(n->lnode, tabs+1, "L"); debug_node(n->rnode, tabs+1, "R"); }}static voidputpathcond(symentry_t *s){ PathCond *np; for (np = pathcond; np; np = np->nxt) { fprintf(stderr, "checkpathcond: val=%s exp=%s %s == ", toksym(np->val->hdr.tok, 1), name_of_node(np->exp->hdr.type), x_stmnt(np->exp)); fprintf(stderr, "%s\n", x_stmnt(np->val)); if (has_symbol(s, np->exp)) { fprintf(stderr, " 1\n"); if (np->val->hdr.tok == IDENT && simple_form(s, np)) { fprintf(stderr, " 2\n"); return; } fprintf(stderr, " 3\n"); debug_node(np->exp, 0, ""); return; } if (has_symbol(s, np->val)) { fprintf(stderr, " 4\n"); return; } } fprintf(stderr, " 5\n");}#endifstatic voidsetknownzeros(treenode *n, Trans *t, PathCond *np){ DefUse *d; SymList *s; SymRef *r; if (!n) return; if (n->hdr.type == TN_IF) d = ((if_node *)n)->cond->hdr.defuse; else d = n->hdr.defuse; if (d) for (s = d->other; s; s = s->nxt) if (s->sm->decl_level < FUNCTION_SCOPE /* global */ && (s->mark & USE)) if (simple_form(s->sm, np)) { /* s known nonzero */ r = uno_getref(s->sm); r->nxt = t->knz; t->knz = r; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -