param_key: fix container of when no struct member is referenced
[smatch.git] / smatch_state_assigned.c
blobb6eee85870bd4d9c456d156ab6327bf25a777931
1 /*
2 * Copyright (C) 2022 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;
23 static int ssa_id;
25 static sm_hook **hooks;
26 static sm_hook **ssa_hooks;
28 void add_state_assigned_hook(int owner, sm_hook *call_back)
30 if (hooks[owner])
31 sm_fatal("multiple state_assigned_hook hooks for %s", check_name(owner));
32 hooks[owner] = call_back;
35 void add_ssa_state_assigned_hook(int owner, sm_hook *call_back)
37 if (ssa_hooks[owner])
38 sm_fatal("multiple ssa_state_assigned_hook hooks for %s", check_name(owner));
39 ssa_hooks[owner] = call_back;
42 static void call_ssa_hooks(struct sm_state *ssa_sm, struct sm_state *sm, struct expression *expr)
44 struct sm_state *tmp;
46 if (!ssa_sm)
47 return;
48 if (!ssa_hooks[sm->owner])
49 return;
50 /* should be safe to assume sm->sym is NULL */
51 if (sm->sym)
52 return;
55 * Merged ssa states are a bit complicated to handle.
56 * This is the laziest way to handle it, but it works for my
57 * only use case and it might even be a good way to handle it.
59 FOR_EACH_PTR(ssa_sm->possible, tmp) {
60 if (tmp->state == &merged ||
61 tmp->state == &undefined)
62 continue;
63 if (strcmp(tmp->state->name, sm->name) == 0)
64 ssa_hooks[sm->owner](sm, expr);
65 } END_FOR_EACH_PTR(tmp);
69 static void match_assignment(struct expression *expr)
71 struct expression *right;
72 struct sm_state *ssa_sm, *sm;
73 struct symbol *sym;
74 char *name;
76 right = strip_expr(expr->right);
77 name = expr_to_var_sym(right, &sym);
78 if (!name || !sym)
79 return;
81 ssa_sm = get_sm_state(ssa_id, name, sym);
83 FOR_EACH_SM(__get_cur_stree(), sm) {
84 if (sm->owner >= num_checks)
85 continue;
87 call_ssa_hooks(ssa_sm, sm, expr);
89 if (hooks[sm->owner] &&
90 sm->sym == sym &&
91 strcmp(sm->name, name) == 0)
92 hooks[sm->owner](sm, expr);
93 } END_FOR_EACH_SM(sm);
95 free_string(name);
98 void register_state_assigned(int id)
100 my_id = id;
102 hooks = malloc((num_checks + 1) * sizeof(*hooks));
103 memset(hooks, 0, (num_checks + 1) * sizeof(*hooks));
105 ssa_id = id_from_name("register_ssa");
106 ssa_hooks = malloc((num_checks + 1) * sizeof(*ssa_hooks));
107 memset(ssa_hooks, 0, (num_checks + 1) * sizeof(*ssa_hooks));
109 add_hook(&match_assignment, ASSIGNMENT_HOOK_AFTER);