2 * Copyright (C) 2019 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 * The problem here is something like this:
21 * return (blah() || whatever()) ? NULL : some_function();
23 * When we are parsing this what happens is that we first parse all the
24 * expressions "(blah() || whatever()) ? NULL : some_function();" and then
25 * we parse the return statement.
27 * When we parse the return statement, we say "Oh, this is a conditional. Let's
28 * get all the implications for true and false." But because
29 * "(blah() || whatever())" is a function pointer, that means there aren't any
32 * So what this module does is it ties the implications to the expression
33 * pointer so that we can retreive them easily. It's similar to Smatch stored
34 * implications but it doesn't save condition, it saves the pointer.
36 * We ignore pre loop conditions which Smatch parses twice.
41 #include "smatch_slist.h"
48 void record_condition(struct expression
*expr
)
53 if (get_value(expr
, &val
))
56 if (__in_pre_condition
)
59 snprintf(name
, sizeof(name
), "condition %p", expr
);
60 set_true_false_states(my_id
, name
, NULL
, &true_path
, &false_path
);
63 void register_parsed_conditions(int id
)
66 add_hook(&record_condition
, CONDITION_HOOK
);
69 static void filter_by_sm(struct sm_state
*sm
,
70 struct state_list
**true_stack
,
71 struct state_list
**false_stack
)
76 if (sm
->state
== &true_path
)
77 add_ptr_list(true_stack
, sm
);
78 else if (sm
->state
== &false_path
)
79 add_ptr_list(false_stack
, sm
);
82 filter_by_sm(sm
->left
, true_stack
, false_stack
);
83 filter_by_sm(sm
->right
, true_stack
, false_stack
);
87 struct sm_state
*parsed_condition_implication_hook(struct expression
*expr
,
88 struct state_list
**true_stack
,
89 struct state_list
**false_stack
)
91 struct state_list
*tmp_true
= NULL
;
92 struct state_list
*tmp_false
= NULL
;
93 struct sm_state
*sm
, *tmp
;
96 snprintf(name
, sizeof(name
), "condition %p", expr
);
98 sm
= get_sm_state(my_id
, name
, NULL
);
104 filter_by_sm(sm
, &tmp_true
, &tmp_false
);
105 if (!tmp_true
&& !tmp_false
)
108 FOR_EACH_PTR(tmp_true
, tmp
) {
109 add_ptr_list(true_stack
, tmp
);
110 } END_FOR_EACH_PTR(tmp
);
112 FOR_EACH_PTR(tmp_false
, tmp
) {
113 add_ptr_list(false_stack
, tmp
);
114 } END_FOR_EACH_PTR(tmp
);
116 free_slist(&tmp_true
);
117 free_slist(&tmp_false
);