assigned_expr: fix memory leak
[smatch.git] / smatch_math.c
blobed5941e5bec61766c9a99784399dea3484b8e494
1 /*
2 * sparse/smatch_helper.c
4 * Copyright (C) 2010 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "smatch.h"
11 #include "smatch_extra.h"
13 static long long _get_implied_value(struct expression *expr, int *discard, int *undefined, int implied);
14 static long long _get_value(struct expression *expr, int *discard, int *undefined, int implied);
16 #define BOGUS 12345
18 #define NOTIMPLIED 0
19 #define IMPLIED 1
20 #define FUZZYMAX 2
21 #define FUZZYMIN 3
23 static long long cast_to_type(struct expression *expr, long long val)
25 struct symbol *type = get_type(expr);
27 if (!type)
28 return val;
30 switch (type->bit_size) {
31 case 8:
32 if (type->ctype.modifiers & MOD_UNSIGNED)
33 val = (long long)(unsigned char) val;
34 else
35 val = (long long)(char) val;
36 break;
37 case 16:
38 if (type->ctype.modifiers & MOD_UNSIGNED)
39 val = (long long)(unsigned short) val;
40 else
41 val = (long long)(short) val;
42 break;
43 case 32:
44 if (type->ctype.modifiers & MOD_UNSIGNED)
45 val = (long long)(unsigned int) val;
46 else
47 val = (long long)(int) val;
48 break;
50 return val;
53 static long long handle_preop(struct expression *expr, int *discard, int *undefined, int implied)
55 long long ret = BOGUS;
57 switch(expr->op) {
58 case '~':
59 ret = ~ _get_value(expr->unop, discard, undefined, implied);
60 ret = cast_to_type(expr->unop, ret);
61 break;
62 case '-':
63 ret = - _get_value(expr->unop, discard, undefined, implied);
64 break;
65 case '*':
66 ret = _get_implied_value(expr, discard, undefined, implied);
67 break;
68 default:
69 *undefined = 1;
70 *discard = 1;
72 return ret;
75 static long long handle_binop(struct expression *expr, int *discard, int *undefined, int implied)
77 long long left;
78 long long right;
79 long long ret = BOGUS;
81 if (expr->type != EXPR_BINOP) {
82 *undefined = 1;
83 *discard = 1;
84 return ret;
87 left = _get_value(expr->left, discard, undefined, implied);
88 right = _get_value(expr->right, discard, undefined, implied);
90 switch (expr->op) {
91 case '*':
92 ret = left * right;
93 break;
94 case '/':
95 ret = left / right;
96 break;
97 case '+':
98 ret = left + right;
99 break;
100 case '-':
101 ret = left - right;
102 break;
103 case '%':
104 ret = left % right;
105 break;
106 case '|':
107 ret = left | right;
108 break;
109 case '&':
110 ret = left & right;
111 break;
112 case SPECIAL_RIGHTSHIFT:
113 ret = left >> right;
114 break;
115 case SPECIAL_LEFTSHIFT:
116 ret = left << right;
117 break;
118 case '^':
119 ret = left ^ right;
120 break;
121 default:
122 *undefined = 1;
123 *discard = 1;
125 return ret;
128 static long long _get_implied_value(struct expression *expr, int *discard, int *undefined, int implied)
130 long long ret = BOGUS;
132 switch (implied) {
133 case IMPLIED:
134 if (!get_implied_single_val(expr, &ret)) {
135 *undefined = 1;
136 *discard = 1;
138 break;
139 case FUZZYMAX:
140 if (!get_implied_single_fuzzy_max(expr, &ret)) {
141 *undefined = 1;
142 *discard = 1;
144 break;
145 case FUZZYMIN:
146 if (!get_implied_single_fuzzy_min(expr, &ret)) {
147 *undefined = 1;
148 *discard = 1;
150 break;
151 default:
152 *undefined = 1;
153 *discard = 1;
155 return ret;
158 static long long _get_value(struct expression *expr, int *discard, int *undefined, int implied)
160 int dis = 0;
161 long long ret = BOGUS;
163 if (!expr) {
164 *undefined = 1;
165 return BOGUS;
167 if (!discard)
168 discard = &dis;
169 if (*discard) {
170 *undefined = 1;
171 return BOGUS;
174 expr = strip_parens(expr);
176 switch (expr->type){
177 case EXPR_VALUE:
178 ret = expr->value;
179 ret = cast_to_type(expr, ret);
180 break;
181 case EXPR_PREOP:
182 ret = handle_preop(expr, discard, undefined, implied);
183 break;
184 case EXPR_POSTOP:
185 ret = _get_value(expr->unop, discard, undefined, implied);
186 break;
187 case EXPR_CAST:
188 case EXPR_FORCE_CAST:
189 case EXPR_IMPLIED_CAST:
190 ret = _get_value(expr->cast_expression, discard, undefined, implied);
191 return cast_to_type(expr, ret);
192 case EXPR_BINOP:
193 ret = handle_binop(expr, discard, undefined, implied);
194 break;
195 case EXPR_PTRSIZEOF:
196 case EXPR_SIZEOF:
197 ret = get_expression_value(expr);
198 break;
199 default:
200 ret = _get_implied_value(expr, discard, undefined, implied);
202 if (*discard) {
203 *undefined = 1;
204 return BOGUS;
206 return ret;
209 /* returns 1 if it can get a value literal or else returns 0 */
210 int get_value(struct expression *expr, long long *val)
212 int undefined = 0;
214 *val = _get_value(expr, NULL, &undefined, NOTIMPLIED);
215 if (undefined)
216 return 0;
217 return 1;
220 int get_implied_value(struct expression *expr, long long *val)
222 int undefined = 0;
224 *val = _get_value(expr, NULL, &undefined, IMPLIED);
225 return !undefined;
228 int get_fuzzy_max(struct expression *expr, long long *val)
230 int undefined = 0;
232 *val = _get_value(expr, NULL, &undefined, FUZZYMAX);
233 return !undefined;
236 int get_fuzzy_min(struct expression *expr, long long *val)
238 int undefined = 0;
240 *val = _get_value(expr, NULL, &undefined, FUZZYMIN);
241 return !undefined;