Bug 572819 - static checking suite: port esp analyses to Dehydra with GCC 4.5 r=taras

This commit is contained in:
Ehren Metcalfe 2010-08-18 18:05:35 -07:00
Родитель a37e0d8fe3
Коммит e3632c2b97
3 изменённых файлов: 64 добавлений и 76 удалений

Просмотреть файл

@ -33,7 +33,6 @@ function process_tree(fndecl) {
let cfg = function_decl_cfg(fndecl);
try {
let trace = TRACE_ESP;
let a = new FlowCheck(cfg, trace);
@ -63,27 +62,20 @@ function FlowCheck(cfg, trace) {
for (let bb in cfg_bb_iterator(cfg)) {
for (let isn in bb_isn_iterator(bb)) {
switch (isn.tree_code()) {
case CALL_EXPR: {
let fn = call_function_decl(isn)
case GIMPLE_CALL: {
let fn = gimple_call_fndecl(isn)
if (!fn || decl_name(fn) != FLOW_THROUGH)
continue;
this.must_flow_fn = fn
break
}
case RETURN_EXPR: {
let ret_expr = isn.operands()[0]
if (track_return_loc && ret_expr)
switch (ret_expr.tree_code()) {
case GIMPLE_MODIFY_STMT:
this.rval = ret_expr.operands()[1].tree_check(VAR_DECL)
break;
case RESULT_DECL:
this.rval = ret_expr
break;
default:
throw new Error("Unhandled return expression")
}
}
case GIMPLE_RETURN:
let ret_expr = return_expr(isn);
if (track_return_loc && ret_expr) {
TREE_CHECK(ret_expr, VAR_DECL, RESULT_DECL);
this.rval = ret_expr;
}
break;
}
}
}
@ -109,14 +101,14 @@ function char_star_arg2string(tree) {
// another function as either an assignment or a call.
FlowCheck.prototype.flowState = function(isn, state) {
switch (TREE_CODE(isn)) {
case CALL_EXPR: {
let fn = call_function_decl(isn)
case GIMPLE_CALL: {
let fn = gimple_call_fndecl(isn)
if (fn == this.must_flow_fn)
state.assignValue(fn, char_star_arg2string(call_arg(isn, 0)), isn)
state.assignValue(fn, char_star_arg2string(gimple_call_arg(isn, 0)), isn)
break
}
case LABEL_EXPR: {
let label = decl_name(isn.operands()[0])
case GIMPLE_LABEL: {
let label = decl_name(gimple_op(isn, 0))
for ([value, blame] in state.yieldPreconditions(this.must_flow_fn)) {
if (label != value) continue
// reached the goto label we wanted =D
@ -124,7 +116,7 @@ FlowCheck.prototype.flowState = function(isn, state) {
}
break
}
case RETURN_EXPR: {
case GIMPLE_RETURN:
for ([value, blame] in state.yieldPreconditions(this.must_flow_fn)) {
if (typeof value != 'string') continue
let loc;
@ -137,9 +129,8 @@ FlowCheck.prototype.flowState = function(isn, state) {
return
}
break
}
case GIMPLE_MODIFY_STMT:
if (track_return_loc && isn.operands()[0] == this.rval) {
case GIMPLE_ASSIGN:
if (track_return_loc && gimple_op(isn, 0) == this.rval) {
state.assignValue(this.rval, location_of(isn), isn)
break
}

Просмотреть файл

@ -14,27 +14,23 @@ function MayReturnAnalysis() {
MayReturnAnalysis.prototype = new BackwardAnalysis;
MayReturnAnalysis.prototype.flowState = function(isn, state) {
if (TREE_CODE(isn) == RETURN_EXPR) {
let gms = TREE_OPERAND(isn, 0);
if (gms) {
// gms is usually a GIMPLE_MODIFY_STMT but can be a RESULT_DECL
if (TREE_CODE(gms) == GIMPLE_MODIFY_STMT) {
let v = GIMPLE_STMT_OPERAND(gms, 1);
this.vbls.add(v);
state.add(v);
this.retvar = v;
} else if (TREE_CODE(gms) == RESULT_DECL) {
throw new Error("Weird case hit");
}
}
} else if (TREE_CODE(isn) == GIMPLE_MODIFY_STMT) {
let lhs = GIMPLE_STMT_OPERAND(isn, 0);
let rhs = GIMPLE_STMT_OPERAND(isn, 1);
if (TREE_CODE(isn) == GIMPLE_RETURN) {
let v = return_expr(isn);
if (!v)
return;
if (v.tree_code() == RESULT_DECL) // only an issue with 4.3
throw new Error("Weird case hit");
this.vbls.add(v);
state.add(v);
this.retvar = v;
} else if (TREE_CODE(isn) == GIMPLE_ASSIGN) {
let lhs = gimple_op(isn, 0);
let rhs = gimple_op(isn, 1);
if (DECL_P(rhs) && DECL_P(lhs) && state.has(lhs)) {
this.vbls.add(rhs);
state.add(rhs);
}
for (let e in isn_defs(isn, 'strong')) {
if (DECL_P(e)) {
state.remove(e);

Просмотреть файл

@ -49,7 +49,7 @@ function process_tree(func_decl) {
if (!func_filter(func_decl)) return;
// Determine outparams and return if function not relevant
if (is_constructor(func_decl)) return;
if (DECL_CONSTRUCTOR_P(func_decl)) return;
let psem = OutparamCheck.prototype.func_param_semantics(func_decl);
if (!psem.some(function(x) x.check)) return;
let decl = rectify_function_decl(func_decl);
@ -112,11 +112,6 @@ function process_tree(func_decl) {
if (TRACE_PERF) timer_stop(fstring);
}
function is_constructor(function_decl)
{
return function_decl.decl_common.lang_specific.decl_flags.constructor_attr;
}
// Outparam check analysis
function OutparamCheck(cfg, psem_list, outparam_list, retvar, retvar_set,
trace) {
@ -253,14 +248,14 @@ OutparamCheck.prototype.updateEdgeState = function(e) {
OutparamCheck.prototype.flowState = function(isn, state) {
switch (TREE_CODE(isn)) {
case GIMPLE_MODIFY_STMT:
case GIMPLE_ASSIGN:
this.processAssign(isn, state);
break;
case CALL_EXPR:
this.processCall(undefined, isn, isn, state);
case GIMPLE_CALL:
this.processCall(isn, isn, state);
break;
case SWITCH_EXPR:
case COND_EXPR:
case GIMPLE_SWITCH:
case GIMPLE_COND:
// This gets handled by flowStateCond instead, has no exec effect
break;
default:
@ -275,8 +270,8 @@ OutparamCheck.prototype.flowStateCond = function(isn, truth, state) {
// For any outparams-specific semantics, we handle it here and then
// return. Otherwise we delegate to the zero-nonzero analysis.
OutparamCheck.prototype.processAssign = function(isn, state) {
let lhs = isn.operands()[0];
let rhs = isn.operands()[1];
let lhs = gimple_op(isn, 0);
let rhs = gimple_op(isn, 1);
if (DECL_P(lhs)) {
// Unwrap NOP_EXPR, which is semantically a copy.
@ -316,17 +311,8 @@ OutparamCheck.prototype.processAssign = function(isn, state) {
}
break;
case CALL_EXPR:
let fname = call_function_name(rhs);
if (fname == 'NS_FAILED') {
this.processTest(lhs, rhs, av.NONZERO, isn, state);
} else if (fname == 'NS_SUCCEEDED') {
this.processTest(lhs, rhs, av.ZERO, isn, state);
} else if (fname == '__builtin_expect') {
// Same as an assign from arg 0 to lhs
state.assign(lhs, call_args(rhs)[0], isn);
} else {
this.processCall(lhs, rhs, isn, state);
}
/* Embedded CALL_EXPRs are a 4.3 issue */
this.processCall(rhs, isn, state, lhs);
return;
case INDIRECT_REF:
@ -386,7 +372,7 @@ OutparamCheck.prototype.processAssign = function(isn, state) {
// Handle an assignment x := test(foo) where test is a simple predicate
OutparamCheck.prototype.processTest = function(lhs, call, val, blame, state) {
let arg = call_arg(call, 0);
let arg = gimple_call_arg(call, 0);
if (DECL_P(arg)) {
this.zeroNonzero.predicate(state, lhs, val, arg, blame);
} else {
@ -395,11 +381,27 @@ OutparamCheck.prototype.processTest = function(lhs, call, val, blame, state) {
};
// The big one: outparam semantics of function calls.
OutparamCheck.prototype.processCall = function(dest, expr, blame, state) {
let args = call_args(expr);
let callable = callable_arg_function_decl(CALL_EXPR_FN(expr));
OutparamCheck.prototype.processCall = function(call, blame, state, dest) {
if (!dest)
dest = gimple_call_lhs(call);
let args = gimple_call_args(call);
let callable = callable_arg_function_decl(gimple_call_fn(call));
let psem = this.func_param_semantics(callable);
let name = function_decl_name(callable);
if (name == 'NS_FAILED') {
this.processTest(dest, call, av.NONZERO, call, state);
return;
} else if (name == 'NS_SUCCEEDED') {
this.processTest(dest, call, av.ZERO, call, state);
return;
} else if (name == '__builtin_expect') {
// Same as an assign from arg 0 to lhs
state.assign(dest, args[0], call);
return;
}
if (TRACE_CALL_SEM) {
print("param semantics:" + psem);
}
@ -408,7 +410,6 @@ OutparamCheck.prototype.processCall = function(dest, expr, blame, state) {
let ct = TREE_TYPE(callable);
if (TREE_CODE(ct) == POINTER_TYPE) ct = TREE_TYPE(ct);
if (args.length < psem.length || !stdarg_p(ct)) {
let name = function_decl_name(callable);
// TODO Can __builtin_memcpy write to an outparam? Probably not.
if (name != 'operator new' && name != 'operator delete' &&
name != 'operator new []' && name != 'operator delete []' &&
@ -568,7 +569,7 @@ OutparamCheck.prototype.findReturnStmt = function(ss) {
for (let bb in cfg_bb_iterator(this.cfg)) {
for (let isn in bb_isn_iterator(bb)) {
if (TREE_CODE(isn) == RETURN_EXPR) {
if (isn.tree_code() == GIMPLE_RETURN) {
return this.cfg._cached_return = isn;
}
}
@ -593,9 +594,8 @@ OutparamCheck.prototype.checkSubstateSuccess = function(ss) {
let callMsg;
let callName = "";
try {
let callExpr = blameStmt.tree_check(GIMPLE_MODIFY_STMT).
operands()[1].tree_check(CALL_EXPR);
let callDecl = callable_arg_function_decl(CALL_EXPR_FN(callExpr));
let call = TREE_CHECK(blameStmt, GIMPLE_CALL, GIMPLE_MODIFY_STMT);
let callDecl = callable_arg_function_decl(gimple_call_fn(call));
callMsg = [callDecl, "declared here"];
callName = " '" + decl_name(callDecl) + "'";
@ -798,6 +798,7 @@ function pointer_type_is_outparam(pt) {
case ENUMERAL_TYPE:
case REAL_TYPE:
case UNION_TYPE:
case BOOLEAN_TYPE:
return true;
case RECORD_TYPE:
// TODO: should we consider field writes?