From 0bf28f0673a6eb79ee3f7dea8325b49c1644440d Mon Sep 17 00:00:00 2001 From: Daniel Kroening <kroening@cs.ox.ac.uk> Date: Sat, 6 Apr 2019 20:29:07 +0100 Subject: [PATCH 1/2] introduce java_class_typet::componentt This enables Java-specific extensions to components of Java classes (e.g., 'native', 'final'). --- .../java_bytecode_convert_class.cpp | 8 ++-- jbmc/src/java_bytecode/java_types.h | 37 ++++++++++++++++++- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/jbmc/src/java_bytecode/java_bytecode_convert_class.cpp b/jbmc/src/java_bytecode/java_bytecode_convert_class.cpp index 5580caa8862..1b5bc8a7862 100644 --- a/jbmc/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/jbmc/src/java_bytecode/java_bytecode_convert_class.cpp @@ -375,7 +375,7 @@ void java_bytecode_convert_classt::convert( { class_type.add_base(base); } - class_typet::componentt base_class_field; + java_class_typet::componentt base_class_field; base_class_field.type() = class_type.bases().at(0).type(); base_class_field.set_name("@" + id2string(c.super_class)); base_class_field.set_base_name("@" + id2string(c.super_class)); @@ -798,18 +798,18 @@ void java_bytecode_convert_classt::add_array_types(symbol_tablet &symbol_table) class_type.set_name(struct_tag_type_identifier); class_type.components().reserve(3); - class_typet::componentt base_class_component( + java_class_typet::componentt base_class_component( "@java.lang.Object", struct_tag_typet("java::java.lang.Object")); base_class_component.set_pretty_name("@java.lang.Object"); base_class_component.set_base_name("@java.lang.Object"); class_type.components().push_back(base_class_component); - class_typet::componentt length_component("length", java_int_type()); + java_class_typet::componentt length_component("length", java_int_type()); length_component.set_pretty_name("length"); length_component.set_base_name("length"); class_type.components().push_back(length_component); - class_typet::componentt data_component( + java_class_typet::componentt data_component( "data", java_reference_type(java_type_from_char(l))); data_component.set_pretty_name("data"); data_component.set_base_name("data"); diff --git a/jbmc/src/java_bytecode/java_types.h b/jbmc/src/java_bytecode/java_types.h index 7b39f917c3b..b55dae20712 100644 --- a/jbmc/src/java_bytecode/java_types.h +++ b/jbmc/src/java_bytecode/java_types.h @@ -101,7 +101,42 @@ inline bool can_cast_type<annotated_typet>(const typet &) class java_class_typet:public class_typet { - public: +public: + class componentt : public class_typet::componentt + { + public: + componentt() = default; + + componentt(const irep_idt &_name, typet _type) + : class_typet::componentt(_name, std::move(_type)) + { + } + + /// is a method 'native'? + bool get_is_native() const + { + return get_bool(ID_is_native_method); + } + + /// marks a method as 'native' + void set_is_native(const bool is_native) + { + set(ID_is_native_method, is_native); + } + }; + + using componentst = std::vector<componentt>; + + const componentst &components() const + { + return (const componentst &)(find(ID_components).get_sub()); + } + + componentst &components() + { + return (componentst &)(add(ID_components).get_sub()); + } + const irep_idt &get_access() const { return get(ID_access); From 809c5a3a227a4315ba222e66e680bd1b7f8abb93 Mon Sep 17 00:00:00 2001 From: Daniel Kroening <kroening@cs.ox.ac.uk> Date: Sat, 6 Apr 2019 21:06:57 +0100 Subject: [PATCH 2/2] move is_final to java component type 'final' is a field modifier for Java, and has no meaning in C or C++. It should thus move to java_class_typet::componentt. --- .../java_bytecode_convert_class.cpp | 4 ++-- .../java_bytecode/java_bytecode_language.cpp | 2 +- jbmc/src/java_bytecode/java_types.h | 18 ++++++++++++++++ jbmc/unit/java-testing-utils/require_type.cpp | 21 ++++++++++++++++++- jbmc/unit/java-testing-utils/require_type.h | 4 ++++ .../java_bytecode_language/language.cpp | 6 +++--- src/util/std_types.h | 10 --------- 7 files changed, 48 insertions(+), 17 deletions(-) diff --git a/jbmc/src/java_bytecode/java_bytecode_convert_class.cpp b/jbmc/src/java_bytecode/java_bytecode_convert_class.cpp index 1b5bc8a7862..b87fc9c2280 100644 --- a/jbmc/src/java_bytecode/java_bytecode_convert_class.cpp +++ b/jbmc/src/java_bytecode/java_bytecode_convert_class.cpp @@ -740,10 +740,10 @@ void java_bytecode_convert_classt::convert( } else { - class_typet &class_type=to_class_type(class_symbol.type); + auto &class_type = to_java_class_type(class_symbol.type); class_type.components().emplace_back(); - class_typet::componentt &component=class_type.components().back(); + auto &component = class_type.components().back(); component.set_name(f.name); component.set_base_name(f.name); diff --git a/jbmc/src/java_bytecode/java_bytecode_language.cpp b/jbmc/src/java_bytecode/java_bytecode_language.cpp index da84fe35975..31f286026f6 100644 --- a/jbmc/src/java_bytecode/java_bytecode_language.cpp +++ b/jbmc/src/java_bytecode/java_bytecode_language.cpp @@ -332,7 +332,7 @@ static void infer_opaque_type_fields( symbolt &writable_class_symbol = symbol_table.get_writeable_ref(class_symbol_id); auto &components = - to_struct_type(writable_class_symbol.type).components(); + to_java_class_type(writable_class_symbol.type).components(); components.emplace_back(component_name, fieldref.type()); components.back().set_base_name(component_name); components.back().set_pretty_name(component_name); diff --git a/jbmc/src/java_bytecode/java_types.h b/jbmc/src/java_bytecode/java_types.h index b55dae20712..b738f9fdd16 100644 --- a/jbmc/src/java_bytecode/java_types.h +++ b/jbmc/src/java_bytecode/java_types.h @@ -112,6 +112,18 @@ class java_class_typet:public class_typet { } + /// is a method or field 'final'? + bool get_is_final() const + { + return get_bool(ID_final); + } + + /// is a method or field 'final'? + void set_is_final(const bool is_final) + { + set(ID_final, is_final); + } + /// is a method 'native'? bool get_is_native() const { @@ -137,6 +149,12 @@ class java_class_typet:public class_typet return (componentst &)(add(ID_components).get_sub()); } + const componentt &get_component(const irep_idt &component_name) const + { + return static_cast<const componentt &>( + class_typet::get_component(component_name)); + } + const irep_idt &get_access() const { return get(ID_access); diff --git a/jbmc/unit/java-testing-utils/require_type.cpp b/jbmc/unit/java-testing-utils/require_type.cpp index 893cfb8dc7b..9c8e682fa8b 100644 --- a/jbmc/unit/java-testing-utils/require_type.cpp +++ b/jbmc/unit/java-testing-utils/require_type.cpp @@ -30,11 +30,30 @@ pointer_typet require_type::require_pointer( return pointer; } +/// Checks that a class has a component with a specific name +/// \param java_class_type: The class that should have the component +/// \param component_name: The name of the component +/// \return The component with the specified name +java_class_typet::componentt require_type::require_component( + const java_class_typet &java_class_type, + const irep_idt &component_name) +{ + const auto &component = std::find_if( + java_class_type.components().begin(), + java_class_type.components().end(), + [&component_name](const java_class_typet::componentt &component) { + return component.get_name() == component_name; + }); + + REQUIRE(component != java_class_type.components().end()); + return *component; +} + /// Checks a struct like type has a component with a specific name /// \param struct_type: The structure that should have the component /// \param component_name: The name of the component /// \return The component with the specified name -struct_union_typet::componentt require_type::require_component( +struct_typet::componentt require_type::require_component( const struct_typet &struct_type, const irep_idt &component_name) { diff --git a/jbmc/unit/java-testing-utils/require_type.h b/jbmc/unit/java-testing-utils/require_type.h index 14ae5c47f7b..d0d8912453f 100644 --- a/jbmc/unit/java-testing-utils/require_type.h +++ b/jbmc/unit/java-testing-utils/require_type.h @@ -32,6 +32,10 @@ const pointer_typet require_pointer_to_tag( const typet &type, const irep_idt &identifier = irep_idt()); +java_class_typet::componentt require_component( + const java_class_typet &java_class_type, + const irep_idt &component_name); + struct_typet::componentt require_component( const struct_typet &struct_type, const irep_idt &component_name); diff --git a/jbmc/unit/java_bytecode/java_bytecode_language/language.cpp b/jbmc/unit/java_bytecode/java_bytecode_language/language.cpp index 1b9f7d8c9b6..ada4c440109 100644 --- a/jbmc/unit/java_bytecode/java_bytecode_language/language.cpp +++ b/jbmc/unit/java_bytecode/java_bytecode_language/language.cpp @@ -36,9 +36,9 @@ SCENARIO( { const symbolt &opaque_class_symbol = symbol_table.lookup_ref(opaque_class_prefix); - const struct_typet &opaque_class_struct = - to_struct_type(opaque_class_symbol.type); - const struct_union_typet::componentt &field = + const auto &opaque_class_struct = + to_java_class_type(opaque_class_symbol.type); + const auto &field = require_type::require_component(opaque_class_struct, "field2"); REQUIRE(field.get_is_final()); } diff --git a/src/util/std_types.h b/src/util/std_types.h index 85390988cc3..93210340ed5 100644 --- a/src/util/std_types.h +++ b/src/util/std_types.h @@ -123,16 +123,6 @@ class struct_union_typet:public typet { return set(ID_C_is_padding, is_padding); } - - bool get_is_final() const - { - return get_bool(ID_final); - } - - void set_is_final(const bool is_final) - { - set(ID_final, is_final); - } }; typedef std::vector<componentt> componentst;