From: Dan Carpenter Date: Fri, 23 Nov 2012 06:32:55 +0000 (+0300) Subject: extra: type: get the member type when loading values from the database X-Git-Tag: 1.57~167 X-Git-Url: https://repo.or.cz/w/smatch.git/commitdiff_plain/91ba9b1a2aa8c36fda35afd9cd76a5eba7ee7dc8 extra: type: get the member type when loading values from the database 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 --- diff --git a/smatch.h b/smatch.h index dc003473..744918b4 100644 --- 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); diff --git a/smatch_extra.c b/smatch_extra.c index e2a733c1..a33afdb0 100644 --- a/smatch_extra.c +++ b/smatch_extra.c @@ -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); } diff --git a/smatch_type.c b/smatch_type.c index 488a778a..4a132e0f 100644 --- a/smatch_type.c +++ b/smatch_type.c @@ -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); +}