Print this page
12724 update smatch to 0.6.1-rc1-il-5
*** 70,79 ****
--- 70,81 ----
#define implied_debug 0
#define DIMPLIED(msg...) do { if (implied_debug) printf(msg); } while (0)
bool debug_implied(void)
{
+ if (option_debug)
+ return true;
return implied_debug;
}
/*
* tmp_range_list():
*** 89,98 ****
--- 91,107 ----
my_range = alloc_range(ll_to_sval(num), ll_to_sval(num));
add_ptr_list(&my_list, my_range);
return my_list;
}
+ static const char *show_comparison(int op)
+ {
+ if (op == PARAM_LIMIT)
+ return "<lim>";
+ return show_special(op);
+ }
+
static void print_debug_tf(struct sm_state *sm, int istrue, int isfalse)
{
if (!implied_debug && !option_debug)
return;
*** 113,122 ****
--- 122,143 ----
sm->merged ? "[merged]" : "[leaf]",
get_stree_id(sm->pool));
}
}
+ void split_comparison_helper(struct range_list *left_orig, int op, struct range_list *right_orig,
+ struct range_list **left_true_rl, struct range_list **left_false_rl)
+ {
+ if (op == PARAM_LIMIT) {
+ *left_true_rl = rl_intersection(left_orig, right_orig);
+ *left_false_rl = rl_filter(left_orig, right_orig);
+ return;
+ }
+
+ split_comparison_rl(left_orig, op, right_orig, left_true_rl, left_false_rl, NULL, NULL);
+ }
+
static int create_fake_history(struct sm_state *sm, int comparison, struct range_list *rl)
{
struct range_list *orig_rl;
struct range_list *true_rl, *false_rl;
struct stree *true_stree, *false_stree;
*** 129,139 ****
return 0;
if (!estate_rl(sm->state))
return 0;
orig_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
! split_comparison_rl(orig_rl, comparison, rl, &true_rl, &false_rl, NULL, NULL);
true_rl = rl_truncate_cast(estate_type(sm->state), true_rl);
false_rl = rl_truncate_cast(estate_type(sm->state), false_rl);
if (is_whole_rl(true_rl) || is_whole_rl(false_rl) ||
!true_rl || !false_rl ||
--- 150,160 ----
return 0;
if (!estate_rl(sm->state))
return 0;
orig_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
! split_comparison_helper(orig_rl, comparison, rl, &true_rl, &false_rl);
true_rl = rl_truncate_cast(estate_type(sm->state), true_rl);
false_rl = rl_truncate_cast(estate_type(sm->state), false_rl);
if (is_whole_rl(true_rl) || is_whole_rl(false_rl) ||
!true_rl || !false_rl ||
*** 152,162 ****
return 0;
}
if (implied_debug)
sm_msg("fake_history: %s vs %s. %s %s %s. --> T: %s F: %s",
! sm->name, show_rl(rl), sm->state->name, show_special(comparison), show_rl(rl),
show_rl(true_rl), show_rl(false_rl));
true_sm = clone_sm(sm);
false_sm = clone_sm(sm);
--- 173,183 ----
return 0;
}
if (implied_debug)
sm_msg("fake_history: %s vs %s. %s %s %s. --> T: %s F: %s",
! sm->name, show_rl(rl), sm->state->name, show_comparison(comparison), show_rl(rl),
show_rl(true_rl), show_rl(false_rl));
true_sm = clone_sm(sm);
false_sm = clone_sm(sm);
*** 231,240 ****
--- 252,287 ----
} END_FOR_EACH_PTR(tmp);
return ret;
}
+ static bool possibly_true_helper(struct range_list *var_rl, int comparison, struct range_list *rl)
+ {
+ if (comparison == PARAM_LIMIT) {
+ struct range_list *intersect;
+
+ intersect = rl_intersection(var_rl, rl);
+ if (intersect)
+ return true;
+ return false;
+ }
+ return possibly_true_rl(var_rl, comparison, rl);
+ }
+
+ static bool possibly_false_helper(struct range_list *var_rl, int comparison, struct range_list *rl)
+ {
+ if (comparison == PARAM_LIMIT) {
+ struct range_list *intersect;
+
+ intersect = rl_intersection(var_rl, rl);
+ if (!rl_equiv(var_rl, intersect))
+ return true;
+ return false;
+ }
+ return possibly_false_rl(var_rl, comparison, rl);
+ }
+
/*
* If 'foo' == 99 add it that pool to the true pools. If it's false, add it to
* the false pools. If we're not sure, then we don't add it to either.
*/
static void do_compare(struct sm_state *sm, int comparison, struct range_list *rl,
*** 250,261 ****
if (!sm->pool)
return;
var_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
! istrue = !possibly_false_rl(var_rl, comparison, rl);
! isfalse = !possibly_true_rl(var_rl, comparison, rl);
print_debug_tf(sm, istrue, isfalse);
/* give up if we have borrowed implications (smatch_equiv.c) */
if (sm->sym != gate_sm->sym ||
--- 297,308 ----
if (!sm->pool)
return;
var_rl = cast_rl(rl_type(rl), estate_rl(sm->state));
! istrue = !possibly_false_helper(var_rl, comparison, rl);
! isfalse = !possibly_true_helper(var_rl, comparison, rl);
print_debug_tf(sm, istrue, isfalse);
/* give up if we have borrowed implications (smatch_equiv.c) */
if (sm->sym != gate_sm->sym ||
*** 313,323 ****
gettimeofday(&now, NULL);
timersub(&now, start_time, &diff);
if (diff.tv_sec >= 1) {
if (implied_debug) {
sm_msg("debug: %s: implications taking too long. (%s %s %s)",
! __func__, sm->state->name, show_special(comparison), show_rl(rl));
}
if (mixed)
*mixed = 1;
}
--- 360,370 ----
gettimeofday(&now, NULL);
timersub(&now, start_time, &diff);
if (diff.tv_sec >= 1) {
if (implied_debug) {
sm_msg("debug: %s: implications taking too long. (%s %s %s)",
! __func__, sm->state->name, show_comparison(comparison), show_rl(rl));
}
if (mixed)
*mixed = 1;
}
*** 591,601 ****
int sec;
gettimeofday(&time_before, NULL);
DIMPLIED("checking implications: (%s (%s) %s %s)\n",
! sm->name, sm->state->name, show_special(comparison), show_rl(rl));
if (!is_merged(sm)) {
DIMPLIED("%d '%s' from line %d is not merged.\n", get_lineno(), sm->name, sm->line);
return;
}
--- 638,648 ----
int sec;
gettimeofday(&time_before, NULL);
DIMPLIED("checking implications: (%s (%s) %s %s)\n",
! sm->name, sm->state->name, show_comparison(comparison), show_rl(rl));
if (!is_merged(sm)) {
DIMPLIED("%d '%s' from line %d is not merged.\n", get_lineno(), sm->name, sm->line);
return;
}
*** 750,760 ****
name = expr_to_var_sym(expr, &sym);
if (!name || !sym)
goto free;
sm = get_sm_state(SMATCH_EXTRA, name, sym);
! if (!sm)
goto free;
separate_and_filter(sm, SPECIAL_NOTEQUAL, tmp_range_list(estate_type(sm->state), 0), __get_cur_stree(), implied_true, implied_false, &mixed);
delete_gate_sm_equiv(implied_true, sm->name, sm->sym);
delete_gate_sm_equiv(implied_false, sm->name, sm->sym);
--- 797,807 ----
name = expr_to_var_sym(expr, &sym);
if (!name || !sym)
goto free;
sm = get_sm_state(SMATCH_EXTRA, name, sym);
! if (!sm || !sm->merged)
goto free;
separate_and_filter(sm, SPECIAL_NOTEQUAL, tmp_range_list(estate_type(sm->state), 0), __get_cur_stree(), implied_true, implied_false, &mixed);
delete_gate_sm_equiv(implied_true, sm->name, sm->sym);
delete_gate_sm_equiv(implied_false, sm->name, sm->sym);
*** 771,784 ****
static int handled_by_comparison_hook(struct expression *expr,
struct stree **implied_true,
struct stree **implied_false)
{
struct state_list *true_stack = NULL;
struct state_list *false_stack = NULL;
struct stree *pre_stree;
- struct sm_state *sm;
sm = comparison_implication_hook(expr, &true_stack, &false_stack);
if (!sm)
return 0;
--- 818,831 ----
static int handled_by_comparison_hook(struct expression *expr,
struct stree **implied_true,
struct stree **implied_false)
{
+ struct sm_state *sm, *true_sm, *false_sm;
struct state_list *true_stack = NULL;
struct state_list *false_stack = NULL;
struct stree *pre_stree;
sm = comparison_implication_hook(expr, &true_stack, &false_stack);
if (!sm)
return 0;
*** 785,794 ****
--- 832,848 ----
pre_stree = clone_stree(__get_cur_stree());
*implied_true = filter_stack(sm, pre_stree, false_stack, true_stack);
*implied_false = filter_stack(sm, pre_stree, true_stack, false_stack);
+ true_sm = get_sm_state_stree(*implied_true, sm->owner, sm->name, sm->sym);
+ false_sm = get_sm_state_stree(*implied_false, sm->owner, sm->name, sm->sym);
+ if (true_sm && strcmp(true_sm->state->name, "unknown") == 0)
+ delete_state_stree(implied_true, sm->owner, sm->name, sm->sym);
+ if (false_sm && strcmp(false_sm->state->name, "unknown") == 0)
+ delete_state_stree(implied_false, sm->owner, sm->name, sm->sym);
+
free_stree(&pre_stree);
free_slist(&true_stack);
free_slist(&false_stack);
return 1;
*** 951,975 ****
extra_saved_implied_true = NULL;
extra_saved_implied_false = NULL;
set_implied_states(NULL);
}
! void param_limit_implications(struct expression *expr, int param, char *key, char *value)
{
! struct expression *arg;
struct symbol *compare_type;
char *name;
struct symbol *sym;
struct sm_state *sm;
struct sm_state *tmp;
struct stree *implied_true = NULL;
struct stree *implied_false = NULL;
struct range_list *orig, *limit;
if (time_parsing_function() > 40)
return;
while (expr->type == EXPR_ASSIGNMENT)
expr = strip_expr(expr->right);
if (expr->type != EXPR_CALL)
return;
--- 1005,1033 ----
extra_saved_implied_true = NULL;
extra_saved_implied_false = NULL;
set_implied_states(NULL);
}
! void param_limit_implications(struct expression *expr, int param, char *key, char *value, struct stree **implied)
{
! struct expression *orig_expr, *arg;
struct symbol *compare_type;
char *name;
struct symbol *sym;
struct sm_state *sm;
struct sm_state *tmp;
struct stree *implied_true = NULL;
struct stree *implied_false = NULL;
struct range_list *orig, *limit;
+ char *left_name = NULL;
+ struct symbol *left_sym = NULL;
+ int mixed = 0;
if (time_parsing_function() > 40)
return;
+ orig_expr = expr;
while (expr->type == EXPR_ASSIGNMENT)
expr = strip_expr(expr->right);
if (expr->type != EXPR_CALL)
return;
*** 997,1009 ****
orig = estate_rl(sm->state);
orig = cast_rl(compare_type, orig);
call_results_to_rl(expr, compare_type, value, &limit);
! separate_and_filter(sm, SPECIAL_EQUAL, limit, __get_cur_stree(), &implied_true, &implied_false, NULL);
FOR_EACH_SM(implied_true, tmp) {
__set_sm_fake_stree(tmp);
} END_FOR_EACH_SM(tmp);
free_stree(&implied_true);
free_stree(&implied_false);
--- 1055,1083 ----
orig = estate_rl(sm->state);
orig = cast_rl(compare_type, orig);
call_results_to_rl(expr, compare_type, value, &limit);
! separate_and_filter(sm, PARAM_LIMIT, limit, __get_cur_stree(), &implied_true, &implied_false, &mixed);
+ if (orig_expr->type == EXPR_ASSIGNMENT)
+ left_name = expr_to_var_sym(orig_expr->left, &left_sym);
+
FOR_EACH_SM(implied_true, tmp) {
+ /*
+ * What we're trying to do here is preserve the sm state so that
+ * smatch extra doesn't create a new sm state when it parses the
+ * PARAM_LIMIT.
+ */
+ if (!mixed && tmp->sym == sym &&
+ strcmp(tmp->name, name) == 0 &&
+ (!left_name || strcmp(left_name, name) != 0)) {
+ overwrite_sm_state_stree(implied, tmp);
+ continue;
+ }
+
+ // TODO why can't this just be __set_sm()?
__set_sm_fake_stree(tmp);
} END_FOR_EACH_SM(tmp);
free_stree(&implied_true);
free_stree(&implied_false);