db/fixup_kernel.sh: fix clear_user() handling
[smatch.git] / smatch_impossible.c
blob440a4c7bc65abe398b118ec1efe18195212c2a8b
1 /*
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
18 #include "smatch.h"
19 #include "smatch_extra.h"
21 static int my_id;
22 static int my_return_id;
24 unsigned long nothing_impossible;
26 STATE(impossible);
28 int is_impossible_path(void)
30 if (get_state(my_id, "impossible", NULL) == &impossible)
31 return 1;
32 return 0;
35 static void handle_compare(struct expression *left, int op, struct expression *right)
37 int true_impossible = 0;
38 int false_impossible = 0;
40 left = strip_expr(left);
41 while (left && left->type == EXPR_ASSIGNMENT)
42 left = strip_expr(left->left);
44 if (!possibly_true(left, op, right))
45 true_impossible = 1;
46 if (!possibly_false(left, op, right))
47 false_impossible = 1;
49 if (!true_impossible && !false_impossible)
50 return;
52 set_true_false_states(my_id, "impossible", NULL,
53 true_impossible ? &impossible : NULL,
54 false_impossible ? &impossible : NULL);
56 if (inside_loop())
57 return;
59 set_true_false_states(my_return_id, "impossible", NULL,
60 true_impossible ? &impossible : NULL,
61 false_impossible ? &impossible : NULL);
64 static void match_condition(struct expression *expr)
66 if (expr->type == EXPR_COMPARE)
67 handle_compare(expr->left, expr->op, expr->right);
68 else
69 handle_compare(expr, SPECIAL_NOTEQUAL, zero_expr());
72 void set_true_path_impossible(void)
74 set_true_false_states(my_id, "impossible", NULL, &impossible, NULL);
75 if (inside_loop())
76 return;
77 set_true_false_states(my_return_id, "impossible", NULL, &impossible, NULL);
80 void set_false_path_impossible(void)
82 set_true_false_states(my_id, "impossible", NULL, NULL, &impossible);
83 if (inside_loop())
84 return;
85 set_true_false_states(my_return_id, "impossible", NULL, NULL, &impossible);
88 void set_path_impossible(void)
90 set_state(my_id, "impossible", NULL, &impossible);
92 if (inside_loop())
93 return;
95 set_state(my_return_id, "impossible", NULL, &impossible);
98 static void match_case(struct expression *expr, struct range_list *rl)
100 if (rl)
101 return;
102 set_path_impossible();
105 static void print_impossible_return(int return_id, char *return_ranges, struct expression *expr)
107 if (nothing_impossible)
108 return;
110 if (get_state(my_return_id, "impossible", NULL) == &impossible) {
111 if (option_debug)
112 sm_msg("impossible return. return_id = %d return ranges = %s", return_id, return_ranges);
113 sql_insert_return_states(return_id, return_ranges, CULL_PATH, -1, "", "");
117 static void match_thread_stuff(const char *fn, struct expression *expr, void *unused)
119 nothing_impossible = true;
122 void register_impossible(int id)
124 my_id = id;
126 add_hook(&match_condition, CONDITION_HOOK);
127 add_hook(&match_case, CASE_HOOK);
130 void register_impossible_return(int id)
132 my_return_id = id;
134 add_function_data(&nothing_impossible);
135 if (option_project == PROJ_KERNEL) {
136 add_function_hook("wait_for_completion", &match_thread_stuff, NULL);
137 add_function_hook("wait_for_completion_timeout", &match_thread_stuff, NULL);
138 add_function_hook("wait_for_completion_io", &match_thread_stuff, NULL);
139 add_function_hook("wait_for_completion_io_timeout", &match_thread_stuff, NULL);
140 add_function_hook("wait_for_completion_interruptible", &match_thread_stuff, NULL);
141 add_function_hook("wait_for_completion_interruptible_timeout", &match_thread_stuff, NULL);
142 add_function_hook("wait_for_completion_killable", &match_thread_stuff, NULL);
143 add_function_hook("wait_for_completion_state", &match_thread_stuff, NULL);
144 add_function_hook("wait_for_completion_killable_timeout", &match_thread_stuff, NULL);
145 add_function_hook("try_wait_for_completion", &match_thread_stuff, NULL);
148 add_split_return_callback(&print_impossible_return);