1 /*
2  * Copyright (C) 2012 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 static int my_id;
21 
22 static void match_shift_assignment(struct expression *expr)
23 {
24 	struct symbol *left_type, *right_type;
25 	struct expression *right;
26 	sval_t sval;
27 	sval_t bits, shifter;
28 	char *name;
29 
30 	right = strip_expr(expr->right);
31 	if (right->type != EXPR_BINOP || right->op != SPECIAL_LEFTSHIFT)
32 		return;
33 
34 	left_type = get_type(expr->left);
35 	if (left_type != &llong_ctype && left_type != &ullong_ctype)
36 		return;
37 
38 	right_type = get_type(expr->right);
39 
40 	if (type_bits(right_type) == 64)
41 		return;
42 
43 	if (get_value(right, &sval))
44 		return;
45 
46 	get_absolute_max(right->left, &bits);
47 	get_absolute_max(right->right, &shifter);
48 
49 	bits = sval_cast(&ullong_ctype, bits);
50 	if (sval_cmp_val(shifter, 32) < 0) {
51 		sval = sval_binop(bits, SPECIAL_LEFTSHIFT, shifter);
52 		if (sval_cmp_val(sval, UINT_MAX) < 0)
53 			return;
54 	}
55 
56 	name = expr_to_str_sym(right, NULL);
57 	sm_warning("should '%s' be a 64 bit type?", name);
58 	free_string(name);
59 }
60 
61 void check_64bit_shift(int id)
62 {
63 	my_id = id;
64 
65 	add_hook(&match_shift_assignment, ASSIGNMENT_HOOK);
66 }
67