Print this page
12826 update to smatch 0.6.1-rc1-il-6
*** 22,39 ****
#include "smatch_slist.h"
static int my_id;
STATE(inc);
! STATE(orig);
STATE(dec);
static struct smatch_state *unmatched_state(struct sm_state *sm)
{
! if (parent_is_gone_var_sym(sm->name, sm->sym))
return sm->state;
! return &undefined;
}
static struct stree *start_states;
static struct stree_stack *saved_stack;
static void set_start_state(const char *name, struct symbol *sym, struct smatch_state *start)
--- 22,47 ----
#include "smatch_slist.h"
static int my_id;
STATE(inc);
! STATE(start_state);
STATE(dec);
static struct smatch_state *unmatched_state(struct sm_state *sm)
{
! /*
! * We default to decremented. For example, say we have:
! * if (p)
! * atomic_dec(p);
! * <- p is decreemented.
! *
! */
! if ((sm->state == &dec) &&
! parent_is_gone_var_sym(sm->name, sm->sym))
return sm->state;
! return &start_state;
}
static struct stree *start_states;
static struct stree_stack *saved_stack;
static void set_start_state(const char *name, struct symbol *sym, struct smatch_state *start)
*** 84,94 ****
if (cnt == 1)
return match;
return NULL;
}
! static void db_inc_dec(struct expression *expr, int param, const char *key, const char *value, int inc_dec)
{
struct sm_state *start_sm;
struct expression *arg;
char *name;
struct symbol *sym;
--- 92,102 ----
if (cnt == 1)
return match;
return NULL;
}
! static void db_inc_dec(struct expression *expr, int param, const char *key, int inc_dec)
{
struct sm_state *start_sm;
struct expression *arg;
char *name;
struct symbol *sym;
*** 127,205 ****
// set_refcount_dec(name, sym);
if (!start_sm)
set_start_state(name, sym, &inc);
if (start_sm && start_sm->state == &inc)
! set_state(my_id, name, sym, &orig);
else
set_state(my_id, name, sym, &dec);
}
free:
if (free_at_end)
free_string(name);
}
static void db_inc(struct expression *expr, int param, char *key, char *value)
{
! db_inc_dec(expr, param, key, value, ATOMIC_INC);
}
static void db_dec(struct expression *expr, int param, char *key, char *value)
{
! db_inc_dec(expr, param, key, value, ATOMIC_DEC);
}
static void match_atomic_inc(const char *fn, struct expression *expr, void *_unused)
{
! db_inc_dec(expr, 0, "$->counter", "", ATOMIC_INC);
}
static void match_atomic_dec(const char *fn, struct expression *expr, void *_unused)
{
! db_inc_dec(expr, 0, "$->counter", "", ATOMIC_DEC);
}
static void match_atomic_add(const char *fn, struct expression *expr, void *_unused)
{
struct expression *amount;
sval_t sval;
amount = get_argument_from_call_expr(expr->args, 0);
if (get_implied_value(amount, &sval) && sval_is_negative(sval)) {
! db_inc_dec(expr, 1, "$->counter", "", ATOMIC_DEC);
return;
}
! db_inc_dec(expr, 1, "$->counter", "", ATOMIC_INC);
}
static void match_atomic_sub(const char *fn, struct expression *expr, void *_unused)
{
! db_inc_dec(expr, 1, "$->counter", "", ATOMIC_DEC);
}
static void refcount_inc(const char *fn, struct expression *expr, void *param)
{
! db_inc_dec(expr, PTR_INT(param), "$->ref.counter", "", ATOMIC_INC);
}
static void refcount_dec(const char *fn, struct expression *expr, void *param)
{
! db_inc_dec(expr, PTR_INT(param), "$->ref.counter", "", ATOMIC_DEC);
}
static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
{
struct sm_state *sm;
const char *param_name;
int param;
FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
! if (sm->state != &inc &&
! sm->state != &dec)
continue;
if (parent_is_gone_var_sym(sm->name, sm->sym))
continue;
param = get_param_num_from_sym(sm->sym);
if (param < 0)
continue;
--- 135,290 ----
// set_refcount_dec(name, sym);
if (!start_sm)
set_start_state(name, sym, &inc);
if (start_sm && start_sm->state == &inc)
! set_state(my_id, name, sym, &start_state);
else
set_state(my_id, name, sym, &dec);
}
free:
if (free_at_end)
free_string(name);
}
+ static const char *primitive_funcs[] = {
+ "atomic_inc_return",
+ "atomic_add_return",
+ "atomic_sub_return",
+ "atomic_sub_and_test",
+ "atomic_dec_and_test",
+ "_atomic_dec_and_lock",
+ "atomic_dec",
+ "atomic_long_inc",
+ "atomic_long_dec",
+ "atomic_inc",
+ "atomic_sub",
+ "refcount_inc",
+ "refcount_dec",
+ "refcount_add",
+ "refcount_add_not_zero",
+ "refcount_inc_not_zero",
+ "refcount_sub_and_test",
+ "refcount_dec_and_test",
+ "atomic_dec_if_positive",
+ };
+
+ static bool is_inc_dec_primitive(struct expression *expr)
+ {
+ int i;
+
+ while (expr->type == EXPR_ASSIGNMENT)
+ expr = strip_expr(expr->right);
+ if (expr->type != EXPR_CALL)
+ return false;
+
+ if (expr->fn->type != EXPR_SYMBOL)
+ return false;
+
+ for (i = 0; i < ARRAY_SIZE(primitive_funcs); i++) {
+ if (sym_name_is(primitive_funcs[i], expr->fn))
+ return true;
+ }
+
+ return false;
+ }
+
static void db_inc(struct expression *expr, int param, char *key, char *value)
{
! if (is_inc_dec_primitive(expr))
! return;
! db_inc_dec(expr, param, key, ATOMIC_INC);
}
static void db_dec(struct expression *expr, int param, char *key, char *value)
{
! if (is_inc_dec_primitive(expr))
! return;
! db_inc_dec(expr, param, key, ATOMIC_DEC);
}
static void match_atomic_inc(const char *fn, struct expression *expr, void *_unused)
{
! db_inc_dec(expr, 0, "$->counter", ATOMIC_INC);
}
static void match_atomic_dec(const char *fn, struct expression *expr, void *_unused)
{
! db_inc_dec(expr, 0, "$->counter", ATOMIC_DEC);
}
static void match_atomic_add(const char *fn, struct expression *expr, void *_unused)
{
struct expression *amount;
sval_t sval;
amount = get_argument_from_call_expr(expr->args, 0);
if (get_implied_value(amount, &sval) && sval_is_negative(sval)) {
! db_inc_dec(expr, 1, "$->counter", ATOMIC_DEC);
return;
}
! db_inc_dec(expr, 1, "$->counter", ATOMIC_INC);
}
static void match_atomic_sub(const char *fn, struct expression *expr, void *_unused)
{
! db_inc_dec(expr, 1, "$->counter", ATOMIC_DEC);
}
static void refcount_inc(const char *fn, struct expression *expr, void *param)
{
! db_inc_dec(expr, PTR_INT(param), "$->ref.counter", ATOMIC_INC);
}
static void refcount_dec(const char *fn, struct expression *expr, void *param)
{
! db_inc_dec(expr, PTR_INT(param), "$->ref.counter", ATOMIC_DEC);
}
+ static void pm_runtime_get_sync(const char *fn, struct expression *expr, void *param)
+ {
+ db_inc_dec(expr, PTR_INT(param), "$->power.usage_count.counter", ATOMIC_INC);
+ }
+
+ static void match_implies_inc(const char *fn, struct expression *call_expr,
+ struct expression *assign_expr, void *param)
+ {
+ db_inc_dec(call_expr, PTR_INT(param), "$->ref.counter", ATOMIC_INC);
+ }
+
+ static void match_implies_atomic_dec(const char *fn, struct expression *call_expr,
+ struct expression *assign_expr, void *param)
+ {
+ db_inc_dec(call_expr, PTR_INT(param), "$->counter", ATOMIC_DEC);
+ }
+
+ static bool is_maybe_dec(struct sm_state *sm)
+ {
+ if (sm->state == &dec)
+ return true;
+ if (slist_has_state(sm->possible, &dec) &&
+ !slist_has_state(sm->possible, &inc))
+ return true;
+ return false;
+ }
+
static void match_return_info(int return_id, char *return_ranges, struct expression *expr)
{
struct sm_state *sm;
const char *param_name;
int param;
+ if (is_impossible_path())
+ return;
+
FOR_EACH_MY_SM(my_id, __get_cur_stree(), sm) {
! if (sm->state != &inc && !is_maybe_dec(sm))
continue;
+ if (sm->state == get_state_stree(start_states, my_id, sm->name, sm->sym))
+ continue;
if (parent_is_gone_var_sym(sm->name, sm->sym))
continue;
param = get_param_num_from_sym(sm->sym);
if (param < 0)
continue;
*** 219,229 ****
static int success_fail_positive(struct range_list *rl)
{
if (!rl)
return EMPTY;
! if (sval_is_negative(rl_min(rl)))
return NEGATIVE;
if (rl_min(rl).value == 0)
return ZERO;
--- 304,314 ----
static int success_fail_positive(struct range_list *rl)
{
if (!rl)
return EMPTY;
! if (!is_whole_rl(rl) && sval_is_negative(rl_min(rl)))
return NEGATIVE;
if (rl_min(rl).value == 0)
return ZERO;
*** 235,252 ****
--- 320,346 ----
struct range_list *inc_lines = NULL;
struct range_list *dec_lines = NULL;
int inc_buckets[NUM_BUCKETS] = {};
int dec_buckets[NUM_BUCKETS] = {};
struct stree *stree, *orig_stree;
+ struct smatch_state *state;
struct sm_state *return_sm;
struct sm_state *sm;
sval_t line = sval_type_val(&int_ctype, 0);
int bucket;
+ /* static variable are probably just counters */
+ if (sym->ctype.modifiers & MOD_STATIC &&
+ !(sym->ctype.modifiers & MOD_TOPLEVEL))
+ return;
+
FOR_EACH_PTR(get_all_return_strees(), stree) {
orig_stree = __swap_cur_stree(stree);
+ if (is_impossible_path())
+ goto swap_stree;
+
return_sm = get_sm_state(RETURN_ID, "return_ranges", NULL);
if (!return_sm)
goto swap_stree;
line.value = return_sm->line;
*** 255,279 ****
if (parent_is_gone_var_sym(name, sym))
goto swap_stree;
sm = get_sm_state(my_id, name, sym);
! if (!sm)
! goto swap_stree;
! if (sm->state != &inc &&
! sm->state != &dec &&
! sm->state != &orig)
goto swap_stree;
bucket = success_fail_positive(estate_rl(return_sm->state));
! if (sm->state == &inc) {
add_range(&inc_lines, line, line);
inc_buckets[bucket] = true;
}
! if (sm->state == &dec || sm->state == &orig) {
add_range(&dec_lines, line, line);
dec_buckets[bucket] = true;
}
swap_stree:
__swap_cur_stree(orig_stree);
--- 349,375 ----
if (parent_is_gone_var_sym(name, sym))
goto swap_stree;
sm = get_sm_state(my_id, name, sym);
! if (sm)
! state = sm->state;
! else
! state = &start_state;
! if (state != &inc &&
! state != &dec &&
! state != &start_state)
goto swap_stree;
bucket = success_fail_positive(estate_rl(return_sm->state));
! if (state == &inc) {
add_range(&inc_lines, line, line);
inc_buckets[bucket] = true;
}
! if (state == &dec || state == &start_state) {
add_range(&dec_lines, line, line);
dec_buckets[bucket] = true;
}
swap_stree:
__swap_cur_stree(orig_stree);
*** 343,368 ****
add_function_hook("atomic_inc_return", &match_atomic_inc, NULL);
add_function_hook("atomic_add_return", &match_atomic_add, NULL);
add_function_hook("atomic_sub_return", &match_atomic_sub, NULL);
add_function_hook("atomic_sub_and_test", &match_atomic_sub, NULL);
add_function_hook("atomic_dec_and_test", &match_atomic_dec, NULL);
add_function_hook("_atomic_dec_and_lock", &match_atomic_dec, NULL);
add_function_hook("atomic_dec", &match_atomic_dec, NULL);
add_function_hook("atomic_long_inc", &match_atomic_inc, NULL);
add_function_hook("atomic_long_dec", &match_atomic_dec, NULL);
add_function_hook("atomic_inc", &match_atomic_inc, NULL);
add_function_hook("atomic_sub", &match_atomic_sub, NULL);
add_function_hook("refcount_inc", &refcount_inc, INT_PTR(0));
add_function_hook("refcount_dec", &refcount_dec, INT_PTR(0));
add_function_hook("refcount_add", &refcount_inc, INT_PTR(1));
! add_function_hook("refcount_add_not_zero", &refcount_inc, INT_PTR(1));
! add_function_hook("refcount_inc_not_zero", &refcount_inc, INT_PTR(0));
add_function_hook("refcount_sub_and_test", &refcount_dec, INT_PTR(1));
add_function_hook("refcount_dec_and_test", &refcount_dec, INT_PTR(0));
add_hook(&match_check_missed, END_FUNC_HOOK);
add_hook(&match_after_func, AFTER_FUNC_HOOK);
add_hook(&match_save_states, INLINE_FN_START);
add_hook(&match_restore_states, INLINE_FN_END);
--- 439,475 ----
add_function_hook("atomic_inc_return", &match_atomic_inc, NULL);
add_function_hook("atomic_add_return", &match_atomic_add, NULL);
add_function_hook("atomic_sub_return", &match_atomic_sub, NULL);
add_function_hook("atomic_sub_and_test", &match_atomic_sub, NULL);
+ add_function_hook("atomic_long_sub_and_test", &match_atomic_sub, NULL);
+ add_function_hook("atomic64_sub_and_test", &match_atomic_sub, NULL);
add_function_hook("atomic_dec_and_test", &match_atomic_dec, NULL);
+ add_function_hook("atomic_long_dec_and_test", &match_atomic_dec, NULL);
+ add_function_hook("atomic64_dec_and_test", &match_atomic_dec, NULL);
add_function_hook("_atomic_dec_and_lock", &match_atomic_dec, NULL);
add_function_hook("atomic_dec", &match_atomic_dec, NULL);
+ add_function_hook("atomic_dec_return", &match_atomic_dec, NULL);
add_function_hook("atomic_long_inc", &match_atomic_inc, NULL);
add_function_hook("atomic_long_dec", &match_atomic_dec, NULL);
add_function_hook("atomic_inc", &match_atomic_inc, NULL);
add_function_hook("atomic_sub", &match_atomic_sub, NULL);
add_function_hook("refcount_inc", &refcount_inc, INT_PTR(0));
add_function_hook("refcount_dec", &refcount_dec, INT_PTR(0));
add_function_hook("refcount_add", &refcount_inc, INT_PTR(1));
!
! return_implies_state("refcount_add_not_zero", 1, 1, &match_implies_inc, INT_PTR(1));
! return_implies_state("refcount_inc_not_zero", 1, 1, &match_implies_inc, INT_PTR(0));
!
! return_implies_state("atomic_dec_if_positive", 0, INT_MAX, &match_implies_atomic_dec, INT_PTR(0));
!
add_function_hook("refcount_sub_and_test", &refcount_dec, INT_PTR(1));
add_function_hook("refcount_dec_and_test", &refcount_dec, INT_PTR(0));
+ add_function_hook("pm_runtime_get_sync", &pm_runtime_get_sync, INT_PTR(0));
+
add_hook(&match_check_missed, END_FUNC_HOOK);
add_hook(&match_after_func, AFTER_FUNC_HOOK);
add_hook(&match_save_states, INLINE_FN_START);
add_hook(&match_restore_states, INLINE_FN_END);