1 /*
   2  * Copyright (C) 2010 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 #include "smatch.h"
  19 
  20 static int my_id;
  21 static struct symbol *func_sym;
  22 
  23 STATE(argument);
  24 STATE(ok);
  25 
  26 static void set_ok(struct sm_state *sm, struct expression *mod_expr)
  27 {
  28         if (sm->state != &ok)
  29                 set_state(my_id, sm->name, sm->sym, &ok);
  30 }
  31 
  32 static void match_function_def(struct symbol *sym)
  33 {
  34         struct symbol *arg;
  35 
  36         func_sym = sym;
  37         FOR_EACH_PTR(func_sym->ctype.base_type->arguments, arg) {
  38                 if (!arg->ident) {
  39                         continue;
  40                 }
  41                 set_state(my_id, arg->ident->name, arg, &argument);
  42         } END_FOR_EACH_PTR(arg);
  43 }
  44 
  45 static int get_arg_num(struct expression *expr)
  46 {
  47         struct smatch_state *state;
  48         struct symbol *arg;
  49         struct symbol *this_arg;
  50         int i;
  51 
  52         expr = strip_expr(expr);
  53         if (expr->type != EXPR_SYMBOL)
  54                 return -1;
  55         this_arg = expr->symbol;
  56 
  57         state = get_state_expr(my_id, expr);
  58         if (!state || state != &argument)
  59                 return -1;
  60         
  61         i = 0;
  62         FOR_EACH_PTR(func_sym->ctype.base_type->arguments, arg) {
  63                 if (arg == this_arg)
  64                         return i;
  65                 i++;
  66         } END_FOR_EACH_PTR(arg);
  67 
  68         return -1;
  69 }
  70 
  71 static void match_is_err(const char *fn, struct expression *expr, void *unused)
  72 {
  73         struct expression *arg;
  74         int arg_num;
  75 
  76         arg = get_argument_from_call_expr(expr->args, 0);
  77         arg_num = get_arg_num(arg);
  78         if (arg_num < 0)
  79                 return;
  80         sm_msg("info: expects ERR_PTR %d", arg_num);
  81 }
  82 
  83 void check_expects_err_ptr(int id)
  84 {
  85         if (option_project != PROJ_KERNEL)
  86                 return;
  87         if (!option_info)
  88                 return;
  89 
  90         my_id = id;
  91         add_hook(&match_function_def, FUNC_DEF_HOOK);
  92         add_modification_hook(my_id, &set_ok);
  93         add_function_hook("IS_ERR", &match_is_err, NULL);
  94 }