cprover
Loading...
Searching...
No Matches
cpp_typecheck.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: C++ Language Type Checking
4
5Author: 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>
18#include <util/symbol.h>
19
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())
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())
38 else
39 {
41 error() << "unknown parse-tree element: " << item.id() << eom;
42 throw 0;
43 }
44}
45
48{
49 // default linkage is "automatic"
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
77std::string cpp_typecheckt::to_string(const exprt &expr)
78{
79 return expr2cpp(expr, *this);
80}
81
82std::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 return message_handler.get_message_count(messaget::M_ERROR)!=errors_before;
133}
134
150{
151 code_blockt init_block; // Dynamic Initialization Block
152
154
155 for(const irep_idt &d_it : dynamic_initializations)
156 {
157 const symbolt &symbol = symbol_table.lookup_ref(d_it);
158
159 if(symbol.is_extern)
160 continue;
161
162 // PODs are always statically initialized
163 if(cpp_is_pod(symbol.type))
164 continue;
165
166 assert(symbol.is_static_lifetime);
167 assert(!symbol.is_type);
168 assert(symbol.type.id()!=ID_code);
169
170 exprt symbol_expr=cpp_symbol_expr(symbol);
171
172 // initializer given?
173 if(symbol.value.is_not_nil())
174 {
175 // This will be a constructor call,
176 // which we execute.
177 init_block.add(to_code(symbol.value));
178
179 // Make it nil to get zero initialization by
180 // __CPROVER_initialize
182 }
183 else
184 {
185 // use default constructor
187
188 auto call = cpp_constructor(symbol.location, symbol_expr, ops);
189
190 if(call.has_value())
191 init_block.add(call.value());
192 }
193 }
194
196
197 // Create the dynamic initialization procedure
199
200 init_symbol.name="#cpp_dynamic_initialization#"+id2string(module);
201 init_symbol.base_name="#cpp_dynamic_initialization#"+id2string(module);
202 init_symbol.value.swap(init_block);
203 init_symbol.mode=ID_cpp;
204 init_symbol.module=module;
205 init_symbol.type = code_typet({}, typet(ID_constructor));
206 init_symbol.is_type=false;
207 init_symbol.is_macro=false;
208
209 symbol_table.insert(std::move(init_symbol));
210
212}
213
215{
216 bool cont;
217
218 do
219 {
220 cont = false;
221
222 for(const auto &named_symbol : symbol_table.symbols)
223 {
224 const symbolt &symbol=named_symbol.second;
225
226 if(
227 symbol.value.id() == ID_cpp_not_typechecked &&
228 symbol.value.get_bool(ID_is_used))
229 {
230 assert(symbol.type.id()==ID_code);
231 exprt value = symbol.value;
232
233 if(symbol.base_name=="operator=")
234 {
235 cpp_declaratort declarator;
236 declarator.add_source_location() = symbol.location;
238 lookup(symbol.type.get(ID_C_member_name)), declarator);
239 value.swap(declarator.value());
240 cont=true;
241 }
242 else if(symbol.value.operands().size()==1)
243 {
244 value = to_unary_expr(symbol.value).op();
245 cont=true;
246 }
247 else
248 UNREACHABLE; // Don't know what to do!
249
250 symbolt &writable_symbol =
251 symbol_table.get_writeable_ref(named_symbol.first);
252 writable_symbol.value.swap(value);
253 convert_function(writable_symbol);
254 }
255 }
256 }
257 while(cont);
258
259 for(const auto &named_symbol : symbol_table.symbols)
260 {
261 if(named_symbol.second.value.id() == ID_cpp_not_typechecked)
262 symbol_table.get_writeable_ref(named_symbol.first).value.make_nil();
263 }
264}
265
267{
268 symbol_tablet::symbolst::const_iterator it=symbol_table.symbols.begin();
269
270 while(it!=symbol_table.symbols.end())
271 {
272 symbol_tablet::symbolst::const_iterator cur_it = it;
273 it++;
274
275 const symbolt &symbol=cur_it->second;
276
277 // erase templates and all member functions that have not been converted
278 if(
279 symbol.type.get_bool(ID_is_template) ||
281 {
282 symbol_table.erase(cur_it);
283 continue;
284 }
285 else if(symbol.type.id()==ID_struct ||
286 symbol.type.id()==ID_union)
287 {
288 // remove methods from 'components'
289 struct_union_typet &struct_union_type=to_struct_union_type(
290 symbol_table.get_writeable_ref(cur_it->first).type);
291
292 const struct_union_typet::componentst &components=
293 struct_union_type.components();
294
296 data_members.reserve(components.size());
297
298 struct_union_typet::componentst &function_members=
300 (struct_union_type.add(ID_methods).get_sub());
301
302 function_members.reserve(components.size());
303
304 for(const auto &compo_it : components)
305 {
306 if(compo_it.get_bool(ID_is_static) ||
307 compo_it.get_bool(ID_is_type))
308 {
309 // skip it
310 }
311 else if(compo_it.type().id()==ID_code)
312 {
313 function_members.push_back(compo_it);
314 }
315 else
316 {
317 data_members.push_back(compo_it);
318 }
319 }
320
321 struct_union_type.components().swap(data_members);
322 }
323 }
324}
325
327{
328 return ::builtin_factory(identifier, symbol_table, get_message_handler());
329}
330
332{
333 if(expr.id() == ID_cpp_name || expr.id() == ID_cpp_declaration)
334 return true;
335
336 for(const exprt &op : expr.operands())
337 {
338 if(contains_cpp_name(op))
339 return true;
340 }
341 return false;
342}
symbol_tablet & symbol_table
const irep_idt module
A codet representing sequential composition of program statements.
Definition std_code.h:130
void add(const codet &code)
Definition std_code.h:168
Base type of functions.
Definition std_types.h:539
exprt this_expr
Definition cpp_id.h:76
bool is_namespace_spec() const
Definition cpp_item.h:94
cpp_namespace_spect & get_namespace_spec()
Definition cpp_item.h:82
const source_locationt & source_location() const
Definition cpp_item.h:143
cpp_usingt & get_using()
Definition cpp_item.h:107
cpp_linkage_spect & get_linkage_spec()
Definition cpp_item.h:57
cpp_static_assertt & get_static_assert()
Definition cpp_item.h:132
bool is_static_assert() const
Definition cpp_item.h:138
bool is_using() const
Definition cpp_item.h:119
bool is_declaration() const
Definition cpp_item.h:44
bool is_linkage_spec() const
Definition cpp_item.h:69
cpp_scopet & current_scope()
Definition cpp_scopes.h:32
void static_and_dynamic_initialization()
Initialization of static objects:
bool contains_cpp_name(const exprt &)
dynamic_initializationst dynamic_initializations
void convert_function(symbolt &symbol)
irep_idt current_linkage_spec
bool cpp_is_pod(const typet &type) const
void convert(cpp_linkage_spect &)
std::unordered_set< irep_idt > deferred_typechecking
void default_assignop_value(const symbolt &symbol, cpp_declaratort &declarator)
Generate code for the implicit default assignment operator.
optionalt< codet > cpp_constructor(const source_locationt &source_location, const exprt &object, const exprt::operandst &operands)
void typecheck() override
typechecking main method
bool builtin_factory(const irep_idt &)
std::string to_string(const typet &) override
bool disable_access_control
const struct_typet & this_struct_type()
cpp_parse_treet & cpp_parse_tree
cpp_scopest cpp_scopes
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:37
Base class for all expressions.
Definition expr.h:54
std::vector< exprt > operandst
Definition expr.h:56
typet & type()
Return the type of the expression.
Definition expr.h:82
operandst & operands()
Definition expr.h:92
source_locationt & add_source_location()
Definition expr.h:235
bool get_bool(const irep_idt &name) const
Definition irep.cpp:58
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:45
bool is_not_nil() const
Definition irep.h:380
subt & get_sub()
Definition irep.h:456
void make_nil()
Definition irep.h:454
void swap(irept &irep)
Definition irep.h:442
const irep_idt & id() const
Definition irep.h:396
irept & add(const irep_idt &name)
Definition irep.cpp:116
std::size_t get_message_count(unsigned level) const
Definition message.h:56
source_locationt source_location
Definition message.h:247
mstreamt & error() const
Definition message.h:399
message_handlert & get_message_handler()
Definition message.h:184
@ M_ERROR
Definition message.h:170
static eomt eom
Definition message.h:297
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition namespace.cpp:49
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
const symbol_table_baset & get_symbol_table() const
Return first symbol table registered with the namespace.
Definition namespace.h:123
const typet & base_type() const
The type of the data what we point to.
Structure type, corresponds to C style structs.
Definition std_types.h:231
Base type for structs and unions.
Definition std_types.h:62
const componentst & components() const
Definition std_types.h:147
std::vector< componentt > componentst
Definition std_types.h:140
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.
The symbol table.
virtual void erase(const symbolst::const_iterator &entry) override
Remove a symbol from the symbol table.
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
Symbol table entry.
Definition symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition symbol.h:46
bool is_extern
Definition symbol.h:66
bool is_static_lifetime
Definition symbol.h:65
bool is_type
Definition symbol.h:61
source_locationt location
Source code location of definition of symbol.
Definition symbol.h:37
typet type
Type of symbol.
Definition symbol.h:31
irep_idt name
The unique identifier.
Definition symbol.h:40
exprt value
Initial value of symbol.
Definition symbol.h:34
The type of an expression, extends irept.
Definition type.h:29
const exprt & op() const
Definition std_expr.h:293
cpp_declarationt & to_cpp_declaration(irept &irep)
C++ Language Type Checking.
bool cpp_typecheck(cpp_parse_treet &cpp_parse_tree, symbol_tablet &symbol_table, const std::string &module, message_handlert &message_handler)
C++ Language Type Checking.
symbol_exprt cpp_symbol_expr(const symbolt &symbol)
Definition cpp_util.cpp:14
std::string type2cpp(const typet &type, const namespacet &ns)
Definition expr2cpp.cpp:498
std::string expr2cpp(const exprt &expr, const namespacet &ns)
Definition expr2cpp.cpp:491
const std::string & id2string(const irep_idt &d)
Definition irep.h:47
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)
API to expression classes for Pointers.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:503
const codet & to_code(const exprt &expr)
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:328
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:214
Symbol table entry.