2 * Copyright (C) 2012 Oracle.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, see http://www.gnu.org/copyleft/gpl.txt
19 * This test is used to warn about mixups between bit shifters and bit flags.
24 #include "smatch_function_hashtable.h"
28 static DEFINE_HASHTABLE_INSERT(insert_struct
, char, int);
29 static DEFINE_HASHTABLE_SEARCH(search_struct
, char, int);
30 static struct hashtable
*shifters
;
32 static const char *get_shifter(struct expression
*expr
)
36 const int *shifter_value
;
38 expr
= strip_expr(expr
);
39 if (expr
->type
!= EXPR_VALUE
)
41 if (!get_value(expr
, &expr_value
))
43 name
= pos_ident(expr
->pos
);
46 shifter_value
= search_struct(shifters
, (char *)name
);
49 if (sval_cmp_val(expr_value
, *shifter_value
) != 0)
54 static void match_assign(struct expression
*expr
)
58 if (expr
->op
!= SPECIAL_OR_ASSIGN
)
60 if (positions_eq(expr
->pos
, expr
->right
->pos
))
62 name
= get_shifter(expr
->right
);
66 sm_msg("warn: '%s' is a shifter (not for '%s').",
67 name
, show_special(expr
->op
));
70 static void match_binop(struct expression
*expr
)
74 if (positions_eq(expr
->pos
, expr
->right
->pos
))
78 name
= get_shifter(expr
->right
);
82 sm_msg("warn: bit shifter '%s' used for logical '%s'",
83 name
, show_special(expr
->op
));
86 static void register_shifters(void)
93 snprintf(filename
, sizeof(filename
), "%s.bit_shifters", option_project_str
);
94 token
= get_tokens_file(filename
);
97 if (token_type(token
) != TOKEN_STREAMBEGIN
)
100 while (token_type(token
) != TOKEN_STREAMEND
) {
101 if (token_type(token
) != TOKEN_IDENT
)
103 name
= alloc_string(show_ident(token
->ident
));
105 if (token_type(token
) != TOKEN_NUMBER
)
107 val
= malloc(sizeof(int));
108 *val
= atoi(token
->number
);
109 insert_struct(shifters
, name
, val
);
115 static void match_binop_info(struct expression
*expr
)
120 if (positions_eq(expr
->pos
, expr
->right
->pos
))
122 if (expr
->op
!= SPECIAL_LEFTSHIFT
)
124 if (expr
->right
->type
!= EXPR_VALUE
)
126 name
= pos_ident(expr
->right
->pos
);
129 if (!get_value(expr
->right
, &sval
))
131 sm_msg("info: bit shifter '%s' '%s'", name
, sval_to_str(sval
));
134 static void match_call(const char *fn
, struct expression
*expr
, void *_arg_no
)
136 struct expression
*arg_expr
;
137 int arg_no
= PTR_INT(_arg_no
);
141 arg_expr
= get_argument_from_call_expr(expr
->args
, arg_no
);
142 if (positions_eq(expr
->pos
, arg_expr
->pos
))
144 name
= pos_ident(arg_expr
->pos
);
147 if (!get_value(arg_expr
, &sval
))
149 sm_msg("info: bit shifter '%s' '%s'", name
, sval_to_str(sval
));
152 void check_bit_shift(int id
)
156 shifters
= create_function_hashtable(5000);
159 add_hook(&match_assign
, ASSIGNMENT_HOOK
);
160 add_hook(&match_binop
, BINOP_HOOK
);
163 add_hook(&match_binop_info
, BINOP_HOOK
);
164 if (option_project
== PROJ_KERNEL
) {
165 add_function_hook("set_bit", &match_call
, INT_PTR(0));
166 add_function_hook("test_bit", &match_call
, INT_PTR(0));