2 * smatch/check_bit_shift.c
4 * Copyright (C) 2012 Oracle.
6 * Licensed under the Open Software License version 1.1
11 * This test is used to warn about mixups between bit shifters and bit flags.
16 #include "smatch_function_hashtable.h"
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
)
28 const int *shifter_value
;
30 expr
= strip_expr(expr
);
31 if (expr
->type
!= EXPR_VALUE
)
33 if (!get_value(expr
, &expr_value
))
35 name
= pos_ident(expr
->pos
);
38 shifter_value
= search_struct(shifters
, (char *)name
);
41 if (sval_cmp_val(expr_value
, *shifter_value
) != 0)
46 static void match_assign(struct expression
*expr
)
50 if (expr
->op
!= SPECIAL_OR_ASSIGN
)
52 if (positions_eq(expr
->pos
, expr
->right
->pos
))
54 name
= get_shifter(expr
->right
);
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
)
66 if (positions_eq(expr
->pos
, expr
->right
->pos
))
70 name
= get_shifter(expr
->right
);
74 sm_msg("warn: bit shifter '%s' used for logical '%s'",
75 name
, show_special(expr
->op
));
78 static void register_shifters(void)
85 snprintf(filename
, sizeof(filename
), "%s.bit_shifters", option_project_str
);
86 token
= get_tokens_file(filename
);
89 if (token_type(token
) != TOKEN_STREAMBEGIN
)
92 while (token_type(token
) != TOKEN_STREAMEND
) {
93 if (token_type(token
) != TOKEN_IDENT
)
95 name
= alloc_string(show_ident(token
->ident
));
97 if (token_type(token
) != TOKEN_NUMBER
)
99 val
= malloc(sizeof(int));
100 *val
= atoi(token
->number
);
101 insert_struct(shifters
, name
, val
);
107 static void match_binop_info(struct expression
*expr
)
112 if (positions_eq(expr
->pos
, expr
->right
->pos
))
114 if (expr
->op
!= SPECIAL_LEFTSHIFT
)
116 if (expr
->right
->type
!= EXPR_VALUE
)
118 name
= pos_ident(expr
->right
->pos
);
121 if (!get_value(expr
->right
, &sval
))
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
);
133 arg_expr
= get_argument_from_call_expr(expr
->args
, arg_no
);
134 if (positions_eq(expr
->pos
, arg_expr
->pos
))
136 name
= pos_ident(arg_expr
->pos
);
139 if (!get_value(arg_expr
, &sval
))
141 sm_msg("info: bit shifter '%s' '%s'", name
, sval_to_str(sval
));
144 void check_bit_shift(int id
)
148 shifters
= create_function_hashtable(5000);
151 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
152 add_hook(&match_binop
, BINOP_HOOK
);
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));