CBMC
java_static_initializers.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Java Static Initializers
4 
5 Author: Chris Smowton, chris.smowton@diffblue.com
6 
7 \*******************************************************************/
8 
10 
11 #include <util/arith_tools.h>
12 #include <util/cprover_prefix.h>
13 #include <util/json.h>
14 #include <util/std_code.h>
15 #include <util/suffix.h>
16 #include <util/symbol_table.h>
17 
20 
21 #include "assignments_from_json.h"
22 #include "ci_lazy_methods_needed.h"
23 #include "java_object_factory.h"
25 #include "java_types.h"
26 #include "java_utils.h"
27 
49 enum class clinit_statest
50 {
51  NOT_INIT,
54 };
55 
57 {
58  return java_byte_type();
59 }
60 
61 // Disable linter here to allow a std::string constant, since that holds
62 // a length, whereas a cstr would require strlen every time.
63 const std::string clinit_wrapper_suffix = ".<clinit_wrapper>"; // NOLINT(*)
64 const std::string user_specified_clinit_suffix = ".<user_specified_clinit>"; // NOLINT(*)
65 const std::string clinit_function_suffix = ".<clinit>:()V"; // NOLINT(*)
66 
74 {
75  return id2string(class_name) + clinit_wrapper_suffix;
76 }
77 
79 {
80  return id2string(class_name) + user_specified_clinit_suffix;
81 }
82 
86 bool is_clinit_wrapper_function(const irep_idt &function_id)
87 {
88  return has_suffix(id2string(function_id), clinit_wrapper_suffix);
89 }
90 
94 bool is_clinit_function(const irep_idt &function_id)
95 {
96  return has_suffix(id2string(function_id), clinit_function_suffix);
97 }
98 
103 {
104  return has_suffix(id2string(function_id), user_specified_clinit_suffix);
105 }
106 
116  symbol_table_baset &symbol_table,
117  const irep_idt &name,
118  const typet &type,
119  const exprt &value,
120  const bool is_thread_local,
121  const bool is_static_lifetime)
122 {
123  symbolt new_symbol;
124  new_symbol.name = name;
125  new_symbol.pretty_name = name;
126  new_symbol.base_name = name;
127  new_symbol.type = type;
128  new_symbol.type.set(ID_C_no_nondet_initialization, true);
129  new_symbol.value = value;
130  new_symbol.is_lvalue = true;
131  new_symbol.is_state_var = true;
132  new_symbol.is_static_lifetime = is_static_lifetime;
133  new_symbol.is_thread_local = is_thread_local;
134  new_symbol.mode = ID_java;
135  symbol_table.add(new_symbol);
136  return new_symbol;
137 }
138 
144 {
145  return id2string(class_name) + "::clinit_already_run";
146 }
147 
152 static irep_idt clinit_function_name(const irep_idt &class_name)
153 {
154  return id2string(class_name) + clinit_function_suffix;
155 }
156 
161 static irep_idt clinit_state_var_name(const irep_idt &class_name)
162 {
163  return id2string(class_name) + CPROVER_PREFIX "clinit_state";
164 }
165 
171 {
172  return id2string(class_name) + CPROVER_PREFIX "clinit_threadlocal_state";
173 }
174 
179 {
180  return id2string(class_name) + CPROVER_PREFIX "clinit_wrapper::init_complete";
181 }
182 
192 gen_clinit_assign(const exprt &expr, const clinit_statest state)
193 {
194  mp_integer initv(static_cast<int>(state));
196  return code_frontend_assignt(expr, init_s);
197 }
198 
207 static equal_exprt
208 gen_clinit_eqexpr(const exprt &expr, const clinit_statest state)
209 {
210  mp_integer initv(static_cast<int>(state));
212  return equal_exprt(expr, init_s);
213 }
214 
233  symbol_table_baset &symbol_table,
234  const irep_idt &class_name,
235  code_blockt &init_body,
236  const bool nondet_static,
237  const bool replace_clinit,
238  const java_object_factory_parameterst &object_factory_parameters,
239  const select_pointer_typet &pointer_type_selector,
240  message_handlert &message_handler)
241 {
242  const symbolt &class_symbol = symbol_table.lookup_ref(class_name);
243  for(const auto &base : to_class_type(class_symbol.type).bases())
244  {
245  const auto base_name = base.type().get_identifier();
246  irep_idt base_init_routine = clinit_wrapper_name(base_name);
247  if(const auto base_init_func = symbol_table.lookup(base_init_routine))
248  init_body.add(code_function_callt{base_init_func->symbol_expr()});
249  }
250 
251  const irep_idt &clinit_name = replace_clinit
252  ? user_specified_clinit_name(class_name)
253  : clinit_function_name(class_name);
254  if(const auto clinit_func = symbol_table.lookup(clinit_name))
255  init_body.add(code_function_callt{clinit_func->symbol_expr()});
256 
257  // If nondet-static option is given, add a standard nondet initialization for
258  // each non-final static field of this class. Note this is the same invocation
259  // used in get_stub_initializer_body and java_static_lifetime_init.
260  if(nondet_static)
261  {
262  java_object_factory_parameterst parameters = object_factory_parameters;
263  parameters.function_id = clinit_wrapper_name(class_name);
264 
265  std::vector<irep_idt> nondet_ids;
266  std::for_each(
267  symbol_table.symbols.begin(),
268  symbol_table.symbols.end(),
269  [&](const std::pair<irep_idt, symbolt> &symbol) {
270  if(
271  declaring_class(symbol.second) == class_name &&
272  symbol.second.is_static_lifetime &&
273  !symbol.second.type.get_bool(ID_C_constant))
274  {
275  nondet_ids.push_back(symbol.first);
276  }
277  });
278 
279  for(const auto &id : nondet_ids)
280  {
281  const symbol_exprt new_global_symbol =
282  symbol_table.lookup_ref(id).symbol_expr();
283 
284  parameters.min_null_tree_depth =
286  ? std::max(size_t(1), object_factory_parameters.min_null_tree_depth)
287  : object_factory_parameters.min_null_tree_depth;
288 
290  new_global_symbol,
291  init_body,
292  symbol_table,
294  false,
296  parameters,
297  pointer_type_selector,
299  message_handler);
300  }
301  }
302 }
303 
310  const irep_idt &class_name, const symbol_tablet &symbol_table)
311 {
312  if(symbol_table.has_symbol(clinit_function_name(class_name)))
313  return true;
314 
315  const class_typet &class_type =
316  to_class_type(symbol_table.lookup_ref(class_name).type);
317 
318  for(const class_typet::baset &base : class_type.bases())
319  {
320  if(symbol_table.has_symbol(
321  clinit_wrapper_name(base.type().get_identifier())))
322  {
323  return true;
324  }
325  }
326 
327  return false;
328 }
329 
331  const irep_idt &class_name,
332  const irep_idt &function_name,
333  const irep_idt &function_base_name,
334  const synthetic_method_typet &synthetic_method_type,
335  symbol_tablet &symbol_table,
336  synthetic_methods_mapt &synthetic_methods)
337 {
338  symbolt function_symbol;
339  const java_method_typet function_type({}, java_void_type());
340  function_symbol.name = function_name;
341  function_symbol.pretty_name = function_symbol.name;
342  function_symbol.base_name = function_base_name;
343  function_symbol.type = function_type;
344  // This provides a back-link from a method to its associated class, as is done
345  // for java_bytecode_convert_methodt::convert.
346  set_declaring_class(function_symbol, class_name);
347  function_symbol.mode = ID_java;
348  bool failed = symbol_table.add(function_symbol);
349  INVARIANT(!failed, id2string(function_base_name) + " symbol should be fresh");
350 
351  auto insert_result =
352  synthetic_methods.emplace(function_symbol.name, synthetic_method_type);
353  INVARIANT(
354  insert_result.second,
355  "synthetic methods map should not already contain entry for " +
356  id2string(function_base_name));
357 }
358 
359 // Create symbol for the "clinit_wrapper"
361  const irep_idt &class_name,
362  symbol_tablet &symbol_table,
363  synthetic_methods_mapt &synthetic_methods)
364 {
366  class_name,
367  clinit_wrapper_name(class_name),
368  "clinit_wrapper",
370  symbol_table,
371  synthetic_methods);
372 }
373 
374 // Create symbol for the "user_specified_clinit"
376  const irep_idt &class_name,
377  symbol_tablet &symbol_table,
378  synthetic_methods_mapt &synthetic_methods)
379 {
381  class_name,
382  user_specified_clinit_name(class_name),
383  "user_specified_clinit",
385  symbol_table,
386  synthetic_methods);
387 }
388 
400  const irep_idt &class_name,
401  symbol_tablet &symbol_table,
402  synthetic_methods_mapt &synthetic_methods,
403  const bool thread_safe)
404 {
405  if(thread_safe)
406  {
407  exprt not_init_value = from_integer(
408  static_cast<int>(clinit_statest::NOT_INIT), clinit_states_type());
409 
410  // Create two global static synthetic "fields" for the class "id"
411  // these two variables hold the state of the class initialization algorithm
412  // across calls to the clinit_wrapper
414  symbol_table,
415  clinit_state_var_name(class_name),
417  not_init_value,
418  false,
419  true);
420 
422  symbol_table,
425  not_init_value,
426  true,
427  true);
428  }
429  else
430  {
431  const irep_idt &already_run_name =
433 
435  symbol_table,
436  already_run_name,
437  bool_typet(),
438  false_exprt(),
439  false,
440  true);
441  }
442 
444  class_name, symbol_table, synthetic_methods);
445 }
446 
525  const irep_idt &function_id,
526  symbol_table_baset &symbol_table,
527  const bool nondet_static,
528  const bool replace_clinit,
529  const java_object_factory_parameterst &object_factory_parameters,
530  const select_pointer_typet &pointer_type_selector,
531  message_handlert &message_handler)
532 {
533  const symbolt &wrapper_method_symbol = symbol_table.lookup_ref(function_id);
534  const auto class_name = declaring_class(wrapper_method_symbol);
535  INVARIANT(class_name, "Wrapper function should have an owning class.");
536 
537  const symbolt &clinit_state_sym =
538  symbol_table.lookup_ref(clinit_state_var_name(*class_name));
539  const symbolt &clinit_thread_local_state_sym =
540  symbol_table.lookup_ref(clinit_thread_local_state_var_name(*class_name));
541 
542  // Create a function-local variable "init_complete". This variable is used to
543  // avoid inspecting the global state (clinit_state_sym) outside of
544  // the critical-section.
545  const symbolt &init_complete = add_new_variable_symbol(
546  symbol_table,
548  bool_typet(),
549  nil_exprt(),
550  true,
551  false);
552 
553  code_blockt function_body;
554  codet atomic_begin(ID_atomic_begin);
555  codet atomic_end(ID_atomic_end);
556 
557 #if 0
558  // This code defines source locations for every codet generated below for
559  // the static initializer wrapper. Enable this for debugging the symex going
560  // through the clinit_wrapper.
561  //
562  // java::C.<clinit_wrapper>()
563  // You will additionally need to associate the `location` with the
564  // `function_body` and then manually set lines of code for each of the
565  // statements of the function, using something along the lines of:
566  // `mycodet.then_case().add_source_location().set_line(17);`/
567 
568  source_locationt &location = function_body.add_source_location();
569  location.set_file ("<generated>");
570  location.set_line ("<generated>");
572  std::string comment =
573  "Automatically generated function. States are:\n"
574  " 0 = class not initialized, init val of clinit_state/clinit_local_state\n"
575  " 1 = class initialization in progress, by this or another thread\n"
576  " 2 = initialization finished with success, by this or another thread\n";
577  static_assert((int) clinit_statest::NOT_INIT==0, "Check commment above");
578  static_assert((int) clinit_statest::IN_PROGRESS==1, "Check comment above");
579  static_assert((int) clinit_statest::INIT_COMPLETE==2, "Check comment above");
580 #endif
581 
582  // bool init_complete;
583  {
584  code_frontend_declt decl(init_complete.symbol_expr());
585  function_body.add(decl);
586  }
587 
588  // if(C::__CPROVER_PREFIX_clinit_thread_local_state == INIT_COMPLETE) return;
589  {
590  code_ifthenelset conditional(
592  clinit_thread_local_state_sym.symbol_expr(),
595  function_body.add(std::move(conditional));
596  }
597 
598  // C::__CPROVER_PREFIX_clinit_thread_local_state = INIT_COMPLETE;
599  {
601  clinit_thread_local_state_sym.symbol_expr(),
603  function_body.add(assign);
604  }
605 
606  // ATOMIC_BEGIN
607  {
608  function_body.add(atomic_begin);
609  }
610 
611  // Assume: clinit_state_sym != IN_PROGRESS
612  {
613  exprt assumption = gen_clinit_eqexpr(
614  clinit_state_sym.symbol_expr(), clinit_statest::IN_PROGRESS);
615  assumption = not_exprt(assumption);
616  code_assumet assume(assumption);
617  function_body.add(assume);
618  }
619 
620  // If(C::__CPROVER_PREFIX_clinit_state == NOT_INIT)
621  // {
622  // C::__CPROVER_PREFIX_clinit_state = IN_PROGRESS;
623  // init_complete = false;
624  // }
625  // else If(C::__CPROVER_PREFIX_clinit_state == INIT_COMPLETE)
626  // {
627  // init_complete = true;
628  // }
629  {
630  code_ifthenelset init_conditional(
632  clinit_state_sym.symbol_expr(), clinit_statest::INIT_COMPLETE),
633  code_blockt(
634  {code_frontend_assignt(init_complete.symbol_expr(), true_exprt())}));
635 
636  code_ifthenelset not_init_conditional(
638  clinit_state_sym.symbol_expr(), clinit_statest::NOT_INIT),
639  code_blockt(
641  clinit_state_sym.symbol_expr(), clinit_statest::IN_PROGRESS),
642  code_frontend_assignt(init_complete.symbol_expr(), false_exprt())}),
643  std::move(init_conditional));
644 
645  function_body.add(std::move(not_init_conditional));
646  }
647 
648  // ATOMIC_END
649  {
650  function_body.add(atomic_end);
651  }
652 
653  // if(init_complete) return;
654  {
655  code_ifthenelset conditional(
656  init_complete.symbol_expr(), code_frontend_returnt());
657  function_body.add(std::move(conditional));
658  }
659 
660  // Initialize the super-class C' and
661  // the implemented interfaces l_1 ... l_n.
662  // see JVMS p.359 step 7, for the exact definition of
663  // the sequence l_1 to l_n.
664  // This is achieved by iterating through the base types and
665  // adding recursive calls to the clinit_wrapper()
666  //
667  // java::C'.<clinit_wrapper>();
668  // java::I1.<clinit_wrapper>();
669  // java::I2.<clinit_wrapper>();
670  // // ...
671  // java::In.<clinit_wrapper>();
672  //
673  // java::C.<clinit>(); // or nondet-initialization of all static
674  // // variables of C if nondet-static is true
675  //
676  {
677  code_blockt init_body;
679  symbol_table,
680  *class_name,
681  init_body,
683  replace_clinit,
684  object_factory_parameters,
685  pointer_type_selector,
686  message_handler);
687  function_body.append(init_body);
688  }
689 
690  // ATOMIC_START
691  // C::__CPROVER_PREFIX_clinit_state = INIT_COMPLETE;
692  // ATOMIC_END
693  // return;
694  {
695  // synchronization prologue
696  function_body.add(atomic_begin);
697  function_body.add(
699  clinit_state_sym.symbol_expr(), clinit_statest::INIT_COMPLETE));
700  function_body.add(atomic_end);
701  function_body.add(code_frontend_returnt());
702  }
703 
704  return function_body;
705 }
706 
723  const irep_idt &function_id,
724  symbol_table_baset &symbol_table,
725  const bool nondet_static,
726  const bool replace_clinit,
727  const java_object_factory_parameterst &object_factory_parameters,
728  const select_pointer_typet &pointer_type_selector,
729  message_handlert &message_handler)
730 {
731  // Assume that class C extends class C' and implements interfaces
732  // I1, ..., In. We now create the following function (possibly recursively
733  // creating the clinit_wrapper functions for C' and I1, ..., In):
734  //
735  // java::C.<clinit_wrapper>()
736  // {
737  // if (!java::C::clinit_already_run)
738  // {
739  // java::C::clinit_already_run = true; // before recursive calls!
740  //
741  // java::C'.<clinit_wrapper>();
742  // java::I1.<clinit_wrapper>();
743  // java::I2.<clinit_wrapper>();
744  // // ...
745  // java::In.<clinit_wrapper>();
746  //
747  // java::C.<clinit>(); // or nondet-initialization of all static
748  // // variables of C if nondet-static is true
749  // }
750  // }
751  const symbolt &wrapper_method_symbol = symbol_table.lookup_ref(function_id);
752  const auto class_name = declaring_class(wrapper_method_symbol);
753  INVARIANT(class_name, "Wrapper function should have an owning class.");
754 
755  const symbolt &already_run_symbol =
756  symbol_table.lookup_ref(clinit_already_run_variable_name(*class_name));
757 
758  equal_exprt check_already_run(
759  already_run_symbol.symbol_expr(),
760  false_exprt());
761 
762  // add the "already-run = false" statement
763  code_frontend_assignt set_already_run(
764  already_run_symbol.symbol_expr(), true_exprt());
765  code_blockt init_body({set_already_run});
766 
768  symbol_table,
769  *class_name,
770  init_body,
772  replace_clinit,
773  object_factory_parameters,
774  pointer_type_selector,
775  message_handler);
776 
777  // the entire body of the function is an if-then-else
778  return code_ifthenelset(std::move(check_already_run), std::move(init_body));
779 }
780 
782 std::unordered_multimap<irep_idt, symbolt>
784 {
785  std::unordered_multimap<irep_idt, symbolt> result;
786  for(const auto &symbol_pair : symbol_table)
787  {
788  const symbolt &symbol = symbol_pair.second;
789  if(optionalt<irep_idt> declaring = declaring_class(symbol))
790  result.emplace(*declaring, symbol);
791  }
792  return result;
793 }
794 
796  const irep_idt &class_id,
797  const json_objectt &static_values_json,
798  symbol_table_baset &symbol_table,
799  optionalt<ci_lazy_methods_neededt> needed_lazy_methods,
800  size_t max_user_array_length,
801  std::unordered_map<std::string, object_creation_referencet> &references,
802  const std::unordered_multimap<irep_idt, symbolt>
803  &class_to_declared_symbols_map)
804 {
805  const irep_idt &real_clinit_name = clinit_function_name(class_id);
806  const auto clinit_func = symbol_table.lookup(real_clinit_name);
807  if(clinit_func == nullptr)
808  {
809  // Case where the real clinit doesn't appear in the symbol table, even
810  // though their is user specifed one. This may occur when some class
811  // substitution happened after compilation.
812  return code_blockt{};
813  }
814  const auto class_entry =
815  static_values_json.find(id2string(strip_java_namespace_prefix(class_id)));
816  if(class_entry != static_values_json.end() && class_entry->second.is_object())
817  {
818  const auto &class_json_object = to_json_object(class_entry->second);
819  std::map<symbol_exprt, jsont> static_field_values;
820  for(const auto &symbol_pair :
821  equal_range(class_to_declared_symbols_map, class_id))
822  {
823  const symbolt &symbol = symbol_pair.second;
824  if(symbol.is_static_lifetime)
825  {
826  const symbol_exprt &static_field_expr = symbol.symbol_expr();
827  const auto &static_field_entry =
828  class_json_object.find(id2string(symbol.base_name));
829  if(static_field_entry != class_json_object.end())
830  {
831  static_field_values.insert(
832  {static_field_expr, static_field_entry->second});
833  }
834  }
835  }
836  code_with_references_listt code_with_references;
837  for(const auto &value_pair : static_field_values)
838  {
839  code_with_references.append(assign_from_json(
840  value_pair.first,
841  value_pair.second,
842  real_clinit_name,
843  symbol_table,
844  needed_lazy_methods,
845  max_user_array_length,
846  references));
847  }
848  code_with_referencest::reference_substitutiont reference_substitution =
849  [&](const std::string &reference_id) -> object_creation_referencet & {
850  auto it = references.find(reference_id);
851  INVARIANT(it != references.end(), "reference id must be present in map");
852  return it->second;
853  };
854  code_blockt body;
855  for(const auto &code_with_ref : code_with_references.list)
856  body.append(code_with_ref->to_code(reference_substitution));
857  return body;
858  }
859  return code_blockt{{code_function_callt{clinit_func->symbol_expr()}}};
860 }
861 
879  symbol_tablet &symbol_table,
880  synthetic_methods_mapt &synthetic_methods,
881  const bool thread_safe,
882  const bool is_user_clinit_needed)
883 {
884  // Top-sort the class hierarchy, such that we visit parents before children,
885  // and can so identify parents that need static initialisation by whether we
886  // have made them a clinit_wrapper method.
887  class_hierarchy_grapht class_graph;
888  class_graph.populate(symbol_table);
889  std::list<class_hierarchy_grapht::node_indext> topsorted_nodes =
890  class_graph.topsort();
891 
892  for(const auto node : topsorted_nodes)
893  {
894  const irep_idt &class_identifier = class_graph[node].class_identifier;
895  if(needs_clinit_wrapper(class_identifier, symbol_table))
896  {
898  class_identifier, symbol_table, synthetic_methods, thread_safe);
899  if(is_user_clinit_needed)
900  {
902  class_identifier, symbol_table, synthetic_methods);
903  }
904  }
905  }
906 }
907 
911 template<class itertype>
912 static itertype advance_to_next_key(itertype in, itertype end)
913 {
914  PRECONDITION(in != end);
915  auto initial_key = in->first;
916  while(in != end && in->first == initial_key)
917  ++in;
918  return in;
919 }
920 
930  symbol_tablet &symbol_table,
931  const std::unordered_set<irep_idt> &stub_globals_set,
932  synthetic_methods_mapt &synthetic_methods)
933 {
934  // Populate map from class id -> stub globals:
935  for(const irep_idt &stub_global : stub_globals_set)
936  {
937  const symbolt &global_symbol = symbol_table.lookup_ref(stub_global);
938  if(global_symbol.value.is_nil())
939  {
940  // This symbol is already nondet-initialised during __CPROVER_initialize
941  // (generated in java_static_lifetime_init). In future this will only
942  // be the case for primitive-typed fields, but for now reference-typed
943  // fields can also be treated this way in the exceptional case that they
944  // belong to a non-stub class. Skip the field, as it does not need a
945  // synthetic static initializer.
946  continue;
947  }
948 
949  const auto class_id = declaring_class(global_symbol);
950  INVARIANT(class_id, "Static field should have a defining class.");
951  stub_globals_by_class.insert({*class_id, stub_global});
952  }
953 
954  // For each distinct class that has stub globals, create a clinit symbol:
955 
956  for(auto it = stub_globals_by_class.begin(),
957  itend = stub_globals_by_class.end();
958  it != itend;
959  it = advance_to_next_key(it, itend))
960  {
961  const irep_idt static_init_name = clinit_function_name(it->first);
962 
963  INVARIANT(
964  to_java_class_type(symbol_table.lookup_ref(it->first).type).get_is_stub(),
965  "only stub classes should be given synthetic static initialisers");
966  INVARIANT(
967  !symbol_table.has_symbol(static_init_name),
968  "a class cannot be both incomplete, and so have stub static fields, and "
969  "also define a static initializer");
970 
971  const java_method_typet thunk_type({}, java_void_type());
972 
973  symbolt static_init_symbol;
974  static_init_symbol.name = static_init_name;
975  static_init_symbol.pretty_name = static_init_name;
976  static_init_symbol.base_name = "clinit():V";
977  static_init_symbol.mode = ID_java;
978  static_init_symbol.type = thunk_type;
979  // This provides a back-link from a method to its associated class, as is
980  // done for java_bytecode_convert_methodt::convert.
981  set_declaring_class(static_init_symbol, it->first);
982 
983  bool failed = symbol_table.add(static_init_symbol);
984  INVARIANT(!failed, "symbol should not already exist");
985 
986  auto insert_result = synthetic_methods.emplace(
987  static_init_symbol.name,
989  INVARIANT(
990  insert_result.second,
991  "synthetic methods map should not already contain entry for "
992  "stub static initializer");
993  }
994 }
995 
1011  const irep_idt &function_id,
1012  symbol_table_baset &symbol_table,
1013  const java_object_factory_parameterst &object_factory_parameters,
1014  const select_pointer_typet &pointer_type_selector,
1015  message_handlert &message_handler)
1016 {
1017  const symbolt &stub_initializer_symbol = symbol_table.lookup_ref(function_id);
1018  const auto class_id = declaring_class(stub_initializer_symbol);
1019  INVARIANT(
1020  class_id, "Synthetic static initializer should have an owning class.");
1021  code_blockt static_init_body;
1022 
1023  // Add a standard nondet initialisation for each global declared on this
1024  // class. Note this is the same invocation used in
1025  // java_static_lifetime_init.
1026 
1027  auto class_globals = equal_range(stub_globals_by_class, *class_id);
1028  INVARIANT(
1029  !class_globals.empty(),
1030  "class with synthetic clinit should have at least one global to init");
1031 
1032  java_object_factory_parameterst parameters = object_factory_parameters;
1033  parameters.function_id = function_id;
1034 
1035  for(const auto &pair : class_globals)
1036  {
1037  const symbol_exprt new_global_symbol =
1038  symbol_table.lookup_ref(pair.second).symbol_expr();
1039 
1040  parameters.min_null_tree_depth =
1041  is_non_null_library_global(pair.second)
1042  ? object_factory_parameters.min_null_tree_depth + 1
1043  : object_factory_parameters.min_null_tree_depth;
1044 
1045  source_locationt location;
1046  location.set_function(function_id);
1048  new_global_symbol,
1049  static_init_body,
1050  symbol_table,
1051  location,
1052  false,
1054  parameters,
1055  pointer_type_selector,
1057  message_handler);
1058  }
1059 
1060  return static_init_body;
1061 }
java_static_initializers.h
symbol_table_baset::has_symbol
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
Definition: symbol_table_base.h:87
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
code_blockt
A codet representing sequential composition of program statements.
Definition: std_code.h:129
synthetic_method_typet::STATIC_INITIALIZER_WRAPPER
@ STATIC_INITIALIZER_WRAPPER
A static initializer wrapper (code of the form if(!already_run) clinit(); already_run = true;) These ...
get_clinit_wrapper_body
code_ifthenelset get_clinit_wrapper_body(const irep_idt &function_id, symbol_table_baset &symbol_table, const bool nondet_static, const bool replace_clinit, const java_object_factory_parameterst &object_factory_parameters, const select_pointer_typet &pointer_type_selector, message_handlert &message_handler)
Produces the static initializer wrapper body for the given function.
Definition: java_static_initializers.cpp:722
create_clinit_wrapper_function_symbol
static void create_clinit_wrapper_function_symbol(const irep_idt &class_name, symbol_tablet &symbol_table, synthetic_methods_mapt &synthetic_methods)
Definition: java_static_initializers.cpp:360
symbolt::is_state_var
bool is_state_var
Definition: symbol.h:62
symbol_tablet
The symbol table.
Definition: symbol_table.h:13
symbol_table_baset::lookup_ref
const symbolt & lookup_ref(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
Definition: symbol_table_base.h:104
clinit_statest::NOT_INIT
@ NOT_INIT
class_typet
Class type.
Definition: std_types.h:324
gen_clinit_eqexpr
static equal_exprt gen_clinit_eqexpr(const exprt &expr, const clinit_statest state)
Generates an equal_exprt for clinit_statest /param expr: expression to be used as the LHS of generate...
Definition: java_static_initializers.cpp:208
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
stub_global_initializer_factoryt::get_stub_initializer_body
code_blockt get_stub_initializer_body(const irep_idt &function_id, symbol_table_baset &symbol_table, const java_object_factory_parameterst &object_factory_parameters, const select_pointer_typet &pointer_type_selector, message_handlert &message_handler)
Create the body of a synthetic static initializer (clinit method), which initialise stub globals in t...
Definition: java_static_initializers.cpp:1010
arith_tools.h
goto_instruction_code.h
source_locationt::set_function
void set_function(const irep_idt &function)
Definition: source_location.h:120
nondet_static
static void nondet_static(const namespacet &ns, goto_functionst &goto_functions, const irep_idt &fct_name)
Nondeterministically initializes global scope variables in a goto-function.
Definition: nondet_static.cpp:80
synthetic_method_typet
synthetic_method_typet
Synthetic method kinds.
Definition: synthetic_methods_map.h:27
set_declaring_class
void set_declaring_class(symbolt &symbol, const irep_idt &declaring_class)
Sets the identifier of the class which declared a given symbol to declaring_class.
Definition: java_utils.cpp:577
code_with_referencest::reference_substitutiont
std::function< const object_creation_referencet &(const std::string &)> reference_substitutiont
Definition: code_with_references.h:44
typet
The type of an expression, extends irept.
Definition: type.h:28
to_class_type
const class_typet & to_class_type(const typet &type)
Cast a typet to a class_typet.
Definition: std_types.h:381
irept::find
const irept & find(const irep_idt &name) const
Definition: irep.cpp:106
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
create_user_specified_clinit_function_symbol
static void create_user_specified_clinit_function_symbol(const irep_idt &class_name, symbol_tablet &symbol_table, synthetic_methods_mapt &synthetic_methods)
Definition: java_static_initializers.cpp:375
object_factory_parameterst::function_id
irep_idt function_id
Function id, used as a prefix for identifiers of temporaries.
Definition: object_factory_parameters.h:79
get_thread_safe_clinit_wrapper_body
code_blockt get_thread_safe_clinit_wrapper_body(const irep_idt &function_id, symbol_table_baset &symbol_table, const bool nondet_static, const bool replace_clinit, const java_object_factory_parameterst &object_factory_parameters, const select_pointer_typet &pointer_type_selector, message_handlert &message_handler)
Thread safe version of the static initializer.
Definition: java_static_initializers.cpp:524
json_objectt::find
iterator find(const std::string &key)
Definition: json.h:356
declaring_class
optionalt< irep_idt > declaring_class(const symbolt &symbol)
Gets the identifier of the class which declared a given symbol.
Definition: java_utils.cpp:571
user_specified_clinit_suffix
const std::string user_specified_clinit_suffix
Definition: java_static_initializers.cpp:64
is_clinit_function
bool is_clinit_function(const irep_idt &function_id)
Check if function_id is a clinit.
Definition: java_static_initializers.cpp:94
user_specified_clinit_name
irep_idt user_specified_clinit_name(const irep_idt &class_name)
Definition: java_static_initializers.cpp:78
code_frontend_declt
A codet representing the declaration of a local variable.
Definition: std_code.h:346
exprt
Base class for all expressions.
Definition: expr.h:55
symbolt::base_name
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
create_static_initializer_symbols
void create_static_initializer_symbols(symbol_tablet &symbol_table, synthetic_methods_mapt &synthetic_methods, const bool thread_safe, const bool is_user_clinit_needed)
Create static initializer wrappers and possibly user-specified functions for initial static field val...
Definition: java_static_initializers.cpp:878
java_object_factory_parameters.h
bool_typet
The Boolean type.
Definition: std_types.h:35
clinit_local_init_complete_var_name
static irep_idt clinit_local_init_complete_var_name(const irep_idt &class_name)
Get name of the static-initialization local variable for a given class.
Definition: java_static_initializers.cpp:178
synthetic_methods_mapt
std::unordered_map< irep_idt, synthetic_method_typet > synthetic_methods_mapt
Maps method names on to a synthetic method kind.
Definition: synthetic_methods_map.h:57
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
clinit_function_suffix
const std::string clinit_function_suffix
Definition: java_static_initializers.cpp:65
clinit_function_name
static irep_idt clinit_function_name(const irep_idt &class_name)
Get name of the real static initializer for a given class.
Definition: java_static_initializers.cpp:152
has_suffix
bool has_suffix(const std::string &s, const std::string &suffix)
Definition: suffix.h:17
equal_exprt
Equality.
Definition: std_expr.h:1305
class_to_declared_symbols
std::unordered_multimap< irep_idt, symbolt > class_to_declared_symbols(const symbol_tablet &symbol_table)
Definition: java_static_initializers.cpp:783
create_function_symbol
static void create_function_symbol(const irep_idt &class_name, const irep_idt &function_name, const irep_idt &function_base_name, const synthetic_method_typet &synthetic_method_type, symbol_tablet &symbol_table, synthetic_methods_mapt &synthetic_methods)
Definition: java_static_initializers.cpp:330
code_ifthenelset
codet representation of an if-then-else statement.
Definition: std_code.h:459
grapht::topsort
std::list< node_indext > topsort() const
Find a topological order of the nodes if graph is DAG, return empty list for non-DAG or empty graph.
Definition: graph.h:879
symbolt::pretty_name
irep_idt pretty_name
Language-specific display name.
Definition: symbol.h:52
json_objectt
Definition: json.h:299
strip_java_namespace_prefix
irep_idt strip_java_namespace_prefix(const irep_idt &to_strip)
Strip java:: prefix from given identifier.
Definition: java_utils.cpp:410
source_locationt::set_line
void set_line(const irep_idt &line)
Definition: source_location.h:100
get_user_specified_clinit_body
code_blockt get_user_specified_clinit_body(const irep_idt &class_id, const json_objectt &static_values_json, symbol_table_baset &symbol_table, optionalt< ci_lazy_methods_neededt > needed_lazy_methods, size_t max_user_array_length, std::unordered_map< std::string, object_creation_referencet > &references, const std::unordered_multimap< irep_idt, symbolt > &class_to_declared_symbols_map)
Create the body of a user_specified_clinit function for a given class, which includes assignments for...
Definition: java_static_initializers.cpp:795
symbolt::is_thread_local
bool is_thread_local
Definition: symbol.h:65
code_function_callt
goto_instruction_codet representation of a function call statement.
Definition: goto_instruction_code.h:271
symbolt::mode
irep_idt mode
Language mode.
Definition: symbol.h:49
java_object_factory.h
synthetic_method_typet::USER_SPECIFIED_STATIC_INITIALIZER
@ USER_SPECIFIED_STATIC_INITIALIZER
Only exists if the --static-values option was used.
clinit_state_var_name
static irep_idt clinit_state_var_name(const irep_idt &class_name)
Get name of the static-initialization-state global variable for a given class.
Definition: java_static_initializers.cpp:161
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
failed
static bool failed(bool error_indicator)
Definition: symtab2gb_parse_options.cpp:39
irept::set
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:420
clinit_wrapper_do_recursive_calls
static void clinit_wrapper_do_recursive_calls(symbol_table_baset &symbol_table, const irep_idt &class_name, code_blockt &init_body, const bool nondet_static, const bool replace_clinit, const java_object_factory_parameterst &object_factory_parameters, const select_pointer_typet &pointer_type_selector, message_handlert &message_handler)
Generates codet that iterates through the base types of the class specified by class_name,...
Definition: java_static_initializers.cpp:232
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
symbol_table_baset
The symbol table base class interface.
Definition: symbol_table_base.h:21
nil_exprt
The NIL expression.
Definition: std_expr.h:3025
clinit_states_type
static typet clinit_states_type()
Definition: java_static_initializers.cpp:56
needs_clinit_wrapper
static bool needs_clinit_wrapper(const irep_idt &class_name, const symbol_tablet &symbol_table)
Checks whether a static initializer wrapper is needed for a given class, i.e.
Definition: java_static_initializers.cpp:309
code_assumet
An assumption, which must hold in subsequent code.
Definition: std_code.h:216
ci_lazy_methods_needed.h
source_locationt::set_file
void set_file(const irep_idt &file)
Definition: source_location.h:90
symbolt::symbol_expr
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
is_non_null_library_global
bool is_non_null_library_global(const irep_idt &symbolid)
Check if a symbol is a well-known non-null global.
Definition: java_utils.cpp:522
select_pointer_typet
Definition: select_pointer_type.h:22
struct_typet::bases
const basest & bases() const
Get the collection of base classes/structs.
Definition: std_types.h:262
clinit_already_run_variable_name
static irep_idt clinit_already_run_variable_name(const irep_idt &class_name)
Get name of the static-initialization-already-done global variable for a given class.
Definition: java_static_initializers.cpp:143
advance_to_next_key
static itertype advance_to_next_key(itertype in, itertype end)
Advance map iterator to next distinct key.
Definition: java_static_initializers.cpp:912
code_frontend_assignt
A codet representing an assignment in the program.
Definition: std_code.h:23
gen_nondet_init
void gen_nondet_init(const exprt &expr, code_blockt &init_code, symbol_table_baset &symbol_table, const source_locationt &loc, bool skip_classid, lifetimet lifetime, const java_object_factory_parameterst &object_factory_parameters, const select_pointer_typet &pointer_type_selector, update_in_placet update_in_place, message_handlert &log)
Initializes a primitive-typed or reference-typed object tree rooted at expr, allocating child objects...
Definition: java_object_factory.cpp:1624
object_creation_referencet
Information to store when several references point to the same Java object.
Definition: code_with_references.h:23
irept::is_nil
bool is_nil() const
Definition: irep.h:376
message_handlert
Definition: message.h:27
code_blockt::add
void add(const codet &code)
Definition: std_code.h:168
false_exprt
The Boolean constant false.
Definition: std_expr.h:3016
cprover_prefix.h
std_code.h
optionalt
nonstd::optional< T > optionalt
Definition: optional.h:35
object_factory_parameterst::min_null_tree_depth
size_t min_null_tree_depth
To force a certain depth of non-null objects.
Definition: object_factory_parameters.h:70
code_frontend_returnt
codet representation of a "return from a function" statement.
Definition: std_code.h:892
source_locationt
Definition: source_location.h:18
java_byte_type
signedbv_typet java_byte_type()
Definition: java_types.cpp:55
code_with_references_listt::append
void append(code_with_references_listt &&other)
Definition: code_with_references.cpp:70
symbol_table_baset::add
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
Definition: symbol_table_base.cpp:18
assignments_from_json.h
is_user_specified_clinit_function
bool is_user_specified_clinit_function(const irep_idt &function_id)
Check if function_id is a user-specified clinit.
Definition: java_static_initializers.cpp:102
symbolt::value
exprt value
Initial value of symbol.
Definition: symbol.h:34
class_hierarchy.h
synthetic_method_typet::STUB_CLASS_STATIC_INITIALIZER
@ STUB_CLASS_STATIC_INITIALIZER
A generated (synthetic) static initializer function for a stub type.
clinit_wrapper_suffix
const std::string clinit_wrapper_suffix
Definition: java_static_initializers.cpp:63
json_objectt::end
iterator end()
Definition: json.h:386
code_with_references_listt
Wrapper around a list of shared pointer to code_with_referencest objects, which provides a nicer inte...
Definition: code_with_references.h:92
suffix.h
to_json_object
json_objectt & to_json_object(jsont &json)
Definition: json.h:444
class_hierarchy_grapht
Class hierarchy, represented using grapht and therefore suitable for use with generic graph algorithm...
Definition: class_hierarchy.h:102
stub_global_initializer_factoryt::create_stub_global_initializer_symbols
void create_stub_global_initializer_symbols(symbol_tablet &symbol_table, const std::unordered_set< irep_idt > &stub_globals_set, synthetic_methods_mapt &synthetic_methods)
Create static initializer symbols for each distinct class that has stub globals.
Definition: java_static_initializers.cpp:929
clinit_statest
clinit_statest
The three states in which a <clinit> method for a class can be before, after, and during static class...
Definition: java_static_initializers.cpp:49
code_with_references_listt::list
std::list< std::shared_ptr< code_with_referencest > > list
Definition: code_with_references.h:95
clinit_statest::IN_PROGRESS
@ IN_PROGRESS
symbolt
Symbol table entry.
Definition: symbol.h:27
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
code_blockt::append
void append(const code_blockt &extra_block)
Add all the codets from extra_block to the current code_blockt.
Definition: std_code.cpp:89
symbol_table_baset::symbols
const symbolst & symbols
Read-only field, used to look up symbols given their names.
Definition: symbol_table_base.h:30
gen_clinit_assign
static code_frontend_assignt gen_clinit_assign(const exprt &expr, const clinit_statest state)
Generates a code_frontend_assignt for clinit_statest /param expr: expression to be used as the LHS of...
Definition: java_static_initializers.cpp:192
CPROVER_PREFIX
#define CPROVER_PREFIX
Definition: cprover_prefix.h:14
json.h
stub_global_initializer_factoryt::stub_globals_by_class
stub_globals_by_classt stub_globals_by_class
Definition: java_static_initializers.h:101
update_in_placet::NO_UPDATE_IN_PLACE
@ NO_UPDATE_IN_PLACE
clinit_statest::INIT_COMPLETE
@ INIT_COMPLETE
symbolt::is_static_lifetime
bool is_static_lifetime
Definition: symbol.h:65
clinit_wrapper_name
irep_idt clinit_wrapper_name(const irep_idt &class_name)
Get the Java static initializer wrapper name for a given class (the wrapper checks if static initiali...
Definition: java_static_initializers.cpp:73
lifetimet::DYNAMIC
@ DYNAMIC
Allocate dynamic objects (using ALLOCATE)
symbol_table_baset::lookup
const symbolt * lookup(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
Definition: symbol_table_base.h:95
symbolt::is_lvalue
bool is_lvalue
Definition: symbol.h:66
to_java_class_type
const java_class_typet & to_java_class_type(const typet &type)
Definition: java_types.h:582
add_new_variable_symbol
static symbolt add_new_variable_symbol(symbol_table_baset &symbol_table, const irep_idt &name, const typet &type, const exprt &value, const bool is_thread_local, const bool is_static_lifetime)
Add a new symbol to the symbol table.
Definition: java_static_initializers.cpp:115
create_clinit_wrapper_symbols
static void create_clinit_wrapper_symbols(const irep_idt &class_name, symbol_tablet &symbol_table, synthetic_methods_mapt &synthetic_methods, const bool thread_safe)
Creates a static initializer wrapper symbol for the given class, along with a global boolean that tra...
Definition: java_static_initializers.cpp:399
INVARIANT
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition: invariant.h:423
java_types.h
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:216
java_class_typet::get_is_stub
bool get_is_stub() const
Definition: java_types.h:398
symbol_table.h
Author: Diffblue Ltd.
java_void_type
empty_typet java_void_type()
Definition: java_types.cpp:37
true_exprt
The Boolean constant true.
Definition: std_expr.h:3007
java_utils.h
constant_exprt
A constant literal expression.
Definition: std_expr.h:2941
clinit_thread_local_state_var_name
static irep_idt clinit_thread_local_state_var_name(const irep_idt &class_name)
Get name of the static-initialization-state local state variable for a given class.
Definition: java_static_initializers.cpp:170
comment
static std::string comment(const rw_set_baset::entryt &entry, bool write)
Definition: race_check.cpp:109
java_method_typet
Definition: java_types.h:100
is_clinit_wrapper_function
bool is_clinit_wrapper_function(const irep_idt &function_id)
Check if function_id is a clinit wrapper.
Definition: java_static_initializers.cpp:86
java_object_factory_parameterst
Definition: java_object_factory_parameters.h:15
assign_from_json
code_with_references_listt assign_from_json(const exprt &expr, const jsont &json, const irep_idt &function_id, symbol_table_baset &symbol_table, optionalt< ci_lazy_methods_neededt > &needed_lazy_methods, size_t max_user_array_length, std::unordered_map< std::string, object_creation_referencet > &references)
Given an expression expr representing a Java object or primitive and a JSON representation json of th...
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
validation_modet::INVARIANT
@ INVARIANT
struct_typet::baset
Base class or struct that a class or struct inherits from.
Definition: std_types.h:251
codet
Data structure for representing an arbitrary statement in a program.
Definition: std_code_base.h:28
not_exprt
Boolean negation.
Definition: std_expr.h:2277
equal_range
ranget< typename multimapt::const_iterator > equal_range(const multimapt &multimap, const typename multimapt::key_type &key)
Utility function to make equal_range method of multimap easier to use by returning a ranget object.
Definition: range.h:541
class_hierarchy_grapht::populate
void populate(const symbol_tablet &)
Populate the class hierarchy graph, such that there is a node for every struct type in the symbol tab...
Definition: class_hierarchy.cpp:29