CBMC
java_types.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "java_types.h"
10 
11 #include <util/c_types.h>
12 #include <util/ieee_float.h>
13 #include <util/invariant.h>
14 #include <util/std_expr.h>
15 
16 #include "java_utils.h"
17 
18 #include <cctype>
19 #include <iterator>
20 
21 #ifdef DEBUG
22 #include <iostream>
23 #endif
24 
25 std::vector<typet> parse_list_types(
26  const std::string src,
27  const std::string class_name_prefix,
28  const char opening_bracket,
29  const char closing_bracket);
30 
32 {
33  static const auto result = signedbv_typet(32);
34  return result;
35 }
36 
38 {
39  static const auto result = empty_typet();
40  return result;
41 }
42 
44 {
45  static const auto result = signedbv_typet(64);
46  return result;
47 }
48 
50 {
51  static const auto result = signedbv_typet(16);
52  return result;
53 }
54 
56 {
57  static const auto result = signedbv_typet(8);
58  return result;
59 }
60 
62 {
63  static const auto result = unsignedbv_typet(16);
64  return result;
65 }
66 
68 {
69  static const auto result = ieee_float_spect::single_precision().to_type();
70  return result;
71 }
72 
74 {
75  static const auto result = ieee_float_spect::double_precision().to_type();
76  return result;
77 }
78 
80 {
81  // The Java standard doesn't really prescribe the width
82  // of a boolean. However, JNI suggests that it's 8 bits.
83  // http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html
84  static const auto result = c_bool_typet(8);
85  return result;
86 }
87 
89 {
90  return reference_type(subtype);
91 }
92 
94 {
95  return to_java_reference_type(reference_type(subtype));
96 }
97 
99 {
100  static const auto result =
101  java_reference_type(struct_tag_typet("java::java.lang.Object"));
102  return result;
103 }
104 
110 {
111  std::string subtype_str;
112 
113  switch(subtype)
114  {
115  case 'b': subtype_str="byte"; break;
116  case 'f': subtype_str="float"; break;
117  case 'd': subtype_str="double"; break;
118  case 'i': subtype_str="int"; break;
119  case 'c': subtype_str="char"; break;
120  case 's': subtype_str="short"; break;
121  case 'z': subtype_str="boolean"; break;
122  case 'v': subtype_str="void"; break;
123  case 'j': subtype_str="long"; break;
124  case 'l': subtype_str="long"; break;
125  case 'a': subtype_str="reference"; break;
126  default:
127 #ifdef DEBUG
128  std::cout << "Unrecognised subtype str: " << subtype << std::endl;
129 #endif
130  UNREACHABLE;
131  }
132 
133  irep_idt class_name="array["+subtype_str+"]";
134 
135  struct_tag_typet struct_tag_type("java::" + id2string(class_name));
136  struct_tag_type.set(ID_C_base_name, class_name);
137  struct_tag_type.set(ID_element_type, java_type_from_char(subtype));
138 
139  return java_reference_type(struct_tag_type);
140 }
141 
144 const typet &java_array_element_type(const struct_tag_typet &array_symbol)
145 {
147  is_java_array_tag(array_symbol.get_identifier()),
148  "Symbol should have array tag");
149  return array_symbol.find_type(ID_element_type);
150 }
151 
155 {
157  is_java_array_tag(array_symbol.get_identifier()),
158  "Symbol should have array tag");
159  return array_symbol.add_type(ID_element_type);
160 }
161 
163 bool is_java_array_type(const typet &type)
164 {
165  if(
168  {
169  return false;
170  }
171  const auto &subtype_struct_tag =
172  to_struct_tag_type(to_pointer_type(type).base_type());
173  return is_java_array_tag(subtype_struct_tag.get_identifier());
174 }
175 
180 {
181  return is_java_array_type(type) &&
183  to_struct_tag_type(to_pointer_type(type).base_type())));
184 }
185 
188 std::pair<typet, std::size_t>
190 {
191  std::size_t array_dimensions = 0;
192  typet underlying_type;
193  for(underlying_type = java_reference_type(type);
194  is_java_array_type(underlying_type);
196  to_java_reference_type(underlying_type).base_type())))
197  {
198  ++array_dimensions;
199  }
200 
201  return {underlying_type, array_dimensions};
202 }
203 
207 {
208  PRECONDITION(pointer.type().id() == ID_pointer);
209 
214 }
215 
219 {
220  PRECONDITION(pointer.type().id() == ID_pointer);
221 
225  return member_exprt(
227 }
228 
233 bool is_java_array_tag(const irep_idt& tag)
234 {
235  return tag.starts_with("java::array[");
236 }
237 
249 {
250  switch(t)
251  {
252  case 'i': return java_int_type();
253  case 'j': return java_long_type();
254  case 'l': return java_long_type();
255  case 's': return java_short_type();
256  case 'b': return java_byte_type();
257  case 'c': return java_char_type();
258  case 'f': return java_float_type();
259  case 'd': return java_double_type();
260  case 'z': return java_boolean_type();
261  case 'a':
263  default:
264  UNREACHABLE;
265  }
266 }
267 
270 {
271  if(type==java_boolean_type() ||
272  type==java_char_type() ||
273  type==java_byte_type() ||
274  type==java_short_type())
275  return java_int_type();
276 
277  return type;
278 }
279 
282 {
283  typet new_type=java_bytecode_promotion(expr.type());
284 
285  if(new_type==expr.type())
286  return expr;
287  else
288  return typecast_exprt(expr, new_type);
289 }
290 
300  java_generic_typet &generic_type,
301  const std::string &type_arguments,
302  const std::string &class_name_prefix)
303 {
304  PRECONDITION(type_arguments.size() >= 2);
305  PRECONDITION(type_arguments[0] == '<');
306  PRECONDITION(type_arguments[type_arguments.size() - 1] == '>');
307 
308  // Parse contained arguments, can be either type parameters (`TT;`)
309  // or instantiated types - either generic types (`LList<LInteger;>;`) or
310  // just references (`Ljava/lang/Foo;`)
311  std::vector<typet> type_arguments_types =
312  parse_list_types(type_arguments, class_name_prefix, '<', '>');
313 
314  // We should have at least one generic type argument
315  CHECK_RETURN(!type_arguments_types.empty());
316 
317  // Add the type arguments to the generic type
319  type_arguments_types.begin(),
320  type_arguments_types.end(),
321  std::back_inserter(generic_type.generic_type_arguments()),
322  [](const typet &type) -> reference_typet
323  {
324  INVARIANT(
325  is_reference(type), "All generic type arguments should be references");
326  return to_reference_type(type);
327  });
328 }
329 
334 std::string erase_type_arguments(const std::string &src)
335 {
336  std::string class_name = src;
337  std::size_t f_pos = class_name.find('<', 1);
338 
339  while(f_pos != std::string::npos)
340  {
341  std::size_t e_pos = find_closing_delimiter(class_name, f_pos, '<', '>');
342  if(e_pos == std::string::npos)
343  {
345  "Failed to find generic signature closing delimiter (or recursive "
346  "generic): " +
347  src);
348  }
349 
350  // erase generic information between brackets
351  class_name.erase(f_pos, e_pos - f_pos + 1);
352 
353  // Search the remainder of the string for generic signature
354  f_pos = class_name.find('<', f_pos + 1);
355  }
356  return class_name;
357 }
358 
365 std::string gather_full_class_name(const std::string &src)
366 {
367  PRECONDITION(src.size() >= 2);
368  PRECONDITION(src[0] == 'L');
369  PRECONDITION(src[src.size() - 1] == ';');
370 
371  std::string class_name = src.substr(1, src.size() - 2);
372 
373  class_name = erase_type_arguments(class_name);
374 
375  std::replace(class_name.begin(), class_name.end(), '.', '$');
376  std::replace(class_name.begin(), class_name.end(), '/', '.');
377  return class_name;
378 }
379 
392 std::vector<typet> parse_list_types(
393  const std::string src,
394  const std::string class_name_prefix,
395  const char opening_bracket,
396  const char closing_bracket)
397 {
398  // Loop over the types in the given string, parsing each one in turn
399  // and adding to the type_list
400  std::vector<typet> type_list;
401  for(const std::string &raw_type :
402  parse_raw_list_types(src, opening_bracket, closing_bracket))
403  {
404  auto new_type = java_type_from_string(raw_type, class_name_prefix);
405  INVARIANT(new_type.has_value(), "Failed to parse type");
406  type_list.push_back(std::move(*new_type));
407  }
408  return type_list;
409 }
410 
419 std::vector<std::string> parse_raw_list_types(
420  const std::string src,
421  const char opening_bracket,
422  const char closing_bracket)
423 {
424  PRECONDITION(src.size() >= 2);
425  PRECONDITION(src[0] == opening_bracket);
426  PRECONDITION(src[src.size() - 1] == closing_bracket);
427 
428  // Loop over the types in the given string, parsing each one in turn
429  // and adding to the type_list
430  std::vector<std::string> type_list;
431  for(std::size_t i = 1; i < src.size() - 1; i++)
432  {
433  size_t start = i;
434  while(i < src.size())
435  {
436  // type is an object type or instantiated generic type
437  if(src[i] == 'L')
438  {
440  break;
441  }
442 
443  // type is an array
444  else if(src[i] == '[')
445  i++;
446 
447  // type is a type variable/parameter
448  else if(src[i] == 'T')
449  i = src.find(';', i); // ends on ;
450 
451  // type is an atomic type (just one character)
452  else
453  {
454  break;
455  }
456  }
457 
458  std::string sub_str = src.substr(start, i - start + 1);
459  type_list.emplace_back(sub_str);
460  }
461  return type_list;
462 }
463 
472 build_class_name(const std::string &src, const std::string &class_name_prefix)
473 {
474  PRECONDITION(src[0] == 'L');
475 
476  // All reference types must end on a ;
477  PRECONDITION(src[src.size() - 1] == ';');
478 
479  std::string container_class = gather_full_class_name(src);
480  std::string identifier = "java::" + container_class;
481  struct_tag_typet struct_tag_type(identifier);
482  struct_tag_type.set(ID_C_base_name, container_class);
483 
484  std::size_t f_pos = src.find('<', 1);
485  if(f_pos != std::string::npos)
486  {
487  java_generic_typet result(struct_tag_type);
488  // get generic type information
489  do
490  {
491  std::size_t e_pos = find_closing_delimiter(src, f_pos, '<', '>');
492  if(e_pos == std::string::npos)
494  "Parsing type with unmatched generic bracket: " + src);
495 
497  result, src.substr(f_pos, e_pos - f_pos + 1), class_name_prefix);
498 
499  // Look for the next generic type info (if it exists)
500  f_pos = src.find('<', e_pos + 1);
501  } while(f_pos != std::string::npos);
502  return std::move(result);
503  }
504 
505  return java_reference_type(struct_tag_type);
506 }
507 
517  const std::string src,
518  size_t starting_point)
519 {
520  PRECONDITION(src[starting_point] == 'L');
521  size_t next_semi_colon = src.find(';', starting_point);
522  INVARIANT(
523  next_semi_colon != std::string::npos,
524  "There must be a semi-colon somewhere in the input");
525  size_t next_angle_bracket = src.find('<', starting_point);
526 
527  while(next_angle_bracket < next_semi_colon)
528  {
529  size_t end_bracket =
530  find_closing_delimiter(src, next_angle_bracket, '<', '>');
531  INVARIANT(
532  end_bracket != std::string::npos, "Must find matching angle bracket");
533 
534  next_semi_colon = src.find(';', end_bracket + 1);
535  next_angle_bracket = src.find('<', end_bracket + 1);
536  }
537 
538  return next_semi_colon;
539 }
540 
542 {
544  result.base_type().set(ID_element_type, java_reference_type(subtype));
545  return result;
546 }
547 
561 std::optional<typet> java_type_from_string(
562  const std::string &src,
563  const std::string &class_name_prefix)
564 {
565  if(src.empty())
566  return {};
567 
568  // a java type is encoded in different ways
569  // - a method type is encoded as '(...)R' where the parenthesis include the
570  // parameter types and R is the type of the return value
571  // - atomic types are encoded as single characters
572  // - array types are encoded as '[' followed by the type of the array
573  // content
574  // - object types are named with prefix 'L' and suffix ';', e.g.,
575  // Ljava/lang/Object;
576  // - type variables are similar to object types but have the prefix 'T'
577  switch(src[0])
578  {
579  case '<':
580  {
581  // The method signature can optionally have a collection of formal
582  // type parameters (e.g. on generic methods on non-generic classes
583  // or generic static methods). For now we skip over this part of the
584  // signature and continue parsing the rest of the signature as normal
585  // So for example, the following java method:
586  // static void <T, U> foo(T t, U u, int x);
587  // Would have a signature that looks like:
588  // <T:Ljava/lang/Object;U:Ljava/lang/Object;>(TT;TU;I)V
589  // So we skip all inside the angle brackets and parse the rest of the
590  // string:
591  // (TT;TU;I)V
592  size_t closing_generic=find_closing_delimiter(src, 0, '<', '>');
593  if(closing_generic==std::string::npos)
594  {
596  "Failed to find generic signature closing delimiter");
597  }
598 
599  // If there are any bounds between '<' and '>' then we cannot currently
600  // parse them, so we give up. This only happens when parsing the
601  // signature, so we'll fall back to the result of parsing the
602  // descriptor, which will respect the bounds correctly.
603  const size_t colon_pos = src.find(':');
604  if(colon_pos != std::string::npos && colon_pos < closing_generic)
605  {
607  "Cannot currently parse bounds on generic types");
608  }
609 
610  auto method_type = java_type_from_string(
611  src.substr(closing_generic + 1, std::string::npos), class_name_prefix);
612 
613  // This invariant being violated means that tkiley has not understood
614  // part of the signature spec.
615  // Only class and method signatures can start with a '<' and classes are
616  // handled separately.
617  INVARIANT(
618  method_type.has_value() && method_type->id() == ID_code,
619  "This should correspond to method signatures only");
620 
621  return method_type;
622  }
623  case '(': // function type
624  {
625  std::size_t e_pos=src.rfind(')');
626  if(e_pos==std::string::npos)
627  return {};
628 
629  auto return_type = java_type_from_string(
630  std::string(src, e_pos + 1, std::string::npos), class_name_prefix);
631 
632  std::vector<typet> param_types =
633  parse_list_types(src.substr(0, e_pos + 1), class_name_prefix, '(', ')');
634 
635  // create parameters for each type
638  param_types.begin(),
639  param_types.end(),
640  std::back_inserter(parameters),
641  [](const typet &type) { return java_method_typet::parametert(type); });
642 
643  return java_method_typet(std::move(parameters), std::move(*return_type));
644  }
645 
646  case '[': // array type
647  {
648  // If this is a reference array, we generate a plain array[reference]
649  // with void* members, but note the real type in ID_element_type.
650  if(src.size()<=1)
651  return {};
652  char subtype_letter=src[1];
653  auto subtype = java_type_from_string(
654  src.substr(1, std::string::npos), class_name_prefix);
655  if(subtype_letter=='L' || // [L denotes a reference array of some sort.
656  subtype_letter=='[' || // Array-of-arrays
657  subtype_letter=='T') // Array of generic types
658  subtype_letter='A';
659  subtype_letter = std::tolower(subtype_letter);
660  if(subtype_letter == 'a')
661  {
664  }
665  else
666  return java_array_type(subtype_letter);
667  }
668 
669  case 'B': return java_byte_type();
670  case 'F': return java_float_type();
671  case 'D': return java_double_type();
672  case 'I': return java_int_type();
673  case 'C': return java_char_type();
674  case 'S': return java_short_type();
675  case 'Z': return java_boolean_type();
676  case 'V': return java_void_type();
677  case 'J': return java_long_type();
678  case 'T':
679  {
680  // parse name of type variable
681  INVARIANT(src[src.size()-1]==';', "Generic type name must end on ';'.");
682  PRECONDITION(!class_name_prefix.empty());
683  irep_idt type_var_name(class_name_prefix+"::"+src.substr(1, src.size()-2));
685  type_var_name,
687  to_java_reference_type(*java_type_from_string("Ljava/lang/Object;"))
688  .base_type()));
689  }
690  case 'L':
691  {
692  return build_class_name(src, class_name_prefix);
693  }
694  case '*':
695  case '+':
696  case '-':
697  {
698 #ifdef DEBUG
699  std::cout << class_name_prefix << std::endl;
700 #endif
701  throw unsupported_java_class_signature_exceptiont("wild card generic");
702  }
703  default:
704  return {};
705  }
706 }
707 
708 char java_char_from_type(const typet &type)
709 {
710  const irep_idt &id=type.id();
711 
712  if(id==ID_signedbv)
713  {
714  const size_t width=to_signedbv_type(type).get_width();
715  if(java_int_type().get_width() == width)
716  return 'i';
717  else if(java_long_type().get_width() == width)
718  return 'l';
719  else if(java_short_type().get_width() == width)
720  return 's';
721  else if(java_byte_type().get_width() == width)
722  return 'b';
723  }
724  else if(id==ID_unsignedbv)
725  return 'c';
726  else if(id==ID_floatbv)
727  {
728  const size_t width(to_floatbv_type(type).get_width());
729  if(java_float_type().get_width() == width)
730  return 'f';
731  else if(java_double_type().get_width() == width)
732  return 'd';
733  }
734  else if(id==ID_c_bool)
735  return 'z';
736 
737  return 'a';
738 }
739 
749 std::vector<typet> java_generic_type_from_string(
750  const std::string &class_name,
751  const std::string &src)
752 {
755  size_t signature_end = find_closing_delimiter(src, 0, '<', '>');
756  INVARIANT(
757  src[0]=='<' && signature_end!=std::string::npos,
758  "Class signature has unexpected format");
759  std::string signature(src.substr(1, signature_end-1));
760 
761  if(signature.find(";:")!=std::string::npos)
762  throw unsupported_java_class_signature_exceptiont("multiple bounds");
763 
764  PRECONDITION(signature[signature.size()-1]==';');
765 
766  std::vector<typet> types;
767  size_t var_sep=signature.find(';');
768  while(var_sep!=std::string::npos)
769  {
770  size_t bound_sep=signature.find(':');
771  INVARIANT(bound_sep!=std::string::npos, "No bound for type variable.");
772 
773  // is bound an interface?
774  // in this case the separator is '::'
775  if(signature[bound_sep + 1] == ':')
776  {
777  INVARIANT(
778  signature[bound_sep + 2] != ':', "Unknown bound for type variable.");
779  bound_sep++;
780  }
781 
782  std::string type_var_name(
783  "java::"+class_name+"::"+signature.substr(0, bound_sep));
784  std::string bound_type(signature.substr(bound_sep+1, var_sep-bound_sep));
785 
786  java_generic_parametert type_var_type(
787  type_var_name,
789  to_java_reference_type(*java_type_from_string(bound_type, class_name))
790  .base_type()));
791 
792  types.push_back(type_var_type);
793  signature=signature.substr(var_sep+1, std::string::npos);
794  var_sep=signature.find(';');
795  }
796  return types;
797 }
798 
799 // java/lang/Object -> java.lang.Object
800 static std::string slash_to_dot(const std::string &src)
801 {
802  std::string result=src;
803  for(std::string::iterator it=result.begin(); it!=result.end(); it++)
804  if(*it=='/')
805  *it='.';
806  return result;
807 }
808 
809 struct_tag_typet java_classname(const std::string &id)
810 {
811  if(!id.empty() && id[0]=='[')
812  return to_struct_tag_type(
814 
815  std::string class_name=id;
816 
817  class_name=slash_to_dot(class_name);
818  irep_idt identifier="java::"+class_name;
819  struct_tag_typet struct_tag_type(identifier);
820  struct_tag_type.set(ID_C_base_name, class_name);
821 
822  return struct_tag_type;
823 }
824 
839 {
840  bool correct_num_components =
841  type.components().size() ==
842  (type.get_tag() == JAVA_REFERENCE_ARRAY_CLASSID ? 5 : 3);
843  if(!correct_num_components)
844  return false;
845 
846  // First component, the base class (Object) data
847  const struct_union_typet::componentt base_class_component=
848  type.components()[0];
849 
850  if(base_class_component.get_name() != "@java.lang.Object")
851  return false;
852 
853  const struct_union_typet::componentt length_component=
854  type.components()[1];
855  if(length_component.get_name() != "length")
856  return false;
857  if(length_component.type() != java_int_type())
858  return false;
859 
860  const struct_union_typet::componentt data_component=
861  type.components()[2];
862  if(data_component.get_name() != "data")
863  return false;
864  if(data_component.type().id() != ID_pointer)
865  return false;
866 
868  {
869  const struct_union_typet::componentt array_element_type_component =
870  type.components()[3];
871  if(
872  array_element_type_component.get_name() !=
874  return false;
875  if(array_element_type_component.type() != string_typet())
876  return false;
877 
878  const struct_union_typet::componentt array_dimension_component =
879  type.components()[4];
880  if(array_dimension_component.get_name() != JAVA_ARRAY_DIMENSION_FIELD_NAME)
881  return false;
882  if(array_dimension_component.type() != java_int_type())
883  return false;
884  }
885 
886  return true;
887 }
888 
895 bool equal_java_types(const typet &type1, const typet &type2)
896 {
897  bool arrays_with_same_element_type = true;
898  if(
899  type1.id() == ID_pointer && type2.id() == ID_pointer &&
900  to_pointer_type(type1).base_type().id() == ID_struct_tag &&
901  to_pointer_type(type2).base_type().id() == ID_struct_tag)
902  {
903  const auto &subtype_symbol1 =
904  to_struct_tag_type(to_pointer_type(type1).base_type());
905  const auto &subtype_symbol2 =
906  to_struct_tag_type(to_pointer_type(type2).base_type());
907  if(
908  subtype_symbol1.get_identifier() == subtype_symbol2.get_identifier() &&
909  is_java_array_tag(subtype_symbol1.get_identifier()))
910  {
911  const typet &array_element_type1 =
912  java_array_element_type(subtype_symbol1);
913  const typet &array_element_type2 =
914  java_array_element_type(subtype_symbol2);
915 
916  arrays_with_same_element_type =
917  equal_java_types(array_element_type1, array_element_type2);
918  }
919  }
920  return (type1 == type2 && arrays_with_same_element_type);
921 }
922 
923 std::vector<java_generic_parametert>
925 {
926  std::vector<java_generic_parametert> generic_parameters;
928  {
929  const java_implicitly_generic_class_typet &implicitly_generic_class =
931  generic_parameters.insert(
932  generic_parameters.end(),
933  implicitly_generic_class.implicit_generic_types().begin(),
934  implicitly_generic_class.implicit_generic_types().end());
935  }
937  {
938  const java_generic_class_typet &generic_class =
940  generic_parameters.insert(
941  generic_parameters.end(),
942  generic_class.generic_types().begin(),
943  generic_class.generic_types().end());
944  }
945  return generic_parameters;
946 }
947 
949  const typet &t,
950  std::set<irep_idt> &refs)
951 {
952  // Java generic type that holds different types in its type arguments
953  if(is_java_generic_type(t))
954  {
955  for(const auto &type_arg : to_java_generic_type(t).generic_type_arguments())
957  }
958 
959  // Java reference type
960  else if(t.id() == ID_pointer)
961  {
963  to_pointer_type(t).base_type(), refs);
964  }
965 
966  // method type with parameters and return value
967  else if(t.id() == ID_code)
968  {
971  for(const auto &param : c.parameters())
973  }
974 
975  // struct tag
976  else if(t.id() == ID_struct_tag)
977  {
978  const auto &struct_tag_type = to_struct_tag_type(t);
979  const irep_idt class_name(struct_tag_type.get_identifier());
980  if(is_java_array_tag(class_name))
981  {
983  java_array_element_type(struct_tag_type), refs);
984  }
985  else
986  refs.insert(strip_java_namespace_prefix(class_name));
987  }
988 }
989 
997  const std::string &signature,
998  std::set<irep_idt> &refs)
999 {
1000  try
1001  {
1002  // class signature with bounds
1003  if(signature[0] == '<')
1004  {
1005  const std::vector<typet> types = java_generic_type_from_string(
1006  erase_type_arguments(signature), signature);
1007 
1008  for(const auto &t : types)
1010  }
1011 
1012  // class signature without bounds and without wildcards
1013  else if(signature.find('*') == std::string::npos)
1014  {
1015  auto type_from_string =
1016  java_type_from_string(signature, erase_type_arguments(signature));
1017  get_dependencies_from_generic_parameters_rec(*type_from_string, refs);
1018  }
1019  }
1021  {
1022  // skip for now, if we cannot parse it, we cannot detect which additional
1023  // classes should be loaded as dependencies
1024  }
1025 }
1026 
1033  const typet &t,
1034  std::set<irep_idt> &refs)
1035 {
1037 }
1038 
1049  const struct_tag_typet &type,
1050  const std::string &base_ref,
1051  const std::string &class_name_prefix)
1052  : struct_tag_typet(type)
1053 {
1054  set(ID_C_java_generic_symbol, true);
1055  const auto base_type = java_type_from_string(base_ref, class_name_prefix);
1056  PRECONDITION(is_java_generic_type(*base_type));
1057  const java_generic_typet &gen_base_type = to_java_generic_type(*base_type);
1058  INVARIANT(
1059  type.get_identifier() ==
1060  to_struct_tag_type(gen_base_type.base_type()).get_identifier(),
1061  "identifier of " + type.pretty() + "\n and identifier of type " +
1062  gen_base_type.base_type().pretty() +
1063  "\ncreated by java_type_from_string for " + base_ref +
1064  " should be equal");
1065  generic_types().insert(
1066  generic_types().end(),
1067  gen_base_type.generic_type_arguments().begin(),
1068  gen_base_type.generic_type_arguments().end());
1069 }
1070 
1076  const java_generic_parametert &type) const
1077 {
1078  const auto &type_variable = type.get_name();
1079  const auto &generics = generic_types();
1080  for(std::size_t i = 0; i < generics.size(); ++i)
1081  {
1082  auto param = type_try_dynamic_cast<java_generic_parametert>(generics[i]);
1083  if(param && param->get_name() == type_variable)
1084  return i;
1085  }
1086  return {};
1087 }
1088 
1089 std::string pretty_java_type(const typet &type)
1090 {
1091  if(type == java_void_type())
1092  return "void";
1093  if(type == java_int_type())
1094  return "int";
1095  else if(type == java_long_type())
1096  return "long";
1097  else if(type == java_short_type())
1098  return "short";
1099  else if(type == java_byte_type())
1100  return "byte";
1101  else if(type == java_char_type())
1102  return "char";
1103  else if(type == java_float_type())
1104  return "float";
1105  else if(type == java_double_type())
1106  return "double";
1107  else if(type == java_boolean_type())
1108  return "boolean";
1109  else if(type == java_byte_type())
1110  return "byte";
1111  else if(is_reference(type))
1112  {
1113  if(to_reference_type(type).base_type().id() == ID_struct_tag)
1114  {
1115  const auto &struct_tag_type =
1116  to_struct_tag_type(to_reference_type(type).base_type());
1117  const irep_idt &id = struct_tag_type.get_identifier();
1118  if(is_java_array_tag(id))
1119  return pretty_java_type(java_array_element_type(struct_tag_type)) +
1120  "[]";
1121  else
1123  }
1124  else
1125  return "?";
1126  }
1127  else
1128  return "?";
1129 }
1130 
1131 std::string pretty_signature(const java_method_typet &method_type)
1132 {
1133  std::ostringstream result;
1134  result << '(';
1135 
1136  bool first = true;
1137  for(const auto &p : method_type.parameters())
1138  {
1139  if(p.get_this())
1140  continue;
1141 
1142  if(first)
1143  first = false;
1144  else
1145  result << ", ";
1146 
1147  result << pretty_java_type(p.type());
1148  }
1149 
1150  result << ')';
1151  return result.str();
1152 }
static abstract_object_pointert transform(const exprt &expr, const std::vector< abstract_object_pointert > &operands, const abstract_environmentt &environment, const namespacet &ns)
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
const signedbv_typet & to_signedbv_type(const typet &type)
Cast a typet to a signedbv_typet.
reference_typet reference_type(const typet &subtype)
Definition: c_types.cpp:240
std::size_t get_width() const
Definition: std_types.h:920
The C/C++ Booleans.
Definition: c_types.h:97
const typet & return_type() const
Definition: std_types.h:689
const parameterst & parameters() const
Definition: std_types.h:699
Operator to dereference a pointer.
Definition: pointer_expr.h:834
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
bool starts_with(const char *s) const
equivalent of as_string().starts_with(s)
Definition: dstring.h:95
The empty type.
Definition: std_types.h:51
Base class for all expressions.
Definition: expr.h:56
typet & type()
Return the type of the expression.
Definition: expr.h:84
Fixed-width bit-vector with IEEE floating-point interpretation.
static ieee_float_spect single_precision()
Definition: ieee_float.h:70
class floatbv_typet to_type() const
Definition: ieee_float.cpp:25
static ieee_float_spect double_precision()
Definition: ieee_float.h:76
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition: irep.cpp:482
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:408
const irep_idt & id() const
Definition: irep.h:384
Class to hold a class with generics, extends the java class type with a vector of java generic type p...
Definition: java_types.h:972
const generic_typest & generic_types() const
Definition: java_types.h:981
Reference that points to a java_generic_parameter_tagt.
Definition: java_types.h:775
const irep_idt get_name() const
Definition: java_types.h:798
java_generic_struct_tag_typet(const struct_tag_typet &type)
Definition: java_types.h:861
const generic_typest & generic_types() const
Definition: java_types.h:872
std::optional< size_t > generic_type_index(const java_generic_parametert &type) const
Check if this symbol has the given generic type.
Reference that points to a java_generic_struct_tag_typet.
Definition: java_types.h:914
const generic_type_argumentst & generic_type_arguments() const
Definition: java_types.h:925
Type to hold a Java class that is implicitly generic, e.g., an inner class of a generic outer class o...
Definition: java_types.h:1067
const implicit_generic_typest & implicit_generic_types() const
Definition: java_types.h:1083
std::vector< parametert > parameterst
Definition: std_types.h:585
This is a specialization of reference_typet.
Definition: java_types.h:602
Extract member of struct or union.
Definition: std_expr.h:2841
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
The reference type.
Definition: pointer_expr.h:121
Fixed-width bit-vector with two's complement interpretation.
String type.
Definition: std_types.h:957
A struct tag type, i.e., struct_typet with an identifier.
Definition: std_types.h:493
Structure type, corresponds to C style structs.
Definition: std_types.h:231
const irep_idt & get_name() const
Definition: std_types.h:79
irep_idt get_tag() const
Definition: std_types.h:168
const componentst & components() const
Definition: std_types.h:147
const irep_idt & get_identifier() const
Definition: std_types.h:410
Semantic type conversion.
Definition: std_expr.h:2068
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2076
The type of an expression, extends irept.
Definition: type.h:29
typet & add_type(const irep_idt &name)
Definition: type.h:115
const typet & find_type(const irep_idt &name) const
Definition: type.h:120
Fixed-width bit-vector with unsigned binary interpretation.
An exception that is raised for unsupported class signature.
Definition: java_types.h:1131
int tolower(int c)
Definition: ctype.c:100
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
signedbv_typet java_int_type()
Definition: java_types.cpp:31
bool is_java_array_type(const typet &type)
Checks whether the given type is an array pointer type.
Definition: java_types.cpp:163
bool is_valid_java_array(const struct_typet &type)
Programmatic documentation of the structure of a Java array (of either primitives or references) type...
Definition: java_types.cpp:838
typet java_type_from_char(char t)
Constructs a type indicated by the given character:
Definition: java_types.cpp:248
void get_dependencies_from_generic_parameters(const std::string &signature, std::set< irep_idt > &refs)
Collect information about generic type parameters from a given signature.
Definition: java_types.cpp:996
std::string erase_type_arguments(const std::string &src)
Take a signature string and remove everything in angle brackets allowing for the type to be parsed no...
Definition: java_types.cpp:334
java_reference_typet java_reference_array_type(const struct_tag_typet &subtype)
Definition: java_types.cpp:541
empty_typet java_void_type()
Definition: java_types.cpp:37
std::string pretty_java_type(const typet &type)
char java_char_from_type(const typet &type)
Definition: java_types.cpp:708
bool equal_java_types(const typet &type1, const typet &type2)
Compares the types, including checking element types if both types are arrays.
Definition: java_types.cpp:895
std::vector< std::string > parse_raw_list_types(const std::string src, const char opening_bracket, const char closing_bracket)
Given a substring of a descriptor or signature that contains one or more types parse out the individu...
Definition: java_types.cpp:419
void get_dependencies_from_generic_parameters_rec(const typet &t, std::set< irep_idt > &refs)
Definition: java_types.cpp:948
struct_tag_typet java_classname(const std::string &id)
Definition: java_types.cpp:809
const typet & java_array_element_type(const struct_tag_typet &array_symbol)
Return a const reference to the element type of a given java array type.
Definition: java_types.cpp:144
signedbv_typet java_byte_type()
Definition: java_types.cpp:55
std::string pretty_signature(const java_method_typet &method_type)
typet java_bytecode_promotion(const typet &type)
Java does not support byte/short return types. These are always promoted.
Definition: java_types.cpp:269
java_reference_typet java_array_type(const char subtype)
Construct an array pointer type.
Definition: java_types.cpp:109
size_t find_closing_semi_colon_for_reference_type(const std::string src, size_t starting_point)
Finds the closing semi-colon ending a ClassTypeSignature that starts at starting_point.
Definition: java_types.cpp:516
std::pair< typet, std::size_t > java_array_dimension_and_element_type(const struct_tag_typet &type)
Returns the underlying element type and array dimensionality of Java struct type.
Definition: java_types.cpp:189
signedbv_typet java_short_type()
Definition: java_types.cpp:49
std::vector< typet > parse_list_types(const std::string src, const std::string class_name_prefix, const char opening_bracket, const char closing_bracket)
Given a substring of a descriptor or signature that contains one or more types parse out the individu...
Definition: java_types.cpp:392
std::optional< typet > java_type_from_string(const std::string &src, const std::string &class_name_prefix)
Transforms a string representation of a Java type into an internal type representation thereof.
Definition: java_types.cpp:561
static std::string slash_to_dot(const std::string &src)
Definition: java_types.cpp:800
floatbv_typet java_double_type()
Definition: java_types.cpp:73
reference_typet java_reference_type(const typet &subtype)
Definition: java_types.cpp:88
void add_generic_type_information(java_generic_typet &generic_type, const std::string &type_arguments, const std::string &class_name_prefix)
Take a list of generic type arguments and parse them into the generic type.
Definition: java_types.cpp:299
floatbv_typet java_float_type()
Definition: java_types.cpp:67
std::vector< java_generic_parametert > get_all_generic_parameters(const typet &type)
Definition: java_types.cpp:924
c_bool_typet java_boolean_type()
Definition: java_types.cpp:79
std::vector< typet > java_generic_type_from_string(const std::string &class_name, const std::string &src)
Converts the content of a generic class type into a vector of Java types, that is each type variable ...
Definition: java_types.cpp:749
unsignedbv_typet java_char_type()
Definition: java_types.cpp:61
exprt get_array_element_type_field(const exprt &pointer)
Definition: java_types.cpp:218
std::string gather_full_class_name(const std::string &src)
Returns the full class name, skipping over the generics.
Definition: java_types.cpp:365
bool is_java_array_tag(const irep_idt &tag)
See above.
Definition: java_types.cpp:233
signedbv_typet java_long_type()
Definition: java_types.cpp:43
reference_typet build_class_name(const std::string &src, const std::string &class_name_prefix)
For parsing a class type reference.
Definition: java_types.cpp:472
exprt get_array_dimension_field(const exprt &pointer)
Definition: java_types.cpp:206
java_reference_typet java_lang_object_type()
Definition: java_types.cpp:98
bool is_multidim_java_array_type(const typet &type)
Checks whether the given type is a multi-dimensional array pointer type, i.e., a pointer to an array ...
Definition: java_types.cpp:179
const java_class_typet & to_java_class_type(const typet &type)
Definition: java_types.h:581
const java_reference_typet & to_java_reference_type(const typet &type)
Definition: java_types.h:629
#define JAVA_REFERENCE_ARRAY_CLASSID
Definition: java_types.h:655
bool is_java_generic_type(const typet &type)
Definition: java_types.h:946
const java_method_typet & to_java_method_type(const typet &type)
Definition: java_types.h:183
const java_generic_class_typet & to_java_generic_class_type(const java_class_typet &type)
Definition: java_types.h:1002
bool is_java_generic_class_type(const typet &type)
Definition: java_types.h:994
bool is_java_implicitly_generic_class_type(const typet &type)
Definition: java_types.h:1099
const java_generic_typet & to_java_generic_type(const typet &type)
Definition: java_types.h:953
#define JAVA_ARRAY_ELEMENT_CLASSID_FIELD_NAME
Definition: java_types.h:670
#define JAVA_ARRAY_DIMENSION_FIELD_NAME
Definition: java_types.h:668
const java_implicitly_generic_class_typet & to_java_implicitly_generic_class_type(const java_class_typet &type)
Definition: java_types.h:1107
size_t find_closing_delimiter(const std::string &src, size_t open_pos, char open_char, char close_char)
Finds the corresponding closing delimiter to the given opening delimiter.
Definition: java_utils.cpp:302
irep_idt strip_java_namespace_prefix(const irep_idt &to_strip)
Strip java:: prefix from given identifier.
Definition: java_utils.cpp:407
bool can_cast_type< pointer_typet >(const typet &type)
Check whether a reference to a typet is a pointer_typet.
Definition: pointer_expr.h:80
bool is_reference(const typet &type)
Returns true if the type is a reference.
Definition: std_types.cpp:144
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:93
const reference_typet & to_reference_type(const typet &type)
Cast a typet to a reference_typet.
Definition: pointer_expr.h:162
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:534
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition: invariant.h:423
API to expression classes.
bool can_cast_type< struct_tag_typet >(const typet &type)
Check whether a reference to a typet is a struct_tag_typet.
Definition: std_types.h:505
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:518
void replace(const union_find_replacet &replace_map, string_not_contains_constraintt &constraint)