Skip to content

Commit 55fc192

Browse files
committed
member_exprt now checks type of compound operand
This commit adds a precondition to the constructors of member_exprt that enforces that the compound operand has one of the compound types.
1 parent f9bd83e commit 55fc192

File tree

10 files changed

+85
-77
lines changed

10 files changed

+85
-77
lines changed

jbmc/unit/java_bytecode/java_trace_validation/java_trace_validation.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ TEST_CASE("java trace validation", "[core][java_trace_validation]")
2222
{
2323
const exprt plain_expr = exprt();
2424
const exprt expr_with_data = exprt("id", java_int_type());
25-
const symbol_exprt valid_symbol_expr = symbol_exprt("id", java_int_type());
25+
const symbol_exprt valid_symbol_expr =
26+
symbol_exprt("id", struct_typet{{{"member", java_int_type()}}});
2627
const symbol_exprt invalid_symbol_expr = symbol_exprt(java_int_type());
2728
const member_exprt valid_member =
2829
member_exprt(valid_symbol_expr, "member", java_int_type());
29-
const member_exprt invalid_member =
30-
member_exprt(plain_expr, "member", java_int_type());
30+
exprt invalid_member = unary_exprt{ID_member, plain_expr, java_int_type()};
31+
invalid_member.set(ID_component_name, "member");
3132
const constant_exprt invalid_constant = constant_exprt("", java_int_type());
3233
const constant_exprt valid_constant = constant_exprt("0", java_int_type());
3334
const index_exprt valid_index = index_exprt(
@@ -88,7 +89,8 @@ TEST_CASE("java trace validation", "[core][java_trace_validation]")
8889
INFO("valid member structure")
8990
REQUIRE(check_member_structure(valid_member));
9091
INFO("invalid member structure, no symbol operand")
91-
REQUIRE_FALSE(check_member_structure(invalid_member));
92+
REQUIRE_FALSE(check_member_structure(
93+
static_cast<const member_exprt &>(invalid_member)));
9294
}
9395

9496
SECTION("can_evaluate_to_constant")

src/goto-programs/string_abstraction.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -817,24 +817,32 @@ bool string_abstractiont::build(const exprt &object, exprt &dest, bool write)
817817
if(object.id()==ID_member)
818818
{
819819
const member_exprt &o_mem=to_member_expr(object);
820-
dest=member_exprt(exprt(), o_mem.get_component_name(), abstract_type);
821-
return build_wrap(
822-
o_mem.struct_op(), to_member_expr(dest).compound(), write);
820+
exprt compound;
821+
if(build_wrap(o_mem.struct_op(), compound, write))
822+
return true;
823+
dest = member_exprt{
824+
std::move(compound), o_mem.get_component_name(), abstract_type};
825+
return false;
823826
}
824827

825828
if(object.id()==ID_dereference)
826829
{
827830
const dereference_exprt &o_deref=to_dereference_expr(object);
828-
dest=dereference_exprt(exprt(), abstract_type);
829-
return build_wrap(
830-
o_deref.pointer(), to_dereference_expr(dest).pointer(), write);
831+
exprt pointer;
832+
if(build_wrap(o_deref.pointer(), pointer, write))
833+
return true;
834+
dest = dereference_exprt{std::move(pointer)};
835+
return false;
831836
}
832837

833838
if(object.id()==ID_index)
834839
{
835840
const index_exprt &o_index=to_index_expr(object);
836-
dest=index_exprt(exprt(), o_index.index(), abstract_type);
837-
return build_wrap(o_index.array(), to_index_expr(dest).array(), write);
841+
exprt array;
842+
if(build_wrap(o_index.array(), array, write))
843+
return true;
844+
dest = index_exprt{std::move(array), o_index.index()};
845+
return false;
838846
}
839847

840848
// handle pointer stuff

src/pointer-analysis/value_set.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,10 @@ void value_sett::get_reference_set_rec(
11921192

11931193
if(object.id()==ID_unknown)
11941194
insert(dest, exprt(ID_unknown, expr.type()));
1195-
else
1195+
else if(
1196+
object.type().id() == ID_struct ||
1197+
object.type().id() == ID_struct_tag || object.type().id() == ID_union ||
1198+
object.type().id() == ID_union_tag)
11961199
{
11971200
offsett o = it->second;
11981201

@@ -1218,6 +1221,8 @@ void value_sett::get_reference_set_rec(
12181221
else
12191222
insert(dest, exprt(ID_unknown, expr.type()));
12201223
}
1224+
else
1225+
insert(dest, exprt(ID_unknown, expr.type()));
12211226
}
12221227

12231228
return;

src/pointer-analysis/value_set_fi.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -916,11 +916,10 @@ void value_set_fit::get_reference_set_sharing_rec(
916916
if(object.id()==ID_unknown)
917917
insert(dest, exprt(ID_unknown, expr.type()));
918918
else if(
919-
object.id() == ID_dynamic_object && obj_type.id() != ID_struct &&
920-
obj_type.id() != ID_union && obj_type.id() != ID_struct_tag &&
921-
obj_type.id() != ID_union_tag)
919+
obj_type.id() != ID_struct && obj_type.id() != ID_union &&
920+
obj_type.id() != ID_struct_tag && obj_type.id() != ID_union_tag)
922921
{
923-
// we catch dynamic objects of the wrong type,
922+
// we catch objects of the wrong type,
924923
// to avoid non-integral typecasts.
925924
insert(dest, exprt(ID_unknown, expr.type()));
926925
}

src/util/std_expr.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2789,12 +2789,20 @@ class member_exprt:public unary_exprt
27892789
member_exprt(exprt op, const irep_idt &component_name, typet _type)
27902790
: unary_exprt(ID_member, std::move(op), std::move(_type))
27912791
{
2792+
const auto &compound_type_id = compound().type().id();
2793+
PRECONDITION(
2794+
compound_type_id == ID_struct_tag || compound_type_id == ID_union_tag ||
2795+
compound_type_id == ID_struct || compound_type_id == ID_union);
27922796
set_component_name(component_name);
27932797
}
27942798

27952799
member_exprt(exprt op, const struct_typet::componentt &c)
27962800
: unary_exprt(ID_member, std::move(op), c.type())
27972801
{
2802+
const auto &compound_type_id = compound().type().id();
2803+
PRECONDITION(
2804+
compound_type_id == ID_struct_tag || compound_type_id == ID_union_tag ||
2805+
compound_type_id == ID_struct || compound_type_id == ID_union);
27982806
set_component_name(c.get_name());
27992807
}
28002808

unit/analyses/variable-sensitivity/full_struct_abstract_object/merge.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,13 @@ SCENARIO(
3333
// struct val2 = {.a = 1, .b = 4, .c = 5}
3434
auto val2 = std::map<std::string, int>{{"a", 1}, {"b", 4}, {"c", 5}};
3535

36-
// index_exprt for reading from an array
37-
const member_exprt a(nil_exprt(), "a", integer_typet());
38-
const member_exprt b(nil_exprt(), "b", integer_typet());
39-
const member_exprt c(nil_exprt(), "c", integer_typet());
36+
// member_exprt for reading from a struct
37+
exprt dummy = nil_exprt{};
38+
dummy.type() = struct_typet{
39+
{{"a", integer_typet{}}, {"b", integer_typet{}}, {"c", integer_typet{}}}};
40+
const auto a = member_exprt(dummy, "a", integer_typet());
41+
const auto b = member_exprt(dummy, "b", integer_typet());
42+
const auto c = member_exprt(dummy, "c", integer_typet());
4043

4144
auto object_factory = variable_sensitivity_object_factoryt::configured_with(
4245
vsd_configt::constant_domain());

unit/analyses/variable-sensitivity/full_struct_abstract_object/struct_builder.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,18 @@ full_struct_abstract_objectt::constant_struct_pointert build_struct(
1919

2020
auto struct_type = to_struct_type(starting_value.type());
2121
size_t comp_index = 0;
22+
23+
auto nil_with_type = nil_exprt();
24+
nil_with_type.type() = struct_type;
25+
2226
for(const exprt &op : starting_value.operands())
2327
{
2428
const auto &component = struct_type.components()[comp_index];
2529
auto new_result = result->write(
2630
environment,
2731
ns,
2832
std::stack<exprt>(),
29-
member_exprt(nil_exprt(), component.get_name(), component.type()),
33+
member_exprt(nil_with_type, component.get_name(), component.type()),
3034
environment.eval(op, ns),
3135
false);
3236

unit/goto-symex/expr_skeleton.cpp

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,32 @@ Author: Romain Brenguier, [email protected]
1515

1616
SCENARIO("expr skeleton", "[core][goto-symex][symex-assign][expr-skeleton]")
1717
{
18-
const symbol_exprt foo{"foo", typet{}};
18+
const signedbv_typet int_type{32};
19+
const array_typet array_type{int_type, from_integer(2, size_type())};
20+
const symbol_exprt foo_a{"foo", array_type};
21+
const symbol_exprt foo_s{"foo", struct_typet{{{"field1", array_type}}}};
22+
1923
GIVEN("Skeletons `☐`, `☐[index]` and `☐.field1`")
2024
{
2125
const expr_skeletont empty_skeleton;
22-
const signedbv_typet int_type{32};
23-
const expr_skeletont index_skeleton =
24-
expr_skeletont::remove_op0(index_exprt{
25-
array_exprt{{}, array_typet{int_type, from_integer(2, size_type())}},
26-
from_integer(1, size_type())});
27-
const expr_skeletont member_skeleton = expr_skeletont::remove_op0(
28-
member_exprt{symbol_exprt{"struct1", typet{}}, "field1", int_type});
26+
const expr_skeletont index_skeleton = expr_skeletont::remove_op0(
27+
index_exprt{array_exprt{{}, array_type}, from_integer(1, size_type())});
28+
const expr_skeletont member_skeleton =
29+
expr_skeletont::remove_op0(member_exprt{
30+
symbol_exprt{"struct1", struct_typet{{{"field1", array_type}}}},
31+
"field1",
32+
array_type});
2933
THEN(
3034
"Applying the skeletons to `foo` gives `foo`, `foo[index]` and "
3135
"`foo.field1` respectively")
3236
{
33-
REQUIRE(empty_skeleton.apply(foo) == foo);
37+
REQUIRE(empty_skeleton.apply(foo_a) == foo_a);
3438
REQUIRE(
35-
index_skeleton.apply(foo) ==
36-
index_exprt{foo, from_integer(1, size_type()), int_type});
39+
index_skeleton.apply(foo_a) ==
40+
index_exprt{foo_a, from_integer(1, size_type()), int_type});
3741
REQUIRE(
38-
member_skeleton.apply(foo) == member_exprt{foo, "field1", int_type});
42+
member_skeleton.apply(foo_s) ==
43+
member_exprt(foo_s, "field1", array_type));
3944
}
4045
THEN(
4146
"The composition of `☐[index]` with `☐.field1` applied to `foo` gives "
@@ -44,19 +49,19 @@ SCENARIO("expr skeleton", "[core][goto-symex][symex-assign][expr-skeleton]")
4449
const expr_skeletont composition =
4550
index_skeleton.compose(member_skeleton);
4651
REQUIRE(
47-
composition.apply(foo) ==
48-
index_exprt{member_exprt{foo, "field1", int_type},
49-
from_integer(1, size_type()),
50-
int_type});
52+
composition.apply(foo_s) == index_exprt{
53+
member_exprt(foo_s, "field1", array_type),
54+
from_integer(1, size_type()),
55+
int_type});
5156
}
5257
THEN(
5358
"The composition of `☐[index]` with `☐` applied to `foo` gives "
5459
"`foo[index]`")
5560
{
5661
const expr_skeletont composition = index_skeleton.compose(empty_skeleton);
5762
REQUIRE(
58-
composition.apply(foo) ==
59-
index_exprt{foo, from_integer(1, size_type()), int_type});
63+
composition.apply(foo_a) ==
64+
index_exprt{foo_a, from_integer(1, size_type()), int_type});
6065
}
6166
}
6267
}

unit/pointer-analysis/value_set.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ SCENARIO(
135135
WHEN("We query what (a1 WITH x = NULL).x points to")
136136
{
137137
with_exprt a1_with(
138-
a1_symbol.symbol_expr(), member_exprt(nil_exprt(), A_x), null_A_ptr);
138+
a1_symbol.symbol_expr(), exprt{ID_member_name}, null_A_ptr);
139+
a1_with.where().set(ID_component_name, A_x.get_name());
139140

140141
member_exprt member_of_with(a1_with, A_x);
141142

@@ -153,7 +154,8 @@ SCENARIO(
153154
WHEN("We query what (a1 WITH x = NULL).y points to")
154155
{
155156
with_exprt a1_with(
156-
a1_symbol.symbol_expr(), member_exprt(nil_exprt(), A_x), null_A_ptr);
157+
a1_symbol.symbol_expr(), exprt{ID_member_name}, null_A_ptr);
158+
a1_with.where().set(ID_component_name, A_x.get_name());
157159

158160
member_exprt member_of_with(a1_with, A_y);
159161

@@ -171,7 +173,8 @@ SCENARIO(
171173
WHEN("We query what (a1 WITH x = NULL) points to")
172174
{
173175
with_exprt a1_with(
174-
a1_symbol.symbol_expr(), member_exprt(nil_exprt(), A_x), null_A_ptr);
176+
a1_symbol.symbol_expr(), exprt{ID_member_name}, null_A_ptr);
177+
a1_with.where().set(ID_component_name, A_x.get_name());
175178

176179
const std::vector<exprt> maybe_matching_with_result =
177180
value_set.get_value_set(a1_with, ns);

unit/solvers/smt2_incremental/object_tracking.cpp

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,41 +12,12 @@
1212
#include <string>
1313
#include <utility>
1414

15-
TEST_CASE("find_object_base_expression", "[core][smt2_incremental]")
16-
{
17-
const typet base_type = pointer_typet{unsignedbv_typet{8}, 18};
18-
const symbol_exprt object_base{"base", base_type};
19-
const symbol_exprt index{"index", base_type};
20-
const pointer_typet pointer_type{base_type, 12};
21-
std::string description;
22-
optionalt<address_of_exprt> address_of;
23-
using rowt = std::pair<std::string, address_of_exprt>;
24-
std::tie(description, address_of) = GENERATE_REF(
25-
rowt{"Address of symbol", {object_base, pointer_type}},
26-
rowt{"Address of index", {index_exprt{object_base, index}, pointer_type}},
27-
rowt{
28-
"Address of struct member",
29-
{member_exprt{object_base, "baz", unsignedbv_typet{8}}, pointer_type}},
30-
rowt{
31-
"Address of index of struct member",
32-
{index_exprt{member_exprt{object_base, "baz", base_type}, index},
33-
pointer_type}},
34-
rowt{
35-
"Address of struct member at index",
36-
{member_exprt{
37-
index_exprt{object_base, index}, "baz", unsignedbv_typet{8}},
38-
pointer_type}});
39-
SECTION(description)
40-
{
41-
CHECK(find_object_base_expression(*address_of) == object_base);
42-
}
43-
}
44-
4515
TEST_CASE("Tracking object base expressions", "[core][smt2_incremental]")
4616
{
4717
const typet base_type = pointer_typet{signedbv_typet{16}, 18};
4818
const symbol_exprt foo{"foo", base_type};
4919
const symbol_exprt bar{"bar", base_type};
20+
const symbol_exprt qux{"qux", struct_typet{}};
5021
const symbol_exprt index{"index", base_type};
5122
const pointer_typet pointer_type{base_type, 32};
5223
const exprt bar_address = address_of_exprt{bar, pointer_type};
@@ -55,15 +26,15 @@ TEST_CASE("Tracking object base expressions", "[core][smt2_incremental]")
5526
address_of_exprt{index_exprt{foo, index}, pointer_type}, bar_address},
5627
notequal_exprt{
5728
address_of_exprt{
58-
member_exprt{foo, "baz", unsignedbv_typet{8}}, pointer_type},
29+
member_exprt(qux, "baz", unsignedbv_typet{8}), pointer_type},
5930
bar_address}};
6031
SECTION("Find base expressions")
6132
{
6233
std::vector<exprt> expressions;
6334
find_object_base_expressions(compound_expression, [&](const exprt &expr) {
6435
expressions.push_back(expr);
6536
});
66-
CHECK(expressions == std::vector<exprt>{bar, foo, bar, foo});
37+
CHECK(expressions == std::vector<exprt>{bar, qux, bar, foo});
6738
}
6839
smt_object_mapt object_map = initial_smt_object_map();
6940
SECTION("Check initial object map has null pointer")
@@ -83,11 +54,11 @@ TEST_CASE("Tracking object base expressions", "[core][smt2_incremental]")
8354
track_expression_objects(compound_expression, ns, object_map);
8455
SECTION("Tracking expression objects")
8556
{
86-
CHECK(object_map.size() == 3);
57+
CHECK(object_map.size() == 4);
8758
const auto foo_object = object_map.find(foo);
8859
REQUIRE(foo_object != object_map.end());
8960
CHECK(foo_object->second.base_expression == foo);
90-
CHECK(foo_object->second.unique_id == 2);
61+
CHECK(foo_object->second.unique_id == 3);
9162
const auto bar_object = object_map.find(bar);
9263
REQUIRE(bar_object != object_map.end());
9364
CHECK(bar_object->second.base_expression == bar);

0 commit comments

Comments
 (0)