1*1f5207b7SJohn Levon /*
2*1f5207b7SJohn Levon * Copyright (C) 2013 Oracle.
3*1f5207b7SJohn Levon *
4*1f5207b7SJohn Levon * This program is free software; you can redistribute it and/or
5*1f5207b7SJohn Levon * modify it under the terms of the GNU General Public License
6*1f5207b7SJohn Levon * as published by the Free Software Foundation; either version 2
7*1f5207b7SJohn Levon * of the License, or (at your option) any later version.
8*1f5207b7SJohn Levon *
9*1f5207b7SJohn Levon * This program is distributed in the hope that it will be useful,
10*1f5207b7SJohn Levon * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*1f5207b7SJohn Levon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*1f5207b7SJohn Levon * GNU General Public License for more details.
13*1f5207b7SJohn Levon *
14*1f5207b7SJohn Levon * You should have received a copy of the GNU General Public License
15*1f5207b7SJohn Levon * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
16*1f5207b7SJohn Levon */
17*1f5207b7SJohn Levon
18*1f5207b7SJohn Levon #include "smatch.h"
19*1f5207b7SJohn Levon
20*1f5207b7SJohn Levon #define RECURSE_LIMIT 10
21*1f5207b7SJohn Levon
recurse(struct expression * expr,int (func)(struct expression * expr,void * p),void * param,int nr)22*1f5207b7SJohn Levon static int recurse(struct expression *expr,
23*1f5207b7SJohn Levon int (func)(struct expression *expr, void *p),
24*1f5207b7SJohn Levon void *param, int nr)
25*1f5207b7SJohn Levon {
26*1f5207b7SJohn Levon int ret;
27*1f5207b7SJohn Levon
28*1f5207b7SJohn Levon if (!expr)
29*1f5207b7SJohn Levon return 0;
30*1f5207b7SJohn Levon
31*1f5207b7SJohn Levon ret = func(expr, param);
32*1f5207b7SJohn Levon if (ret)
33*1f5207b7SJohn Levon return ret;
34*1f5207b7SJohn Levon
35*1f5207b7SJohn Levon if (nr > RECURSE_LIMIT)
36*1f5207b7SJohn Levon return -1;
37*1f5207b7SJohn Levon nr++;
38*1f5207b7SJohn Levon
39*1f5207b7SJohn Levon switch (expr->type) {
40*1f5207b7SJohn Levon case EXPR_PREOP:
41*1f5207b7SJohn Levon ret = recurse(expr->unop, func, param, nr);
42*1f5207b7SJohn Levon break;
43*1f5207b7SJohn Levon case EXPR_POSTOP:
44*1f5207b7SJohn Levon ret = recurse(expr->unop, func, param, nr);
45*1f5207b7SJohn Levon break;
46*1f5207b7SJohn Levon case EXPR_STATEMENT:
47*1f5207b7SJohn Levon return -1;
48*1f5207b7SJohn Levon break;
49*1f5207b7SJohn Levon case EXPR_LOGICAL:
50*1f5207b7SJohn Levon case EXPR_COMPARE:
51*1f5207b7SJohn Levon case EXPR_BINOP:
52*1f5207b7SJohn Levon case EXPR_COMMA:
53*1f5207b7SJohn Levon ret = recurse(expr->left, func, param, nr);
54*1f5207b7SJohn Levon if (ret)
55*1f5207b7SJohn Levon return ret;
56*1f5207b7SJohn Levon ret = recurse(expr->right, func, param, nr);
57*1f5207b7SJohn Levon break;
58*1f5207b7SJohn Levon case EXPR_ASSIGNMENT:
59*1f5207b7SJohn Levon ret = recurse(expr->right, func, param, nr);
60*1f5207b7SJohn Levon if (ret)
61*1f5207b7SJohn Levon return ret;
62*1f5207b7SJohn Levon ret = recurse(expr->left, func, param, nr);
63*1f5207b7SJohn Levon break;
64*1f5207b7SJohn Levon case EXPR_DEREF:
65*1f5207b7SJohn Levon ret = recurse(expr->deref, func, param, nr);
66*1f5207b7SJohn Levon break;
67*1f5207b7SJohn Levon case EXPR_SLICE:
68*1f5207b7SJohn Levon ret = recurse(expr->base, func, param, nr);
69*1f5207b7SJohn Levon break;
70*1f5207b7SJohn Levon case EXPR_CAST:
71*1f5207b7SJohn Levon case EXPR_FORCE_CAST:
72*1f5207b7SJohn Levon ret = recurse(expr->cast_expression, func, param, nr);
73*1f5207b7SJohn Levon break;
74*1f5207b7SJohn Levon case EXPR_SIZEOF:
75*1f5207b7SJohn Levon case EXPR_OFFSETOF:
76*1f5207b7SJohn Levon case EXPR_ALIGNOF:
77*1f5207b7SJohn Levon break;
78*1f5207b7SJohn Levon case EXPR_CONDITIONAL:
79*1f5207b7SJohn Levon case EXPR_SELECT:
80*1f5207b7SJohn Levon ret = recurse(expr->conditional, func, param, nr);
81*1f5207b7SJohn Levon if (ret)
82*1f5207b7SJohn Levon return ret;
83*1f5207b7SJohn Levon ret = recurse(expr->cond_true, func, param, nr);
84*1f5207b7SJohn Levon if (ret)
85*1f5207b7SJohn Levon return ret;
86*1f5207b7SJohn Levon ret = recurse(expr->cond_false, func, param, nr);
87*1f5207b7SJohn Levon break;
88*1f5207b7SJohn Levon case EXPR_CALL:
89*1f5207b7SJohn Levon return -1;
90*1f5207b7SJohn Levon break;
91*1f5207b7SJohn Levon case EXPR_INITIALIZER:
92*1f5207b7SJohn Levon return -1;
93*1f5207b7SJohn Levon break;
94*1f5207b7SJohn Levon case EXPR_IDENTIFIER:
95*1f5207b7SJohn Levon ret = recurse(expr->ident_expression, func, param, nr);
96*1f5207b7SJohn Levon break;
97*1f5207b7SJohn Levon case EXPR_INDEX:
98*1f5207b7SJohn Levon ret = recurse(expr->idx_expression, func, param, nr);
99*1f5207b7SJohn Levon break;
100*1f5207b7SJohn Levon case EXPR_POS:
101*1f5207b7SJohn Levon ret = recurse(expr->init_expr, func, param, nr);
102*1f5207b7SJohn Levon break;
103*1f5207b7SJohn Levon case EXPR_SYMBOL:
104*1f5207b7SJohn Levon case EXPR_STRING:
105*1f5207b7SJohn Levon case EXPR_VALUE:
106*1f5207b7SJohn Levon break;
107*1f5207b7SJohn Levon default:
108*1f5207b7SJohn Levon return -1;
109*1f5207b7SJohn Levon break;
110*1f5207b7SJohn Levon };
111*1f5207b7SJohn Levon return ret;
112*1f5207b7SJohn Levon }
113*1f5207b7SJohn Levon
has_symbol_helper(struct expression * expr,void * _sym)114*1f5207b7SJohn Levon static int has_symbol_helper(struct expression *expr, void *_sym)
115*1f5207b7SJohn Levon {
116*1f5207b7SJohn Levon struct symbol *sym = _sym;
117*1f5207b7SJohn Levon
118*1f5207b7SJohn Levon if (!expr || expr->type != EXPR_SYMBOL)
119*1f5207b7SJohn Levon return 0;
120*1f5207b7SJohn Levon if (expr->symbol == sym)
121*1f5207b7SJohn Levon return 1;
122*1f5207b7SJohn Levon return 0;
123*1f5207b7SJohn Levon }
124*1f5207b7SJohn Levon
has_symbol(struct expression * expr,struct symbol * sym)125*1f5207b7SJohn Levon int has_symbol(struct expression *expr, struct symbol *sym)
126*1f5207b7SJohn Levon {
127*1f5207b7SJohn Levon return recurse(expr, has_symbol_helper, sym, 0);
128*1f5207b7SJohn Levon }
129*1f5207b7SJohn Levon
130*1f5207b7SJohn Levon struct expr_name_sym {
131*1f5207b7SJohn Levon struct expression *expr;
132*1f5207b7SJohn Levon char *name;
133*1f5207b7SJohn Levon struct symbol *sym;
134*1f5207b7SJohn Levon };
135*1f5207b7SJohn Levon
has_var_helper(struct expression * expr,void * _var)136*1f5207b7SJohn Levon static int has_var_helper(struct expression *expr, void *_var)
137*1f5207b7SJohn Levon {
138*1f5207b7SJohn Levon struct expr_name_sym *xns = _var;
139*1f5207b7SJohn Levon char *name;
140*1f5207b7SJohn Levon struct symbol *sym;
141*1f5207b7SJohn Levon int matched = 0;
142*1f5207b7SJohn Levon
143*1f5207b7SJohn Levon if (!expr)
144*1f5207b7SJohn Levon return 0;
145*1f5207b7SJohn Levon if (expr->type != xns->expr->type)
146*1f5207b7SJohn Levon return 0;
147*1f5207b7SJohn Levon // I hope this is defined for everything? It should work, right?
148*1f5207b7SJohn Levon if (expr->op != xns->expr->op)
149*1f5207b7SJohn Levon return 0;
150*1f5207b7SJohn Levon
151*1f5207b7SJohn Levon name = expr_to_var_sym(expr, &sym);
152*1f5207b7SJohn Levon if (!name || !sym)
153*1f5207b7SJohn Levon goto free;
154*1f5207b7SJohn Levon if (sym == xns->sym && strcmp(name, xns->name) == 0)
155*1f5207b7SJohn Levon matched = 1;
156*1f5207b7SJohn Levon free:
157*1f5207b7SJohn Levon free_string(name);
158*1f5207b7SJohn Levon return matched;
159*1f5207b7SJohn Levon }
160*1f5207b7SJohn Levon
has_variable(struct expression * expr,struct expression * var)161*1f5207b7SJohn Levon int has_variable(struct expression *expr, struct expression *var)
162*1f5207b7SJohn Levon {
163*1f5207b7SJohn Levon struct expr_name_sym xns;
164*1f5207b7SJohn Levon int ret = -1;
165*1f5207b7SJohn Levon
166*1f5207b7SJohn Levon xns.expr = var;
167*1f5207b7SJohn Levon xns.name = expr_to_var_sym(var, &xns.sym);
168*1f5207b7SJohn Levon if (!xns.name || !xns.sym)
169*1f5207b7SJohn Levon goto free;
170*1f5207b7SJohn Levon ret = recurse(expr, has_var_helper, &xns, 0);
171*1f5207b7SJohn Levon free:
172*1f5207b7SJohn Levon free_string(xns.name);
173*1f5207b7SJohn Levon return ret;
174*1f5207b7SJohn Levon }
175*1f5207b7SJohn Levon
has_inc_dec_helper(struct expression * expr,void * unused)176*1f5207b7SJohn Levon static int has_inc_dec_helper(struct expression *expr, void *unused)
177*1f5207b7SJohn Levon {
178*1f5207b7SJohn Levon if (!expr)
179*1f5207b7SJohn Levon return 0;
180*1f5207b7SJohn Levon if (expr->type != EXPR_PREOP && expr->type != EXPR_POSTOP)
181*1f5207b7SJohn Levon return 0;
182*1f5207b7SJohn Levon if (expr->op == SPECIAL_INCREMENT || expr->op == SPECIAL_DECREMENT)
183*1f5207b7SJohn Levon return 1;
184*1f5207b7SJohn Levon return 0;
185*1f5207b7SJohn Levon }
186*1f5207b7SJohn Levon
has_inc_dec(struct expression * expr)187*1f5207b7SJohn Levon int has_inc_dec(struct expression *expr)
188*1f5207b7SJohn Levon {
189*1f5207b7SJohn Levon return recurse(expr, has_inc_dec_helper, NULL, 0);
190*1f5207b7SJohn Levon }
191*1f5207b7SJohn Levon
192