smatch.h: include scope.h
[smatch.git] / check_bit_shift.c
blob6bf84dd38f9525daeab6320e99ac914835726e26
1 /*
2 * smatch/check_bit_shift.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
8 */
11 * This test is used to warn about mixups between bit shifters and bit flags.
15 #include "smatch.h"
16 #include "smatch_function_hashtable.h"
18 static int my_id;
20 static DEFINE_HASHTABLE_INSERT(insert_struct, char, int);
21 static DEFINE_HASHTABLE_SEARCH(search_struct, char, int);
22 static struct hashtable *shifters;
24 static const char *get_shifter(struct expression *expr)
26 const char *name;
27 sval_t expr_value;
28 const int *shifter_value;
30 expr = strip_expr(expr);
31 if (expr->type != EXPR_VALUE)
32 return NULL;
33 if (!get_value(expr, &expr_value))
34 return NULL;
35 name = pos_ident(expr->pos);
36 if (!name)
37 return NULL;
38 shifter_value = search_struct(shifters, (char *)name);
39 if (!shifter_value)
40 return NULL;
41 if (sval_cmp_val(expr_value, *shifter_value) != 0)
42 return NULL;
43 return name;
46 static void match_assign(struct expression *expr)
48 const char *name;
50 if (expr->op != SPECIAL_OR_ASSIGN)
51 return;
52 if (positions_eq(expr->pos, expr->right->pos))
53 return;
54 name = get_shifter(expr->right);
55 if (!name)
56 return;
58 sm_msg("warn: '%s' is a shifter (not for '%s').",
59 name, show_special(expr->op));
62 static void match_binop(struct expression *expr)
64 const char *name;
66 if (positions_eq(expr->pos, expr->right->pos))
67 return;
68 if (expr->op != '&')
69 return;
70 name = get_shifter(expr->right);
71 if (!name)
72 return;
74 sm_msg("warn: bit shifter '%s' used for logical '%s'",
75 name, show_special(expr->op));
78 static void register_shifters(void)
80 char filename[256];
81 struct token *token;
82 char *name;
83 int *val;
85 snprintf(filename, sizeof(filename), "%s.bit_shifters", option_project_str);
86 token = get_tokens_file(filename);
87 if (!token)
88 return;
89 if (token_type(token) != TOKEN_STREAMBEGIN)
90 return;
91 token = token->next;
92 while (token_type(token) != TOKEN_STREAMEND) {
93 if (token_type(token) != TOKEN_IDENT)
94 return;
95 name = alloc_string(show_ident(token->ident));
96 token = token->next;
97 if (token_type(token) != TOKEN_NUMBER)
98 return;
99 val = malloc(sizeof(int));
100 *val = atoi(token->number);
101 insert_struct(shifters, name, val);
102 token = token->next;
104 clear_token_alloc();
107 static void match_binop_info(struct expression *expr)
109 char *name;
110 sval_t sval;
112 if (positions_eq(expr->pos, expr->right->pos))
113 return;
114 if (expr->op != SPECIAL_LEFTSHIFT)
115 return;
116 if (expr->right->type != EXPR_VALUE)
117 return;
118 name = pos_ident(expr->right->pos);
119 if (!name)
120 return;
121 if (!get_value(expr->right, &sval))
122 return;
123 sm_msg("info: bit shifter '%s' '%s'", name, sval_to_str(sval));
126 static void match_call(const char *fn, struct expression *expr, void *_arg_no)
128 struct expression *arg_expr;
129 int arg_no = PTR_INT(_arg_no);
130 sval_t sval;
131 char *name;
133 arg_expr = get_argument_from_call_expr(expr->args, arg_no);
134 if (positions_eq(expr->pos, arg_expr->pos))
135 return;
136 name = pos_ident(arg_expr->pos);
137 if (!name)
138 return;
139 if (!get_value(arg_expr, &sval))
140 return;
141 sm_msg("info: bit shifter '%s' '%s'", name, sval_to_str(sval));
144 void check_bit_shift(int id)
146 my_id = id;
148 shifters = create_function_hashtable(5000);
149 register_shifters();
151 add_hook(&match_assign, ASSIGNMENT_HOOK);
152 add_hook(&match_binop, BINOP_HOOK);
154 if (option_info) {
155 add_hook(&match_binop_info, BINOP_HOOK);
156 if (option_project == PROJ_KERNEL) {
157 add_function_hook("set_bit", &match_call, INT_PTR(0));
158 add_function_hook("test_bit", &match_call, INT_PTR(0));