36 size_t _max_array_length,
40 :
log(_message_handler),
73 const bool loading_success =
79 for(
auto overlay_class_it = std::next(parse_trees.begin());
80 overlay_class_it != parse_trees.end();
83 overlay_classes.push_front(std::cref(overlay_class_it->parsed_class));
92 else if(!loading_success)
161 static irep_idt org_cprover_CProver_name =
"org.cprover.CProver";
163 (class_name == org_cprover_CProver_name &&
170 const irep_idt &qualified_fieldname,
189 if(signature.has_value())
194 signature.value().front() ==
'<'
201 const std::string superclass_ref =
202 signature.value().substr(start, (end - start) + 1);
208 if(superclass_ref.find(
'<') != std::string::npos)
209 return superclass_ref;
228 const std::string &interface_name)
230 if(signature.has_value())
235 signature.value().front() ==
'<'
245 std::string interface_name_slash_to_dot = interface_name;
247 interface_name_slash_to_dot.begin(),
248 interface_name_slash_to_dot.end(),
253 signature.value().find(
"L" + interface_name_slash_to_dot +
"<", start);
254 if(start != std::string::npos)
258 return signature.value().substr(start, (end - start) + 1);
274 log.
debug() <<
"Skip class " << c.
name <<
" (already loaded)"
284 std::cout <<
"INFO: found generic class signature "
286 <<
" in parsed class "
294 for(
const typet &t : generic_types)
299 class_type=generic_class_type;
304 <<
"\n could not parse signature: " << c.
signature.value()
327 <<
" won't work properly because max "
329 <<
") is less than the "
333 ID_java_enum_static_unwind,
357 if(superclass_ref.has_value())
362 base, superclass_ref.value(), qualified_classname);
368 <<
" of class: " << c.
name
369 <<
"\n could not parse signature: "
370 << superclass_ref.value() <<
"\n " << e.what()
371 <<
"\n ignoring that the superclass is generic"
381 base_class_field.type() = class_type.
bases().at(0).type();
385 class_type.
components().push_back(base_class_field);
399 if(interface_ref.has_value())
404 base, interface_ref.value(), qualified_classname);
409 log.
debug() <<
"Interface: " <<
interface << " of class: " << c.name
410 << "\n could not parse signature: " << interface_ref.value()
412 << "\n ignoring that the interface is generic"
414 class_type.add_base(base);
419 class_type.add_base(base);
424 for(const auto &lambda_entry : c.lambda_method_handle_map)
429 lambda_entry.second.is_unknown_handle()
430 ? class_type.add_unknown_lambda_method_handle()
431 : class_type.add_lambda_method_handle(
432 lambda_entry.second.get_method_descriptor(),
433 lambda_entry.second.handle_type);
437 if(!c.annotations.empty())
438 convert_annotations(c.annotations, class_type.get_annotations());
441 const irep_idt base_name = [](const std::string &full_name) {
442 const size_t last_dot = full_name.find_last_of('.');
443 return last_dot == std::string::npos
445 : std::string(full_name, last_dot + 1, std::string::npos);
446 }(id2string(c.name));
450 new_symbol.base_name = base_name;
451 new_symbol.pretty_name=c.name;
452 new_symbol.name=qualified_classname;
453 class_type.set_name(new_symbol.name);
454 new_symbol.type=class_type;
455 new_symbol.mode=ID_java;
456 new_symbol.is_type=true;
458 symbolt *class_symbol;
461 log.debug() << "Adding symbol: class '" << c.name << "'" << messaget::eom;
462 if(symbol_table.move(new_symbol, class_symbol))
464 log.error() << "failed to add class symbol " << new_symbol.name
470 const class_typet::componentst &fields =
471 to_class_type(class_symbol->type).components();
474 for(auto overlay_class : overlay_classes)
476 for(const auto &field : overlay_class.get().fields)
478 std::string field_id = qualified_classname + "." + id2string(field.name);
479 if(check_field_exists(field, field_id, fields))
482 "Duplicate field definition for " + field_id + " in overlay class";
484 log.error() << err << messaget::eom;
487 log.debug() << "Adding symbol from overlay class: field '" << field.name
488 << "'" << messaget::eom;
489 convert(*class_symbol, field);
490 POSTCONDITION(check_field_exists(field, field_id, fields));
493 for(const auto &field : c.fields)
495 std::string field_id = qualified_classname + "." + id2string(field.name);
496 if(check_field_exists(field, field_id, fields))
499 log.error() << "Field definition for " << field_id
500 << " already loaded from overlay class" << messaget::eom;
503 log.debug() << "Adding symbol: field '" << field.name << "'"
505 convert(*class_symbol, field);
506 POSTCONDITION(check_field_exists(field, field_id, fields));
510 std::set<irep_idt> overlay_methods;
511 for(auto overlay_class : overlay_classes)
513 for(const methodt &method : overlay_class.get().methods)
515 const irep_idt method_identifier =
516 qualified_classname + "." + id2string(method.name)
517 + ":" + method.descriptor;
518 if(is_ignored_method(c.name, method))
520 log.debug() << "Ignoring method: '" << method_identifier << "'"
524 if(method_bytecode.contains_method(method_identifier))
531 if(overlay_methods.count(method_identifier) == 0)
536 << "Method " << method_identifier
537 << " exists in an overlay class without being marked as an "
538 "overlay and also exists in another overlay class that appears "
539 "earlier in the classpath"
546 log.debug() << "Adding symbol from overlay class: method '"
547 << method_identifier << "'" << messaget::eom;
548 java_bytecode_convert_method_lazy(
553 log.get_message_handler());
554 method_bytecode.add(qualified_classname, method_identifier, method);
555 if(is_overlay_method(method))
556 overlay_methods.insert(method_identifier);
559 for(const methodt &method : c.methods)
561 const irep_idt method_identifier=
562 qualified_classname + "." + id2string(method.name)
563 + ":" + method.descriptor;
564 if(is_ignored_method(c.name, method))
566 log.debug() << "Ignoring method: '" << method_identifier << "'"
570 if(method_bytecode.contains_method(method_identifier))
576 if(overlay_methods.erase(method_identifier) == 0)
581 << "Method " << method_identifier
582 << " exists in an overlay class without being marked as an overlay "
583 "and also exists in the underlying class"
590 log.debug() << "Adding symbol: method '" << method_identifier << "'"
592 java_bytecode_convert_method_lazy(
597 log.get_message_handler());
598 method_bytecode.add(qualified_classname, method_identifier, method);
599 if(is_overlay_method(method))
602 << "Method " << method_identifier
603 << " marked as an overlay where defined in the underlying class"
607 if(!overlay_methods.empty())
610 << "Overlay methods defined in overlay classes did not exist in the "
611 "underlying class:\n";
612 for(const irep_idt &method_id : overlay_methods)
613 log.error() << " " << method_id << "\n";
614 log.error() << messaget::eom;
618 if(c.super_class.empty())
619 java_root_class(*class_symbol);
622 bool java_bytecode_convert_classt::check_field_exists(
623 const java_bytecode_parse_treet::fieldt &field,
624 const irep_idt &qualified_fieldname,
625 const struct_union_typet::componentst &fields) const
628 return symbol_table.has_symbol(qualified_fieldname);
630 auto existing_field = std::find_if(
633 [&field](const struct_union_typet::componentt &f)
635 return f.get_name() == field.name;
637 return existing_field != fields.end();
643 void java_bytecode_convert_classt::convert(
644 symbolt &class_symbol,
648 if(f.signature.has_value())
650 field_type = *java_type_from_string_with_exception(
651 f.descriptor, f.signature, id2string(class_symbol.name));
654 if(is_java_generic_parameter(field_type))
657 std::cout << "fieldtype: generic "
658 << to_java_generic_parameter(field_type).type_variable()
660 << " name " << f.name << "\n";
666 else if(is_java_generic_type(field_type))
668 java_generic_typet &with_gen_type=
669 to_java_generic_type(field_type);
671 std::cout << "fieldtype: generic container type "
672 << std::to_string(with_gen_type.generic_type_arguments().size())
673 << " type " << with_gen_type.id()
674 << " name " << f.name
675 << " subtype id " << with_gen_type.subtype().id() << "\n";
677 field_type=with_gen_type;
681 field_type = *java_type_from_string(f.descriptor);
688 else if(f.is_protected)
689 access = ID_protected;
695 auto &class_type = to_java_class_type(class_symbol.type);
700 const irep_idt field_identifier =
701 id2string(class_symbol.name) + "." + id2string(f.name);
703 class_type.static_members().emplace_back();
704 auto &component = class_type.static_members().back();
706 component.set_name(field_identifier);
707 component.set_base_name(f.name);
708 component.set_pretty_name(f.name);
709 component.set_access(access);
710 component.set_is_final(f.is_final);
711 component.type() = field_type;
716 new_symbol.is_static_lifetime=true;
717 new_symbol.is_lvalue=true;
718 new_symbol.is_state_var=true;
719 new_symbol.name=id2string(class_symbol.name)+"."+id2string(f.name);
720 new_symbol.base_name=f.name;
721 new_symbol.type=field_type;
724 set_declaring_class(new_symbol, class_symbol.name);
725 new_symbol.type.set(ID_C_field, f.name);
726 new_symbol.type.set(ID_C_constant, f.is_final);
727 new_symbol.pretty_name=id2string(class_symbol.pretty_name)+
728 "."+id2string(f.name);
729 new_symbol.mode=ID_java;
730 new_symbol.is_type=false;
737 new_symbol.type.set(ID_C_access, ID_public);
738 else if(f.is_protected)
739 new_symbol.type.set(ID_C_access, ID_protected);
740 else if(f.is_private)
741 new_symbol.type.set(ID_C_access, ID_private);
743 new_symbol.type.set(ID_C_access, ID_default);
745 const namespacet ns(symbol_table);
746 const auto value = zero_initializer(field_type, class_symbol.location, ns);
747 if(!value.has_value())
749 log.error().source_location = class_symbol.location;
750 log.error() << "failed to zero-initialize " << f.name << messaget::eom;
753 new_symbol.value = *value;
756 if(!f.annotations.empty())
760 type_checked_cast<annotated_typet>(new_symbol.type).get_annotations());
764 const auto s_it=symbol_table.symbols.find(new_symbol.name);
765 if(s_it!=symbol_table.symbols.end())
766 symbol_table.erase(s_it);
768 if(symbol_table.add(new_symbol))
769 assert(false && "failed to add static field symbol");
773 class_type.components().emplace_back();
774 auto &component = class_type.components().back();
776 component.set_name(f.name);
777 component.set_base_name(f.name);
778 component.set_pretty_name(f.name);
779 component.set_access(access);
780 component.set_is_final(f.is_final);
781 component.type() = field_type;
784 if(!f.annotations.empty())
788 static_cast<annotated_typet &>(component.type()).get_annotations());
793 void add_java_array_types(symbol_tablet &symbol_table)
795 const std::string letters="ijsbcfdza";
797 for(const char l : letters)
799 struct_tag_typet struct_tag_type =
800 to_struct_tag_type(java_array_type(l).subtype());
802 const irep_idt &struct_tag_type_identifier =
803 struct_tag_type.get_identifier();
804 if(symbol_table.has_symbol(struct_tag_type_identifier))
807 java_class_typet class_type;
810 class_type.set_tag(struct_tag_type_identifier);
815 class_type.set_name(struct_tag_type_identifier);
817 class_type.components().reserve(3);
818 java_class_typet::componentt base_class_component(
819 "@java.lang.Object", struct_tag_typet("java::java.lang.Object"));
820 base_class_component.set_pretty_name("@java.lang.Object");
821 base_class_component.set_base_name("@java.lang.Object");
822 class_type.components().push_back(base_class_component);
824 java_class_typet::componentt length_component("length", java_int_type());
825 length_component.set_pretty_name("length");
826 length_component.set_base_name("length");
827 class_type.components().push_back(length_component);
829 java_class_typet::componentt data_component(
830 "data", java_reference_type(java_type_from_char(l)));
831 data_component.set_pretty_name("data");
832 data_component.set_base_name("data");
833 class_type.components().push_back(data_component);
839 java_class_typet::componentt array_element_classid_component(
840 JAVA_ARRAY_ELEMENT_CLASSID_FIELD_NAME, string_typet());
841 array_element_classid_component.set_pretty_name(
842 JAVA_ARRAY_ELEMENT_CLASSID_FIELD_NAME);
843 array_element_classid_component.set_base_name(
844 JAVA_ARRAY_ELEMENT_CLASSID_FIELD_NAME);
845 class_type.components().push_back(array_element_classid_component);
847 java_class_typet::componentt array_dimension_component(
848 JAVA_ARRAY_DIMENSION_FIELD_NAME, java_int_type());
849 array_dimension_component.set_pretty_name(
850 JAVA_ARRAY_DIMENSION_FIELD_NAME);
851 array_dimension_component.set_base_name(JAVA_ARRAY_DIMENSION_FIELD_NAME);
852 class_type.components().push_back(array_dimension_component);
855 class_type.add_base(struct_tag_typet("java::java.lang.Object"));
858 is_valid_java_array(class_type),
859 "Constructed a new type representing a Java Array "
860 "object that doesn't match expectations");
863 symbol.name = struct_tag_type_identifier;
864 symbol.base_name = struct_tag_type.get(ID_C_base_name);
866 symbol.type = class_type;
867 symbol.mode = ID_java;
868 symbol_table.add(symbol);
873 const irep_idt clone_name =
874 id2string(struct_tag_type_identifier) + ".clone:()Ljava/lang/Object;";
875 java_method_typet::parametert this_param(
876 java_reference_type(struct_tag_type));
877 this_param.set_identifier(id2string(clone_name)+"::this");
878 this_param.set_base_name(ID_this);
879 this_param.set_this();
880 const java_method_typet clone_type({this_param}, java_lang_object_type());
882 parameter_symbolt this_symbol;
883 this_symbol.name=this_param.get_identifier();
884 this_symbol.base_name=this_param.get_base_name();
885 this_symbol.pretty_name=this_symbol.base_name;
886 this_symbol.type=this_param.type();
887 this_symbol.mode=ID_java;
888 symbol_table.add(this_symbol);
890 const irep_idt local_name=
891 id2string(clone_name)+"::cloned_array";
892 auxiliary_symbolt local_symbol;
893 local_symbol.name=local_name;
894 local_symbol.base_name="cloned_array";
895 local_symbol.pretty_name=local_symbol.base_name;
896 local_symbol.type = java_reference_type(struct_tag_type);
897 local_symbol.mode=ID_java;
898 symbol_table.add(local_symbol);
899 const auto local_symexpr = local_symbol.symbol_expr();
901 code_declt declare_cloned(local_symexpr);
903 source_locationt location;
904 location.set_function(local_name);
905 side_effect_exprt java_new_array(
906 ID_java_new_array, java_reference_type(struct_tag_type), location);
907 dereference_exprt old_array{this_symbol.symbol_expr()};
908 dereference_exprt new_array{local_symexpr};
909 member_exprt old_length(
910 old_array, length_component.get_name(), length_component.type());
911 java_new_array.copy_to_operands(old_length);
912 code_frontend_assignt create_blank(local_symexpr, java_new_array);
914 codet copy_type_information = code_skipt();
919 const auto &array_dimension_component =
920 class_type.get_component(JAVA_ARRAY_DIMENSION_FIELD_NAME);
921 const auto &array_element_classid_component =
922 class_type.get_component(JAVA_ARRAY_ELEMENT_CLASSID_FIELD_NAME);
924 member_exprt old_array_dimension(old_array, array_dimension_component);
925 member_exprt old_array_element_classid(
926 old_array, array_element_classid_component);
928 member_exprt new_array_dimension(new_array, array_dimension_component);
929 member_exprt new_array_element_classid(
930 new_array, array_element_classid_component);
932 copy_type_information = code_blockt{
933 {code_frontend_assignt(new_array_dimension, old_array_dimension),
934 code_frontend_assignt(
935 new_array_element_classid, old_array_element_classid)}};
938 member_exprt old_data(
939 old_array, data_component.get_name(), data_component.type());
940 member_exprt new_data(
941 new_array, data_component.get_name(), data_component.type());
953 const irep_idt index_name=
954 id2string(clone_name)+"::index";
955 auxiliary_symbolt index_symbol;
956 index_symbol.name=index_name;
957 index_symbol.base_name="index";
958 index_symbol.pretty_name=index_symbol.base_name;
959 index_symbol.type = length_component.type();
960 index_symbol.mode=ID_java;
961 symbol_table.add(index_symbol);
962 const auto &index_symexpr=index_symbol.symbol_expr();
964 code_declt declare_index(index_symexpr);
966 dereference_exprt old_cell(
967 plus_exprt(old_data, index_symexpr),
968 to_type_with_subtype(old_data.type()).subtype());
969 dereference_exprt new_cell(
970 plus_exprt(new_data, index_symexpr),
971 to_type_with_subtype(new_data.type()).subtype());
973 const code_fort copy_loop = code_fort::from_index_bounds(
974 from_integer(0, index_symexpr.type()),
977 code_frontend_assignt(std::move(new_cell), std::move(old_cell)),
980 member_exprt new_base_class(
981 new_array, base_class_component.get_name(), base_class_component.type());
982 address_of_exprt retval(new_base_class);
983 code_returnt return_inst(retval);
985 const code_blockt clone_body({declare_cloned,
987 copy_type_information,
992 symbolt clone_symbol;
993 clone_symbol.name=clone_name;
994 clone_symbol.pretty_name =
995 id2string(struct_tag_type_identifier) + ".clone:()";
996 clone_symbol.base_name="clone";
997 clone_symbol.type=clone_type;
998 clone_symbol.value=clone_body;
999 clone_symbol.mode=ID_java;
1000 symbol_table.add(clone_symbol);
1004 bool java_bytecode_convert_class(
1005 const java_class_loadert::parse_tree_with_overlayst &parse_trees,
1006 symbol_tablet &symbol_table,
1007 message_handlert &message_handler,
1008 size_t max_array_length,
1009 method_bytecodet &method_bytecode,
1010 java_string_library_preprocesst &string_preprocess,
1011 const std::unordered_set<std::string> &no_load_classes)
1013 java_bytecode_convert_classt java_bytecode_convert_class(
1023 java_bytecode_convert_class(parse_trees);
1031 catch(const char *e)
1033 messaget log{message_handler};
1034 log.error() << e << messaget::eom;
1037 catch(const std::string &e)
1039 messaget log{message_handler};
1040 log.error() << e << messaget::eom;
1046 static std::string get_final_name_component(const std::string &name)
1048 return name.substr(name.rfind("::") + 2);
1051 static std::string get_without_final_name_component(const std::string &name)
1053 return name.substr(0, name.rfind("::"));
1068 static void find_and_replace_parameter(
1069 java_generic_parametert ¶meter,
1070 const std::vector<java_generic_parametert> &replacement_parameters)
1073 const std::string ¶meter_full_name =
1074 id2string(parameter.type_variable_ref().get_identifier());
1075 const std::string parameter_name =
1076 get_final_name_component(parameter_full_name);
1079 const auto replacement_parameter_it = std::find_if(
1080 replacement_parameters.begin(),
1081 replacement_parameters.end(),
1082 [¶meter_name](const java_generic_parametert &replacement_param) {
1083 return parameter_name ==
1084 get_final_name_component(
1085 id2string(replacement_param.type_variable().get_identifier()));
1087 if(replacement_parameter_it == replacement_parameters.end())
1091 const std::string &replacement_parameter_full_name =
1092 id2string(replacement_parameter_it->type_variable().get_identifier());
1095 PRECONDITION(has_prefix(
1096 replacement_parameter_full_name,
1097 get_without_final_name_component(parameter_full_name)));
1099 parameter.type_variable_ref().set_identifier(replacement_parameter_full_name);
1107 static void find_and_replace_parameters(
1109 const std::vector<java_generic_parametert> &replacement_parameters)
1111 if(is_java_generic_parameter(type))
1113 find_and_replace_parameter(
1114 to_java_generic_parameter(type), replacement_parameters);
1116 else if(is_java_generic_type(type))
1118 java_generic_typet &generic_type = to_java_generic_type(type);
1119 std::vector<reference_typet> &arguments =
1120 generic_type.generic_type_arguments();
1121 for(auto &argument : arguments)
1123 find_and_replace_parameters(argument, replacement_parameters);
1126 else if(is_java_generic_struct_tag_type(type))
1128 java_generic_struct_tag_typet &generic_base =
1129 to_java_generic_struct_tag_type(type);
1130 std::vector<reference_typet> &gen_types = generic_base.generic_types();
1131 for(auto &gen_type : gen_types)
1133 find_and_replace_parameters(gen_type, replacement_parameters);
1141 void convert_annotations(
1142 const java_bytecode_parse_treet::annotationst &parsed_annotations,
1143 std::vector<java_annotationt> &java_annotations)
1145 for(const auto &annotation : parsed_annotations)
1147 java_annotations.emplace_back(annotation.type);
1148 std::vector<java_annotationt::valuet> &values =
1149 java_annotations.back().get_values();
1151 annotation.element_value_pairs.begin(),
1152 annotation.element_value_pairs.end(),
1153 std::back_inserter(values),
1154 [](const decltype(annotation.element_value_pairs)::value_type &value) {
1155 return java_annotationt::valuet(value.element_name, value.value);
1164 void convert_java_annotations(
1165 const std::vector<java_annotationt> &java_annotations,
1166 java_bytecode_parse_treet::annotationst &annotations)
1168 for(const auto &java_annotation : java_annotations)
1170 annotations.emplace_back(java_bytecode_parse_treet::annotationt());
1171 auto &annotation = annotations.back();
1172 annotation.type = java_annotation.get_type();
1175 java_annotation.get_values().begin(),
1176 java_annotation.get_values().end(),
1177 std::back_inserter(annotation.element_value_pairs),
1178 [](const java_annotationt::valuet &value)
1179 -> java_bytecode_parse_treet::annotationt::element_value_pairt {
1180 return {value.get_name(), value.get_value()};
1189 void mark_java_implicitly_generic_class_type(
1190 const irep_idt &class_name,
1191 symbol_tablet &symbol_table)
1193 const std::string qualified_class_name = "java::" + id2string(class_name);
1194 PRECONDITION(symbol_table.has_symbol(qualified_class_name));
1196 symbolt &class_symbol = symbol_table.get_writeable_ref(qualified_class_name);
1197 const java_class_typet &class_type = to_java_class_type(class_symbol.type);
1202 bool no_this_field = std::none_of(
1203 class_type.components().begin(),
1204 class_type.components().end(),
1205 [](const struct_union_typet::componentt &component)
1207 return id2string(component.get_name()).substr(0, 5) == "this$";
1216 std::vector<java_generic_parametert> implicit_generic_type_parameters;
1217 std::string::size_type outer_class_delimiter =
1218 qualified_class_name.rfind('$');
1219 while(outer_class_delimiter != std::string::npos)
1221 std::string outer_class_name =
1222 qualified_class_name.substr(0, outer_class_delimiter);
1223 if(symbol_table.has_symbol(outer_class_name))
1225 const symbolt &outer_class_symbol =
1226 symbol_table.lookup_ref(outer_class_name);
1227 const java_class_typet &outer_class_type =
1228 to_java_class_type(outer_class_symbol.type);
1229 if(is_java_generic_class_type(outer_class_type))
1231 for(const java_generic_parametert &outer_generic_type_parameter :
1232 to_java_generic_class_type(outer_class_type).generic_types())
1236 irep_idt identifier = qualified_class_name + "::" +
1237 id2string(strip_java_namespace_prefix(
1238 outer_generic_type_parameter.get_name()));
1239 java_generic_parameter_tagt bound = to_java_generic_parameter_tag(
1240 outer_generic_type_parameter.base_type());
1241 bound.type_variable_ref().set_identifier(identifier);
1242 implicit_generic_type_parameters.emplace_back(identifier, bound);
1245 outer_class_delimiter = outer_class_name.rfind('$');
1249 throw missing_outer_class_symbol_exceptiont(
1250 outer_class_name, qualified_class_name);
1256 if(!implicit_generic_type_parameters.empty())
1258 java_implicitly_generic_class_typet new_class_type(
1259 class_type, implicit_generic_type_parameters);
1262 if(is_java_generic_class_type(class_type))
1264 const java_generic_class_typet::generic_typest &class_type_params =
1265 to_java_generic_class_type(class_type).generic_types();
1266 implicit_generic_type_parameters.insert(
1267 implicit_generic_type_parameters.begin(),
1268 class_type_params.begin(),
1269 class_type_params.end());
1272 for(auto &field : new_class_type.components())
1274 find_and_replace_parameters(
1275 field.type(), implicit_generic_type_parameters);
1278 for(auto &base : new_class_type.bases())
1280 find_and_replace_parameters(
1281 base.type(), implicit_generic_type_parameters);
1284 class_symbol.type = new_class_type;