dereference: handle frob(&foo->bar); better
[smatch.git] / smatch_data_source.c
blobe63c27a89fc24e1fa46c58b1ed699a4d2332d772
1 /*
2 * Copyright (C) 2013 Oracle.
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.
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.
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
18 #include "smatch.h"
19 #include "smatch_slist.h"
20 #include "smatch_extra.h"
22 static int my_id;
24 static char *get_source_parameter(struct expression *expr)
26 struct expression *tmp;
27 const char *param_name;
28 struct symbol *sym;
29 char *name;
30 int param;
31 char *ret = NULL;
32 char buf[32];
33 int cnt = 0;
34 bool modified = false;
36 tmp = expr;
37 while ((tmp = get_assigned_expr(tmp))) {
38 expr = tmp;
39 if (cnt++ > 3)
40 break;
43 expr = strip_expr(expr);
44 if (expr->type != EXPR_SYMBOL)
45 return NULL;
47 name = expr_to_var_sym(expr, &sym);
48 if (!name || !sym)
49 goto free;
50 param = get_param_num_from_sym(sym);
51 if (param < 0)
52 goto free;
53 param_name = get_param_name_var_sym(name, sym);
54 if (!param_name)
55 goto free;
56 if (param_was_set_var_sym(name, sym))
57 modified = true;
59 snprintf(buf, sizeof(buf), "$%d%s%s", param, param_name + 1,
60 modified ? " [m]" : "");
61 ret = alloc_string(buf);
63 free:
64 free_string(name);
65 return ret;
68 static char *get_source_assignment(struct expression *expr)
70 struct expression *right;
71 char *name;
72 char buf[64];
73 char *ret;
75 right = get_assigned_expr(expr);
76 right = strip_expr(right);
77 if (!right)
78 return NULL;
79 if (right->type != EXPR_CALL || right->fn->type != EXPR_SYMBOL)
80 return NULL;
81 if (is_fake_call(right))
82 return NULL;
83 name = expr_to_str(right->fn);
84 if (!name)
85 return NULL;
86 snprintf(buf, sizeof(buf), "r %s", name);
87 ret = alloc_string(buf);
88 free_string(name);
89 return ret;
92 static char *get_source_str(struct expression *arg)
94 char *source;
96 source = get_source_parameter(arg);
97 if (source)
98 return source;
99 return get_source_assignment(arg);
102 static void match_caller_info(struct expression *expr)
104 struct expression *arg;
105 char *source;
106 int i;
108 i = -1;
109 FOR_EACH_PTR(expr->args, arg) {
110 i++;
111 source = get_source_str(arg);
112 if (!source)
113 continue;
114 sql_insert_caller_info(expr, DATA_SOURCE, i, "$", source);
115 free_string(source);
116 } END_FOR_EACH_PTR(arg);
119 void register_data_source(int id)
121 // if (!option_info)
122 // return;
123 my_id = id;
124 add_hook(&match_caller_info, FUNCTION_CALL_HOOK);