CBMC
nondet_static.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Nondeterministically initializes global scope variables, except for
4  constants (such as string literals, final fields) and internal variables
5  (such as CPROVER and symex variables, language specific internal
6  variables).
7 
8 Author: Daniel Kroening, Michael Tautschnig
9 
10 Date: November 2011
11 
12 \*******************************************************************/
13 
19 
20 #include "nondet_static.h"
21 
22 #include <util/prefix.h>
23 #include <util/std_code.h>
24 
26 
28 
29 #include <regex>
30 
37  const symbol_exprt &symbol_expr,
38  const namespacet &ns)
39 {
40  const irep_idt &id = symbol_expr.get_identifier();
41 
42  // is it a __CPROVER_* variable?
43  if(id.starts_with(CPROVER_PREFIX))
44  return false;
45 
46  // variable not in symbol table such as symex variable?
47  if(!ns.get_symbol_table().has_symbol(id))
48  return false;
49 
50  const symbolt &symbol = ns.lookup(id);
51 
52  // is the symbol explicitly marked as not to be nondet initialized?
53  if(symbol.value.get_bool(ID_C_no_nondet_initialization))
54  {
55  return false;
56  }
57 
58  // is the type explicitly marked as not to be nondet initialized?
59  if(symbol.type.get_bool(ID_C_no_nondet_initialization))
60  return false;
61 
62  // is the type explicitly marked as not to be initialized?
63  if(symbol.type.get_bool(ID_C_no_initialization_required))
64  return false;
65 
66  // static lifetime?
67  if(!symbol.is_static_lifetime)
68  return false;
69 
70  // constant?
71  return !is_constant_or_has_constant_components(symbol_expr.type(), ns) &&
73 }
74 
83 static void nondet_static(
84  const namespacet &ns,
85  goto_modelt &goto_model,
86  const irep_idt &fct_name)
87 {
88  goto_functionst::function_mapt::iterator fct_entry =
89  goto_model.goto_functions.function_map.find(fct_name);
90  CHECK_RETURN(fct_entry != goto_model.goto_functions.function_map.end());
91 
92  goto_programt &init = fct_entry->second.body;
93 
94  for(auto &instruction : init.instructions)
95  {
96  if(instruction.is_assign())
97  {
98  const symbol_exprt sym =
99  to_symbol_expr(as_const(instruction).assign_lhs());
100 
101  if(is_nondet_initializable_static(sym, ns))
102  {
104  sym.type(), instruction.source_location()};
105  instruction.assign_rhs_nonconst() = nondet;
107  nondet;
108  }
109  }
110  else if(instruction.is_function_call())
111  {
112  const symbol_exprt &fsym = to_symbol_expr(instruction.call_function());
113 
114  // see cpp/cpp_typecheck.cpp, which creates initialization functions
115  if(fsym.get_identifier().starts_with("#cpp_dynamic_initialization#"))
116  {
117  nondet_static(ns, goto_model, fsym.get_identifier());
118  }
119  }
120  }
121 
122  // update counters etc.
123  goto_model.goto_functions.update();
124 }
125 
131 void nondet_static(goto_modelt &goto_model)
132 {
133  const namespacet ns(goto_model.symbol_table);
134  nondet_static(ns, goto_model, INITIALIZE_FUNCTION);
135 }
136 
144  goto_modelt &goto_model,
145  const std::set<std::string> &except_values)
146 {
147  const namespacet ns(goto_model.symbol_table);
148  std::set<std::string> to_exclude;
149 
150  for(auto const &except : except_values)
151  {
152  const bool file_prefix_found = except.find(":") != std::string::npos;
153 
154  if(file_prefix_found)
155  {
156  to_exclude.insert(except);
157  if(has_prefix(except, "./"))
158  {
159  to_exclude.insert(except.substr(2, except.length() - 2));
160  }
161  else
162  {
163  to_exclude.insert("./" + except);
164  }
165  }
166  else
167  {
168  irep_idt symbol_name(except);
169  symbolt lookup_results = ns.lookup(symbol_name);
170  to_exclude.insert(
171  id2string(lookup_results.location.get_file()) + ":" + except);
172  }
173  }
174 
175  symbol_tablet &symbol_table = goto_model.symbol_table;
176 
177  for(symbol_tablet::iteratort symbol_it = symbol_table.begin();
178  symbol_it != symbol_table.end();
179  symbol_it++)
180  {
181  symbolt &symbol = symbol_it.get_writeable_symbol();
182  std::string qualified_name = id2string(symbol.location.get_file()) + ":" +
183  id2string(symbol.display_name());
184  if(to_exclude.find(qualified_name) != to_exclude.end())
185  {
186  symbol.value.set(ID_C_no_nondet_initialization, 1);
187  }
188  else if(is_nondet_initializable_static(symbol.symbol_expr(), ns))
189  {
190  symbol.value = side_effect_expr_nondett(symbol.type, symbol.location);
191  }
192  }
193 
194  nondet_static(ns, goto_model, INITIALIZE_FUNCTION);
195 }
196 
203 void nondet_static_matching(goto_modelt &goto_model, const std::string &regex)
204 {
205  const auto regex_matcher = std::regex(regex);
206  symbol_tablet &symbol_table = goto_model.symbol_table;
207 
208  for(symbol_tablet::iteratort symbol_it = symbol_table.begin();
209  symbol_it != symbol_table.end();
210  symbol_it++)
211  {
212  symbolt &symbol = symbol_it.get_writeable_symbol();
213  std::string qualified_name = id2string(symbol.location.get_file()) + ":" +
214  id2string(symbol.display_name());
215  if(!std::regex_match(qualified_name, regex_matcher))
216  {
217  symbol.value.set(ID_C_no_nondet_initialization, 1);
218  }
219  }
220 
221  const namespacet ns(goto_model.symbol_table);
222  nondet_static(ns, goto_model, INITIALIZE_FUNCTION);
223 }
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
Definition: as_const.h:14
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
typet & type()
Return the type of the expression.
Definition: expr.h:84
function_mapt function_map
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:73
instructionst instructions
The list of instructions in the goto program.
Definition: goto_program.h:622
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
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
const symbol_table_baset & get_symbol_table() const
Return first symbol table registered with the namespace.
Definition: namespace.h:126
A side_effect_exprt that returns a non-deterministically chosen value.
Definition: std_code.h:1520
const irep_idt & get_file() const
Expression to hold a symbol (variable)
Definition: std_expr.h:131
const irep_idt & get_identifier() const
Definition: std_expr.h:160
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
The symbol table.
Definition: symbol_table.h:14
virtual iteratort begin() override
Definition: symbol_table.h:108
virtual iteratort end() override
Definition: symbol_table.h:112
Symbol table entry.
Definition: symbol.h:28
const irep_idt & display_name() const
Return language specific display name if present.
Definition: symbol.h:55
bool is_static_lifetime
Definition: symbol.h:70
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
const source_locationt & source_location() const
Definition: type.h:72
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
#define CPROVER_PREFIX
Symbol Table + CFG.
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
void nondet_static_matching(goto_modelt &goto_model, const std::string &regex)
Nondeterministically initializes global scope variables that match the given regex.
bool is_nondet_initializable_static(const symbol_exprt &symbol_expr, const namespacet &ns)
See the return.
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.
Nondeterministically initializes global scope variables, except for constants (such as string literal...
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
#define INITIALIZE_FUNCTION
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:272
bool is_constant_or_has_constant_components(const typet &type, const namespacet &ns)
Identify whether a given type is constant itself or contains constant components.
Definition: std_types.cpp:197