CBMC
cpp_typecheck.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: C++ Language Type Checking
4 
5 Author: Daniel Kroening, kroening@cs.cmu.edu
6 
7 \*******************************************************************/
8 
11 
12 #include "cpp_typecheck.h"
13 
14 #include <algorithm>
15 
16 #include <util/pointer_expr.h>
17 #include <util/source_location.h>
18 #include <util/symbol.h>
19 
20 #include <ansi-c/builtin_factory.h>
21 
22 #include "cpp_declarator.h"
23 #include "cpp_util.h"
24 #include "expr2cpp.h"
25 
27 {
28  if(item.is_declaration())
30  else if(item.is_linkage_spec())
31  convert(item.get_linkage_spec());
32  else if(item.is_namespace_spec())
34  else if(item.is_using())
35  convert(item.get_using());
36  else if(item.is_static_assert())
37  convert(item.get_static_assert());
38  else
39  {
41  error() << "unknown parse-tree element: " << item.id() << eom;
42  throw 0;
43  }
44 }
45 
48 {
49  // default linkage is "automatic"
50  current_linkage_spec=ID_auto;
51 
52  for(auto &item : cpp_parse_tree.items)
53  convert(item);
54 
56 
58 
60 
61  clean_up();
62 }
63 
65 {
66  const exprt &this_expr=
68 
69  assert(this_expr.is_not_nil());
70  assert(this_expr.type().id()==ID_pointer);
71 
72  const typet &t = follow(to_pointer_type(this_expr.type()).base_type());
73  assert(t.id()==ID_struct);
74  return to_struct_type(t);
75 }
76 
77 std::string cpp_typecheckt::to_string(const exprt &expr)
78 {
79  return expr2cpp(expr, *this);
80 }
81 
82 std::string cpp_typecheckt::to_string(const typet &type)
83 {
84  return type2cpp(type, *this);
85 }
86 
88  cpp_parse_treet &cpp_parse_tree,
89  symbol_tablet &symbol_table,
90  const std::string &module,
91  message_handlert &message_handler)
92 {
94  cpp_parse_tree, symbol_table, module, message_handler);
95  return cpp_typecheck.typecheck_main();
96 }
97 
99  exprt &expr,
100  message_handlert &message_handler,
101  const namespacet &ns)
102 {
103  const unsigned errors_before=
104  message_handler.get_message_count(messaget::M_ERROR);
105 
106  symbol_tablet symbol_table;
107  cpp_parse_treet cpp_parse_tree;
108 
109  cpp_typecheckt cpp_typecheck(cpp_parse_tree, symbol_table,
110  ns.get_symbol_table(), "", message_handler);
111 
112  try
113  {
114  cpp_typecheck.typecheck_expr(expr);
115  }
116 
117  catch(int)
118  {
119  cpp_typecheck.error();
120  }
121 
122  catch(const char *e)
123  {
124  cpp_typecheck.error() << e << messaget::eom;
125  }
126 
127  catch(const std::string &e)
128  {
129  cpp_typecheck.error() << e << messaget::eom;
130  }
131 
132  catch(const invalid_source_file_exceptiont &e)
133  {
134  cpp_typecheck.error().source_location = e.get_source_location();
135  cpp_typecheck.error() << e.get_reason() << messaget::eom;
136  }
137 
138  return message_handler.get_message_count(messaget::M_ERROR)!=errors_before;
139 }
140 
156 {
157  code_blockt init_block; // Dynamic Initialization Block
158 
159  disable_access_control = true;
160 
161  for(const irep_idt &d_it : dynamic_initializations)
162  {
163  const symbolt &symbol = symbol_table.lookup_ref(d_it);
164 
165  if(symbol.is_extern)
166  continue;
167 
168  // PODs are always statically initialized
169  if(cpp_is_pod(symbol.type))
170  continue;
171 
172  assert(symbol.is_static_lifetime);
173  assert(!symbol.is_type);
174  assert(symbol.type.id()!=ID_code);
175 
176  exprt symbol_expr=cpp_symbol_expr(symbol);
177 
178  // initializer given?
179  if(symbol.value.is_not_nil())
180  {
181  // This will be a constructor call,
182  // which we execute.
183  init_block.add(to_code(symbol.value));
184 
185  // Make it nil to get zero initialization by
186  // __CPROVER_initialize
188  }
189  else
190  {
191  // use default constructor
192  exprt::operandst ops;
193 
194  auto call = cpp_constructor(symbol.location, symbol_expr, ops);
195 
196  if(call.has_value())
197  init_block.add(call.value());
198  }
199  }
200 
201  dynamic_initializations.clear();
202 
203  // Create the dynamic initialization procedure
205 
206  init_symbol.name="#cpp_dynamic_initialization#"+id2string(module);
207  init_symbol.base_name="#cpp_dynamic_initialization#"+id2string(module);
208  init_symbol.value.swap(init_block);
209  init_symbol.mode=ID_cpp;
210  init_symbol.module=module;
211  init_symbol.type = code_typet({}, typet(ID_constructor));
212  init_symbol.is_type=false;
213  init_symbol.is_macro=false;
214 
215  symbol_table.insert(std::move(init_symbol));
216 
218 }
219 
221 {
222  bool cont;
223 
224  do
225  {
226  cont = false;
227 
228  for(const auto &named_symbol : symbol_table.symbols)
229  {
230  const symbolt &symbol=named_symbol.second;
231 
232  if(
233  symbol.value.id() == ID_cpp_not_typechecked &&
234  symbol.value.get_bool(ID_is_used))
235  {
236  assert(symbol.type.id()==ID_code);
237  exprt value = symbol.value;
238 
239  if(symbol.base_name=="operator=")
240  {
241  cpp_declaratort declarator;
242  declarator.add_source_location() = symbol.location;
244  lookup(symbol.type.get(ID_C_member_name)), declarator);
245  value.swap(declarator.value());
246  cont=true;
247  }
248  else if(symbol.value.operands().size()==1)
249  {
250  value = to_unary_expr(symbol.value).op();
251  cont=true;
252  }
253  else
254  UNREACHABLE; // Don't know what to do!
255 
256  symbolt &writable_symbol =
257  symbol_table.get_writeable_ref(named_symbol.first);
258  writable_symbol.value.swap(value);
259  convert_function(writable_symbol);
260  }
261  }
262  }
263  while(cont);
264 
265  for(const auto &named_symbol : symbol_table.symbols)
266  {
267  if(named_symbol.second.value.id() == ID_cpp_not_typechecked)
268  symbol_table.get_writeable_ref(named_symbol.first).value.make_nil();
269  }
270 }
271 
273 {
274  symbol_tablet::symbolst::const_iterator it=symbol_table.symbols.begin();
275 
276  while(it!=symbol_table.symbols.end())
277  {
278  symbol_tablet::symbolst::const_iterator cur_it = it;
279  it++;
280 
281  const symbolt &symbol=cur_it->second;
282 
283  // erase templates and all member functions that have not been converted
284  if(
285  symbol.type.get_bool(ID_is_template) ||
286  deferred_typechecking.find(symbol.name) != deferred_typechecking.end())
287  {
288  symbol_table.erase(cur_it);
289  continue;
290  }
291  else if(symbol.type.id()==ID_struct ||
292  symbol.type.id()==ID_union)
293  {
294  // remove methods from 'components'
295  struct_union_typet &struct_union_type=to_struct_union_type(
296  symbol_table.get_writeable_ref(cur_it->first).type);
297 
298  const struct_union_typet::componentst &components=
299  struct_union_type.components();
300 
301  struct_union_typet::componentst data_members;
302  data_members.reserve(components.size());
303 
304  struct_union_typet::componentst &function_members=
306  (struct_union_type.add(ID_methods).get_sub());
307 
308  function_members.reserve(components.size());
309 
310  for(const auto &compo_it : components)
311  {
312  if(compo_it.get_bool(ID_is_static) ||
313  compo_it.get_bool(ID_is_type))
314  {
315  // skip it
316  }
317  else if(compo_it.type().id()==ID_code)
318  {
319  function_members.push_back(compo_it);
320  }
321  else
322  {
323  data_members.push_back(compo_it);
324  }
325  }
326 
327  struct_union_type.components().swap(data_members);
328  }
329  }
330 }
331 
333 {
335 }
336 
338 {
339  if(expr.id() == ID_cpp_name || expr.id() == ID_cpp_declaration)
340  return true;
341 
342  for(const exprt &op : expr.operands())
343  {
344  if(contains_cpp_name(op))
345  return true;
346  }
347  return false;
348 }
cpp_typecheckt::convert
void convert(cpp_linkage_spect &)
Definition: cpp_typecheck_linkage_spec.cpp:14
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:147
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
to_unary_expr
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition: std_expr.h:361
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
cpp_parse_treet
Definition: cpp_parse_tree.h:19
cpp_typecheckt::convert_function
void convert_function(symbolt &symbol)
Definition: cpp_typecheck_function.cpp:82
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
cpp_typecheckt::typecheck_method_bodies
void typecheck_method_bodies()
Definition: cpp_typecheck_method_bodies.cpp:18
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
cpp_typecheckt::cpp_scopes
cpp_scopest cpp_scopes
Definition: cpp_typecheck.h:104
cpp_idt::this_expr
exprt this_expr
Definition: cpp_id.h:76
irept::make_nil
void make_nil()
Definition: irep.h:454
typet
The type of an expression, extends irept.
Definition: type.h:28
cpp_typecheckt::this_struct_type
const struct_typet & this_struct_type()
Definition: cpp_typecheck.cpp:64
to_cpp_declaration
cpp_declarationt & to_cpp_declaration(irept &irep)
Definition: cpp_declaration.h:146
struct_union_typet
Base type for structs and unions.
Definition: std_types.h:61
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
cpp_typecheckt::clean_up
void clean_up()
Definition: cpp_typecheck.cpp:272
builtin_factory
bool builtin_factory(const irep_idt &identifier, symbol_tablet &symbol_table, message_handlert &mh)
Check whether given identifier is a compiler built-in.
Definition: builtin_factory.cpp:97
cpp_typecheckt::builtin_factory
bool builtin_factory(const irep_idt &)
Definition: cpp_typecheck.cpp:332
cpp_typecheckt::default_assignop_value
void default_assignop_value(const symbolt &symbol, cpp_declaratort &declarator)
Generate code for the implicit default assignment operator.
Definition: cpp_typecheck_constructor.cpp:347
cpp_typecheckt::current_linkage_spec
irep_idt current_linkage_spec
Definition: cpp_typecheck.h:107
exprt
Base class for all expressions.
Definition: expr.h:55
struct_union_typet::componentst
std::vector< componentt > componentst
Definition: std_types.h:140
cpp_typecheckt::cpp_constructor
optionalt< codet > cpp_constructor(const source_locationt &source_location, const exprt &object, const exprt::operandst &operands)
Definition: cpp_constructor.cpp:22
symbolt::base_name
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
invalid_source_file_exceptiont
Thrown when we can't handle something in an input source file.
Definition: exception_utils.h:171
expr2cpp.h
messaget::eom
static eomt eom
Definition: message.h:297
expr2cpp
std::string expr2cpp(const exprt &expr, const namespacet &ns)
Definition: expr2cpp.cpp:495
cpp_typecheckt::static_and_dynamic_initialization
void static_and_dynamic_initialization()
Initialization of static objects:
Definition: cpp_typecheck.cpp:155
cpp_typecheckt::contains_cpp_name
bool contains_cpp_name(const exprt &)
Definition: cpp_typecheck.cpp:337
invalid_source_file_exceptiont::get_source_location
const source_locationt & get_source_location() const
Definition: exception_utils.h:184
cpp_itemt::source_location
const source_locationt & source_location() const
Definition: cpp_item.h:143
cpp_typecheck
bool cpp_typecheck(cpp_parse_treet &cpp_parse_tree, symbol_tablet &symbol_table, const std::string &module, message_handlert &message_handler)
Definition: cpp_typecheck.cpp:87
irept::get
const irep_idt & get(const irep_idt &name) const
Definition: irep.cpp:45
cpp_itemt::get_linkage_spec
cpp_linkage_spect & get_linkage_spec()
Definition: cpp_item.h:57
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
cpp_typecheckt::cpp_is_pod
bool cpp_is_pod(const typet &type) const
Definition: cpp_is_pod.cpp:16
to_code
const codet & to_code(const exprt &expr)
Definition: std_code_base.h:104
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:138
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
c_typecheck_baset::module
const irep_idt module
Definition: c_typecheck_base.h:69
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
messaget::error
mstreamt & error() const
Definition: message.h:399
cpp_itemt::get_using
cpp_usingt & get_using()
Definition: cpp_item.h:107
cpp_itemt::is_linkage_spec
bool is_linkage_spec() const
Definition: cpp_item.h:69
cpp_util.h
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
cpp_scopest::current_scope
cpp_scopet & current_scope()
Definition: cpp_scopes.h:32
messaget::mstreamt::source_location
source_locationt source_location
Definition: message.h:247
type2cpp
std::string type2cpp(const typet &type, const namespacet &ns)
Definition: expr2cpp.cpp:502
cpp_symbol_expr
symbol_exprt cpp_symbol_expr(const symbolt &symbol)
Definition: cpp_util.cpp:14
pointer_expr.h
messaget::M_ERROR
@ M_ERROR
Definition: message.h:170
to_pointer_type
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:79
source_location.h
symbol_tablet::insert
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
Definition: symbol_table.cpp:17
c_typecheck_baset::symbol_table
symbol_tablet & symbol_table
Definition: c_typecheck_base.h:68
cpp_typecheckt::deferred_typechecking
std::unordered_set< irep_idt > deferred_typechecking
Definition: cpp_typecheck.h:590
irept::swap
void swap(irept &irep)
Definition: irep.h:442
code_typet
Base type of functions.
Definition: std_types.h:538
cpp_typecheckt
Definition: cpp_typecheck.h:39
symbol.h
Symbol table entry.
irept::id
const irep_idt & id() const
Definition: irep.h:396
message_handlert
Definition: message.h:27
cpp_typecheckt::cpp_parse_tree
cpp_parse_treet & cpp_parse_tree
Definition: cpp_typecheck.h:106
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
code_blockt::add
void add(const codet &code)
Definition: std_code.h:168
unary_exprt::op
const exprt & op() const
Definition: std_expr.h:326
cpp_declarator.h
cpp_itemt::is_static_assert
bool is_static_assert() const
Definition: cpp_item.h:138
cpp_typecheck.h
builtin_factory.h
cpp_itemt::is_using
bool is_using() const
Definition: cpp_item.h:119
symbolt::value
exprt value
Initial value of symbol.
Definition: symbol.h:34
messaget::get_message_handler
message_handlert & get_message_handler()
Definition: message.h:184
namespacet::get_symbol_table
const symbol_table_baset & get_symbol_table() const
Return first symbol table registered with the namespace.
Definition: namespace.h:123
struct_typet
Structure type, corresponds to C style structs.
Definition: std_types.h:230
irept::add
irept & add(const irep_idt &name)
Definition: irep.cpp:116
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
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
pointer_typet::base_type
const typet & base_type() const
The type of the data what we point to.
Definition: pointer_expr.h:35
cpp_typecheckt::do_not_typechecked
void do_not_typechecked()
Definition: cpp_typecheck.cpp:220
irept::get_sub
subt & get_sub()
Definition: irep.h:456
symbolt::is_static_lifetime
bool is_static_lifetime
Definition: symbol.h:65
cpp_itemt::is_namespace_spec
bool is_namespace_spec() const
Definition: cpp_item.h:94
cpp_declaratort::value
exprt & value()
Definition: cpp_declarator.h:42
invalid_source_file_exceptiont::get_reason
const std::string & get_reason() const
Definition: exception_utils.h:179
cpp_itemt::get_static_assert
cpp_static_assertt & get_static_assert()
Definition: cpp_item.h:132
symbol_tablet::erase
virtual void erase(const symbolst::const_iterator &entry) override
Remove a symbol from the symbol table.
Definition: symbol_table.cpp:90
cpp_typecheckt::to_string
std::string to_string(const typet &) override
Definition: cpp_typecheck.cpp:82
exprt::operands
operandst & operands()
Definition: expr.h:94
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:216
cpp_itemt::get_namespace_spec
cpp_namespace_spect & get_namespace_spec()
Definition: cpp_item.h:82
cpp_typecheckt::dynamic_initializations
dynamic_initializationst dynamic_initializations
Definition: cpp_typecheck.h:588
cpp_typecheckt::disable_access_control
bool disable_access_control
Definition: cpp_typecheck.h:589
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
cpp_parse_treet::items
itemst items
Definition: cpp_parse_tree.h:25
irept::get_bool
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:58
cpp_itemt
Definition: cpp_item.h:21
cpp_declaratort
Definition: cpp_declarator.h:19
message_handlert::get_message_count
std::size_t get_message_count(unsigned level) const
Definition: message.h:56
cpp_typecheckt::typecheck
void typecheck() override
typechecking main method
Definition: cpp_typecheck.cpp:47
cpp_itemt::is_declaration
bool is_declaration() const
Definition: cpp_item.h:44