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