CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
java_static_initializers.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Java Static Initializers
4
5Author: 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>
17
20
22#include "ci_lazy_methods_needed.h" // IWYU pragma: keep
23#include "java_object_factory.h"
25#include "java_types.h"
26#include "java_utils.h"
27
50{
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.
63const std::string clinit_wrapper_suffix = ".<clinit_wrapper>"; // NOLINT(*)
64const std::string user_specified_clinit_suffix = ".<user_specified_clinit>"; // NOLINT(*)
65const 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
86bool is_clinit_wrapper_function(const irep_idt &function_id)
87{
88 return has_suffix(id2string(function_id), clinit_wrapper_suffix);
89}
90
94bool is_clinit_function(const irep_idt &function_id)
95{
96 return has_suffix(id2string(function_id), clinit_function_suffix);
97}
98
103{
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{name, type, ID_java};
124 new_symbol.pretty_name = name;
125 new_symbol.base_name = name;
126 new_symbol.type.set(ID_C_no_nondet_initialization, true);
127 new_symbol.value = value;
128 new_symbol.is_lvalue = true;
129 new_symbol.is_state_var = true;
130 new_symbol.is_static_lifetime = is_static_lifetime;
131 new_symbol.is_thread_local = is_thread_local;
132 symbol_table.add(new_symbol);
133 return new_symbol;
134}
135
141{
142 return id2string(class_name) + "::clinit_already_run";
143}
144
149static irep_idt clinit_function_name(const irep_idt &class_name)
150{
151 return id2string(class_name) + clinit_function_suffix;
152}
153
158static irep_idt clinit_state_var_name(const irep_idt &class_name)
159{
160 return id2string(class_name) + CPROVER_PREFIX "clinit_state";
161}
162
168{
169 return id2string(class_name) + CPROVER_PREFIX "clinit_threadlocal_state";
170}
171
176{
177 return id2string(class_name) + CPROVER_PREFIX "clinit_wrapper::init_complete";
178}
179
189gen_clinit_assign(const exprt &expr, const clinit_statest state)
190{
191 mp_integer initv(static_cast<int>(state));
193 return code_frontend_assignt(expr, init_s);
194}
195
204static equal_exprt
205gen_clinit_eqexpr(const exprt &expr, const clinit_statest state)
206{
207 mp_integer initv(static_cast<int>(state));
209 return equal_exprt(expr, init_s);
210}
211
230 symbol_table_baset &symbol_table,
231 const irep_idt &class_name,
233 const bool nondet_static,
234 const bool replace_clinit,
235 const java_object_factory_parameterst &object_factory_parameters,
236 const select_pointer_typet &pointer_type_selector,
237 message_handlert &message_handler)
238{
239 const symbolt &class_symbol = symbol_table.lookup_ref(class_name);
240 for(const auto &base : to_class_type(class_symbol.type).bases())
241 {
242 const auto base_name = base.type().get_identifier();
244 if(const auto base_init_func = symbol_table.lookup(base_init_routine))
245 init_body.add(code_function_callt{base_init_func->symbol_expr()});
246 }
247
249 ? user_specified_clinit_name(class_name)
250 : clinit_function_name(class_name);
251 if(const auto clinit_func = symbol_table.lookup(clinit_name))
252 init_body.add(code_function_callt{clinit_func->symbol_expr()});
253
254 // If nondet-static option is given, add a standard nondet initialization for
255 // each non-final static field of this class. Note this is the same invocation
256 // used in get_stub_initializer_body and java_static_lifetime_init.
257 if(nondet_static)
258 {
259 java_object_factory_parameterst parameters = object_factory_parameters;
260 parameters.function_id = clinit_wrapper_name(class_name);
261
262 std::vector<irep_idt> nondet_ids;
263 std::for_each(
264 symbol_table.symbols.begin(),
265 symbol_table.symbols.end(),
266 [&](const std::pair<irep_idt, symbolt> &symbol) {
267 if(
268 declaring_class(symbol.second) == class_name &&
269 symbol.second.is_static_lifetime &&
270 !symbol.second.type.get_bool(ID_C_constant))
271 {
272 nondet_ids.push_back(symbol.first);
273 }
274 });
275
276 for(const auto &id : nondet_ids)
277 {
279 symbol_table.lookup_ref(id).symbol_expr();
280
281 parameters.min_null_tree_depth =
283 ? std::max(size_t(1), object_factory_parameters.min_null_tree_depth)
284 : object_factory_parameters.min_null_tree_depth;
285
288 init_body,
289 symbol_table,
291 false,
293 parameters,
294 pointer_type_selector,
296 message_handler);
297 }
298 }
299}
300
307 const irep_idt &class_name,
308 const symbol_table_baset &symbol_table)
309{
310 if(symbol_table.has_symbol(clinit_function_name(class_name)))
311 return true;
312
313 const class_typet &class_type =
314 to_class_type(symbol_table.lookup_ref(class_name).type);
315
316 for(const class_typet::baset &base : class_type.bases())
317 {
318 if(symbol_table.has_symbol(
319 clinit_wrapper_name(base.type().get_identifier())))
320 {
321 return true;
322 }
323 }
324
325 return false;
326}
327
329 const irep_idt &class_name,
330 const irep_idt &function_name,
333 symbol_table_baset &symbol_table,
334 synthetic_methods_mapt &synthetic_methods)
335{
337 function_name, java_method_typet({}, java_void_type()), ID_java};
338 function_symbol.name = function_name;
339 function_symbol.pretty_name = function_symbol.name;
341 // This provides a back-link from a method to its associated class, as is done
342 // for java_bytecode_convert_methodt::convert.
344 bool failed = symbol_table.add(function_symbol);
345 INVARIANT(!failed, id2string(function_base_name) + " symbol should be fresh");
346
347 auto insert_result =
348 synthetic_methods.emplace(function_symbol.name, synthetic_method_type);
349 INVARIANT(
350 insert_result.second,
351 "synthetic methods map should not already contain entry for " +
353}
354
355// Create symbol for the "clinit_wrapper"
357 const irep_idt &class_name,
358 symbol_table_baset &symbol_table,
359 synthetic_methods_mapt &synthetic_methods)
360{
362 class_name,
363 clinit_wrapper_name(class_name),
364 "clinit_wrapper",
366 symbol_table,
367 synthetic_methods);
368}
369
370// Create symbol for the "user_specified_clinit"
372 const irep_idt &class_name,
373 symbol_table_baset &symbol_table,
374 synthetic_methods_mapt &synthetic_methods)
375{
377 class_name,
378 user_specified_clinit_name(class_name),
379 "user_specified_clinit",
381 symbol_table,
382 synthetic_methods);
383}
384
396 const irep_idt &class_name,
397 symbol_table_baset &symbol_table,
398 synthetic_methods_mapt &synthetic_methods,
399 const bool thread_safe)
400{
401 if(thread_safe)
402 {
404 static_cast<int>(clinit_statest::NOT_INIT), clinit_states_type());
405
406 // Create two global static synthetic "fields" for the class "id"
407 // these two variables hold the state of the class initialization algorithm
408 // across calls to the clinit_wrapper
410 symbol_table,
411 clinit_state_var_name(class_name),
414 false,
415 true);
416
418 symbol_table,
422 true,
423 true);
424 }
425 else
426 {
429
431 symbol_table,
433 bool_typet(),
434 false_exprt(),
435 false,
436 true);
437 }
438
440 class_name, symbol_table, synthetic_methods);
441}
442
521 const irep_idt &function_id,
522 symbol_table_baset &symbol_table,
523 const bool nondet_static,
524 const bool replace_clinit,
525 const java_object_factory_parameterst &object_factory_parameters,
526 const select_pointer_typet &pointer_type_selector,
527 message_handlert &message_handler)
528{
529 const symbolt &wrapper_method_symbol = symbol_table.lookup_ref(function_id);
530 const auto class_name = declaring_class(wrapper_method_symbol);
531 INVARIANT(class_name, "Wrapper function should have an owning class.");
532
534 symbol_table.lookup_ref(clinit_state_var_name(*class_name));
536 symbol_table.lookup_ref(clinit_thread_local_state_var_name(*class_name));
537
538 // Create a function-local variable "init_complete". This variable is used to
539 // avoid inspecting the global state (clinit_state_sym) outside of
540 // the critical-section.
542 symbol_table,
544 bool_typet(),
545 nil_exprt(),
546 true,
547 false);
548
550 codet atomic_begin(ID_atomic_begin);
551 codet atomic_end(ID_atomic_end);
552
553#if 0
554 // This code defines source locations for every codet generated below for
555 // the static initializer wrapper. Enable this for debugging the symex going
556 // through the clinit_wrapper.
557 //
558 // java::C.<clinit_wrapper>()
559 // You will additionally need to associate the `location` with the
560 // `function_body` and then manually set lines of code for each of the
561 // statements of the function, using something along the lines of:
562 // `mycodet.then_case().add_source_location().set_line(17);`/
563
564 source_locationt &location = function_body.add_source_location();
565 location.set_file ("<generated>");
566 location.set_line ("<generated>");
568 std::string comment =
569 "Automatically generated function. States are:\n"
570 " 0 = class not initialized, init val of clinit_state/clinit_local_state\n"
571 " 1 = class initialization in progress, by this or another thread\n"
572 " 2 = initialization finished with success, by this or another thread\n";
573 static_assert((int) clinit_statest::NOT_INIT==0, "Check commment above");
574 static_assert((int) clinit_statest::IN_PROGRESS==1, "Check comment above");
575 static_assert((int) clinit_statest::INIT_COMPLETE==2, "Check comment above");
576#endif
577
578 // bool init_complete;
579 {
580 code_frontend_declt decl(init_complete.symbol_expr());
581 function_body.add(decl);
582 }
583
584 // if(C::__CPROVER_PREFIX_clinit_thread_local_state == INIT_COMPLETE) return;
585 {
588 clinit_thread_local_state_sym.symbol_expr(),
591 function_body.add(std::move(conditional));
592 }
593
594 // C::__CPROVER_PREFIX_clinit_thread_local_state = INIT_COMPLETE;
595 {
597 clinit_thread_local_state_sym.symbol_expr(),
599 function_body.add(assign);
600 }
601
602 // ATOMIC_BEGIN
603 {
604 function_body.add(atomic_begin);
605 }
606
607 // Assume: clinit_state_sym != IN_PROGRESS
608 {
609 exprt assumption = gen_clinit_eqexpr(
611 assumption = not_exprt(assumption);
612 code_assumet assume(assumption);
613 function_body.add(assume);
614 }
615
616 // If(C::__CPROVER_PREFIX_clinit_state == NOT_INIT)
617 // {
618 // C::__CPROVER_PREFIX_clinit_state = IN_PROGRESS;
619 // init_complete = false;
620 // }
621 // else If(C::__CPROVER_PREFIX_clinit_state == INIT_COMPLETE)
622 // {
623 // init_complete = true;
624 // }
625 {
630 {code_frontend_assignt(init_complete.symbol_expr(), true_exprt())}));
631
639 std::move(init_conditional));
640
641 function_body.add(std::move(not_init_conditional));
642 }
643
644 // ATOMIC_END
645 {
646 function_body.add(atomic_end);
647 }
648
649 // if(init_complete) return;
650 {
652 init_complete.symbol_expr(), code_frontend_returnt());
653 function_body.add(std::move(conditional));
654 }
655
656 // Initialize the super-class C' and
657 // the implemented interfaces l_1 ... l_n.
658 // see JVMS p.359 step 7, for the exact definition of
659 // the sequence l_1 to l_n.
660 // This is achieved by iterating through the base types and
661 // adding recursive calls to the clinit_wrapper()
662 //
663 // java::C'.<clinit_wrapper>();
664 // java::I1.<clinit_wrapper>();
665 // java::I2.<clinit_wrapper>();
666 // // ...
667 // java::In.<clinit_wrapper>();
668 //
669 // java::C.<clinit>(); // or nondet-initialization of all static
670 // // variables of C if nondet-static is true
671 //
672 {
675 symbol_table,
676 *class_name,
677 init_body,
680 object_factory_parameters,
681 pointer_type_selector,
682 message_handler);
683 function_body.append(init_body);
684 }
685
686 // ATOMIC_START
687 // C::__CPROVER_PREFIX_clinit_state = INIT_COMPLETE;
688 // ATOMIC_END
689 // return;
690 {
691 // synchronization prologue
692 function_body.add(atomic_begin);
693 function_body.add(
696 function_body.add(atomic_end);
698 }
699
700 return function_body;
701}
702
719 const irep_idt &function_id,
720 symbol_table_baset &symbol_table,
721 const bool nondet_static,
722 const bool replace_clinit,
723 const java_object_factory_parameterst &object_factory_parameters,
724 const select_pointer_typet &pointer_type_selector,
725 message_handlert &message_handler)
726{
727 // Assume that class C extends class C' and implements interfaces
728 // I1, ..., In. We now create the following function (possibly recursively
729 // creating the clinit_wrapper functions for C' and I1, ..., In):
730 //
731 // java::C.<clinit_wrapper>()
732 // {
733 // if (!java::C::clinit_already_run)
734 // {
735 // java::C::clinit_already_run = true; // before recursive calls!
736 //
737 // java::C'.<clinit_wrapper>();
738 // java::I1.<clinit_wrapper>();
739 // java::I2.<clinit_wrapper>();
740 // // ...
741 // java::In.<clinit_wrapper>();
742 //
743 // java::C.<clinit>(); // or nondet-initialization of all static
744 // // variables of C if nondet-static is true
745 // }
746 // }
747 const symbolt &wrapper_method_symbol = symbol_table.lookup_ref(function_id);
748 const auto class_name = declaring_class(wrapper_method_symbol);
749 INVARIANT(class_name, "Wrapper function should have an owning class.");
750
752 symbol_table.lookup_ref(clinit_already_run_variable_name(*class_name));
753
755 already_run_symbol.symbol_expr(),
756 false_exprt());
757
758 // add the "already-run = false" statement
760 already_run_symbol.symbol_expr(), true_exprt());
762
764 symbol_table,
765 *class_name,
766 init_body,
769 object_factory_parameters,
770 pointer_type_selector,
771 message_handler);
772
773 // the entire body of the function is an if-then-else
774 return code_ifthenelset(std::move(check_already_run), std::move(init_body));
775}
776
778std::unordered_multimap<irep_idt, symbolt>
780{
781 std::unordered_multimap<irep_idt, symbolt> result;
782 for(const auto &symbol_pair : symbol_table)
783 {
784 const symbolt &symbol = symbol_pair.second;
785 if(std::optional<irep_idt> declaring = declaring_class(symbol))
786 result.emplace(*declaring, symbol);
787 }
788 return result;
789}
790
792 const irep_idt &class_id,
793 const json_objectt &static_values_json,
794 symbol_table_baset &symbol_table,
795 std::optional<ci_lazy_methods_neededt> needed_lazy_methods,
796 size_t max_user_array_length,
797 std::unordered_map<std::string, object_creation_referencet> &references,
798 const std::unordered_multimap<irep_idt, symbolt>
800{
802 const auto clinit_func = symbol_table.lookup(real_clinit_name);
803 if(clinit_func == nullptr)
804 {
805 // Case where the real clinit doesn't appear in the symbol table, even
806 // though their is user specifed one. This may occur when some class
807 // substitution happened after compilation.
808 return code_blockt{};
809 }
810 const auto class_entry =
811 static_values_json.find(id2string(strip_java_namespace_prefix(class_id)));
812 if(class_entry != static_values_json.end() && class_entry->second.is_object())
813 {
814 const auto &class_json_object = to_json_object(class_entry->second);
815 std::map<symbol_exprt, jsont> static_field_values;
816 for(const auto &symbol_pair :
818 {
819 const symbolt &symbol = symbol_pair.second;
820 if(symbol.is_static_lifetime)
821 {
823 const auto &static_field_entry =
826 {
827 static_field_values.insert(
829 }
830 }
831 }
833 for(const auto &value_pair : static_field_values)
834 {
836 value_pair.first,
837 value_pair.second,
839 symbol_table,
840 needed_lazy_methods,
841 max_user_array_length,
842 references));
843 }
845 [&](const std::string &reference_id) -> object_creation_referencet & {
846 auto it = references.find(reference_id);
847 INVARIANT(it != references.end(), "reference id must be present in map");
848 return it->second;
849 };
850 code_blockt body;
851 for(const auto &code_with_ref : code_with_references.list)
853 return body;
854 }
855 return code_blockt{{code_function_callt{clinit_func->symbol_expr()}}};
856}
857
875 symbol_table_baset &symbol_table,
876 synthetic_methods_mapt &synthetic_methods,
877 const bool thread_safe,
878 const bool is_user_clinit_needed)
879{
880 // Top-sort the class hierarchy, such that we visit parents before children,
881 // and can so identify parents that need static initialisation by whether we
882 // have made them a clinit_wrapper method.
884 class_graph.populate(symbol_table);
885 std::list<class_hierarchy_grapht::node_indext> topsorted_nodes =
886 class_graph.topsort();
887
888 for(const auto node : topsorted_nodes)
889 {
890 const irep_idt &class_identifier = class_graph[node].class_identifier;
891 if(needs_clinit_wrapper(class_identifier, symbol_table))
892 {
894 class_identifier, symbol_table, synthetic_methods, thread_safe);
896 {
898 class_identifier, symbol_table, synthetic_methods);
899 }
900 }
901 }
902}
903
907template<class itertype>
909{
910 PRECONDITION(in != end);
911 auto initial_key = in->first;
912 while(in != end && in->first == initial_key)
913 ++in;
914 return in;
915}
916
926 symbol_table_baset &symbol_table,
927 const std::unordered_set<irep_idt> &stub_globals_set,
928 synthetic_methods_mapt &synthetic_methods)
929{
930 // Populate map from class id -> stub globals:
932 {
933 const symbolt &global_symbol = symbol_table.lookup_ref(stub_global);
934 if(global_symbol.value.is_nil())
935 {
936 // This symbol is already nondet-initialised during __CPROVER_initialize
937 // (generated in java_static_lifetime_init). In future this will only
938 // be the case for primitive-typed fields, but for now reference-typed
939 // fields can also be treated this way in the exceptional case that they
940 // belong to a non-stub class. Skip the field, as it does not need a
941 // synthetic static initializer.
942 continue;
943 }
944
945 const auto class_id = declaring_class(global_symbol);
946 INVARIANT(class_id, "Static field should have a defining class.");
947 stub_globals_by_class.insert({*class_id, stub_global});
948 }
949
950 // For each distinct class that has stub globals, create a clinit symbol:
951
952 for(auto it = stub_globals_by_class.begin(),
954 it != itend;
955 it = advance_to_next_key(it, itend))
956 {
958
959 INVARIANT(
960 to_java_class_type(symbol_table.lookup_ref(it->first).type).get_is_stub(),
961 "only stub classes should be given synthetic static initialisers");
962 INVARIANT(
963 !symbol_table.has_symbol(static_init_name),
964 "a class cannot be both incomplete, and so have stub static fields, and "
965 "also define a static initializer");
966
970 static_init_symbol.base_name = "clinit():V";
971 // This provides a back-link from a method to its associated class, as is
972 // done for java_bytecode_convert_methodt::convert.
974
975 bool failed = symbol_table.add(static_init_symbol);
976 INVARIANT(!failed, "symbol should not already exist");
977
978 auto insert_result = synthetic_methods.emplace(
981 INVARIANT(
982 insert_result.second,
983 "synthetic methods map should not already contain entry for "
984 "stub static initializer");
985 }
986}
987
1003 const irep_idt &function_id,
1004 symbol_table_baset &symbol_table,
1005 const java_object_factory_parameterst &object_factory_parameters,
1006 const select_pointer_typet &pointer_type_selector,
1007 message_handlert &message_handler)
1008{
1009 const symbolt &stub_initializer_symbol = symbol_table.lookup_ref(function_id);
1010 const auto class_id = declaring_class(stub_initializer_symbol);
1011 INVARIANT(
1012 class_id, "Synthetic static initializer should have an owning class.");
1014
1015 // Add a standard nondet initialisation for each global declared on this
1016 // class. Note this is the same invocation used in
1017 // java_static_lifetime_init.
1018
1020 INVARIANT(
1021 !class_globals.empty(),
1022 "class with synthetic clinit should have at least one global to init");
1023
1024 java_object_factory_parameterst parameters = object_factory_parameters;
1025 parameters.function_id = function_id;
1026
1027 for(const auto &pair : class_globals)
1028 {
1030 symbol_table.lookup_ref(pair.second).symbol_expr();
1031
1032 parameters.min_null_tree_depth =
1034 ? object_factory_parameters.min_null_tree_depth + 1
1035 : object_factory_parameters.min_null_tree_depth;
1036
1037 source_locationt location;
1038 location.set_function(function_id);
1042 symbol_table,
1043 location,
1044 false,
1046 parameters,
1047 pointer_type_selector,
1049 message_handler);
1050 }
1051
1052 return static_init_body;
1053}
@ DYNAMIC
Allocate dynamic objects (using ALLOCATE)
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
code_with_references_listt assign_from_json(const exprt &expr, const jsont &json, const irep_idt &function_id, symbol_table_baset &symbol_table, std::optional< 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...
Context-insensitive lazy methods container.
Class Hierarchy.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
The Boolean type.
Definition std_types.h:36
Class hierarchy, represented using grapht and therefore suitable for use with generic graph algorithm...
Class type.
Definition std_types.h:325
An assumption, which must hold in subsequent code.
Definition std_code.h:217
A codet representing sequential composition of program statements.
Definition std_code.h:130
void append(const code_blockt &extra_block)
Add all the codets from extra_block to the current code_blockt.
Definition std_code.cpp:86
A codet representing an assignment in the program.
Definition std_code.h:24
A codet representing the declaration of a local variable.
Definition std_code.h:347
codet representation of a "return from a function" statement.
Definition std_code.h:893
goto_instruction_codet representation of a function call statement.
codet representation of an if-then-else statement.
Definition std_code.h:460
Wrapper around a list of shared pointer to code_with_referencest objects, which provides a nicer inte...
std::function< const object_creation_referencet &(const std::string &)> reference_substitutiont
Data structure for representing an arbitrary statement in a program.
A constant literal expression.
Definition std_expr.h:3117
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
Equality.
Definition std_expr.h:1366
Base class for all expressions.
Definition expr.h:56
The Boolean constant false.
Definition std_expr.h:3199
iterator find(const std::string &key)
Definition json.h:354
iterator end()
Definition json.h:384
The NIL expression.
Definition std_expr.h:3208
Boolean negation.
Definition std_expr.h:2454
void set_file(const irep_idt &file)
void set_line(const irep_idt &line)
void set_function(const irep_idt &function)
Base class or struct that a class or struct inherits from.
Definition std_types.h:252
void create_stub_global_initializer_symbols(symbol_table_baset &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.
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...
Expression to hold a symbol (variable)
Definition std_expr.h:131
The symbol table base class interface.
const symbolt * lookup(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
const symbolst & symbols
Read-only field, used to look up symbols given their names.
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
const symbolt & lookup_ref(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
Symbol table entry.
Definition symbol.h:28
bool is_static_lifetime
Definition symbol.h:70
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition symbol.cpp:121
irep_idt irep_idt base_name
Name of module the symbol belongs to.
Definition symbol.h:46
The Boolean constant true.
Definition std_expr.h:3190
The type of an expression, extends irept.
Definition type.h:29
#define CPROVER_PREFIX
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
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...
This module is responsible for the synthesis of code (in the form of a sequence of codet statements) ...
std::unordered_multimap< irep_idt, symbolt > class_to_declared_symbols(const symbol_table_baset &symbol_table)
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...
clinit_statest
The three states in which a <clinit> method for a class can be before, after, and during static class...
code_blockt get_user_specified_clinit_body(const irep_idt &class_id, const json_objectt &static_values_json, symbol_table_baset &symbol_table, std::optional< 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...
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_table_baset &symbol_table, synthetic_methods_mapt &synthetic_methods)
void create_static_initializer_symbols(symbol_table_baset &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...
static typet clinit_states_type()
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.
const std::string clinit_function_suffix
static void create_user_specified_clinit_function_symbol(const irep_idt &class_name, symbol_table_baset &symbol_table, synthetic_methods_mapt &synthetic_methods)
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.
static void create_clinit_wrapper_function_symbol(const irep_idt &class_name, symbol_table_baset &symbol_table, synthetic_methods_mapt &synthetic_methods)
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...
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,...
static void create_clinit_wrapper_symbols(const irep_idt &class_name, symbol_table_baset &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...
bool is_user_specified_clinit_function(const irep_idt &function_id)
Check if function_id is a user-specified clinit.
irep_idt user_specified_clinit_name(const irep_idt &class_name)
const std::string user_specified_clinit_suffix
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.
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.
static itertype advance_to_next_key(itertype in, itertype end)
Advance map iterator to next distinct key.
bool is_clinit_wrapper_function(const irep_idt &function_id)
Check if function_id is a clinit wrapper.
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...
static irep_idt clinit_function_name(const irep_idt &class_name)
Get name of the real static initializer for a given class.
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.
bool is_clinit_function(const irep_idt &function_id)
Check if function_id is a clinit.
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.
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.
const std::string clinit_wrapper_suffix
static bool needs_clinit_wrapper(const irep_idt &class_name, const symbol_table_baset &symbol_table)
Checks whether a static initializer wrapper is needed for a given class, i.e.
empty_typet java_void_type()
signedbv_typet java_byte_type()
const java_class_typet & to_java_class_type(const typet &type)
Definition java_types.h:581
bool is_non_null_library_global(const irep_idt &symbolid)
Check if a symbol is a well-known non-null global.
std::optional< irep_idt > declaring_class(const symbolt &symbol)
Gets the identifier of the class which declared a given symbol.
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.
irep_idt strip_java_namespace_prefix(const irep_idt &to_strip)
Strip java:: prefix from given identifier.
json_objectt & to_json_object(jsont &json)
Definition json.h:442
static void nondet_static(const namespacet &ns, goto_modelt &goto_model, const irep_idt &fct_name)
Nondeterministically initializes global scope variables in a goto-function.
static std::string comment(const rw_set_baset::entryt &entry, bool write)
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:539
BigInt mp_integer
Definition smt_terms.h:17
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
const class_typet & to_class_type(const typet &type)
Cast a typet to a class_typet.
Definition std_types.h:381
Information to store when several references point to the same Java object.
irep_idt function_id
Function id, used as a prefix for identifiers of temporaries.
size_t min_null_tree_depth
To force a certain depth of non-null objects.
bool has_suffix(const std::string &s, const std::string &suffix)
Definition suffix.h:17
Author: Diffblue Ltd.
static bool failed(bool error_indicator)
std::unordered_map< irep_idt, synthetic_method_typet > synthetic_methods_mapt
Maps method names on to a synthetic method kind.
synthetic_method_typet
Synthetic method kinds.
@ USER_SPECIFIED_STATIC_INITIALIZER
Only exists if the --static-values option was used.
@ STATIC_INITIALIZER_WRAPPER
A static initializer wrapper (code of the form if(!already_run) clinit(); already_run = true;) These ...
@ STUB_CLASS_STATIC_INITIALIZER
A generated (synthetic) static initializer function for a stub type.