2 * sparse/smatch_conditions.c
4 * Copyright (C) 2006,2008 Dan Carpenter.
6 * Licensed under the Open Software License version 1.1
18 static void split_conditions(struct expression
*expr
);
20 static int is_logical_and(struct expression
*expr
)
22 /* If you have if (!(a && b)) smatch translates that to
23 * if (!a || !b). Logically those are the same.
26 if ((!__negate
&& expr
->op
== SPECIAL_LOGICAL_AND
) ||
27 (__negate
&& expr
->op
== SPECIAL_LOGICAL_OR
))
32 static int is_logical_or(struct expression
*expr
)
34 if ((!__negate
&& expr
->op
== SPECIAL_LOGICAL_OR
) ||
35 (__negate
&& expr
->op
== SPECIAL_LOGICAL_AND
))
40 static void inc_ands_ors(struct expression
*expr
)
42 if (is_logical_and(expr
))
44 else if (is_logical_or(expr
))
48 static void dec_ands_ors(struct expression
*expr
)
50 if (is_logical_and(expr
))
52 else if (is_logical_or(expr
))
56 static void special_kernel_macros(struct expression
*expr
)
59 struct expression
*tmp
;
61 tmp
= first_ptr_list((struct ptr_list
*) expr
->args
);
62 if (tmp
->op
== '!' && tmp
->unop
->op
== '!'
63 && tmp
->unop
->unop
->op
== '(') {
64 split_conditions(tmp
->unop
->unop
->unop
);
66 __pass_to_client(expr
, CONDITION_HOOK
);
74 static int is_zero(struct expression
*expr
)
76 if (expr
->type
== EXPR_VALUE
&& expr
->value
== 0)
79 return is_zero(expr
->unop
);
80 if (expr
->type
== EXPR_CAST
)
81 return is_zero(expr
->cast_expression
);
85 static int handle_zero_comparisons(struct expression
*expr
)
87 struct expression
*tmp
= NULL
;
89 // if left is zero or right is zero
90 if (is_zero(expr
->left
))
92 else if (is_zero(expr
->right
))
97 // "if (foo != 0)" is the same as "if (foo)"
98 if (expr
->op
== SPECIAL_NOTEQUAL
) {
99 split_conditions(tmp
);
103 // "if (foo == 0)" is the same as "if (!foo)"
104 if (expr
->op
== SPECIAL_EQUAL
) {
105 __negate
= (__negate
+ 1)%2;
106 split_conditions(tmp
);
107 __negate
= (__negate
+ 1)%2;
114 static void split_conditions(struct expression
*expr
)
117 * If you have if ((a || a = foo()), we know a is
118 * non-null on the true state because 'a' is checked in both and
119 * groups. __ors_reached helps with that. Unfortunately
120 * smatch doesn't handle stuff like if (a && a = foo())
121 * because it never occured to me that people would do that...
124 static int __ors_reached
;
126 SM_DEBUG("%d in split_conditions type=%d\n", get_lineno(), expr
->type
);
128 if (expr
->type
== EXPR_COMPARE
)
129 if (handle_zero_comparisons(expr
))
132 if (expr
->type
== EXPR_LOGICAL
) {
133 unsigned int path_orig
;
136 path_orig
= __split_path_id();
137 __split_false_states_mini();
139 split_conditions(expr
->left
);
141 if (is_logical_and(expr
)) {
143 __pop_false_states_mini();
144 split_conditions(expr
->right
);
145 } else if (is_logical_or(expr
)) {
146 if (!__ors_reached
) {
153 __use_false_states_mini();
154 split_conditions(expr
->right
);
158 if (__ands
+ __ors
== 0) {
164 __restore_path_id(path_orig
);
166 } else if (expr
->type
== EXPR_PREOP
&& expr
->op
== '!') {
167 __negate
= (__negate
+ 1)%2;
168 split_conditions(expr
->unop
);
169 __negate
= (__negate
+ 1)%2;
171 } else if (expr
->type
== EXPR_PREOP
&& expr
->op
== '(') {
172 split_conditions(expr
->unop
);
173 } else if (expr
->type
== EXPR_CALL
) {
175 if (expr
->fn
->type
!= EXPR_SYMBOL
||
176 strcmp("__builtin_expect", expr
->fn
->symbol_name
->name
)) {
177 __pass_to_client(expr
, CONDITION_HOOK
);
181 special_kernel_macros(expr
);
183 __pass_to_client(expr
, CONDITION_HOOK
);
188 void __split_whole_condition(struct expression
*expr
)
191 split_conditions(expr
);
192 SM_DEBUG("%d __ands = %d __ors = %d __negate = %d\n", get_lineno(),
193 __ands
, __ors
, __negate
);