locking: tons of locks were ignored because of changes in smatch_helper.c
[smatch.git] / check_bit_shift.c
blob92330d632699339d58fe5e66c2010b9e8579513a
1 /*
2 * smatch/check_bit_shift.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
8 */
10 #include "smatch.h"
11 #include "smatch_function_hashtable.h"
13 static int my_id;
15 static DEFINE_HASHTABLE_INSERT(insert_struct, char, int);
16 static DEFINE_HASHTABLE_SEARCH(search_struct, char, int);
17 static struct hashtable *shifters;
19 static int positions_eq(struct position *pos1, struct position *pos2)
21 if (pos1->line != pos2->line)
22 return 0;
23 if (pos1->pos != pos2->pos)
24 return 0;
25 if (pos1->stream != pos2->stream)
26 return 0;
27 return 1;
30 static const char *get_shifter(struct expression *expr)
32 const char *name;
33 long long expr_value;
34 const int *shifter_value;
36 expr = strip_expr(expr);
37 if (expr->type != EXPR_VALUE)
38 return NULL;
39 if (!get_value(expr, &expr_value))
40 return NULL;
41 name = pos_ident(expr->pos);
42 if (!name)
43 return NULL;
44 shifter_value = search_struct(shifters, (char *)name);
45 if (!shifter_value)
46 return NULL;
47 if (*shifter_value != expr_value)
48 return NULL;
49 return name;
52 static void match_assign(struct expression *expr)
54 const char *name;
56 if (expr->op != SPECIAL_OR_ASSIGN)
57 return;
58 if (positions_eq(&expr->pos, &expr->right->pos))
59 return;
60 name = get_shifter(expr->right);
61 if (!name)
62 return;
64 sm_msg("warn: '%s' is a shifter (not for '%s').",
65 name, show_special(expr->op));
68 static void match_binop(struct expression *expr)
70 const char *name;
72 if (positions_eq(&expr->pos, &expr->right->pos))
73 return;
74 if (expr->op != '&')
75 return;
76 name = get_shifter(expr->right);
77 if (!name)
78 return;
80 sm_msg("warn: bit shifter '%s' used for logical '%s'",
81 name, show_special(expr->op));
84 static void register_shifters(void)
86 char filename[256];
87 struct token *token;
88 char *name;
89 int *val;
91 snprintf(filename, sizeof(filename), "%s.bit_shifters", option_project_str);
92 token = get_tokens_file(filename);
93 if (!token)
94 return;
95 if (token_type(token) != TOKEN_STREAMBEGIN)
96 return;
97 token = token->next;
98 while (token_type(token) != TOKEN_STREAMEND) {
99 if (token_type(token) != TOKEN_IDENT)
100 return;
101 name = alloc_string(show_ident(token->ident));
102 token = token->next;
103 if (token_type(token) != TOKEN_NUMBER)
104 return;
105 val = malloc(sizeof(int));
106 *val = atoi(token->number);
107 insert_struct(shifters, name, val);
108 token = token->next;
110 clear_token_alloc();
113 static void match_binop_info(struct expression *expr)
115 char *name;
116 long long val;
118 if (positions_eq(&expr->pos, &expr->right->pos))
119 return;
120 if (expr->op != SPECIAL_LEFTSHIFT)
121 return;
122 if (expr->right->type != EXPR_VALUE)
123 return;
124 name = pos_ident(expr->right->pos);
125 if (!name)
126 return;
127 if (!get_value(expr->right, &val))
128 return;
129 sm_msg("info: bit shifter '%s' '%lld'", name, val);
132 static void match_call(const char *fn, struct expression *expr, void *_arg_no)
134 struct expression *arg_expr;
135 int arg_no = PTR_INT(_arg_no);
136 long long val;
137 char *name;
139 arg_expr = get_argument_from_call_expr(expr->args, arg_no);
140 if (positions_eq(&expr->pos, &arg_expr->pos))
141 return;
142 name = pos_ident(arg_expr->pos);
143 if (!name)
144 return;
145 if (!get_value(arg_expr, &val))
146 return;
147 sm_msg("info: bit shifter '%s' '%lld'", name, val);
150 void check_bit_shift(int id)
152 my_id = id;
154 shifters = create_function_hashtable(5000);
155 register_shifters();
157 add_hook(&match_assign, ASSIGNMENT_HOOK);
158 add_hook(&match_binop, BINOP_HOOK);
160 if (option_info) {
161 add_hook(&match_binop_info, BINOP_HOOK);
162 if (option_project == PROJ_KERNEL)
163 add_function_hook("set_bit", &match_call, INT_PTR(0));