Print this page
12724 update smatch to 0.6.1-rc1-il-5
@@ -70,10 +70,12 @@
#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,10 +91,17 @@
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,10 +122,22 @@
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,11 +150,11 @@
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);
+ 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,11 +173,11 @@
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),
+ 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,10 +252,36 @@
} 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,12 +297,12 @@
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);
+ 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,11 +360,11 @@
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));
+ __func__, sm->state->name, show_comparison(comparison), show_rl(rl));
}
if (mixed)
*mixed = 1;
}
@@ -591,11 +638,11 @@
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));
+ 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,11 +797,11 @@
name = expr_to_var_sym(expr, &sym);
if (!name || !sym)
goto free;
sm = get_sm_state(SMATCH_EXTRA, name, sym);
- if (!sm)
+ 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,14 +818,14 @@
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;
- struct sm_state *sm;
sm = comparison_implication_hook(expr, &true_stack, &false_stack);
if (!sm)
return 0;
@@ -785,10 +832,17 @@
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,25 +1005,29 @@
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)
+void param_limit_implications(struct expression *expr, int param, char *key, char *value, struct stree **implied)
{
- struct expression *arg;
+ 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,13 +1055,29 @@
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);
+ 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);