1 /*
   2  * Copyright (C) 2016 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 /*
  19  * Say you have a condition like:
  20  *
  21  *     if (foo < 0)
  22  *         return foo;
  23  *
  24  * But we actually know that foo is zero.  Then in smatch_extra.c we set "foo"
  25  * to the empty state and then for the return statement we say that "foo" is
  26  * s32min-s32max because we can't return the empty state.
  27  *
  28  * This file is supposed to provide an alternative to say that actually "foo" is
  29  * less than zero.
  30  *
  31  */
  32 
  33 #include "smatch.h"
  34 #include "smatch_slist.h"
  35 #include "smatch_extra.h"
  36 
  37 static int my_id;
  38 
  39 static struct smatch_state *empty_state(struct sm_state *sm)
  40 {
  41         return alloc_estate_empty();
  42 }
  43 
  44 struct smatch_state *merge_is_empty(struct smatch_state *s1, struct smatch_state *s2)
  45 {
  46         return alloc_estate_empty();
  47 }
  48 
  49 static void reset(struct sm_state *sm, struct expression *mod_expr)
  50 {
  51         set_state(my_id, sm->name, sm->sym, alloc_estate_empty());
  52 }
  53 
  54 void __save_imaginary_state(struct expression *expr, struct range_list *true_rl, struct range_list *false_rl)
  55 {
  56         if (__in_pre_condition)
  57                 return;
  58         set_true_false_states_expr(my_id, expr, alloc_estate_rl(true_rl), alloc_estate_rl(false_rl));
  59 }
  60 
  61 int get_imaginary_absolute(struct expression *expr, struct range_list **rl)
  62 {
  63         struct smatch_state *state;
  64 
  65         *rl = NULL;
  66 
  67         state = get_state_expr(my_id, expr);
  68         if (!state || !estate_rl(state))
  69                 return 0;
  70 
  71         *rl = estate_rl(state);
  72         return 1;
  73 }
  74 
  75 void register_imaginary_absolute(int id)
  76 {
  77         my_id = id;
  78 
  79         set_dynamic_states(my_id);
  80         add_unmatched_state_hook(my_id, &empty_state);
  81         add_merge_hook(my_id, &merge_is_empty);
  82         add_modification_hook(my_id, &reset);
  83 }
  84