2 * smatch/check_bit_shift.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
11 #include "smatch_function_hashtable.h"
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
)
23 if (pos1
->pos
!= pos2
->pos
)
25 if (pos1
->stream
!= pos2
->stream
)
30 static const char *get_shifter(struct expression
*expr
)
34 const int *shifter_value
;
36 expr
= strip_expr(expr
);
37 if (expr
->type
!= EXPR_VALUE
)
39 if (!get_value(expr
, &expr_value
))
41 name
= pos_ident(expr
->pos
);
44 shifter_value
= search_struct(shifters
, (char *)name
);
47 if (*shifter_value
!= expr_value
)
52 static void match_assign(struct expression
*expr
)
56 if (expr
->op
!= SPECIAL_OR_ASSIGN
)
58 if (positions_eq(&expr
->pos
, &expr
->right
->pos
))
60 name
= get_shifter(expr
->right
);
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
)
72 if (positions_eq(&expr
->pos
, &expr
->right
->pos
))
76 name
= get_shifter(expr
->right
);
80 sm_msg("warn: bit shifter '%s' used for logical '%s'",
81 name
, show_special(expr
->op
));
84 static void register_shifters(void)
91 snprintf(filename
, sizeof(filename
), "%s.bit_shifters", option_project_str
);
92 token
= get_tokens_file(filename
);
95 if (token_type(token
) != TOKEN_STREAMBEGIN
)
98 while (token_type(token
) != TOKEN_STREAMEND
) {
99 if (token_type(token
) != TOKEN_IDENT
)
101 name
= alloc_string(show_ident(token
->ident
));
103 if (token_type(token
) != TOKEN_NUMBER
)
105 val
= malloc(sizeof(int));
106 *val
= atoi(token
->number
);
107 insert_struct(shifters
, name
, val
);
113 static void match_binop_info(struct expression
*expr
)
118 if (positions_eq(&expr
->pos
, &expr
->right
->pos
))
120 if (expr
->op
!= SPECIAL_LEFTSHIFT
)
122 if (expr
->right
->type
!= EXPR_VALUE
)
124 name
= pos_ident(expr
->right
->pos
);
127 if (!get_value(expr
->right
, &val
))
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
);
139 arg_expr
= get_argument_from_call_expr(expr
->args
, arg_no
);
140 if (positions_eq(&expr
->pos
, &arg_expr
->pos
))
142 name
= pos_ident(arg_expr
->pos
);
145 if (!get_value(arg_expr
, &val
))
147 sm_msg("info: bit shifter '%s' '%lld'", name
, val
);
150 void check_bit_shift(int id
)
154 shifters
= create_function_hashtable(5000);
157 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
158 add_hook(&match_binop
, BINOP_HOOK
);
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));