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
;
119 if (__in_fake_parameter_assign
)
122 if (get_macro_name(expr
->pos
))
125 if (is_loop_condition(expr
))
128 if (is_part_of_logical(expr
))
131 if (last_in_chain_of_else_if_statements(expr
))
137 if (is_dereference(expr
))
140 state
= get_stored_condition(expr
);
141 if (!state
|| !state
->data
)
143 old_condition
= state
->data
;
144 if (get_macro_name(old_condition
->pos
))
147 if (inside_loop() && !in_same_block(old_condition
, expr
))
150 name
= expr_to_str(expr
);
151 sm_warning("duplicate check '%s' (previous on line %d)", name
, old_condition
->pos
.line
);
155 void check_double_checking(int id
)
162 add_hook(&match_condition
, CONDITION_HOOK
);