1 /* 2 * Copyright (C) 2014 Oracle. 3 * 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. 8 * 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. 13 * 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 16 */ 17 18 #include "smatch.h" 19 #include "smatch_extra.h" 20 21 static int my_id; 22 static int my_return_id; 23 24 STATE(impossible); 25 26 int is_impossible_path(void) 27 { 28 if (get_state(my_id, "impossible", NULL) == &impossible) 29 return 1; 30 return 0; 31 } 32 33 static void handle_compare(struct expression *left, int op, struct expression *right) 34 { 35 int true_impossible = 0; 36 int false_impossible = 0; 37 38 left = strip_expr(left); 39 while (left && left->type == EXPR_ASSIGNMENT) 40 left = strip_expr(left->left); 41 42 if (!possibly_true(left, op, right)) 43 true_impossible = 1; 44 if (!possibly_false(left, op, right)) 45 false_impossible = 1; 46 47 if (!true_impossible && !false_impossible) 48 return; 49 50 set_true_false_states(my_id, "impossible", NULL, 51 true_impossible ? &impossible : NULL, 52 false_impossible ? &impossible : NULL); 53 54 if (inside_loop()) 55 return; 56 57 set_true_false_states(my_return_id, "impossible", NULL, 58 true_impossible ? &impossible : NULL, 59 false_impossible ? &impossible : NULL); 60 } 61 62 static void match_condition(struct expression *expr) 63 { 64 if (expr->type == EXPR_COMPARE) 65 handle_compare(expr->left, expr->op, expr->right); 66 else 67 handle_compare(expr, SPECIAL_NOTEQUAL, zero_expr()); 68 } 69 70 void set_path_impossible(void) 71 { 72 set_state(my_id, "impossible", NULL, &impossible); 73 74 if (inside_loop()) 75 return; 76 77 set_state(my_return_id, "impossible", NULL, &impossible); 78 } 79 80 static void match_case(struct expression *expr, struct range_list *rl) 81 { 82 if (rl) 83 return; 84 set_path_impossible(); 85 } 86 87 static void print_impossible_return(int return_id, char *return_ranges, struct expression *expr) 88 { 89 if (get_state(my_return_id, "impossible", NULL) == &impossible) { 90 if (option_debug) 91 sm_msg("impossible return. return_id = %d return ranges = %s", return_id, return_ranges); 92 sql_insert_return_states(return_id, return_ranges, CULL_PATH, -1, "", ""); 93 } 94 } 95 96 void register_impossible(int id) 97 { 98 my_id = id; 99 100 add_hook(&match_condition, CONDITION_HOOK); 101 add_hook(&match_case, CASE_HOOK); 102 } 103 104 void register_impossible_return(int id) 105 { 106 my_return_id = id; 107 108 add_split_return_callback(&print_impossible_return); 109 } 110