cprover
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/arith_tools.h>
17 #include <util/expr_initializer.h>
18 #include <util/source_location.h>
19 #include <util/symbol.h>
20 
21 #include <ansi-c/builtin_factory.h>
22 #include <ansi-c/c_typecast.h>
23 
24 #include "expr2cpp.h"
25 #include "cpp_convert_type.h"
26 #include "cpp_declarator.h"
27 
29 {
30  if(item.is_declaration())
32  else if(item.is_linkage_spec())
33  convert(item.get_linkage_spec());
34  else if(item.is_namespace_spec())
36  else if(item.is_using())
37  convert(item.get_using());
38  else if(item.is_static_assert())
39  convert(item.get_static_assert());
40  else
41  {
43  error() << "unknown parse-tree element: " << item.id() << eom;
44  throw 0;
45  }
46 }
47 
50 {
51  // default linkage is "automatic"
52  current_linkage_spec=ID_auto;
53 
54  for(auto &item : cpp_parse_tree.items)
55  convert(item);
56 
58 
60 
62 
63  clean_up();
64 }
65 
67 {
68  const exprt &this_expr=
70 
71  assert(this_expr.is_not_nil());
72  assert(this_expr.type().id()==ID_pointer);
73 
74  const typet &t=follow(this_expr.type().subtype());
75  assert(t.id()==ID_struct);
76  return to_struct_type(t);
77 }
78 
79 std::string cpp_typecheckt::to_string(const exprt &expr)
80 {
81  return expr2cpp(expr, *this);
82 }
83 
84 std::string cpp_typecheckt::to_string(const typet &type)
85 {
86  return type2cpp(type, *this);
87 }
88 
90  cpp_parse_treet &cpp_parse_tree,
91  symbol_tablet &symbol_table,
92  const std::string &module,
94 {
96  cpp_parse_tree, symbol_table, module, message_handler);
97  return cpp_typecheck.typecheck_main();
98 }
99 
101  exprt &expr,
103  const namespacet &ns)
104 {
105  const unsigned errors_before=
106  message_handler.get_message_count(messaget::M_ERROR);
107 
108  symbol_tablet symbol_table;
109  cpp_parse_treet cpp_parse_tree;
110 
111  cpp_typecheckt cpp_typecheck(cpp_parse_tree, symbol_table,
113 
114  try
115  {
116  cpp_typecheck.typecheck_expr(expr);
117  }
118 
119  catch(int)
120  {
121  cpp_typecheck.error();
122  }
123 
124  catch(const char *e)
125  {
126  cpp_typecheck.error() << e << messaget::eom;
127  }
128 
129  catch(const std::string &e)
130  {
131  cpp_typecheck.error() << e << messaget::eom;
132  }
133 
134  return message_handler.get_message_count(messaget::M_ERROR)!=errors_before;
135 }
136 
152 {
153  code_blockt init_block; // Dynamic Initialization Block
154 
155  disable_access_control = true;
156 
157  for(const irep_idt &d_it : dynamic_initializations)
158  {
159  const symbolt &symbol=*symbol_table.lookup(d_it);
160 
161  if(symbol.is_extern)
162  continue;
163 
164  // PODs are always statically initialized
165  if(cpp_is_pod(symbol.type))
166  continue;
167 
168  assert(symbol.is_static_lifetime);
169  assert(!symbol.is_type);
170  assert(symbol.type.id()!=ID_code);
171 
172  exprt symbol_expr=cpp_symbol_expr(symbol);
173 
174  // initializer given?
175  if(symbol.value.is_not_nil())
176  {
177  // This will be a constructor call,
178  // which we execute.
179  assert(symbol.value.id()==ID_code);
180  init_block.copy_to_operands(symbol.value);
181 
182  // Make it nil to get zero initialization by
183  // __CPROVER_initialize
185  }
186  else
187  {
188  // use default constructor
189  exprt::operandst ops;
190 
191  codet call=
192  cpp_constructor(symbol.location, symbol_expr, ops);
193 
194  if(call.is_not_nil())
195  init_block.move_to_operands(call);
196  }
197  }
198 
199  dynamic_initializations.clear();
200 
201  // block_sini.move_to_operands(block_dini);
202 
203  // Create the dynamic initialization procedure
204  symbolt init_symbol;
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();
212  init_symbol.type.add(ID_return_type)=typet(ID_constructor);
213  init_symbol.is_type=false;
214  init_symbol.is_macro=false;
215 
216  symbol_table.insert(std::move(init_symbol));
217 
219 }
220 
222 {
223  bool cont;
224 
225  do
226  {
227  cont = false;
228 
229  for(const auto &named_symbol : symbol_table.symbols)
230  {
231  const symbolt &symbol=named_symbol.second;
232 
233  if(symbol.value.id()=="cpp_not_typechecked" &&
234  symbol.value.get_bool("is_used"))
235  {
236  assert(symbol.type.id()==ID_code);
237  symbolt &symbol=*symbol_table.get_writeable(named_symbol.first);
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  symbol.value.swap(declarator.value());
246  convert_function(symbol);
247  cont=true;
248  }
249  else if(symbol.value.operands().size()==1)
250  {
251  exprt tmp = symbol.value.op0();
252  symbol.value.swap(tmp);
253  convert_function(symbol);
254  cont=true;
255  }
256  else
257  UNREACHABLE; // Don't know what to do!
258  }
259  }
260  }
261  while(cont);
262 
263  for(const auto &named_symbol : symbol_table.symbols)
264  {
265  if(named_symbol.second.value.id()=="cpp_not_typechecked")
266  symbol_table.get_writeable_ref(named_symbol.first).value.make_nil();
267  }
268 }
269 
271 {
272  symbol_tablet::symbolst::const_iterator it=symbol_table.symbols.begin();
273 
274  while(it!=symbol_table.symbols.end())
275  {
276  symbol_tablet::symbolst::const_iterator cur_it = it;
277  it++;
278 
279  const symbolt &symbol=cur_it->second;
280 
281  // erase templates
282  if(symbol.type.get_bool(ID_is_template) ||
283  // Remove all symbols that have not been converted.
284  // In particular this includes symbols created for functions
285  // during template instantiation that are never called,
286  // and hence, their bodies have not been converted.
287  contains_cpp_name(symbol.value))
288  {
289  symbol_table.erase(cur_it);
290  continue;
291  }
292  else if(symbol.type.id()==ID_struct ||
293  symbol.type.id()==ID_union)
294  {
295  // remove methods from 'components'
296  struct_union_typet &struct_union_type=to_struct_union_type(
297  symbol_table.get_writeable_ref(cur_it->first).type);
298 
299  const struct_union_typet::componentst &components=
300  struct_union_type.components();
301 
302  struct_union_typet::componentst data_members;
303  data_members.reserve(components.size());
304 
305  struct_union_typet::componentst &function_members=
307  (struct_union_type.add(ID_methods).get_sub());
308 
309  function_members.reserve(components.size());
310 
311  for(const auto &compo_it : components)
312  {
313  if(compo_it.get_bool(ID_is_static) ||
314  compo_it.get_bool(ID_is_type))
315  {
316  // skip it
317  }
318  else if(compo_it.type().id()==ID_code)
319  {
320  function_members.push_back(compo_it);
321  }
322  else
323  {
324  data_members.push_back(compo_it);
325  }
326  }
327 
328  struct_union_type.components().swap(data_members);
329  }
330  }
331 }
332 
334 {
336 }
337 
339 {
340  if(expr.id() == ID_cpp_name || expr.id() == ID_cpp_declaration)
341  return true;
342  forall_operands(it, expr)
343  if(contains_cpp_name(*it))
344  return true;
345  return false;
346 }
The type of an expression.
Definition: type.h:22
irep_idt name
The unique identifier.
Definition: symbol.h:43
void convert_function(symbolt &symbol)
bool is_using() const
Definition: cpp_item.h:121
Base type of functions.
Definition: std_types.h:764
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
bool is_not_nil() const
Definition: irep.h:173
Symbol table entry.
cpp_usingt & get_using()
Definition: cpp_item.h:109
const symbol_tablet & get_symbol_table() const
Definition: namespace.h:106
exprt & op0()
Definition: expr.h:72
bool contains_cpp_name(const exprt &expr)
irep_idt mode
Language mode.
Definition: symbol.h:52
bool is_static_assert() const
Definition: cpp_item.h:140
void copy_to_operands(const exprt &expr)
Definition: expr.cpp:55
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
std::vector< componentt > componentst
Definition: std_types.h:243
void move_to_operands(exprt &expr)
Definition: expr.cpp:22
exprt value
Initial value of symbol.
Definition: symbol.h:37
const componentst & components() const
Definition: std_types.h:245
void static_and_dynamic_initialization()
Initialization of static objects:
irep_idt module
Name of module the symbol belongs to.
Definition: symbol.h:46
typet & type()
Definition: expr.h:56
bool cpp_typecheck(cpp_parse_treet &cpp_parse_tree, symbol_tablet &symbol_table, const std::string &module, message_handlert &message_handler)
Symbol table entry.This is a symbol in the symbol table, stored in an object of type symbol_tablet...
Definition: symbol.h:30
static mstreamt & eom(mstreamt &m)
Definition: message.h:272
Structure type.
Definition: std_types.h:297
bool get_bool(const irep_namet &name) const
Definition: irep.cpp:240
C++ Language Type Checking.
bool is_static_lifetime
Definition: symbol.h:67
subt & get_sub()
Definition: irep.h:317
void convert(cpp_linkage_spect &)
bool builtin_factory(const irep_idt &identifier, symbol_tablet &symbol_table, message_handlert &mh)
Check whether given identifier is a compiler built-in.
symbol_tablet & symbol_table
virtual symbolt * get_writeable(const irep_idt &name) override
Find a symbol in the symbol table for read-write access.
Definition: symbol_table.h:87
void default_assignop_value(const symbolt &symbol, cpp_declaratort &declarator)
Generate code for the implicit default assignment operator.
bool is_declaration() const
Definition: cpp_item.h:46
bool is_namespace_spec() const
Definition: cpp_item.h:96
Expression Initialization.
const irep_idt & id() const
Definition: irep.h:259
cpp_namespace_spect & get_namespace_spec()
Definition: cpp_item.h:84
virtual void typecheck()
typechecking main method
std::string expr2cpp(const exprt &expr, const namespacet &ns)
Definition: expr2cpp.cpp:504
source_locationt source_location
Definition: message.h:214
bool cpp_is_pod(const typet &type) const
Definition: cpp_is_pod.cpp:14
cpp_parse_treet & cpp_parse_tree
C++ Language Conversion.
cpp_static_assertt & get_static_assert()
Definition: cpp_item.h:134
The symbol table.
Definition: symbol_table.h:19
mstreamt & error() const
Definition: message.h:302
TO_BE_DOCUMENTED.
Definition: namespace.h:74
#define forall_operands(it, expr)
Definition: expr.h:17
C++ Language Type Checking.
const typet & follow(const typet &) const
Definition: namespace.cpp:55
const struct_typet & to_struct_type(const typet &type)
Cast a generic typet to a struct_typet.
Definition: std_types.h:318
dstringt has one field, an unsigned integer no which is an index into a static table of strings...
Definition: dstring.h:33
const symbolst & symbols
virtual void erase(const symbolst::const_iterator &entry) override
Remove a symbol from the symbol table.
std::vector< exprt > operandst
Definition: expr.h:45
exprt this_expr
Definition: cpp_id.h:77
bool is_extern
Definition: symbol.h:68
typet type
Type of symbol.
Definition: symbol.h:34
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:40
cpp_declarationt & to_cpp_declaration(irept &irep)
message_handlert & get_message_handler()
Definition: message.h:153
Base type of C structs and unions, and C++ classes.
Definition: std_types.h:162
bool builtin_factory(const irep_idt &)
void do_not_typechecked()
irep_idt current_linkage_spec
std::string type2cpp(const typet &type, const namespacet &ns)
Definition: expr2cpp.cpp:511
Base class for all expressions.
Definition: expr.h:42
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:49
cpp_scopet & current_scope()
Definition: cpp_scopes.h:33
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a generic typet to a struct_union_typet.
Definition: std_types.h:280
const source_locationt & source_location() const
Definition: cpp_item.h:145
#define UNREACHABLE
Definition: invariant.h:271
irept & add(const irep_namet &name)
Definition: irep.cpp:306
virtual std::string to_string(const typet &type)
cpp_linkage_spect & get_linkage_spec()
Definition: cpp_item.h:59
const irep_idt module
void make_nil()
Definition: irep.h:315
const struct_typet & this_struct_type()
dynamic_initializationst dynamic_initializations
bool disable_access_control
void swap(irept &irep)
Definition: irep.h:303
source_locationt & add_source_location()
Definition: expr.h:130
Sequential composition.
Definition: std_code.h:89
goto_programt coverage_criteriont message_handlert & message_handler
Definition: cover.cpp:66
A statement in a programming language.
Definition: std_code.h:21
exprt cpp_symbol_expr(const symbolt &symbol)
Definition: cpp_util.cpp:14
bool is_type
Definition: symbol.h:63
const typet & subtype() const
Definition: type.h:33
const symbolt * lookup(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
bool is_macro
Definition: symbol.h:63
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See namespace_baset::lookup().
Definition: namespace.cpp:136
codet cpp_constructor(const source_locationt &source_location, const exprt &object, const exprt::operandst &operands)
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
bool is_linkage_spec() const
Definition: cpp_item.h:71
cpp_scopest cpp_scopes