CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 <util/pointer_expr.h>
16#include <util/symbol_table.h>
17
19#include <ansi-c/gcc_version.h>
20
21#include "cpp_declarator.h"
22#include "cpp_util.h"
23#include "expr2cpp.h"
24
28 const std::string &_module,
29 message_handlert &message_handler)
30 : c_typecheck_baset(_symbol_table, _module, message_handler),
31 cpp_parse_tree(_cpp_parse_tree),
32 template_counter(0),
33 anon_counter(0),
34 disable_access_control(false),
35 support_float16_type(false)
36{
38 {
39 gcc_versiont gcc_version;
40 gcc_version.get("gcc");
41 if(
42 gcc_version.flavor == gcc_versiont::flavort::GCC &&
43 gcc_version.is_at_least(13u))
44 {
46 }
47 }
48}
49
54 const std::string &_module,
55 message_handlert &message_handler)
57 cpp_parse_tree(_cpp_parse_tree),
58 template_counter(0),
59 anon_counter(0),
60 disable_access_control(false),
61 support_float16_type(false)
62{
64 {
65 gcc_versiont gcc_version;
66 gcc_version.get("gcc");
67 if(
68 gcc_version.flavor == gcc_versiont::flavort::GCC &&
69 gcc_version.is_at_least(13u))
70 {
72 }
73 }
74}
75
77{
78 if(item.is_declaration())
80 else if(item.is_linkage_spec())
81 convert(item.get_linkage_spec());
82 else if(item.is_namespace_spec())
83 convert(item.get_namespace_spec());
84 else if(item.is_using())
85 convert(item.get_using());
86 else if(item.is_static_assert())
87 convert(item.get_static_assert());
88 else
89 {
90 error().source_location=item.source_location();
91 error() << "unknown parse-tree element: " << item.id() << eom;
92 throw 0;
93 }
94}
95
98{
99 // default linkage is "automatic"
101
102 for(auto &item : cpp_parse_tree.items)
103 convert(item);
104
106
108
110
111 clean_up();
112}
113
115{
116 const exprt &this_expr=
118
119 CHECK_RETURN(this_expr.is_not_nil());
120 CHECK_RETURN(this_expr.type().id() == ID_pointer);
121
122 const typet &t = to_pointer_type(this_expr.type()).base_type();
125}
126
127std::string cpp_typecheckt::to_string(const exprt &expr)
128{
129 return expr2cpp(expr, *this);
130}
131
132std::string cpp_typecheckt::to_string(const typet &type)
133{
134 return type2cpp(type, *this);
135}
136
138 cpp_parse_treet &cpp_parse_tree,
139 symbol_table_baset &symbol_table,
140 const std::string &module,
141 message_handlert &message_handler)
142{
144 cpp_parse_tree, symbol_table, module, message_handler);
145 return cpp_typecheck.typecheck_main();
146}
147
149 exprt &expr,
150 message_handlert &message_handler,
151 const namespacet &ns)
152{
153 const unsigned errors_before=
154 message_handler.get_message_count(messaget::M_ERROR);
155
156 symbol_tablet symbol_table;
157 cpp_parse_treet cpp_parse_tree;
158
159 cpp_typecheckt cpp_typecheck(cpp_parse_tree, symbol_table,
160 ns.get_symbol_table(), "", message_handler);
161
162 try
163 {
164 cpp_typecheck.typecheck_expr(expr);
165 }
166
167 catch(int)
168 {
169 cpp_typecheck.error();
170 }
171
172 catch(const char *e)
173 {
174 cpp_typecheck.error() << e << messaget::eom;
175 }
176
177 catch(const std::string &e)
178 {
179 cpp_typecheck.error() << e << messaget::eom;
180 }
181
182 catch(const invalid_source_file_exceptiont &e)
183 {
184 cpp_typecheck.error().source_location = e.get_source_location();
185 cpp_typecheck.error() << e.get_reason() << messaget::eom;
186 }
187
188 return message_handler.get_message_count(messaget::M_ERROR)!=errors_before;
189}
190
206{
207 code_blockt init_block; // Dynamic Initialization Block
208
210
211 for(const irep_idt &d_it : dynamic_initializations)
212 {
213 symbolt &symbol = symbol_table.get_writeable_ref(d_it);
214
215 if(symbol.is_extern)
216 continue;
217
218 // PODs are always statically initialized
219 if(cpp_is_pod(symbol.type))
220 continue;
221
222 DATA_INVARIANT(symbol.is_static_lifetime, "should be static");
223 DATA_INVARIANT(!symbol.is_type, "should not be a type");
224 DATA_INVARIANT(symbol.type.id() != ID_code, "should not be code");
225
226 exprt symbol_expr=cpp_symbol_expr(symbol);
227
228 // initializer given?
229 if(symbol.value.is_not_nil())
230 {
231 // This will be a constructor call,
232 // which we execute.
233 init_block.add(to_code(symbol.value));
234
235 // Make it nil to get zero initialization by
236 // __CPROVER_initialize
237 symbol.value.make_nil();
238 }
239 else
240 {
241 // use default constructor
243
244 auto call = cpp_constructor(symbol.location, symbol_expr, ops);
245
246 if(call.has_value())
247 init_block.add(call.value());
248 }
249 }
250
252
253 // Create the dynamic initialization procedure
255 "#cpp_dynamic_initialization#" + id2string(module),
257 ID_cpp};
258 init_symbol.base_name="#cpp_dynamic_initialization#"+id2string(module);
259 init_symbol.value.swap(init_block);
260 init_symbol.module=module;
261
262 symbol_table.insert(std::move(init_symbol));
263
265}
266
268{
269 bool cont;
270
271 do
272 {
273 cont = false;
274
275 for(auto it = symbol_table.begin(); it != symbol_table.end(); ++it)
276 {
277 const symbolt &symbol = it->second;
278
279 if(
280 symbol.value.id() == ID_cpp_not_typechecked &&
281 symbol.value.get_bool(ID_is_used))
282 {
283 DATA_INVARIANT(symbol.type.id() == ID_code, "must be code");
284 exprt value = symbol.value;
285
286 if(symbol.base_name=="operator=")
287 {
288 cpp_declaratort declarator;
289 declarator.add_source_location() = symbol.location;
291 lookup(symbol.type.get(ID_C_member_name)), declarator);
292 value.swap(declarator.value());
293 cont=true;
294 }
295 else if(symbol.value.operands().size()==1)
296 {
297 value = to_unary_expr(symbol.value).op();
298 cont=true;
299 }
300 else
301 UNREACHABLE; // Don't know what to do!
302
303 symbolt &writable_symbol = it.get_writeable_symbol();
304 writable_symbol.value.swap(value);
306 }
307 }
308 }
309 while(cont);
310
311 for(auto it = symbol_table.begin(); it != symbol_table.end(); ++it)
312 {
313 if(it->second.value.id() == ID_cpp_not_typechecked)
314 it.get_writeable_symbol().value.make_nil();
315 }
316}
317
319{
320 auto it = symbol_table.begin();
321
322 while(it != symbol_table.end())
323 {
324 auto cur_it = it;
325 it++;
326
327 const symbolt &symbol=cur_it->second;
328
329 // erase templates and all member functions that have not been converted
330 if(
331 symbol.type.get_bool(ID_is_template) ||
333 {
335 continue;
336 }
337 else if(symbol.type.id()==ID_struct ||
338 symbol.type.id()==ID_union)
339 {
340 // remove methods from 'components'
342 to_struct_union_type(cur_it.get_writeable_symbol().type);
343
344 const struct_union_typet::componentst &components=
345 struct_union_type.components();
346
348 data_members.reserve(components.size());
349
352 (struct_union_type.add(ID_methods).get_sub());
353
354 function_members.reserve(components.size());
355
356 for(const auto &compo_it : components)
357 {
358 if(compo_it.get_bool(ID_is_static) ||
359 compo_it.get_bool(ID_is_type))
360 {
361 // skip it
362 }
363 else if(compo_it.type().id()==ID_code)
364 {
365 function_members.push_back(compo_it);
366 }
367 else
368 {
369 data_members.push_back(compo_it);
370 }
371 }
372
373 struct_union_type.components().swap(data_members);
374 }
375 }
376}
377
379{
380 return ::builtin_factory(
382}
383
385{
386 if(expr.id() == ID_cpp_name || expr.id() == ID_cpp_declaration)
387 return true;
388
389 for(const exprt &op : expr.operands())
390 {
391 if(contains_cpp_name(op))
392 return true;
393 }
394 return false;
395}
configt config
Definition config.cpp:25
virtual void clear()
Reset the abstract state.
Definition ai.h:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
symbol_table_baset & symbol_table
A codet representing sequential composition of program statements.
Definition std_code.h:130
Base type of functions.
Definition std_types.h:583
struct configt::ansi_ct ansi_c
exprt this_expr
Definition cpp_id.h:76
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
std::optional< codet > cpp_constructor(const source_locationt &source_location, const exprt &object, const exprt::operandst &operands)
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.
cpp_typecheckt(cpp_parse_treet &_cpp_parse_tree, symbol_table_baset &_symbol_table, const std::string &_module, message_handlert &message_handler)
bool builtin_factory(const irep_idt &) override
void typecheck() override
typechecking main method
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:38
Base class for all expressions.
Definition expr.h:56
std::vector< exprt > operandst
Definition expr.h:58
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
source_locationt & add_source_location()
Definition expr.h:236
bool is_at_least(unsigned v_major, unsigned v_minor=0, unsigned v_patchlevel=0) const
void get(const std::string &executable)
enum gcc_versiont::flavort flavor
Thrown when we can't handle something in an input source file.
bool get_bool(const irep_idt &name) const
Definition irep.cpp:57
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
bool is_not_nil() const
Definition irep.h:372
void make_nil()
Definition irep.h:446
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
std::size_t get_message_count(unsigned level) const
Definition message.h:55
source_locationt source_location
Definition message.h:239
mstreamt & error() const
Definition message.h:391
message_handlert & get_message_handler()
Definition message.h:183
@ M_ERROR
Definition message.h:169
static eomt eom
Definition message.h:289
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
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
Structure type, corresponds to C style structs.
Definition std_types.h:231
Base type for structs and unions.
Definition std_types.h:62
std::vector< componentt > componentst
Definition std_types.h:140
The symbol table base class interface.
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
virtual std::pair< symbolt &, bool > insert(symbolt symbol)=0
Move or copy a new symbol to the symbol table.
virtual void erase(const symbolst::const_iterator &entry)=0
Remove a symbol from the symbol table.
virtual iteratort begin()=0
virtual iteratort end()=0
The symbol table.
Symbol table entry.
Definition symbol.h:28
bool is_extern
Definition symbol.h:74
bool is_static_lifetime
Definition symbol.h:70
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
irep_idt irep_idt base_name
Name of module the symbol belongs to.
Definition symbol.h:46
exprt value
Initial value of symbol.
Definition symbol.h:34
The type of an expression, extends irept.
Definition type.h:29
cpp_declarationt & to_cpp_declaration(irept &irep)
C++ Language Type Checking.
bool cpp_typecheck(cpp_parse_treet &cpp_parse_tree, symbol_table_baset &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:493
std::string expr2cpp(const exprt &expr, const namespacet &ns)
Definition expr2cpp.cpp:486
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
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 CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
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:426
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition std_types.h:518
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:214
Author: Diffblue Ltd.