extra: type: get the member type when loading values from the database
authorDan Carpenter <dan.carpenter@oracle.com>
Fri, 23 Nov 2012 06:32:55 +0000 (23 09:32 +0300)
committerDan Carpenter <dan.carpenter@oracle.com>
Fri, 23 Nov 2012 06:32:55 +0000 (23 09:32 +0300)
Before it was taking the type of the struct pointer for everything (ie a
pointer).  We have a similar function but it takes a struct ident instead
of a string.

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

index dc00347..744918b 100644 (file)
--- a/smatch.h
+++ b/smatch.h
@@ -275,6 +275,7 @@ int types_equiv(struct symbol *one, struct symbol *two);
 const char *global_static();
 struct symbol *cur_func_return_type(void);
 struct symbol *get_arg_type(struct expression *fn, int arg);
+struct symbol *get_param_type_from_key(struct symbol *sym, char *key);
 
 /* smatch_ignore.c */
 void add_ignore(int owner, const char *name, struct symbol *sym);
index e2a733c..a33afdb 100644 (file)
@@ -976,13 +976,15 @@ static void set_param_value(const char *name, struct symbol *sym, char *key, cha
 {
        struct range_list *rl = NULL;
        struct smatch_state *state;
+       struct symbol *type;
        char fullname[256];
 
        if (strncmp(key, "$$", 2))
                return;
 
        snprintf(fullname, 256, "%s%s", name, key + 2);
-       parse_value_ranges_type(get_real_base_type(sym), value, &rl);
+       type = get_param_type_from_key(sym, key);
+       parse_value_ranges_type(type, value, &rl);
        state = alloc_estate_range_list(rl);
        set_state(SMATCH_EXTRA, fullname, sym, state);
 }
index 488a778..4a132e0 100644 (file)
@@ -414,3 +414,52 @@ struct symbol *get_arg_type(struct expression *fn, int arg)
        return NULL;
 }
 
+static struct symbol *get_member_from_string(struct symbol_list *symbol_list, char *name)
+{
+       struct symbol *tmp, *sub;
+       int chunk_len;
+
+       if (strncmp(name, ".", 1) == 0)
+               name += 1;
+       if (strncmp(name, "->", 2) == 0)
+               name += 2;
+
+       FOR_EACH_PTR(symbol_list, tmp) {
+               if (!tmp->ident) {
+                       sub = get_real_base_type(tmp);
+                       sub = get_member_from_string(sub->symbol_list, name);
+                       if (sub)
+                               return sub;
+                       continue;
+               }
+
+               if (strcmp(tmp->ident->name, name) == 0)
+                       return tmp;
+
+               chunk_len = strlen(tmp->ident->name);
+               if (strncmp(tmp->ident->name, name, chunk_len) == 0 &&
+                   (name[chunk_len] == '.' || name[chunk_len] == '-')) {
+                       sub = get_real_base_type(tmp);
+                       return get_member_from_string(sub->symbol_list, name + chunk_len);
+               }
+
+       } END_FOR_EACH_PTR(tmp);
+
+       return NULL;
+}
+
+struct symbol *get_param_type_from_key(struct symbol *sym, char *key)
+{
+       if (strcmp(key, "$$") == 0)
+               return get_real_base_type(sym);
+
+       key = key + 2;
+       sym = get_real_base_type(sym);
+       if (sym->type == SYM_PTR)
+               sym = get_real_base_type(sym);
+
+       sym = get_member_from_string(sym->symbol_list, key);
+       if (!sym)
+               return NULL;
+       return get_real_base_type(sym);
+}