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 const char *get_shifter(struct expression
*expr
)
23 const int *shifter_value
;
25 expr
= strip_expr(expr
);
26 if (expr
->type
!= EXPR_VALUE
)
28 if (!get_value(expr
, &expr_value
))
30 name
= pos_ident(expr
->pos
);
33 shifter_value
= search_struct(shifters
, (char *)name
);
36 if (sval_cmp_val(expr_value
, *shifter_value
) != 0)
41 static void match_assign(struct expression
*expr
)
45 if (expr
->op
!= SPECIAL_OR_ASSIGN
)
47 if (positions_eq(expr
->pos
, expr
->right
->pos
))
49 name
= get_shifter(expr
->right
);
53 sm_msg("warn: '%s' is a shifter (not for '%s').",
54 name
, show_special(expr
->op
));
57 static void match_binop(struct expression
*expr
)
61 if (positions_eq(expr
->pos
, expr
->right
->pos
))
65 name
= get_shifter(expr
->right
);
69 sm_msg("warn: bit shifter '%s' used for logical '%s'",
70 name
, show_special(expr
->op
));
73 static void register_shifters(void)
80 snprintf(filename
, sizeof(filename
), "%s.bit_shifters", option_project_str
);
81 token
= get_tokens_file(filename
);
84 if (token_type(token
) != TOKEN_STREAMBEGIN
)
87 while (token_type(token
) != TOKEN_STREAMEND
) {
88 if (token_type(token
) != TOKEN_IDENT
)
90 name
= alloc_string(show_ident(token
->ident
));
92 if (token_type(token
) != TOKEN_NUMBER
)
94 val
= malloc(sizeof(int));
95 *val
= atoi(token
->number
);
96 insert_struct(shifters
, name
, val
);
102 static void match_binop_info(struct expression
*expr
)
107 if (positions_eq(expr
->pos
, expr
->right
->pos
))
109 if (expr
->op
!= SPECIAL_LEFTSHIFT
)
111 if (expr
->right
->type
!= EXPR_VALUE
)
113 name
= pos_ident(expr
->right
->pos
);
116 if (!get_value(expr
->right
, &sval
))
118 sm_msg("info: bit shifter '%s' '%s'", name
, sval_to_str(sval
));
121 static void match_call(const char *fn
, struct expression
*expr
, void *_arg_no
)
123 struct expression
*arg_expr
;
124 int arg_no
= PTR_INT(_arg_no
);
128 arg_expr
= get_argument_from_call_expr(expr
->args
, arg_no
);
129 if (positions_eq(expr
->pos
, arg_expr
->pos
))
131 name
= pos_ident(arg_expr
->pos
);
134 if (!get_value(arg_expr
, &sval
))
136 sm_msg("info: bit shifter '%s' '%s'", name
, sval_to_str(sval
));
139 void check_bit_shift(int id
)
143 shifters
= create_function_hashtable(5000);
146 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
147 add_hook(&match_binop
, BINOP_HOOK
);
150 add_hook(&match_binop_info
, BINOP_HOOK
);
151 if (option_project
== PROJ_KERNEL
) {
152 add_function_hook("set_bit", &match_call
, INT_PTR(0));
153 add_function_hook("test_bit", &match_call
, INT_PTR(0));