Skip to content

Commit 2b715dd

Browse files
Add a class for code with references
This will be use in assign_from_json for json files in which the "@ref" and "@id" entries are used, so that we can easily substitute code marked by "@ref" by the code corresponding to the object marked by "@id". This also move object_creation_referencet to the new header file since it will be used there, and the allocate_array is now declared in the new header and defined in the corresponding cpp file.
1 parent efe2f6a commit 2b715dd

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

jbmc/src/java_bytecode/code_with_references.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,48 @@ codet allocate_array(
2323
java_new_array.type().subtype().set(ID_element_type, element_type);
2424
return code_assignt{expr, java_new_array, loc};
2525
}
26+
27+
code_blockt
28+
reference_allocationt::to_code(reference_substitutiont &references) const
29+
{
30+
const object_creation_referencet &reference = references(reference_id);
31+
INVARIANT(reference.array_length, "Length of reference array must be known");
32+
if(can_cast_expr<constant_exprt>(*reference.array_length))
33+
{
34+
return code_blockt(
35+
{allocate_array(reference.expr, *reference.array_length, loc)});
36+
}
37+
// Fallback in case the array definition has not been seen yet, this can
38+
// happen if `to_code` is called before the whole json file has been processed
39+
// or the "@id" json field corresponding to `reference_id` doesn't appear in
40+
// the file.
41+
code_blockt code;
42+
code.add(code_assignt{*reference.array_length,
43+
side_effect_expr_nondett{java_int_type()}});
44+
code.add(code_assumet{binary_predicate_exprt{
45+
*reference.array_length, ID_ge, from_integer(0, java_int_type())}});
46+
code.add(allocate_array(reference.expr, *reference.array_length, loc));
47+
return code;
48+
}
49+
50+
void code_with_references_listt::add(code_without_referencest code)
51+
{
52+
auto ptr = std::make_shared<code_without_referencest>(std::move(code));
53+
list.emplace_back(std::move(ptr));
54+
}
55+
56+
void code_with_references_listt::add(codet code)
57+
{
58+
add(code_without_referencest{std::move(code)});
59+
}
60+
61+
void code_with_references_listt::add(reference_allocationt ref)
62+
{
63+
auto ptr = std::make_shared<reference_allocationt>(std::move(ref));
64+
list.emplace_back(std::move(ptr));
65+
}
66+
67+
void code_with_references_listt::append(code_with_references_listt &&other)
68+
{
69+
list.splice(list.end(), other.list);
70+
}

jbmc/src/java_bytecode/code_with_references.h

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,74 @@ struct object_creation_referencet
3333
optionalt<exprt> array_length;
3434
};
3535

36+
/// Base class for code which can contain references which can get replaced
37+
/// before generating actual codet.
38+
/// Currently only references in array allocations are supported, because this
39+
/// is currently the only use required by \ref assign_from_json.
40+
class code_with_referencest
41+
{
42+
public:
43+
using reference_substitutiont =
44+
std::function<const object_creation_referencet &(const std::string &)>;
45+
46+
virtual code_blockt to_code(reference_substitutiont &) const = 0;
47+
48+
virtual ~code_with_referencest() = default;
49+
};
50+
51+
/// Code that should not contain reference
52+
class code_without_referencest : public code_with_referencest
53+
{
54+
public:
55+
codet code;
56+
57+
explicit code_without_referencest(codet code) : code(std::move(code))
58+
{
59+
}
60+
61+
code_blockt to_code(reference_substitutiont &) const override
62+
{
63+
return code_blockt({code});
64+
}
65+
};
66+
67+
/// Allocation code which contains a reference.
68+
/// The generated code will be of the form:
69+
///
70+
/// array_length = nondet(int)
71+
/// assume(array_length >= 0)
72+
/// array_expr = new array_type[array_length];
73+
///
74+
/// Where array_length and array_expr are given by the reference substitution
75+
/// function.
76+
class reference_allocationt : public code_with_referencest
77+
{
78+
public:
79+
std::string reference_id;
80+
source_locationt loc;
81+
82+
reference_allocationt(std::string reference_id, source_locationt loc)
83+
: reference_id(std::move(reference_id)), loc(std::move(loc))
84+
{
85+
}
86+
87+
code_blockt to_code(reference_substitutiont &references) const override;
88+
};
89+
90+
/// Wrapper around a list of shared pointer to code_with_referencest objects,
91+
/// which provides a nicer interface.
92+
class code_with_references_listt
93+
{
94+
public:
95+
std::list<std::shared_ptr<code_with_referencest>> list;
96+
97+
void add(code_without_referencest code);
98+
99+
void add(codet code);
100+
101+
void add(reference_allocationt ref);
102+
103+
void append(code_with_references_listt &&other);
104+
};
105+
36106
#endif // CPROVER_JAVA_BYTECODE_CODE_WITH_REFERENCES_H

0 commit comments

Comments
 (0)