hooks: add a warning to detect unimplemented hooks
[smatch.git] / smatch_parsed_conditions.c
blob338d2a2605a068e0f8fa2fd7963be59cc4116be1
1 /*
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
30 * implications.
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.
40 #include "smatch.h"
41 #include "smatch_slist.h"
43 static int my_id;
45 STATE(true_path);
46 STATE(false_path);
48 void record_condition(struct expression *expr)
50 char name[32];
51 sval_t val;
53 if (get_value(expr, &val))
54 return;
56 if (__in_pre_condition)
57 return;
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)
65 my_id = 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)
73 if (!sm)
74 return;
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);
81 if (sm->merged) {
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;
94 char name[32];
96 snprintf(name, sizeof(name), "condition %p", expr);
98 sm = get_sm_state(my_id, name, NULL);
99 if (!sm)
100 return NULL;
101 if (!sm->merged)
102 return NULL;
104 filter_by_sm(sm, &tmp_true, &tmp_false);
105 if (!tmp_true && !tmp_false)
106 return NULL;
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);
119 return sm;