2 * Copyright (C) 2014 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
21 #include "smatch_extra.h"
25 static bool in_same_block(struct expression
*one
, struct expression
*two
)
27 struct statement
*a
, *b
;
29 a
= get_parent_stmt(one
);
30 b
= get_parent_stmt(two
);
33 return a
->parent
== b
->parent
;
36 static bool is_loop_condition(struct expression
*expr
)
38 struct statement
*stmt
;
41 * Two things. First of all get_stored_condition() is buggy.
42 * Secondly, even if it were not buggy there would be an
43 * issue checking the pre condition before the loop runs.
45 stmt
= get_parent_stmt(expr
);
46 if (stmt
&& stmt
->type
== STMT_ITERATOR
)
51 static bool is_part_of_logical(struct expression
*expr
)
53 while ((expr
= expr_get_parent_expr(expr
))) {
54 if (expr
->type
== EXPR_PREOP
) {
55 if (expr
->op
== '!' ||
59 if (expr
->type
== EXPR_COMPARE
)
61 if (expr
->type
== EXPR_LOGICAL
)
68 static bool last_in_chain_of_else_if_statements(struct expression
*expr
)
70 struct statement
*stmt
;
72 stmt
= get_parent_stmt(expr
);
75 if (stmt
->type
!= STMT_IF
)
79 stmt
= stmt_get_parent_stmt(stmt
);
82 if (stmt
->type
!= STMT_IF
)
87 static bool is_global(struct expression
*expr
)
91 sym
= expr_to_sym(expr
);
94 return !!(sym
->ctype
.modifiers
& MOD_TOPLEVEL
);
97 static bool is_dereference(struct expression
*expr
)
99 expr
= strip_expr(expr
);
101 if (expr
->type
== EXPR_COMPARE
||
102 expr
->type
== EXPR_BINOP
) {
103 if (is_dereference(expr
->left
) ||
104 is_dereference(expr
->right
))
108 if (expr
->type
!= EXPR_DEREF
)
113 static void match_condition(struct expression
*expr
)
115 struct expression
*old_condition
;
116 struct smatch_state
*state
;
120 if (__in_fake_parameter_assign
|| __reparsing_code
)
123 if (get_macro_name(expr
->pos
))
126 if (is_loop_condition(expr
))
129 if (is_part_of_logical(expr
))
132 if (last_in_chain_of_else_if_statements(expr
))
138 if (is_dereference(expr
))
141 state
= get_stored_condition(expr
);
142 if (!state
|| !state
->data
)
144 old_condition
= state
->data
;
145 if (get_macro_name(old_condition
->pos
))
148 if (inside_loop() && !in_same_block(old_condition
, expr
))
151 name
= expr_to_str_sym(expr
, &sym
);
152 state
= get_state(my_id
, name
, sym
);
153 if (state
!= &true_state
&& state
!= &false_state
)
156 sm_warning("duplicate check '%s' (previous on line %d)", name
, old_condition
->pos
.line
);
161 static bool has_array(struct expression
*expr
)
168 if (expr
->type
== EXPR_COMPARE
)
169 return is_array(expr
->left
);
173 static void match_condition_store(struct expression
*expr
)
179 if (get_value(expr
, &dummy
))
185 name
= expr_to_str_sym(expr
, &sym
);
189 if (sym
&& sym
->ctype
.modifiers
& MOD_TOPLEVEL
)
192 set_true_false_states(my_id
, name
, sym
, &true_state
, &false_state
);
197 void check_double_checking(int id
)
204 turn_off_implications(my_id
);
206 add_hook(&match_condition
, CONDITION_HOOK
);
207 add_hook(&match_condition_store
, CONDITION_HOOK
);