extra, modification_hooks: set "*p" to unknown if we call "function(p)"
authorDan Carpenter <dan.carpenter@oracle.com>
Wed, 23 Jan 2013 12:33:08 +0000 (23 15:33 +0300)
committerDan Carpenter <dan.carpenter@oracle.com>
Wed, 23 Jan 2013 12:33:08 +0000 (23 15:33 +0300)
This only affects people who are not using the smatch_db.  Before if you
called "foo(&bar)", then it would set "bar" to unknown.  Now if you call
"foo(bar)" it sets "*bar" to unknown.  It does not set "bar->xxx" to
unknown.

It's awkward that smatch_extra.c and smatch_modification_hooks.c both
needed to be modified.  There is some cleanup work here that could be done.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
smatch_extra.c
smatch_modification_hooks.c

index 23c510b..ab06f4b 100644 (file)
@@ -402,18 +402,47 @@ static struct smatch_state *unmatched_state(struct sm_state *sm)
        return alloc_estate_whole(estate_type(sm->state));
 }
 
+static void clear_the_pointed_at(struct expression *expr, struct state_list *slist)
+{
+       char *name;
+       struct symbol *sym;
+       struct sm_state *tmp;
+
+       name = expr_to_var_sym(expr, &sym);
+       if (!name || !sym)
+               goto free;
+
+       FOR_EACH_PTR(slist, tmp) {
+               if (tmp->name[0] != '*')
+                       continue;
+               if (tmp->sym != sym)
+                       continue;
+               if (strcmp(tmp->name + 1, name) != 0)
+                       continue;
+               set_extra_mod(tmp->name, tmp->sym, alloc_estate_whole(estate_type(tmp->state)));
+       } END_FOR_EACH_PTR(tmp);
+
+free:
+       free_string(name);
+}
+
 static void match_function_call(struct expression *expr)
 {
        struct expression *arg;
        struct expression *tmp;
+       struct state_list *slist;
+
+       slist = get_all_states(SMATCH_EXTRA);
 
        FOR_EACH_PTR(expr->args, arg) {
                tmp = strip_expr(arg);
-               if (tmp->type == EXPR_PREOP && tmp->op == '&') {
-                       remove_from_equiv_expr(tmp->unop);
-                       set_state_expr(SMATCH_EXTRA, tmp->unop, alloc_estate_whole(get_type(tmp->unop)));
-               }
+               if (tmp->type == EXPR_PREOP && tmp->op == '&')
+                       set_extra_expr_mod(tmp->unop, alloc_estate_whole(get_type(tmp->unop)));
+               else
+                       clear_the_pointed_at(tmp, slist);
        } END_FOR_EACH_PTR(arg);
+
+       free_slist(&slist);
 }
 
 static int types_equiv_or_pointer(struct symbol *one, struct symbol *two)
index 029ec97..09fe7ec 100644 (file)
@@ -10,6 +10,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include "smatch.h"
+#include "smatch_extra.h"
 #include "smatch_slist.h"
 
 enum {
@@ -104,10 +105,12 @@ static void match_call(struct expression *expr)
 
        FOR_EACH_PTR(expr->args, arg) {
                tmp = strip_expr(arg);
-               if (tmp->type != EXPR_PREOP || tmp->op != '&')
-                       continue;
-               tmp = strip_expr(tmp->unop);
-               call_modification_hooks(tmp);
+               if (tmp->type == EXPR_PREOP && tmp->op == '&') {
+                       tmp = strip_expr(tmp->unop);
+                       call_modification_hooks(tmp);
+               } else {
+                       call_modification_hooks(deref_expression(tmp));
+               }
        } END_FOR_EACH_PTR(arg);
 }