Print this page
new smatch

@@ -34,16 +34,33 @@
 {
         if (sm->state != &ok)
                 set_state(my_id, sm->name, sm->sym, &ok);
 }
 
-static void pre_merge_hook(struct sm_state *sm)
+static void pre_merge_hook(struct sm_state *cur, struct sm_state *other)
 {
         if (is_impossible_path())
-                set_state(my_id, sm->name, sm->sym, &ok);
+                set_state(my_id, cur->name, cur->sym, &ok);
 }
 
+static struct smatch_state *unmatched_state(struct sm_state *sm)
+{
+        struct smatch_state *state;
+        sval_t sval;
+
+        if (sm->state != &freed)
+                return &undefined;
+
+        state = get_state(SMATCH_EXTRA, sm->name, sm->sym);
+        if (!state)
+                return &undefined;
+        if (!estate_get_single_value(state, &sval) || sval.value != 0)
+                return &undefined;
+        /* It makes it easier to consider NULL pointers as freed.  */
+        return &freed;
+}
+
 static int is_freed(struct expression *expr)
 {
         struct sm_state *sm;
 
         sm = get_sm_state_expr(my_id, expr);

@@ -339,9 +356,10 @@
         add_hook(&match_call, FUNCTION_CALL_HOOK);
         add_hook(&match_return, RETURN_HOOK);
 
         add_modification_hook_late(my_id, &ok_to_use);
         add_pre_merge_hook(my_id, &pre_merge_hook);
+        add_unmatched_state_hook(my_id, &unmatched_state);
 
         select_return_states_hook(PARAM_FREED, &set_param_freed);
         add_untracked_param_hook(&match_untracked);
 }