CBMC
static_lifetime_init.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 "static_lifetime_init.h"
10 
11 #include <util/arith_tools.h>
12 #include <util/c_types.h>
13 #include <util/expr_initializer.h>
14 #include <util/namespace.h>
15 #include <util/prefix.h>
16 #include <util/std_code.h>
17 #include <util/symbol_table_base.h>
18 
20 
22 
23 #include <set>
24 
25 static std::optional<codet> static_lifetime_init(
26  const irep_idt &identifier,
27  symbol_table_baset &symbol_table)
28 {
29  const namespacet ns(symbol_table);
30  const symbolt &symbol = ns.lookup(identifier);
31 
32  if(!symbol.is_static_lifetime)
33  return {};
34 
35  if(symbol.is_type || symbol.is_macro)
36  return {};
37 
38  // special values
39  if(
40  identifier == CPROVER_PREFIX "constant_infinity_uint" ||
41  identifier == CPROVER_PREFIX "memory" || identifier == "__func__" ||
42  identifier == "__FUNCTION__" || identifier == "__PRETTY_FUNCTION__" ||
43  identifier == "argc'" || identifier == "argv'" || identifier == "envp'" ||
44  identifier == "envp_size'")
45  return {};
46 
47  // just for linking
48  if(identifier.starts_with(CPROVER_PREFIX "architecture_"))
49  return {};
50 
51  // check type
52  if(symbol.type.id() == ID_code || symbol.type.id() == ID_empty)
53  return {};
54 
55  if(symbol.type.id() == ID_array && to_array_type(symbol.type).size().is_nil())
56  {
57  // C standard 6.9.2, paragraph 5
58  // adjust the type to an array of size 1
59  symbolt &writable_symbol = symbol_table.get_writeable_ref(identifier);
60  writable_symbol.type = symbol.type;
61  writable_symbol.type.set(ID_size, from_integer(1, size_type()));
62  }
63 
64  if(
65  (symbol.type.id() == ID_struct_tag &&
67  (symbol.type.id() == ID_union_tag &&
69  {
70  return {}; // do not initialize
71  }
72 
73  exprt rhs;
74 
75  if((symbol.value.is_nil() && symbol.is_extern) ||
76  symbol.value.id() == ID_nondet)
77  {
78  if(symbol.value.get_bool(ID_C_no_nondet_initialization))
79  return {};
80 
81  // Nondet initialise if not linked, or if explicitly requested.
82  // Compilers would usually complain about the unlinked symbol case.
83  const auto nondet = nondet_initializer(symbol.type, symbol.location, ns);
84  CHECK_RETURN(nondet.has_value());
85  rhs = *nondet;
86  }
87  else if(symbol.value.is_nil())
88  {
89  const auto zero = zero_initializer(symbol.type, symbol.location, ns);
90  CHECK_RETURN(zero.has_value());
91  rhs = *zero;
92  }
93  else
94  rhs = symbol.value;
95 
96  return code_frontend_assignt{symbol.symbol_expr(), rhs, symbol.location};
97 }
98 
100  symbol_table_baset &symbol_table,
101  const source_locationt &source_location)
102 {
104 
105  const namespacet ns(symbol_table);
106 
108 
109  init_symbol.value=code_blockt();
110  init_symbol.value.add_source_location()=source_location;
111 
113 
114  // add the magic label to hide
115  dest.add(code_labelt(CPROVER_PREFIX "HIDE", code_skipt()));
116 
117  // do assignments based on "value"
118 
119  // sort alphabetically for reproducible results
120  std::set<std::string> symbols;
121 
122  for(const auto &symbol_pair : symbol_table.symbols)
123  {
124  symbols.insert(id2string(symbol_pair.first));
125  }
126 
127  // first do framework variables
128  for(const std::string &id : symbols)
129  if(has_prefix(id, CPROVER_PREFIX))
130  {
131  auto code = static_lifetime_init(id, symbol_table);
132  if(code.has_value())
133  dest.add(std::move(*code));
134  }
135 
136  // now all other variables
137  for(const std::string &id : symbols)
138  if(!has_prefix(id, CPROVER_PREFIX))
139  {
140  auto code = static_lifetime_init(id, symbol_table);
141  if(code.has_value())
142  dest.add(std::move(*code));
143  }
144 
145  // now call designated "initialization" functions
146 
147  for(const std::string &id : symbols)
148  {
149  const symbolt &symbol=ns.lookup(id);
150 
151  if(symbol.type.id() != ID_code)
152  continue;
153 
154  const code_typet &code_type = to_code_type(symbol.type);
155  if(
156  code_type.return_type().id() == ID_constructor &&
157  code_type.parameters().empty())
158  {
160  symbol.symbol_expr(), {}, code_type.return_type(), source_location}});
161  }
162  }
163 }
164 
166  goto_modelt &goto_model,
167  message_handlert &message_handler)
168 {
169  auto unloaded = goto_model.unload(INITIALIZE_FUNCTION);
170  PRECONDITION(unloaded == 1);
171 
173  goto_model.symbol_table,
175  goto_convert(
177  goto_model.symbol_table,
178  goto_model.goto_functions,
179  message_handler);
180  goto_model.goto_functions.update();
181 }
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:224
const exprt & size() const
Definition: std_types.h:840
A codet representing sequential composition of program statements.
Definition: std_code.h:130
void add(const codet &code)
Definition: std_code.h:168
codet representation of an expression statement.
Definition: std_code.h:1394
A codet representing an assignment in the program.
Definition: std_code.h:24
codet representation of a label for branch targets.
Definition: std_code.h:959
A codet representing a skip statement.
Definition: std_code.h:322
Base type of functions.
Definition: std_types.h:583
const typet & return_type() const
Definition: std_types.h:689
const parameterst & parameters() const
Definition: std_types.h:699
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
Base class for all expressions.
Definition: expr.h:56
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
std::size_t unload(const irep_idt &name)
Remove the function named name from the function map, if it exists.
Definition: goto_model.h:72
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:57
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:412
const irep_idt & id() const
Definition: irep.h:388
bool is_nil() const
Definition: irep.h:368
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:94
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:148
A side_effect_exprt representation of a function call side effect.
Definition: std_code.h:1692
bool is_incomplete() const
A struct/union may be incomplete.
Definition: std_types.h:185
The symbol table base class interface.
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
const symbolst & symbols
Read-only field, used to look up symbols given their names.
const symbolt & lookup_ref(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
Symbol table entry.
Definition: symbol.h:28
bool is_extern
Definition: symbol.h:74
bool is_macro
Definition: symbol.h:62
bool is_static_lifetime
Definition: symbol.h:70
bool is_type
Definition: symbol.h:61
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
typet type
Type of symbol.
Definition: symbol.h:31
exprt value
Initial value of symbol.
Definition: symbol.h:34
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
#define CPROVER_PREFIX
std::optional< exprt > nondet_initializer(const typet &type, const source_locationt &source_location, const namespacet &ns)
Create a non-deterministic value for type type, with all subtypes independently expanded as non-deter...
std::optional< exprt > zero_initializer(const typet &type, const source_locationt &source_location, const namespacet &ns)
Create the equivalent of zero for type type.
Expression Initialization.
void goto_convert(const codet &code, symbol_table_baset &symbol_table, goto_programt &dest, message_handlert &message_handler, const irep_idt &mode)
Goto Programs with Functions.
Symbol Table + CFG.
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
static std::unordered_set< irep_idt > init_symbol(const symbolt &sym, code_blockt &code_block, symbol_table_baset &symbol_table, const source_locationt &source_location, bool assume_init_pointers_not_null, const java_object_factory_parameterst &object_factory_parameters, const select_pointer_typet &pointer_type_selector, bool string_refinement_enabled, message_handlert &message_handler)
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
static std::optional< codet > static_lifetime_init(const irep_idt &identifier, symbol_table_baset &symbol_table)
void recreate_initialize_function(goto_modelt &goto_model, message_handlert &message_handler)
Regenerates the CPROVER_INITIALIZE function, which initializes all non-function symbols of the goto m...
#define INITIALIZE_FUNCTION
const code_blockt & to_code_block(const codet &code)
Definition: std_code.h:203
const codet & to_code(const exprt &expr)
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:788
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:888
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:518
Author: Diffblue Ltd.
#define size_type
Definition: unistd.c:347