1+ /* ******************************************************************\
2+
3+ Module: Unit test utilities
4+
5+ Author: DiffBlue Limited. All rights reserved.
6+
7+ \*******************************************************************/
8+
9+ #include < goto-programs/goto_program.h>
10+ #include " java_testing_utils.h"
11+
12+ struct_component_assignment_locationt combine_locations (
13+ const struct_component_assignment_locationt &a,
14+ const struct_component_assignment_locationt &b)
15+ {
16+ struct_component_assignment_locationt new_locations;
17+
18+ new_locations.assignment_locations .insert (
19+ new_locations.assignment_locations .end (),
20+ a.assignment_locations .begin (),
21+ a.assignment_locations .end ());
22+
23+ new_locations.assignment_locations .insert (
24+ new_locations.assignment_locations .end (),
25+ b.assignment_locations .begin (),
26+ b.assignment_locations .end ());
27+
28+ return new_locations;
29+ }
30+
31+ struct_component_assignment_locationt find_struct_component_assignments (
32+ const exprt::operandst &entry_point_instructions,
33+ const irep_idt &structure_name,
34+ const irep_idt &component_name)
35+ {
36+ struct_component_assignment_locationt component_assignments;
37+
38+ for (const auto &instruction : entry_point_instructions)
39+ {
40+ const codet &assignment = to_code (instruction);
41+ INVARIANT (instruction.id () == ID_code, " All instructions must be code" );
42+ if (assignment.get_statement () == ID_assign)
43+ {
44+ const code_assignt &code_assign = to_code_assign (assignment);
45+
46+ if (code_assign.lhs ().id () == ID_member)
47+ {
48+ const auto &member_expr = to_member_expr (code_assign.lhs ());
49+ const auto &symbol = member_expr.symbol ();
50+
51+ if (
52+ symbol.get_identifier () == structure_name &&
53+ member_expr.get_component_name () == component_name)
54+ {
55+ component_assignments.assignment_locations .push_back (code_assign);
56+ }
57+ }
58+ }
59+ else if (assignment.get_statement () == ID_block)
60+ {
61+ const auto &assignments_in_block = find_struct_component_assignments (
62+ assignment.operands (), structure_name, component_name);
63+ component_assignments =
64+ combine_locations (component_assignments, assignments_in_block);
65+ }
66+ else if (assignment.get_statement () == ID_ifthenelse)
67+ {
68+ const code_ifthenelset &if_else_block =
69+ to_code_ifthenelse (to_code (assignment));
70+ const auto &assignments_in_block = find_struct_component_assignments (
71+ exprt::operandst{if_else_block.then_case ()},
72+ structure_name,
73+ component_name);
74+ component_assignments =
75+ combine_locations (component_assignments, assignments_in_block);
76+
77+ if (if_else_block.has_else_case ())
78+ {
79+ const auto &assignments_in_else = find_struct_component_assignments (
80+ exprt::operandst{if_else_block.else_case ()},
81+ structure_name,
82+ component_name);
83+ component_assignments =
84+ combine_locations (component_assignments, assignments_in_else);
85+ }
86+ }
87+ else if (assignment.get_statement () == ID_label)
88+ {
89+ const code_labelt &label_statement = to_code_label (assignment);
90+ const auto &assignments_in_label = find_struct_component_assignments (
91+ exprt::operandst{label_statement.code ()},
92+ structure_name,
93+ component_name);
94+ component_assignments =
95+ combine_locations (component_assignments, assignments_in_label);
96+ }
97+ }
98+ return component_assignments;
99+ }
100+
101+ // / Combine two pointer locations. Takes the null assignment if present in
102+ // / either (fails if present in both) and appends the non-null assignments
103+ // / \param a: The first set of assignments
104+ // / \param b: The second set of assignments
105+ // / \return The resulting assignment
106+ pointer_assignment_locationt combine_locations (
107+ const pointer_assignment_locationt &a,
108+ const pointer_assignment_locationt &b)
109+ {
110+ pointer_assignment_locationt new_locations;
111+ if (a.null_assignment .has_value ())
112+ {
113+ INVARIANT (
114+ !b.null_assignment .has_value (), " Only expected one assignment to null" );
115+ new_locations.null_assignment = a.null_assignment ;
116+ }
117+ else if (b.null_assignment .has_value ())
118+ {
119+ INVARIANT (
120+ !a.null_assignment .has_value (), " Only expected one assignment to null" );
121+ new_locations.null_assignment = b.null_assignment ;
122+ }
123+
124+ new_locations.non_null_assignments .insert (
125+ new_locations.non_null_assignments .end (),
126+ a.non_null_assignments .begin (),
127+ a.non_null_assignments .end ());
128+
129+ new_locations.non_null_assignments .insert (
130+ new_locations.non_null_assignments .end (),
131+ b.non_null_assignments .begin (),
132+ b.non_null_assignments .end ());
133+
134+ return new_locations;
135+ }
136+
137+ // / For a given variable name, gets the assignments to it in the functions
138+ // / \param pointer_name: The name of the variable
139+ // / \param instructions: The instructions to look through
140+ // / \return: A structure that contains the null assignment if found, and a
141+ // / vector of all other assignments
142+ pointer_assignment_locationt find_pointer_assignments (
143+ const irep_idt &pointer_name,
144+ const exprt::operandst &instructions)
145+ {
146+ pointer_assignment_locationt locations;
147+ for (const exprt &assignment : instructions)
148+ {
149+ const codet &statement = to_code (assignment);
150+ INVARIANT (assignment.id () == ID_code, " All instructions must be code" );
151+ if (statement.get_statement () == ID_assign)
152+ {
153+ const code_assignt &code_assign = to_code_assign (to_code (assignment));
154+ if (
155+ code_assign.lhs ().id () == ID_symbol &&
156+ to_symbol_expr (code_assign.lhs ()).get_identifier () == pointer_name)
157+ {
158+ if (
159+ code_assign.rhs () ==
160+ null_pointer_exprt (to_pointer_type (code_assign.lhs ().type ())))
161+ {
162+ locations.null_assignment = code_assign;
163+ }
164+ else
165+ {
166+ locations.non_null_assignments .push_back (code_assign);
167+ }
168+ }
169+ }
170+ else if (statement.get_statement () == ID_block)
171+ {
172+ const auto &assignments_in_block =
173+ find_pointer_assignments (pointer_name, assignment.operands ());
174+ locations = combine_locations (locations, assignments_in_block);
175+ }
176+ else if (statement.get_statement () == ID_ifthenelse)
177+ {
178+ const code_ifthenelset &if_else_block =
179+ to_code_ifthenelse (to_code (assignment));
180+ const auto &assignments_in_block = find_pointer_assignments (
181+ pointer_name, exprt::operandst{if_else_block.then_case ()});
182+ locations = combine_locations (locations, assignments_in_block);
183+
184+ if (if_else_block.has_else_case ())
185+ {
186+ const auto &assignments_in_else = find_pointer_assignments (
187+ pointer_name, exprt::operandst{if_else_block.else_case ()});
188+ locations = combine_locations (locations, assignments_in_else);
189+ }
190+ }
191+ else if (statement.get_statement () == ID_label)
192+ {
193+ const code_labelt &label_statement = to_code_label (statement);
194+ const auto &assignments_in_label = find_pointer_assignments (
195+ pointer_name, exprt::operandst{label_statement.code ()});
196+ locations = combine_locations (locations, assignments_in_label);
197+ }
198+ }
199+
200+ return locations;
201+ }
202+
203+ const exprt &find_declaration_by_name (
204+ const irep_idt &variable_name,
205+ const exprt::operandst &entry_point_instructions)
206+ {
207+ for (const auto &instruction : entry_point_instructions)
208+ {
209+ const codet &statement = to_code (instruction);
210+ INVARIANT (instruction.id () == ID_code, " All instructions must be code" );
211+ if (statement.get_statement () == ID_decl)
212+ {
213+ const auto &decl_statement = to_code_decl (statement);
214+
215+ if (decl_statement.get_identifier () == variable_name)
216+ {
217+ return instruction;
218+ }
219+ }
220+ }
221+ throw no_decl_found_exception (variable_name.c_str ());
222+ }
0 commit comments