Skip to content

Commit dc4ffae

Browse files
authored
Merge pull request #3898 from tautschnig/use-object_descriptor
Extend object_descriptor_exprt::build and use it
2 parents dca1a9f + 83af955 commit dc4ffae

File tree

4 files changed

+75
-40
lines changed

4 files changed

+75
-40
lines changed

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

+7-37
Original file line numberDiff line numberDiff line change
@@ -18,39 +18,6 @@ Author: Diffblue Ltd.
1818
#include <util/expr_util.h>
1919
#include <util/suffix.h>
2020

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-
5421
/// Expand value of a function to include all child codets
5522
/// \param function_value: The value of the function (e.g. got by looking up
5623
/// the function in the symbol table and getting the value)
@@ -139,7 +106,7 @@ require_goto_statements::find_struct_component_assignments(
139106
ode.build(superclass_expr, ns);
140107
if(
141108
superclass_expr.get_component_name() == supercomponent_name &&
142-
root_object(ode.root_object(), symbol_table)->get_identifier() ==
109+
to_symbol_expr(ode.root_object()).get_identifier() ==
143110
structure_name)
144111
{
145112
if(
@@ -162,10 +129,13 @@ require_goto_statements::find_struct_component_assignments(
162129
// - component name: \p component_name
163130
// - operand (component of): symbol for \p structure_name
164131

165-
const auto &root_object =
166-
::root_object(member_expr.struct_op(), symbol_table);
132+
object_descriptor_exprt ode;
133+
const namespacet ns(symbol_table);
134+
ode.build(member_expr, ns);
167135
if(
168-
root_object && root_object->get_identifier() == structure_name &&
136+
ode.root_object().id() == ID_symbol &&
137+
to_symbol_expr(ode.root_object()).get_identifier() ==
138+
structure_name &&
169139
member_expr.get_component_name() == component_name)
170140
{
171141
if(

src/util/std_expr.cpp

+19-2
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ Author: Daniel Kroening, [email protected]
1010

1111
#include <util/namespace.h>
1212

13-
#include <cassert>
14-
1513
#include "arith_tools.h"
1614
#include "byte_operators.h"
1715
#include "c_types.h"
16+
#include "expr_util.h"
1817
#include "mathematical_types.h"
1918
#include "pointer_offset_size.h"
2019

@@ -114,6 +113,24 @@ static void build_object_descriptor_rec(
114113

115114
build_object_descriptor_rec(ns, tc.op(), dest);
116115
}
116+
else if(const auto deref = expr_try_dynamic_cast<dereference_exprt>(expr))
117+
{
118+
const exprt &pointer = skip_typecast(deref->pointer());
119+
if(const auto address_of = expr_try_dynamic_cast<address_of_exprt>(pointer))
120+
{
121+
dest.object() = address_of->object();
122+
build_object_descriptor_rec(ns, address_of->object(), dest);
123+
}
124+
}
125+
else if(const auto address_of = expr_try_dynamic_cast<address_of_exprt>(expr))
126+
{
127+
const exprt &object = skip_typecast(address_of->object());
128+
if(const auto deref = expr_try_dynamic_cast<dereference_exprt>(object))
129+
{
130+
dest.object() = deref->pointer();
131+
build_object_descriptor_rec(ns, deref->pointer(), dest);
132+
}
133+
}
117134
}
118135

119136
/// Build an object_descriptor_exprt from a given expr

src/util/std_expr.h

+4
Original file line numberDiff line numberDiff line change
@@ -2027,6 +2027,10 @@ class object_descriptor_exprt:public binary_exprt
20272027
{
20282028
}
20292029

2030+
/// Given an expression \p expr, attempt to find the underlying object it
2031+
/// represents by skipping over type casts and removing balanced
2032+
/// dereference/address_of operations; that object will then be available
2033+
/// as root_object().
20302034
void build(const exprt &expr, const namespacet &ns);
20312035

20322036
exprt &object()

unit/util/std_expr.cpp

+45-1
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,16 @@ Author: Diffblue Ltd
99
#include <testing-utils/use_catch.h>
1010

1111
#include <util/arith_tools.h>
12+
#include <util/c_types.h>
13+
#include <util/config.h>
1214
#include <util/mathematical_types.h>
15+
#include <util/namespace.h>
16+
#include <util/simplify_expr.h>
1317
#include <util/std_expr.h>
1418
#include <util/std_types.h>
19+
#include <util/symbol_table.h>
1520

16-
TEST_CASE("for a division expression...")
21+
TEST_CASE("for a division expression...", "[unit][util][std_expr]")
1722
{
1823
auto dividend = from_integer(10, integer_typet());
1924
auto divisor = from_integer(5, integer_typet());
@@ -30,3 +35,42 @@ TEST_CASE("for a division expression...")
3035
REQUIRE(div.type() == integer_typet());
3136
}
3237
}
38+
39+
TEST_CASE("object descriptor expression", "[unit][util][std_expr]")
40+
{
41+
config.ansi_c.set_LP64();
42+
43+
symbol_tablet symbol_table;
44+
const namespacet ns(symbol_table);
45+
46+
array_typet array_type(signed_int_type(), from_integer(2, size_type()));
47+
struct_typet struct_type({{"foo", array_type}});
48+
49+
SECTION("object descriptors of index expressions")
50+
{
51+
const symbol_exprt s("array", array_type);
52+
// s[1]
53+
const index_exprt index(s, from_integer(1, index_type()));
54+
55+
object_descriptor_exprt ode;
56+
ode.build(index, ns);
57+
REQUIRE(ode.root_object() == s);
58+
// in LP64 a signed int is 4 bytes
59+
REQUIRE(simplify_expr(ode.offset(), ns) == from_integer(4, index_type()));
60+
}
61+
62+
SECTION("object descriptors of member expressions")
63+
{
64+
const symbol_exprt s("struct", struct_type);
65+
// s.foo
66+
const member_exprt member(s, "foo", array_type);
67+
// s.foo[1]
68+
const index_exprt index(member, from_integer(1, index_type()));
69+
70+
object_descriptor_exprt ode;
71+
ode.build(index, ns);
72+
REQUIRE(ode.root_object() == s);
73+
// in LP64 a signed int is 4 bytes
74+
REQUIRE(simplify_expr(ode.offset(), ns) == from_integer(4, index_type()));
75+
}
76+
}

0 commit comments

Comments
 (0)