Skip to content

Commit bbc9bb3

Browse files
authored
Merge pull request diffblue#5039 from smowton/smowton/cleanup/java-instanceof-expr
Add java_instanceof_exprt, and use it in place of raw exprts
2 parents 0319cd6 + bb05926 commit bbc9bb3

File tree

6 files changed

+150
-31
lines changed

6 files changed

+150
-31
lines changed

jbmc/src/java_bytecode/expr2java.cpp

+4-9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Author: Daniel Kroening, [email protected]
2222
#include <ansi-c/c_misc.h>
2323
#include <ansi-c/expr2c_class.h>
2424

25+
#include "java_expr.h"
2526
#include "java_qualifiers.h"
2627
#include "java_string_literal_expr.h"
2728
#include "java_types.h"
@@ -320,16 +321,10 @@ std::string expr2javat::convert_java_this()
320321

321322
std::string expr2javat::convert_java_instanceof(const exprt &src)
322323
{
323-
if(src.operands().size()!=2)
324-
{
325-
unsigned precedence;
326-
return convert_norep(src, precedence);
327-
}
328-
329-
const auto &binary_expr = to_binary_expr(src);
324+
const auto &instanceof_expr = to_java_instanceof_expr(src);
330325

331-
return convert(binary_expr.op0()) + " instanceof " +
332-
convert(binary_expr.op1().type());
326+
return convert(instanceof_expr.tested_expr()) + " instanceof " +
327+
convert(instanceof_expr.target_type());
333328
}
334329

335330
std::string expr2javat::convert_code_java_new(const exprt &src, unsigned indent)

jbmc/src/java_bytecode/java_bytecode_convert_method.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Daniel Kroening, [email protected]
1616
#include "bytecode_info.h"
1717
#include "java_bytecode_convert_method.h"
1818
#include "java_bytecode_convert_method_class.h"
19+
#include "java_expr.h"
1920
#include "java_static_initializers.h"
2021
#include "java_string_library_preprocess.h"
2122
#include "java_string_literal_expr.h"
@@ -1687,8 +1688,8 @@ java_bytecode_convert_methodt::convert_instructions(const methodt &method)
16871688
{
16881689
PRECONDITION(op.size() == 1 && results.size() == 1);
16891690

1690-
results[0]=
1691-
binary_predicate_exprt(op[0], ID_java_instanceof, arg0);
1691+
results[0] =
1692+
java_instanceof_exprt(op[0], to_struct_tag_type(arg0.type()));
16921693
}
16931694
else if(bytecode == BC_monitorenter || bytecode == BC_monitorexit)
16941695
{
@@ -2326,7 +2327,7 @@ void java_bytecode_convert_methodt::convert_checkcast(
23262327
codet &c,
23272328
exprt::operandst &results) const
23282329
{
2329-
binary_predicate_exprt check(op[0], ID_java_instanceof, arg0);
2330+
java_instanceof_exprt check(op[0], to_struct_tag_type(arg0.type()));
23302331
code_assertt assert_class(check);
23312332
assert_class.add_source_location().set_comment("Dynamic cast check");
23322333
assert_class.add_source_location().set_property_class("bad-dynamic-cast");

jbmc/src/java_bytecode/java_bytecode_instrument.cpp

+14-17
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Date: June 2017
1919

2020
#include "java_bytecode_convert_class.h"
2121
#include "java_entry_point.h"
22+
#include "java_expr.h"
2223
#include "java_utils.h"
2324

2425
class java_bytecode_instrumentt:public messaget
@@ -61,8 +62,8 @@ class java_bytecode_instrumentt:public messaget
6162
const source_locationt &original_loc);
6263

6364
code_ifthenelset check_class_cast(
64-
const exprt &class1,
65-
const exprt &class2,
65+
const exprt &tested_expr,
66+
const struct_tag_typet &target_type,
6667
const source_locationt &original_loc);
6768

6869
codet check_array_length(
@@ -203,22 +204,21 @@ codet java_bytecode_instrumentt::check_array_access(
203204
/// ClassCastException/generates an assertion when necessary;
204205
/// Exceptions are thrown when the `throw_runtime_exceptions` flag is set.
205206
/// Otherwise, assertions are emitted.
206-
/// \param class1: the subclass
207-
/// \param class2: the super class
207+
/// \param tested_expr: expression to test
208+
/// \param target_type: type to test for
208209
/// \param original_loc: source location in the original code
209210
/// \return Based on the value of the flag `throw_runtime_exceptions`,
210211
/// it returns code that either throws an ClassCastException or emits an
211212
/// assertion checking the subtype relation
212213
code_ifthenelset java_bytecode_instrumentt::check_class_cast(
213-
const exprt &class1,
214-
const exprt &class2,
214+
const exprt &tested_expr,
215+
const struct_tag_typet &target_type,
215216
const source_locationt &original_loc)
216217
{
217-
binary_predicate_exprt class_cast_check(
218-
class1, ID_java_instanceof, class2);
218+
java_instanceof_exprt class_cast_check(tested_expr, target_type);
219219

220220
pointer_typet voidptr = pointer_type(java_void_type());
221-
exprt null_check_op = typecast_exprt::conditional_cast(class1, voidptr);
221+
exprt null_check_op = typecast_exprt::conditional_cast(tested_expr, voidptr);
222222

223223
optionalt<codet> check_code;
224224
if(throw_runtime_exceptions)
@@ -373,15 +373,12 @@ void java_bytecode_instrumentt::instrument_code(codet &code)
373373
if(code_assert.assertion().id()==ID_java_instanceof)
374374
{
375375
code_blockt block;
376+
const auto & instanceof
377+
= to_java_instanceof_expr(code_assert.assertion());
376378

377-
INVARIANT(
378-
code_assert.assertion().operands().size()==2,
379-
"Instanceof should have 2 operands");
380-
381-
const auto & instanceof = to_binary_expr(code_assert.assertion());
382-
383-
code = check_class_cast(
384-
instanceof.op0(), instanceof.op1(), code_assert.source_location());
379+
code = check_class_cast(instanceof.tested_expr(),
380+
instanceof
381+
.target_type(), code_assert.source_location());
385382
}
386383
}
387384
else if(statement==ID_block)

jbmc/src/java_bytecode/java_expr.h

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*******************************************************************\
2+
3+
Module: Java-specific exprt subclasses
4+
5+
Author: Diffblue Ltd
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Java-specific exprt subclasses
11+
12+
#ifndef CPROVER_JAVA_BYTECODE_JAVA_EXPR_H
13+
#define CPROVER_JAVA_BYTECODE_JAVA_EXPR_H
14+
15+
#include <util/std_expr.h>
16+
17+
class java_instanceof_exprt : public binary_predicate_exprt
18+
{
19+
public:
20+
java_instanceof_exprt(exprt lhs, const struct_tag_typet &target_type)
21+
: binary_predicate_exprt(
22+
std::move(lhs),
23+
ID_java_instanceof,
24+
type_exprt(target_type))
25+
{
26+
}
27+
28+
const exprt &tested_expr() const
29+
{
30+
return op0();
31+
}
32+
exprt &tested_expr()
33+
{
34+
return op0();
35+
}
36+
37+
const struct_tag_typet &target_type() const
38+
{
39+
return to_struct_tag_type(op1().type());
40+
}
41+
42+
static void check(
43+
const exprt &expr,
44+
const validation_modet vm = validation_modet::INVARIANT)
45+
{
46+
binary_predicate_exprt::check(expr, vm);
47+
}
48+
49+
static void validate(
50+
const exprt &expr,
51+
const namespacet &ns,
52+
const validation_modet vm = validation_modet::INVARIANT)
53+
{
54+
binary_predicate_exprt::validate(expr, ns, vm);
55+
56+
DATA_CHECK(
57+
vm,
58+
can_cast_expr<type_exprt>(expr.op1()),
59+
"java_instanceof_exprt rhs should be a type_exprt");
60+
DATA_CHECK(
61+
vm,
62+
can_cast_type<struct_tag_typet>(expr.op1().type()),
63+
"java_instanceof_exprt rhs should denote a struct_tag_typet");
64+
}
65+
};
66+
67+
template <>
68+
inline bool can_cast_expr<java_instanceof_exprt>(const exprt &base)
69+
{
70+
return can_cast_expr<binary_exprt>(base) && base.id() == ID_java_instanceof;
71+
}
72+
73+
inline void validate_expr(const java_instanceof_exprt &value)
74+
{
75+
java_instanceof_exprt::check(value);
76+
}
77+
78+
/// \brief Cast an exprt to a \ref java_instanceof_exprt
79+
///
80+
/// \a expr must be known to be \ref java_instanceof_exprt.
81+
///
82+
/// \param expr: Source expression
83+
/// \return Object of type \ref java_instanceof_exprt
84+
inline const java_instanceof_exprt &to_java_instanceof_expr(const exprt &expr)
85+
{
86+
java_instanceof_exprt::check(expr);
87+
PRECONDITION(can_cast_expr<java_instanceof_exprt>(expr));
88+
return static_cast<const java_instanceof_exprt &>(expr);
89+
}
90+
91+
/// \copydoc to_java_instanceof_expr(const exprt &)
92+
inline java_instanceof_exprt &to_java_instanceof_expr(exprt &expr)
93+
{
94+
java_instanceof_exprt::check(expr);
95+
PRECONDITION(can_cast_expr<java_instanceof_exprt>(expr));
96+
return static_cast<java_instanceof_exprt &>(expr);
97+
}
98+
99+
#endif // CPROVER_JAVA_BYTECODE_JAVA_EXPR_H

jbmc/src/java_bytecode/remove_exceptions.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Date: December 2016
3232

3333
#include <linking/static_lifetime_init.h>
3434

35+
#include "java_expr.h"
3536
#include "java_types.h"
3637

3738
/// Lowers high-level exception descriptions into low-level operations suitable
@@ -366,9 +367,8 @@ void remove_exceptionst::add_exception_dispatch_sequence(
366367

367368
// use instanceof to check that this is the correct handler
368369
struct_tag_typet type(stack_catch[i][j].first);
369-
type_exprt expr(type);
370370

371-
binary_predicate_exprt check(exc_thrown, ID_java_instanceof, expr);
371+
java_instanceof_exprt check(exc_thrown, type);
372372
t_exc->guard=check;
373373

374374
if(remove_added_instanceof)

src/util/std_expr.h

+27
Original file line numberDiff line numberDiff line change
@@ -4071,6 +4071,33 @@ class type_exprt : public nullary_exprt
40714071
}
40724072
};
40734073

4074+
template <>
4075+
inline bool can_cast_expr<type_exprt>(const exprt &base)
4076+
{
4077+
return base.id() == ID_type;
4078+
}
4079+
4080+
/// \brief Cast an exprt to an \ref type_exprt
4081+
///
4082+
/// \a expr must be known to be \ref type_exprt.
4083+
///
4084+
/// \param expr: Source expression
4085+
/// \return Object of type \ref type_exprt
4086+
inline const type_exprt &to_type_expr(const exprt &expr)
4087+
{
4088+
PRECONDITION(can_cast_expr<type_exprt>(expr));
4089+
const type_exprt &ret = static_cast<const type_exprt &>(expr);
4090+
return ret;
4091+
}
4092+
4093+
/// \copydoc to_type_expr(const exprt &)
4094+
inline type_exprt &to_type_expr(exprt &expr)
4095+
{
4096+
PRECONDITION(can_cast_expr<type_exprt>(expr));
4097+
type_exprt &ret = static_cast<type_exprt &>(expr);
4098+
return ret;
4099+
}
4100+
40744101
/// \brief A constant literal expression
40754102
class constant_exprt : public expr_protectedt
40764103
{

0 commit comments

Comments
 (0)