1*1f5207b7SJohn Levon /* 2*1f5207b7SJohn Levon * Copyright (C) 2010 Dan Carpenter. 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 #include "smatch_extra.h" 20*1f5207b7SJohn Levon 21*1f5207b7SJohn Levon static int my_id; 22*1f5207b7SJohn Levon 23*1f5207b7SJohn Levon static int is_bool(struct expression *expr) 24*1f5207b7SJohn Levon { 25*1f5207b7SJohn Levon struct symbol *type; 26*1f5207b7SJohn Levon 27*1f5207b7SJohn Levon type = get_type(expr); 28*1f5207b7SJohn Levon if (!type) 29*1f5207b7SJohn Levon return 0; 30*1f5207b7SJohn Levon if (type_bits(type) == 1 && type->ctype.modifiers & MOD_UNSIGNED) 31*1f5207b7SJohn Levon return 1; 32*1f5207b7SJohn Levon return 0; 33*1f5207b7SJohn Levon } 34*1f5207b7SJohn Levon 35*1f5207b7SJohn Levon static int is_bool_from_context(struct expression *expr) 36*1f5207b7SJohn Levon { 37*1f5207b7SJohn Levon sval_t sval; 38*1f5207b7SJohn Levon 39*1f5207b7SJohn Levon if (!get_implied_max(expr, &sval) || sval.uvalue > 1) 40*1f5207b7SJohn Levon return 0; 41*1f5207b7SJohn Levon if (!get_implied_min(expr, &sval) || sval.value < 0) 42*1f5207b7SJohn Levon return 0; 43*1f5207b7SJohn Levon return 1; 44*1f5207b7SJohn Levon } 45*1f5207b7SJohn Levon 46*1f5207b7SJohn Levon static int is_bool_op(struct expression *expr) 47*1f5207b7SJohn Levon { 48*1f5207b7SJohn Levon expr = strip_expr(expr); 49*1f5207b7SJohn Levon 50*1f5207b7SJohn Levon if (expr->type == EXPR_PREOP && expr->op == '!') 51*1f5207b7SJohn Levon return 1; 52*1f5207b7SJohn Levon if (expr->type == EXPR_COMPARE) 53*1f5207b7SJohn Levon return 1; 54*1f5207b7SJohn Levon if (expr->type == EXPR_LOGICAL) 55*1f5207b7SJohn Levon return 1; 56*1f5207b7SJohn Levon return is_bool(expr); 57*1f5207b7SJohn Levon } 58*1f5207b7SJohn Levon 59*1f5207b7SJohn Levon static void match_condition(struct expression *expr) 60*1f5207b7SJohn Levon { 61*1f5207b7SJohn Levon int print = 0; 62*1f5207b7SJohn Levon 63*1f5207b7SJohn Levon if (expr->type == EXPR_COMPARE) { 64*1f5207b7SJohn Levon if (expr->left->type == EXPR_COMPARE || expr->right->type == EXPR_COMPARE) 65*1f5207b7SJohn Levon print = 1; 66*1f5207b7SJohn Levon if (expr->left->type == EXPR_PREOP && expr->left->op == '!') { 67*1f5207b7SJohn Levon if (expr->left->unop->type == EXPR_PREOP && expr->left->unop->op == '!') 68*1f5207b7SJohn Levon return; 69*1f5207b7SJohn Levon if (expr->right->op == '!') 70*1f5207b7SJohn Levon return; 71*1f5207b7SJohn Levon if (is_bool(expr->right)) 72*1f5207b7SJohn Levon return; 73*1f5207b7SJohn Levon if (is_bool(expr->left->unop)) 74*1f5207b7SJohn Levon return; 75*1f5207b7SJohn Levon if (is_bool_from_context(expr->left->unop)) 76*1f5207b7SJohn Levon return; 77*1f5207b7SJohn Levon print = 1; 78*1f5207b7SJohn Levon } 79*1f5207b7SJohn Levon } 80*1f5207b7SJohn Levon 81*1f5207b7SJohn Levon if (expr->type == EXPR_BINOP) { 82*1f5207b7SJohn Levon if (expr->left->type == EXPR_COMPARE || expr->right->type == EXPR_COMPARE) 83*1f5207b7SJohn Levon print = 1; 84*1f5207b7SJohn Levon } 85*1f5207b7SJohn Levon 86*1f5207b7SJohn Levon if (print) { 87*1f5207b7SJohn Levon sm_warning("add some parenthesis here?"); 88*1f5207b7SJohn Levon return; 89*1f5207b7SJohn Levon } 90*1f5207b7SJohn Levon 91*1f5207b7SJohn Levon if (expr->type == EXPR_BINOP && expr->op == '&') { 92*1f5207b7SJohn Levon int i = 0; 93*1f5207b7SJohn Levon 94*1f5207b7SJohn Levon if (is_bool_op(expr->left)) 95*1f5207b7SJohn Levon i++; 96*1f5207b7SJohn Levon if (is_bool_op(expr->right)) 97*1f5207b7SJohn Levon i++; 98*1f5207b7SJohn Levon if (i == 1) 99*1f5207b7SJohn Levon sm_warning("maybe use && instead of &"); 100*1f5207b7SJohn Levon } 101*1f5207b7SJohn Levon } 102*1f5207b7SJohn Levon 103*1f5207b7SJohn Levon static void match_binop(struct expression *expr) 104*1f5207b7SJohn Levon { 105*1f5207b7SJohn Levon if (expr->op != '&') 106*1f5207b7SJohn Levon return; 107*1f5207b7SJohn Levon if (expr->left->op == '!') 108*1f5207b7SJohn Levon sm_warning("add some parenthesis here?"); 109*1f5207b7SJohn Levon } 110*1f5207b7SJohn Levon 111*1f5207b7SJohn Levon static void match_mask(struct expression *expr) 112*1f5207b7SJohn Levon { 113*1f5207b7SJohn Levon if (expr->op != '&') 114*1f5207b7SJohn Levon return; 115*1f5207b7SJohn Levon if (expr->right->type != EXPR_BINOP) 116*1f5207b7SJohn Levon return; 117*1f5207b7SJohn Levon if (expr->right->op != SPECIAL_RIGHTSHIFT) 118*1f5207b7SJohn Levon return; 119*1f5207b7SJohn Levon 120*1f5207b7SJohn Levon sm_warning("shift has higher precedence than mask"); 121*1f5207b7SJohn Levon } 122*1f5207b7SJohn Levon 123*1f5207b7SJohn Levon static void match_subtract_shift(struct expression *expr) 124*1f5207b7SJohn Levon { 125*1f5207b7SJohn Levon if (expr->op != SPECIAL_LEFTSHIFT) 126*1f5207b7SJohn Levon return; 127*1f5207b7SJohn Levon if (expr->right->type != EXPR_BINOP) 128*1f5207b7SJohn Levon return; 129*1f5207b7SJohn Levon if (expr->right->op != '-') 130*1f5207b7SJohn Levon return; 131*1f5207b7SJohn Levon sm_warning("subtract is higher precedence than shift"); 132*1f5207b7SJohn Levon } 133*1f5207b7SJohn Levon 134*1f5207b7SJohn Levon void check_precedence(int id) 135*1f5207b7SJohn Levon { 136*1f5207b7SJohn Levon my_id = id; 137*1f5207b7SJohn Levon 138*1f5207b7SJohn Levon add_hook(&match_condition, CONDITION_HOOK); 139*1f5207b7SJohn Levon add_hook(&match_binop, BINOP_HOOK); 140*1f5207b7SJohn Levon add_hook(&match_mask, BINOP_HOOK); 141*1f5207b7SJohn Levon add_hook(&match_subtract_shift, BINOP_HOOK); 142*1f5207b7SJohn Levon } 143