Skip to content

Commit cd1258a

Browse files
Merge pull request #1425 from romainbrenguier/feature/java_new_array_data
TG-58 Java new array data in symex
2 parents 9efb65c + 1fa64a9 commit cd1258a

9 files changed

+70
-70
lines changed

src/goto-programs/builtin_functions.cpp

Lines changed: 16 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -569,35 +569,15 @@ void goto_convertt::do_java_new(
569569
const side_effect_exprt &rhs,
570570
goto_programt &dest)
571571
{
572-
if(lhs.is_nil())
573-
{
574-
error().source_location=lhs.find_source_location();
575-
error() << "do_java_new without lhs is yet to be implemented" << eom;
576-
throw 0;
577-
}
578-
572+
PRECONDITION(!lhs.is_nil());
573+
PRECONDITION(rhs.operands().empty());
574+
PRECONDITION(rhs.type().id() == ID_pointer);
579575
source_locationt location=rhs.source_location();
580-
581-
assert(rhs.operands().empty());
582-
583-
if(rhs.type().id()!=ID_pointer)
584-
{
585-
error().source_location=rhs.find_source_location();
586-
error() << "do_java_new returns pointer" << eom;
587-
throw 0;
588-
}
589-
590576
typet object_type=rhs.type().subtype();
591577

592578
// build size expression
593579
exprt object_size=size_of_expr(object_type, ns);
594-
595-
if(object_size.is_nil())
596-
{
597-
error().source_location=rhs.find_source_location();
598-
error() << "do_java_new got nil object_size" << eom;
599-
throw 0;
600-
}
580+
CHECK_RETURN(object_size.is_not_nil());
601581

602582
// we produce a malloc side-effect, which stays
603583
side_effect_exprt malloc_expr(ID_malloc);
@@ -624,36 +604,18 @@ void goto_convertt::do_java_new_array(
624604
const side_effect_exprt &rhs,
625605
goto_programt &dest)
626606
{
627-
if(lhs.is_nil())
628-
{
629-
error().source_location=lhs.find_source_location();
630-
error() << "do_java_new_array without lhs is yet to be implemented"
631-
<< eom;
632-
throw 0;
633-
}
607+
PRECONDITION(!lhs.is_nil()); // do_java_new_array without lhs not implemented
608+
PRECONDITION(rhs.operands().size() >= 1); // one per dimension
609+
PRECONDITION(rhs.type().id() == ID_pointer);
634610

635611
source_locationt location=rhs.source_location();
636-
637-
assert(rhs.operands().size()>=1); // one per dimension
638-
639-
if(rhs.type().id()!=ID_pointer)
640-
{
641-
error().source_location=rhs.find_source_location();
642-
error() << "do_java_new_array returns pointer" << eom;
643-
throw 0;
644-
}
645-
646612
typet object_type=rhs.type().subtype();
613+
PRECONDITION(ns.follow(object_type).id() == ID_struct);
647614

648615
// build size expression
649616
exprt object_size=size_of_expr(object_type, ns);
650617

651-
if(object_size.is_nil())
652-
{
653-
error().source_location=rhs.find_source_location();
654-
error() << "do_java_new_array got nil object_size" << eom;
655-
throw 0;
656-
}
618+
CHECK_RETURN(!object_size.is_nil());
657619

658620
// we produce a malloc side-effect, which stays
659621
side_effect_exprt malloc_expr(ID_malloc);
@@ -664,9 +626,12 @@ void goto_convertt::do_java_new_array(
664626
t_n->code=code_assignt(lhs, malloc_expr);
665627
t_n->source_location=location;
666628

667-
assert(ns.follow(object_type).id()==ID_struct);
668629
const struct_typet &struct_type=to_struct_type(ns.follow(object_type));
669-
assert(struct_type.components().size()==3);
630+
631+
// Ideally we would have a check for `is_valid_java_array(struct_type)` but
632+
// `is_valid_java_array is part of the java_bytecode module and we cannot
633+
// introduce such dependencies. We do this simple check instead:
634+
PRECONDITION(struct_type.components().size()==3);
670635

671636
// Init base class:
672637
dereference_exprt deref(lhs, object_type);
@@ -696,7 +661,6 @@ void goto_convertt::do_java_new_array(
696661
// Allocate a (struct realtype**) instead of a (void**) if possible.
697662
const irept &given_element_type=object_type.find(ID_C_element_type);
698663
typet allocate_data_type;
699-
exprt cast_data_member;
700664
if(given_element_type.is_not_nil())
701665
{
702666
allocate_data_type=
@@ -705,7 +669,8 @@ void goto_convertt::do_java_new_array(
705669
else
706670
allocate_data_type=data.type();
707671

708-
side_effect_exprt data_java_new_expr(ID_java_new_array, allocate_data_type);
672+
side_effect_exprt data_java_new_expr(
673+
ID_java_new_array_data, allocate_data_type);
709674

710675
// The instruction may specify a (hopefully small) upper bound on the
711676
// array size, in which case we allocate a fixed-length array that may

src/goto-programs/goto_convert.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -760,8 +760,10 @@ void goto_convertt::convert_assign(
760760

761761
do_java_new_array(lhs, to_side_effect_expr(rhs), dest);
762762
}
763-
else if(rhs.id()==ID_side_effect &&
764-
rhs.get(ID_statement)==ID_malloc)
763+
else if(
764+
rhs.id() == ID_side_effect &&
765+
(rhs.get(ID_statement) == ID_malloc ||
766+
rhs.get(ID_statement) == ID_java_new_array_data))
765767
{
766768
// just preserve
767769
Forall_operands(it, rhs)

src/goto-programs/goto_trace.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ void goto_trace_stept::output(
4747
case goto_trace_stept::typet::DEAD: out << "DEAD"; break;
4848
case goto_trace_stept::typet::OUTPUT: out << "OUTPUT"; break;
4949
case goto_trace_stept::typet::INPUT: out << "INPUT"; break;
50-
case goto_trace_stept::typet::ATOMIC_BEGIN: out << "ATOMC_BEGIN"; break;
50+
case goto_trace_stept::typet::ATOMIC_BEGIN:
51+
out << "ATOMIC_BEGIN";
52+
break;
5153
case goto_trace_stept::typet::ATOMIC_END: out << "ATOMIC_END"; break;
5254
case goto_trace_stept::typet::SHARED_READ: out << "SHARED_READ"; break;
5355
case goto_trace_stept::typet::SHARED_WRITE: out << "SHARED WRITE"; break;
@@ -91,7 +93,7 @@ void goto_trace_stept::output(
9193

9294
out << "\n";
9395

94-
if(pc->is_other() || pc->is_assign())
96+
if((pc->is_other() && lhs_object.is_not_nil()) || pc->is_assign())
9597
{
9698
irep_idt identifier=lhs_object.get_object_name();
9799
out << " " << from_expr(ns, identifier, lhs_object.get_original_expr())
@@ -386,14 +388,8 @@ void show_goto_trace(
386388
break;
387389

388390
case goto_trace_stept::typet::CONSTRAINT:
389-
UNREACHABLE;
390-
break;
391-
392391
case goto_trace_stept::typet::SHARED_READ:
393392
case goto_trace_stept::typet::SHARED_WRITE:
394-
UNREACHABLE;
395-
break;
396-
397393
default:
398394
UNREACHABLE;
399395
}

src/goto-programs/interpreter_evaluate.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ Author: Daniel Kroening, [email protected]
2121
#include <util/pointer_offset_size.h>
2222
#include <string.h>
2323

24-
/// reads a memory address and loads it into the dest variable marks cell as
25-
/// read before written if cell has never been written
24+
/// Reads a memory address and loads it into the `dest` variable.
25+
/// Marks cell as `READ_BEFORE_WRITTEN` if cell has never been written.
2626
void interpretert::read(
2727
const mp_integer &address,
2828
mp_vectort &dest) const
@@ -102,7 +102,12 @@ void interpretert::clear_input_flags()
102102
}
103103
}
104104

105-
/// \return Number of leaf primitive types; returns true on error
105+
/// Count the number of leaf subtypes of `ty`, a leaf type is a type that is
106+
/// not an array or a struct. For instance the count for a type such as
107+
/// `struct { (int[3])[5]; int }` would be 16 = (3 * 5 + 1).
108+
/// \param ty: a type
109+
/// \param [out] result: Number of leaf primitive types in `ty`
110+
/// \return returns true on error
106111
bool interpretert::count_type_leaves(const typet &ty, mp_integer &result)
107112
{
108113
if(ty.id()==ID_struct)
@@ -299,6 +304,9 @@ bool interpretert::memory_offset_to_byte_offset(
299304
}
300305
}
301306

307+
/// Evaluate an expression
308+
/// \param expr: expression to evaluate
309+
/// \param [out] dest: vector in which the result of the evaluation is stored
302310
void interpretert::evaluate(
303311
const exprt &expr,
304312
mp_vectort &dest)

src/goto-symex/symex_assign.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ void goto_symext::symex_assign(
5959

6060
throw "symex_assign: unexpected function call: "+id2string(identifier);
6161
}
62-
else if(statement==ID_cpp_new ||
63-
statement==ID_cpp_new_array ||
64-
statement==ID_java_new_array)
62+
else if(
63+
statement == ID_cpp_new || statement == ID_cpp_new_array ||
64+
statement == ID_java_new_array_data)
6565
symex_cpp_new(state, lhs, side_effect_expr);
6666
else if(statement==ID_malloc)
6767
symex_malloc(state, lhs, side_effect_expr);

src/goto-symex/symex_builtin_functions.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,9 @@ void goto_symext::symex_cpp_new(
376376
if(code.type().id()!=ID_pointer)
377377
throw "new expected to return pointer";
378378

379-
do_array=(code.get(ID_statement)==ID_cpp_new_array ||
380-
code.get(ID_statement)==ID_java_new_array);
379+
do_array =
380+
(code.get(ID_statement) == ID_cpp_new_array ||
381+
code.get(ID_statement) == ID_java_new_array_data);
381382

382383
dynamic_counter++;
383384

@@ -393,7 +394,7 @@ void goto_symext::symex_cpp_new(
393394
if(code.get(ID_statement)==ID_cpp_new_array ||
394395
code.get(ID_statement)==ID_cpp_new)
395396
symbol.mode=ID_cpp;
396-
else if(code.get(ID_statement)==ID_java_new_array)
397+
else if(code.get(ID_statement) == ID_java_new_array_data)
397398
symbol.mode=ID_java;
398399
else
399400
INVARIANT_WITH_IREP(false, "Unexpected side effect expression", code);

src/util/irep_ids.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ IREP_ID_TWO(cpp_new_array, cpp_new[])
217217
IREP_ID_TWO(cpp_delete_array, cpp_delete[])
218218
IREP_ID_ONE(java_new)
219219
IREP_ID_ONE(java_new_array)
220+
IREP_ID_ONE(java_new_array_data)
220221
IREP_ID_ONE(java_string_literal)
221222
IREP_ID_ONE(printf)
222223
IREP_ID_ONE(input)

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ SRC += unit_tests.cpp \
1616
analyses/does_remove_const/does_expr_lose_const.cpp \
1717
analyses/does_remove_const/does_type_preserve_const_correctness.cpp \
1818
analyses/does_remove_const/is_type_at_least_as_const_as.cpp \
19+
goto-programs/goto_trace_output.cpp \
1920
java_bytecode/java_bytecode_convert_class/convert_abstract_class.cpp \
2021
java_bytecode/java_bytecode_parse_generics/parse_generic_class.cpp \
2122
java_bytecode/java_object_factory/gen_nondet_string_init.cpp \
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for goto_trace_stept::output
4+
5+
Author: Diffblue Limited. All rights reserved.
6+
7+
\*******************************************************************/
8+
9+
#include <testing-utils/catch.hpp>
10+
#include <goto-programs/goto_program_template.h>
11+
#include <goto-programs/goto_trace.h>
12+
#include <iostream>
13+
14+
SCENARIO(
15+
"Output trace with nil lhs object",
16+
"[core][goto-programs][goto_trace]")
17+
{
18+
symbol_tablet symbol_table;
19+
namespacet ns(symbol_table);
20+
goto_programt::instructionst instructions;
21+
instructions.emplace_back(goto_program_instruction_typet::OTHER);
22+
goto_trace_stept step;
23+
step.pc = instructions.begin();
24+
step.type = goto_trace_stept::typet::ATOMIC_BEGIN;
25+
step.output(ns, std::cout);
26+
}

0 commit comments

Comments
 (0)