1 /*
   2  * Copyright (C) 2009 Dan Carpenter.
   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  * The idea behind this test is that if we have:
  20  * void foo(int bar)
  21  * {
  22  *         baz(1, bar);
  23  * }
  24  *
  25  * Passing "bar" to foo() really means passing "bar" to baz();
  26  * 
  27  * In this case it would print:
  28  * info: param_mapper 0 => bar 1
  29  *
  30  */
  31 
  32 #include "smatch.h"
  33 
  34 static int my_id;
  35 
  36 STATE(argument);
  37 
  38 static struct symbol *func_sym;
  39 
  40 static void delete(struct sm_state *sm, struct expression *mod_expr)
  41 {
  42         set_state(my_id, sm->name, sm->sym, &undefined);
  43 }
  44 
  45 static void match_function_def(struct symbol *sym)
  46 {
  47         struct symbol *arg;
  48 
  49         func_sym = sym;
  50         FOR_EACH_PTR(func_sym->ctype.base_type->arguments, arg) {
  51                 if (!arg->ident) {
  52                         continue;
  53                 }
  54                 set_state(my_id, arg->ident->name, arg, &argument);
  55         } END_FOR_EACH_PTR(arg);
  56 }
  57 
  58 static int get_arg_num(struct expression *expr)
  59 {
  60         struct smatch_state *state;
  61         struct symbol *arg;
  62         struct symbol *this_arg;
  63         int i;
  64 
  65         expr = strip_expr(expr);
  66         if (expr->type != EXPR_SYMBOL)
  67                 return -1;
  68         this_arg = expr->symbol;
  69 
  70         state = get_state_expr(my_id, expr);
  71         if (!state || state != &argument)
  72                 return -1;
  73         
  74         i = 0;
  75         FOR_EACH_PTR(func_sym->ctype.base_type->arguments, arg) {
  76                 if (arg == this_arg)
  77                         return i;
  78                 i++;
  79         } END_FOR_EACH_PTR(arg);
  80 
  81         return -1;
  82 }
  83 
  84 static void match_call(struct expression *expr)
  85 {
  86         struct expression *tmp;
  87         char *func;
  88         int arg_num;
  89         int i;
  90 
  91         if (expr->fn->type != EXPR_SYMBOL)
  92                 return;
  93 
  94         func = expr->fn->symbol_name->name;
  95 
  96         i = 0;
  97         FOR_EACH_PTR(expr->args, tmp) {
  98                 tmp = strip_expr(tmp);
  99                 arg_num = get_arg_num(tmp);
 100                 if (arg_num >= 0)
 101                         sm_msg("info: param_mapper %d => %s %d", arg_num, func, i);
 102                 i++;
 103         } END_FOR_EACH_PTR(tmp);
 104 }
 105 
 106 void check_param_mapper(int id)
 107 {
 108         if (!option_param_mapper)
 109                 return;
 110         my_id = id;
 111         add_modification_hook(my_id, &delete);
 112         add_hook(&match_function_def, FUNC_DEF_HOOK);
 113         add_hook(&match_call, FUNCTION_CALL_HOOK);
 114 }