user_data: serious bug in handling modifications (missed errors)
[smatch.git] / smatch_var_sym.c
blob8c9e6f9a810be75c46b943bc72930819c2eb678b
1 /*
2 * sparse/smatch_var_sym.c
4 * Copyright (C) 2013 Oracle.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "smatch.h"
12 ALLOCATOR(var_sym, "var_sym structs");
14 struct var_sym *alloc_var_sym(const char *var, struct symbol *sym)
16 struct var_sym *tmp;
18 tmp = __alloc_var_sym(0);
19 tmp->var = alloc_string(var);
20 tmp->sym = sym;
21 return tmp;
24 struct var_sym_list *expr_to_vsl(struct expression *expr)
26 struct var_sym_list *ret = NULL;
27 char *var;
28 struct symbol *sym;
30 expr = strip_expr(expr);
31 if (!expr)
32 return NULL;
34 if (expr->type == EXPR_BINOP ||
35 expr->type == EXPR_LOGICAL ||
36 expr->type == EXPR_COMPARE) {
37 struct var_sym_list *left, *right;
39 left = expr_to_vsl(expr->left);
40 right = expr_to_vsl(expr->right);
41 ret = combine_var_sym_lists(left, right);
42 free_var_syms_and_list(&left);
43 free_var_syms_and_list(&right);
44 return ret;
46 var = expr_to_var_sym(expr, &sym);
47 if (!var || !sym) {
48 free_string(var);
49 return NULL;
51 add_var_sym(&ret, var, sym);
52 return ret;
55 void add_var_sym(struct var_sym_list **list, const char *var, struct symbol *sym)
57 struct var_sym *tmp;
59 if (in_var_sym_list(*list, var, sym))
60 return;
61 tmp = alloc_var_sym(var, sym);
62 add_ptr_list(list, tmp);
65 void add_var_sym_expr(struct var_sym_list **list, struct expression *expr)
67 char *var;
68 struct symbol *sym;
70 var = expr_to_var_sym(expr, &sym);
71 if (!var || !sym)
72 goto free;
73 add_var_sym(list, var, sym);
74 free:
75 free_string(var);
78 static void free_var_sym(struct var_sym *vs)
80 free_string(vs->var);
81 __free_var_sym(vs);
84 void del_var_sym(struct var_sym_list **list, const char *var, struct symbol *sym)
86 struct var_sym *tmp;
88 FOR_EACH_PTR(*list, tmp) {
89 if (tmp->sym == sym && strcmp(tmp->var, var) == 0) {
90 DELETE_CURRENT_PTR(tmp);
91 free_var_sym(tmp);
92 return;
94 } END_FOR_EACH_PTR(tmp);
97 int in_var_sym_list(struct var_sym_list *list, const char *var, struct symbol *sym)
99 struct var_sym *tmp;
101 FOR_EACH_PTR(list, tmp) {
102 if (tmp->sym == sym && strcmp(tmp->var, var) == 0)
103 return 1;
104 } END_FOR_EACH_PTR(tmp);
105 return 0;
108 struct var_sym_list *clone_var_sym_list(struct var_sym_list *from_vsl)
110 struct var_sym *tmp, *clone_vs;
111 struct var_sym_list *to_vsl = NULL;
113 FOR_EACH_PTR(from_vsl, tmp) {
114 clone_vs = alloc_var_sym(tmp->var, tmp->sym);
115 add_ptr_list(&to_vsl, clone_vs);
116 } END_FOR_EACH_PTR(tmp);
117 return to_vsl;
120 void merge_var_sym_list(struct var_sym_list **dest, struct var_sym_list *src)
122 struct var_sym *tmp;
124 FOR_EACH_PTR(src, tmp) {
125 add_var_sym(dest, tmp->var, tmp->sym);
126 } END_FOR_EACH_PTR(tmp);
129 struct var_sym_list *combine_var_sym_lists(struct var_sym_list *one, struct var_sym_list *two)
131 struct var_sym_list *to_vsl;
133 to_vsl = clone_var_sym_list(one);
134 merge_var_sym_list(&to_vsl, two);
135 return to_vsl;
138 void free_var_sym_list(struct var_sym_list **list)
140 __free_ptr_list((struct ptr_list **)list);
143 void free_var_syms_and_list(struct var_sym_list **list)
145 struct var_sym *tmp;
147 FOR_EACH_PTR(*list, tmp) {
148 free_var_sym(tmp);
149 } END_FOR_EACH_PTR(tmp);
150 free_var_sym_list(list);