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.h>
18 
19 #include <set>
20 
21 static optionalt<codet>
22 static_lifetime_init(const irep_idt &identifier, symbol_tablet &symbol_table)
23 {
24  const namespacet ns(symbol_table);
25  const symbolt &symbol = ns.lookup(identifier);
26 
27  if(!symbol.is_static_lifetime)
28  return {};
29 
30  if(symbol.is_type || symbol.is_macro)
31  return {};
32 
33  // special values
34  if(
35  identifier == CPROVER_PREFIX "constant_infinity_uint" ||
36  identifier == CPROVER_PREFIX "memory" || identifier == "__func__" ||
37  identifier == "__FUNCTION__" || identifier == "__PRETTY_FUNCTION__" ||
38  identifier == "argc'" || identifier == "argv'" || identifier == "envp'" ||
39  identifier == "envp_size'")
40  return {};
41 
42  // just for linking
43  if(has_prefix(id2string(identifier), CPROVER_PREFIX "architecture_"))
44  return {};
45 
46  const typet &type = ns.follow(symbol.type);
47 
48  // check type
49  if(type.id() == ID_code || type.id() == ID_empty)
50  return {};
51 
52  if(type.id() == ID_array && to_array_type(type).size().is_nil())
53  {
54  // C standard 6.9.2, paragraph 5
55  // adjust the type to an array of size 1
56  symbolt &writable_symbol = symbol_table.get_writeable_ref(identifier);
57  writable_symbol.type = type;
58  writable_symbol.type.set(ID_size, from_integer(1, size_type()));
59  }
60 
61  if(
62  (type.id() == ID_struct || type.id() == ID_union) &&
63  to_struct_union_type(type).is_incomplete())
64  {
65  return {}; // do not initialize
66  }
67 
68  exprt rhs;
69 
70  if((symbol.value.is_nil() && symbol.is_extern) ||
71  symbol.value.id() == ID_nondet)
72  {
73  if(symbol.value.get_bool(ID_C_no_nondet_initialization))
74  return {};
75 
76  // Nondet initialise if not linked, or if explicitly requested.
77  // Compilers would usually complain about the unlinked symbol case.
78  const auto nondet = nondet_initializer(symbol.type, symbol.location, ns);
79  CHECK_RETURN(nondet.has_value());
80  rhs = *nondet;
81  }
82  else if(symbol.value.is_nil())
83  {
84  const auto zero = zero_initializer(symbol.type, symbol.location, ns);
85  CHECK_RETURN(zero.has_value());
86  rhs = *zero;
87  }
88  else
89  rhs = symbol.value;
90 
91  return code_frontend_assignt{symbol.symbol_expr(), rhs, symbol.location};
92 }
93 
95  symbol_tablet &symbol_table,
96  const source_locationt &source_location)
97 {
99 
100  const namespacet ns(symbol_table);
101 
103 
104  init_symbol.value=code_blockt();
105  init_symbol.value.add_source_location()=source_location;
106 
108 
109  // add the magic label to hide
110  dest.add(code_labelt(CPROVER_PREFIX "HIDE", code_skipt()));
111 
112  // do assignments based on "value"
113 
114  // sort alphabetically for reproducible results
115  std::set<std::string> symbols;
116 
117  for(const auto &symbol_pair : symbol_table.symbols)
118  {
119  symbols.insert(id2string(symbol_pair.first));
120  }
121 
122  // first do framework variables
123  for(const std::string &id : symbols)
124  if(has_prefix(id, CPROVER_PREFIX))
125  {
126  auto code = static_lifetime_init(id, symbol_table);
127  if(code.has_value())
128  dest.add(std::move(*code));
129  }
130 
131  // now all other variables
132  for(const std::string &id : symbols)
133  if(!has_prefix(id, CPROVER_PREFIX))
134  {
135  auto code = static_lifetime_init(id, symbol_table);
136  if(code.has_value())
137  dest.add(std::move(*code));
138  }
139 
140  // now call designated "initialization" functions
141 
142  for(const std::string &id : symbols)
143  {
144  const symbolt &symbol=ns.lookup(id);
145 
146  if(symbol.type.id() != ID_code)
147  continue;
148 
149  const code_typet &code_type = to_code_type(symbol.type);
150  if(
151  code_type.return_type().id() == ID_constructor &&
152  code_type.parameters().empty())
153  {
155  symbol.symbol_expr(), {}, code_type.return_type(), source_location}});
156  }
157  }
158 }
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
symbol_tablet
The symbol table.
Definition: symbol_table.h:13
arith_tools.h
symbolt::is_macro
bool is_macro
Definition: symbol.h:61
to_struct_union_type
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition: std_types.h:214
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
typet
The type of an expression, extends irept.
Definition: type.h:28
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
side_effect_expr_function_callt
A side_effect_exprt representation of a function call side effect.
Definition: std_code.h:1691
prefix.h
nondet_initializer
optionalt< 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...
Definition: expr_initializer.cpp:312
exprt
Base class for all expressions.
Definition: expr.h:55
namespace.h
zero_initializer
optionalt< exprt > zero_initializer(const typet &type, const source_locationt &source_location, const namespacet &ns)
Create the equivalent of zero for type type.
Definition: expr_initializer.cpp:297
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
to_code
const codet & to_code(const exprt &expr)
Definition: std_code_base.h:104
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:138
init_symbol
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)
Definition: java_entry_point.cpp:109
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
expr_initializer.h
has_prefix
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
symbol_table_baset::get_writeable_ref
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
Definition: symbol_table_base.h:121
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
irept::set
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:420
code_labelt
codet representation of a label for branch targets.
Definition: std_code.h:958
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
symbolt::symbol_expr
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
INITIALIZE_FUNCTION
#define INITIALIZE_FUNCTION
Definition: static_lifetime_init.h:22
code_frontend_assignt
A codet representing an assignment in the program.
Definition: std_code.h:23
code_typet
Base type of functions.
Definition: std_types.h:538
irept::is_nil
bool is_nil() const
Definition: irep.h:376
irept::id
const irep_idt & id() const
Definition: irep.h:396
code_blockt::add
void add(const codet &code)
Definition: std_code.h:168
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:655
std_code.h
optionalt
nonstd::optional< T > optionalt
Definition: optional.h:35
source_locationt
Definition: source_location.h:18
symbolt::value
exprt value
Initial value of symbol.
Definition: symbol.h:34
code_skipt
A codet representing a skip statement.
Definition: std_code.h:321
symbolt::is_extern
bool is_extern
Definition: symbol.h:66
namespace_baset::follow
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:49
symbolt::location
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
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
static_lifetime_init
static optionalt< codet > static_lifetime_init(const irep_idt &identifier, symbol_tablet &symbol_table)
Definition: static_lifetime_init.cpp:22
symbol_table_baset::symbols
const symbolst & symbols
Read-only field, used to look up symbols given their names.
Definition: symbol_table_base.h:30
symbolt::is_type
bool is_type
Definition: symbol.h:61
CPROVER_PREFIX
#define CPROVER_PREFIX
Definition: cprover_prefix.h:14
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
symbolt::is_static_lifetime
bool is_static_lifetime
Definition: symbol.h:65
code_typet::return_type
const typet & return_type() const
Definition: std_types.h:645
to_code_block
const code_blockt & to_code_block(const codet &code)
Definition: std_code.h:203
static_lifetime_init.h
symbol_table.h
Author: Diffblue Ltd.
size_type
unsignedbv_typet size_type()
Definition: c_types.cpp:68
c_types.h
irept::get_bool
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:58
code_expressiont
codet representation of an expression statement.
Definition: std_code.h:1393