1 /*
   2  * Copyright (C) 2015 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_slist.h"
  20 
  21 static int my_id;
  22 
  23 static struct stree *used_stree;
  24 static struct stree_stack *saved_stack;
  25 
  26 STATE(used);
  27 
  28 static void get_state_hook(int owner, const char *name, struct symbol *sym)
  29 {
  30         int arg;
  31 
  32         if (!option_info)
  33                 return;
  34         if (__in_fake_assign || __in_fake_parameter_assign || __in_function_def)
  35                 return;
  36 
  37         arg = get_param_num_from_sym(sym);
  38         if (arg >= 0)
  39                 set_state_stree(&used_stree, my_id, name, sym, &used);
  40 }
  41 
  42 static void set_param_used(struct expression *call, struct expression *arg, char *key, char *unused)
  43 {
  44         struct symbol *sym;
  45         char *name;
  46         int arg_nr;
  47 
  48         name = get_variable_from_key(arg, key, &sym);
  49         if (!name || !sym)
  50                 goto free;
  51 
  52         arg_nr = get_param_num_from_sym(sym);
  53         if (arg_nr >= 0)
  54                 set_state_stree(&used_stree, my_id, name, sym, &used);
  55 free:
  56         free_string(name);
  57 }
  58 
  59 static void process_states(void)
  60 {
  61         struct sm_state *tmp;
  62         int arg;
  63         const char *name;
  64 
  65         FOR_EACH_SM(used_stree, tmp) {
  66                 arg = get_param_num_from_sym(tmp->sym);
  67                 if (arg < 0)
  68                         continue;
  69                 name = get_param_name(tmp);
  70                 if (!name)
  71                         continue;
  72                 if (is_recursive_member(name))
  73                         continue;
  74 
  75                 if (is_ignored_kernel_data(name))
  76                         continue;
  77 
  78                 sql_insert_return_implies(PARAM_USED, arg, name, "");
  79         } END_FOR_EACH_SM(tmp);
  80 
  81         free_stree(&used_stree);
  82 }
  83 
  84 static void match_function_def(struct symbol *sym)
  85 {
  86         free_stree(&used_stree);
  87 }
  88 
  89 static void match_save_states(struct expression *expr)
  90 {
  91         push_stree(&saved_stack, used_stree);
  92         used_stree = NULL;
  93 }
  94 
  95 static void match_restore_states(struct expression *expr)
  96 {
  97         free_stree(&used_stree);
  98         used_stree = pop_stree(&saved_stack);
  99 }
 100 
 101 void register_param_used(int id)
 102 {
 103         my_id = id;
 104 
 105         add_hook(&match_function_def, FUNC_DEF_HOOK);
 106 
 107         add_get_state_hook(&get_state_hook);
 108 
 109         add_hook(&match_save_states, INLINE_FN_START);
 110         add_hook(&match_restore_states, INLINE_FN_END);
 111 
 112         select_return_implies_hook(PARAM_USED, &set_param_used);
 113         all_return_states_hook(&process_states);
 114 }