Skip to content

Commit a1e398d

Browse files
author
thk123
committed
Fixing unit tests wrt new GOTO format
Specifically - be impartial to deref/cast/address of combinations on the lhs. Be impartial to direct assignments without casts Be impartial to casts before assigning to address of another variable
1 parent 1a583d4 commit a1e398d

File tree

1 file changed

+56
-28
lines changed

1 file changed

+56
-28
lines changed

jbmc/unit/java-testing-utils/require_goto_statements.cpp

+56-28
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,46 @@ Author: Diffblue Ltd.
1111
#include <testing-utils/use_catch.h>
1212

1313
#include <algorithm>
14-
#include <util/expr_iterator.h>
1514
#include <goto-programs/goto_functions.h>
15+
#include <goto-programs/show_goto_functions.h>
1616
#include <java_bytecode/java_types.h>
17+
#include <util/expr_iterator.h>
18+
#include <util/expr_util.h>
1719
#include <util/suffix.h>
1820

21+
/// Given an expression, attempt to find the underlying symbol it represents
22+
/// by skipping over type casts and removing balanced dereference/address_of
23+
/// operations
24+
optionalt<symbol_exprt>
25+
root_object(const exprt &lhs_expr, const symbol_tablet &symbol_table)
26+
{
27+
auto expr = skip_typecast(lhs_expr);
28+
int dereference_balance = 0;
29+
while(!can_cast_expr<symbol_exprt>(expr))
30+
{
31+
if(const auto deref = expr_try_dynamic_cast<dereference_exprt>(expr))
32+
{
33+
++dereference_balance;
34+
expr = skip_typecast(deref->pointer());
35+
}
36+
else if(
37+
const auto address_of = expr_try_dynamic_cast<address_of_exprt>(expr))
38+
{
39+
--dereference_balance;
40+
expr = skip_typecast(address_of->object());
41+
}
42+
else
43+
{
44+
return {};
45+
}
46+
}
47+
if(dereference_balance != 0)
48+
{
49+
return {};
50+
}
51+
return to_symbol_expr(expr);
52+
}
53+
1954
/// Expand value of a function to include all child codets
2055
/// \param function_value: The value of the function (e.g. got by looking up
2156
/// the function in the symbol table and getting the value)
@@ -104,8 +139,8 @@ require_goto_statements::find_struct_component_assignments(
104139
ode.build(superclass_expr, ns);
105140
if(
106141
superclass_expr.get_component_name() == supercomponent_name &&
107-
to_symbol_expr(ode.root_object()).get_identifier() ==
108-
structure_name)
142+
root_object(ode.root_object(), symbol_table)->get_identifier() ==
143+
structure_name)
109144
{
110145
if(
111146
code_assign.rhs() ==
@@ -126,9 +161,11 @@ require_goto_statements::find_struct_component_assignments(
126161
// member_exprt member_expr:
127162
// - component name: \p component_name
128163
// - operand (component of): symbol for \p structure_name
164+
165+
const auto &root_object =
166+
::root_object(member_expr.struct_op(), symbol_table);
129167
if(
130-
member_expr.op().id() == ID_symbol &&
131-
to_symbol_expr(member_expr.op()).get_identifier() == structure_name &&
168+
root_object && root_object->get_identifier() == structure_name &&
132169
member_expr.get_component_name() == component_name)
133170
{
134171
if(
@@ -317,42 +354,32 @@ const irep_idt &require_goto_statements::require_struct_component_assignment(
317354
superclass_name,
318355
component_name,
319356
symbol_table);
357+
INFO(
358+
"looking for component assignment " << component_name << " in "
359+
<< structure_name);
320360
REQUIRE(component_assignments.non_null_assignments.size() == 1);
321361

322-
// We are expecting that the resulting statement can be of two forms:
362+
// We are expecting that the resulting statement can be of the form:
323363
// 1. structure_name.(@superclass_name if given).component =
324-
// (struct cast_type_name *) tmp_object_factory$1;
364+
// (optional type cast *) tmp_object_factory$1;
325365
// followed by a direct assignment like this:
326366
// tmp_object_factory$1 = &tmp_object_factory$2;
327-
// 2. structure_name.component = &tmp_object_factory$1;
367+
// 2. structure_name.component = (optional cast *)&tmp_object_factory$1
328368
exprt component_assignment_rhs_expr =
329-
component_assignments.non_null_assignments[0].rhs();
369+
skip_typecast(component_assignments.non_null_assignments[0].rhs());
330370

331-
// If the rhs is a typecast (case 1 above), deconstruct it to get the name of
332-
// the variable and find the assignment to it
333-
if(component_assignment_rhs_expr.id() == ID_typecast)
371+
// If the rhs is not an address of must be in case 1
372+
if(!can_cast_expr<address_of_exprt>(component_assignment_rhs_expr))
334373
{
335-
const auto &component_assignment_rhs =
336-
to_typecast_expr(component_assignment_rhs_expr);
337-
338-
// Check the type we are casting to
339-
if(typecast_name.has_value())
340-
{
341-
REQUIRE(component_assignment_rhs.type().id() == ID_pointer);
342-
REQUIRE(
343-
to_struct_tag_type(
344-
to_pointer_type(component_assignment_rhs.type()).subtype())
345-
.get(ID_identifier) == typecast_name.value());
346-
}
347-
348374
const auto &component_reference_tmp_name =
349-
to_symbol_expr(component_assignment_rhs.op()).get_identifier();
375+
to_symbol_expr(component_assignment_rhs_expr).get_identifier();
350376
const auto &component_reference_assignments =
351377
require_goto_statements::find_pointer_assignments(
352378
component_reference_tmp_name, entry_point_instructions)
353379
.non_null_assignments;
354380
REQUIRE(component_reference_assignments.size() == 1);
355-
component_assignment_rhs_expr = component_reference_assignments[0].rhs();
381+
component_assignment_rhs_expr =
382+
skip_typecast(component_reference_assignments[0].rhs());
356383
}
357384

358385
// The rhs assigns an address of a variable, get its name
@@ -480,7 +507,8 @@ require_goto_statements::require_entry_point_argument_assignment(
480507
const auto &argument_assignment =
481508
argument_assignments.non_null_assignments[0];
482509
const auto &argument_tmp_name =
483-
to_symbol_expr(to_address_of_expr(argument_assignment.rhs()).object())
510+
to_symbol_expr(
511+
to_address_of_expr(skip_typecast(argument_assignment.rhs())).object())
484512
.get_identifier();
485513
return argument_tmp_name;
486514
}

0 commit comments

Comments
 (0)