11f5207b7SJohn Levon /*
21f5207b7SJohn Levon * Copyright (C) 2012 Oracle.
31f5207b7SJohn Levon *
41f5207b7SJohn Levon * This program is free software; you can redistribute it and/or
51f5207b7SJohn Levon * modify it under the terms of the GNU General Public License
61f5207b7SJohn Levon * as published by the Free Software Foundation; either version 2
71f5207b7SJohn Levon * of the License, or (at your option) any later version.
81f5207b7SJohn Levon *
91f5207b7SJohn Levon * This program is distributed in the hope that it will be useful,
101f5207b7SJohn Levon * but WITHOUT ANY WARRANTY; without even the implied warranty of
111f5207b7SJohn Levon * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
121f5207b7SJohn Levon * GNU General Public License for more details.
131f5207b7SJohn Levon *
141f5207b7SJohn Levon * You should have received a copy of the GNU General Public License
151f5207b7SJohn Levon * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
161f5207b7SJohn Levon */
171f5207b7SJohn Levon
181f5207b7SJohn Levon #include "smatch.h"
19*efe51d0cSJohn Levon #include "smatch_extra.h"
201f5207b7SJohn Levon
211f5207b7SJohn Levon static int my_id;
221f5207b7SJohn Levon
match_shift_mask(struct expression * expr)23*efe51d0cSJohn Levon static void match_shift_mask(struct expression *expr)
24*efe51d0cSJohn Levon {
25*efe51d0cSJohn Levon struct expression *right, *shifter;
26*efe51d0cSJohn Levon struct range_list *rl;
27*efe51d0cSJohn Levon char *str;
28*efe51d0cSJohn Levon
29*efe51d0cSJohn Levon expr = strip_expr(expr);
30*efe51d0cSJohn Levon if (expr->type != EXPR_BINOP || expr->op != '&')
31*efe51d0cSJohn Levon return;
32*efe51d0cSJohn Levon
33*efe51d0cSJohn Levon if (get_type(expr->left) != &ullong_ctype)
34*efe51d0cSJohn Levon return;
35*efe51d0cSJohn Levon
36*efe51d0cSJohn Levon if (type_bits(get_type(expr->right)) == 64)
37*efe51d0cSJohn Levon return;
38*efe51d0cSJohn Levon
39*efe51d0cSJohn Levon right = strip_expr(expr->right);
40*efe51d0cSJohn Levon if (right->type != EXPR_BINOP || right->op != SPECIAL_LEFTSHIFT)
41*efe51d0cSJohn Levon return;
42*efe51d0cSJohn Levon
43*efe51d0cSJohn Levon shifter = strip_expr(right->right);
44*efe51d0cSJohn Levon get_real_absolute_rl(shifter, &rl);
45*efe51d0cSJohn Levon if (rl_max(rl).uvalue < 32)
46*efe51d0cSJohn Levon return;
47*efe51d0cSJohn Levon
48*efe51d0cSJohn Levon str = expr_to_str(expr->right);
49*efe51d0cSJohn Levon sm_warning("should '%s' be a 64 bit type?", str);
50*efe51d0cSJohn Levon free_string(str);
51*efe51d0cSJohn Levon }
52*efe51d0cSJohn Levon
match_shift_assignment(struct expression * expr)531f5207b7SJohn Levon static void match_shift_assignment(struct expression *expr)
541f5207b7SJohn Levon {
551f5207b7SJohn Levon struct symbol *left_type, *right_type;
561f5207b7SJohn Levon struct expression *right;
571f5207b7SJohn Levon sval_t sval;
581f5207b7SJohn Levon sval_t bits, shifter;
591f5207b7SJohn Levon char *name;
601f5207b7SJohn Levon
611f5207b7SJohn Levon right = strip_expr(expr->right);
621f5207b7SJohn Levon if (right->type != EXPR_BINOP || right->op != SPECIAL_LEFTSHIFT)
631f5207b7SJohn Levon return;
641f5207b7SJohn Levon
651f5207b7SJohn Levon left_type = get_type(expr->left);
661f5207b7SJohn Levon if (left_type != &llong_ctype && left_type != &ullong_ctype)
671f5207b7SJohn Levon return;
681f5207b7SJohn Levon
691f5207b7SJohn Levon right_type = get_type(expr->right);
701f5207b7SJohn Levon
711f5207b7SJohn Levon if (type_bits(right_type) == 64)
721f5207b7SJohn Levon return;
731f5207b7SJohn Levon
741f5207b7SJohn Levon if (get_value(right, &sval))
751f5207b7SJohn Levon return;
761f5207b7SJohn Levon
771f5207b7SJohn Levon get_absolute_max(right->left, &bits);
781f5207b7SJohn Levon get_absolute_max(right->right, &shifter);
791f5207b7SJohn Levon
801f5207b7SJohn Levon bits = sval_cast(&ullong_ctype, bits);
811f5207b7SJohn Levon if (sval_cmp_val(shifter, 32) < 0) {
821f5207b7SJohn Levon sval = sval_binop(bits, SPECIAL_LEFTSHIFT, shifter);
831f5207b7SJohn Levon if (sval_cmp_val(sval, UINT_MAX) < 0)
841f5207b7SJohn Levon return;
851f5207b7SJohn Levon }
861f5207b7SJohn Levon
871f5207b7SJohn Levon name = expr_to_str_sym(right, NULL);
881f5207b7SJohn Levon sm_warning("should '%s' be a 64 bit type?", name);
891f5207b7SJohn Levon free_string(name);
901f5207b7SJohn Levon }
911f5207b7SJohn Levon
check_64bit_shift(int id)921f5207b7SJohn Levon void check_64bit_shift(int id)
931f5207b7SJohn Levon {
941f5207b7SJohn Levon my_id = id;
951f5207b7SJohn Levon
961f5207b7SJohn Levon add_hook(&match_shift_assignment, ASSIGNMENT_HOOK);
97*efe51d0cSJohn Levon add_hook(&match_shift_mask, BINOP_HOOK);
981f5207b7SJohn Levon }
99