CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ansi_c_convert_type.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: SpecC Language Conversion
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include "ansi_c_convert_type.h"
13
14#include <util/c_types.h>
15#include <util/config.h>
16#include <util/message.h>
17#include <util/std_types.h>
19
20#include "gcc_types.h"
21
23{
24 if(type.id()==ID_merged_type)
25 {
26 for(const typet &subtype : to_type_with_subtypes(type).subtypes())
27 read_rec(subtype);
28 }
29 else if(type.id()==ID_signed)
30 signed_cnt++;
31 else if(type.id()==ID_unsigned)
33 else if(type.id()==ID_ptr32)
35 else if(type.id()==ID_ptr64)
37 else if(type.id()==ID_volatile)
39 else if(type.id()==ID_asm)
40 {
41 // These can have up to 5 subtypes; we only use the first one.
42 const auto &type_with_subtypes = to_type_with_subtypes(type);
43 if(
44 !type_with_subtypes.subtypes().empty() &&
45 type_with_subtypes.subtypes()[0].id() == ID_string_constant)
47 to_string_constant(type_with_subtypes.subtypes()[0]).value();
48 }
49 else if(
50 type.id() == ID_section && type.has_subtype() &&
51 to_type_with_subtype(type).subtype().id() == ID_string_constant)
52 {
54 to_string_constant(to_type_with_subtype(type).subtype()).value();
55 }
56 else if(type.id()==ID_const)
58 else if(type.id()==ID_restrict)
60 else if(type.id()==ID_atomic)
62 else if(type.id()==ID_atomic_type_specifier)
63 {
64 // this gets turned into the qualifier, uh
66 read_rec(to_type_with_subtype(type).subtype());
67 }
68 else if(type.id()==ID_char)
69 char_cnt++;
70 else if(type.id()==ID_int)
71 int_cnt++;
72 else if(type.id()==ID_int8)
73 int8_cnt++;
74 else if(type.id()==ID_int16)
75 int16_cnt++;
76 else if(type.id()==ID_int32)
77 int32_cnt++;
78 else if(type.id()==ID_int64)
79 int64_cnt++;
80 else if(type.id()==ID_gcc_float16)
82 else if(type.id()==ID_gcc_float32)
84 else if(type.id()==ID_gcc_float32x)
86 else if(type.id()==ID_gcc_float64)
88 else if(type.id()==ID_gcc_float64x)
90 else if(type.id()==ID_gcc_float128)
92 else if(type.id()==ID_gcc_float128x)
94 else if(type.id()==ID_gcc_int128)
96 else if(type.id()==ID_gcc_attribute_mode)
97 {
99 }
100 else if(type.id()==ID_msc_based)
101 {
102 const exprt &as_expr=
103 static_cast<const exprt &>(static_cast<const irept &>(type));
104 msc_based = to_unary_expr(as_expr).op();
105 }
106 else if(type.id()==ID_custom_bv)
107 {
108 bv_cnt++;
109 const exprt &size_expr=
110 static_cast<const exprt &>(type.find(ID_size));
111
113 }
114 else if(type.id()==ID_custom_floatbv)
115 {
116 floatbv_cnt++;
117
118 const exprt &size_expr=
119 static_cast<const exprt &>(type.find(ID_size));
120 const exprt &fsize_expr=
121 static_cast<const exprt &>(type.find(ID_f));
122
125 }
126 else if(type.id()==ID_custom_fixedbv)
127 {
128 fixedbv_cnt++;
129
130 const exprt &size_expr=
131 static_cast<const exprt &>(type.find(ID_size));
132 const exprt &fsize_expr=
133 static_cast<const exprt &>(type.find(ID_f));
134
137 }
138 else if(type.id()==ID_short)
139 short_cnt++;
140 else if(type.id()==ID_long)
141 long_cnt++;
142 else if(type.id()==ID_double)
143 double_cnt++;
144 else if(type.id()==ID_float)
145 float_cnt++;
146 else if(type.id()==ID_c_bool)
147 c_bool_cnt++;
148 else if(type.id()==ID_proper_bool)
150 else if(type.id()==ID_complex)
151 complex_cnt++;
152 else if(type.id()==ID_static)
154 else if(type.id()==ID_thread_local)
156 else if(type.id()==ID_inline)
158 else if(type.id()==ID_extern)
160 else if(type.id()==ID_typedef)
162 else if(type.id()==ID_register)
164 else if(type.id()==ID_weak)
166 else if(type.id() == ID_used)
167 c_storage_spec.is_used = true;
168 else if(type.id()==ID_auto)
169 {
170 // ignore
171 }
172 else if(type.id()==ID_packed)
173 packed=true;
174 else if(type.id()==ID_aligned)
175 {
176 aligned=true;
177
178 // may come with size or not
179 if(type.find(ID_size).is_nil())
181 else
182 alignment=static_cast<const exprt &>(type.find(ID_size));
183 }
184 else if(type.id()==ID_transparent_union)
185 {
187 }
188 else if(type.id() == ID_frontend_vector)
189 {
190 // note that this is not yet a vector_typet -- this is a size only
191 vector_size = static_cast<const constant_exprt &>(type.find(ID_size));
192 }
193 else if(type.id()==ID_void)
194 {
195 // we store 'void' as 'empty'
196 typet tmp=type;
197 tmp.id(ID_empty);
198 other.push_back(tmp);
199 }
200 else if(type.id()==ID_msc_declspec)
201 {
202 const exprt &as_expr=
203 static_cast<const exprt &>(static_cast<const irept &>(type));
204
205 for(const auto &op : as_expr.operands())
206 {
207 // these are symbols
208 const irep_idt &id = op.get(ID_identifier);
209
210 if(id==ID_thread)
212 else if(id=="align")
213 {
214 aligned=true;
215 alignment = to_unary_expr(op).op();
216 }
217 }
218 }
219 else if(type.id() == ID_nodiscard)
221 else if(type.id()==ID_noreturn)
223 else if(type.id()==ID_constructor)
224 constructor=true;
225 else if(type.id()==ID_destructor)
226 destructor=true;
227 else if(
228 type.id() == ID_alias && type.has_subtype() &&
229 to_type_with_subtype(type).subtype().id() == ID_string_constant)
230 {
232 to_string_constant(to_type_with_subtype(type).subtype()).value();
233 }
234 else if(type.id()==ID_frontend_pointer)
235 {
236 // We turn ID_frontend_pointer to ID_pointer
237 // Pointers have a width, much like integers,
238 // which is added here.
240 to_type_with_subtype(type).subtype(), config.ansi_c.pointer_width);
241 tmp.add_source_location()=type.source_location();
243 if(!typedef_identifier.empty())
245 other.push_back(tmp);
246 }
247 else if(type.id()==ID_pointer)
248 {
250 }
251 else if(type.id() == ID_C_spec_requires)
252 {
253 const exprt &as_expr =
254 static_cast<const exprt &>(static_cast<const irept &>(type));
255 c_requires.push_back(to_unary_expr(as_expr).op());
256 }
257 else if(type.id() == ID_C_spec_assigns)
258 {
259 const exprt &as_expr =
260 static_cast<const exprt &>(static_cast<const irept &>(type));
261
262 for(const exprt &target : to_unary_expr(as_expr).op().operands())
263 c_assigns.push_back(target);
264 }
265 else if(type.id() == ID_C_spec_frees)
266 {
267 const exprt &as_expr =
268 static_cast<const exprt &>(static_cast<const irept &>(type));
269
270 for(const exprt &target : to_unary_expr(as_expr).op().operands())
271 c_frees.push_back(target);
272 }
273 else if(type.id() == ID_C_spec_ensures)
274 {
275 const exprt &as_expr =
276 static_cast<const exprt &>(static_cast<const irept &>(type));
277 c_ensures.push_back(to_unary_expr(as_expr).op());
278 }
279 else
280 other.push_back(type);
281}
282
284{
286
287 type.clear();
288
289 // first, do "other"
290
291 if(!other.empty())
292 {
302 {
303 log.error().source_location = source_location;
304 log.error() << "illegal type modifier for defined type" << messaget::eom;
305 throw 0;
306 }
307
308 // asm blocks (cf. regression/ansi-c/asm1) - ignore the asm
309 if(other.size()==2)
310 {
311 if(other.front().id()==ID_asm && other.back().id()==ID_empty)
312 other.pop_front();
313 else if(other.front().id()==ID_empty && other.back().id()==ID_asm)
314 other.pop_back();
315 }
316
317 if(other.size()!=1)
318 {
319 log.error().source_location = source_location;
320 log.error() << "illegal combination of defined types" << messaget::eom;
321 throw 0;
322 }
323
324 type.swap(other.front());
325
326 // the contract expressions are meant for function types only
327 if(!c_requires.empty())
328 to_code_with_contract_type(type).c_requires() = std::move(c_requires);
329
330 if(!c_assigns.empty())
331 to_code_with_contract_type(type).c_assigns() = std::move(c_assigns);
332
333 if(!c_frees.empty())
334 to_code_with_contract_type(type).c_frees() = std::move(c_frees);
335
336 if(!c_ensures.empty())
337 to_code_with_contract_type(type).c_ensures() = std::move(c_ensures);
338
340 {
342 {
343 log.error().source_location = source_location;
344 log.error() << "combining constructor and destructor not supported"
345 << messaget::eom;
346 throw 0;
347 }
348
349 typet *type_p=&type;
350 if(type.id()==ID_code)
351 type_p=&(to_code_type(type).return_type());
352
353 else if(type_p->id()!=ID_empty)
354 {
355 log.error().source_location = source_location;
356 log.error() << "constructor and destructor required to be type void, "
357 << "found " << type_p->pretty() << messaget::eom;
358 throw 0;
359 }
360
362 }
363 }
364 else if(constructor || destructor)
365 {
366 log.error().source_location = source_location;
367 log.error() << "constructor and destructor required to be type void, "
368 << "found " << type.pretty() << messaget::eom;
369 throw 0;
370 }
371 else if(gcc_float16_cnt ||
375 {
380 {
381 log.error().source_location = source_location;
382 log.error() << "cannot combine integer type with floating-point type"
383 << messaget::eom;
384 throw 0;
385 }
386
392 {
393 log.error().source_location = source_location;
394 log.error() << "conflicting type modifiers" << messaget::eom;
395 throw 0;
396 }
397
398 // _not_ the same as float, double, long double
400 type=gcc_float16_type();
401 else if(gcc_float32_cnt)
402 type=gcc_float32_type();
403 else if(gcc_float32x_cnt)
404 type=gcc_float32x_type();
405 else if(gcc_float64_cnt)
406 type=gcc_float64_type();
407 else if(gcc_float64x_cnt)
408 type=gcc_float64x_type();
409 else if(gcc_float128_cnt)
410 type=gcc_float128_type();
411 else if(gcc_float128x_cnt)
412 type=gcc_float128x_type();
413 else
415 }
416 else if(double_cnt || float_cnt)
417 {
422 {
423 log.error().source_location = source_location;
424 log.error() << "cannot combine integer type with floating-point type"
425 << messaget::eom;
426 throw 0;
427 }
428
429 if(double_cnt && float_cnt)
430 {
431 log.error().source_location = source_location;
432 log.error() << "conflicting type modifiers" << messaget::eom;
433 throw 0;
434 }
435
436 if(long_cnt==0)
437 {
438 if(double_cnt!=0)
439 type=double_type();
440 else
441 type=float_type();
442 }
443 else if(long_cnt==1 || long_cnt==2)
444 {
445 if(double_cnt!=0)
446 type=long_double_type();
447 else
448 {
449 log.error().source_location = source_location;
450 log.error() << "conflicting type modifiers" << messaget::eom;
451 throw 0;
452 }
453 }
454 else
455 {
456 log.error().source_location = source_location;
457 log.error() << "illegal type modifier for float" << messaget::eom;
458 throw 0;
459 }
460 }
461 else if(c_bool_cnt)
462 {
467 {
468 log.error().source_location = source_location;
469 log.error() << "illegal type modifier for C boolean type"
470 << messaget::eom;
471 throw 0;
472 }
473
474 type=c_bool_type();
475 }
476 else if(proper_bool_cnt)
477 {
482 {
483 log.error().source_location = source_location;
484 log.error() << "illegal type modifier for proper boolean type"
485 << messaget::eom;
486 throw 0;
487 }
488
489 type.id(ID_bool);
490 }
491 else if(complex_cnt && !char_cnt && !signed_cnt && !unsigned_cnt &&
493 {
494 // the "default" for complex is double
495 type=double_type();
496 }
497 else if(char_cnt)
498 {
499 if(int_cnt || short_cnt || long_cnt ||
502 {
503 log.error().source_location = source_location;
504 log.error() << "illegal type modifier for char type" << messaget::eom;
505 throw 0;
506 }
507
509 {
510 log.error().source_location = source_location;
511 log.error() << "conflicting type modifiers" << messaget::eom;
512 throw 0;
513 }
514 else if(unsigned_cnt)
515 type=unsigned_char_type();
516 else if(signed_cnt)
517 type=signed_char_type();
518 else
519 type=char_type();
520 }
521 else
522 {
523 // it is integer -- signed or unsigned?
524
525 bool is_signed=true; // default
526
528 {
529 log.error().source_location = source_location;
530 log.error() << "conflicting type modifiers" << messaget::eom;
531 throw 0;
532 }
533 else if(unsigned_cnt)
534 is_signed=false;
535 else if(signed_cnt)
536 is_signed=true;
537
539 {
541 {
542 log.error().source_location = source_location;
543 log.error() << "conflicting type modifiers" << messaget::eom;
544 throw 0;
545 }
546
547 if(int8_cnt)
548 if(is_signed)
549 type=signed_char_type();
550 else
551 type=unsigned_char_type();
552 else if(int16_cnt)
553 if(is_signed)
555 else
557 else if(int32_cnt)
558 if(is_signed)
559 type=signed_int_type();
560 else
561 type=unsigned_int_type();
562 else if(int64_cnt) // Visual Studio: equivalent to long long int
563 if(is_signed)
565 else
567 else
569 }
570 else if(gcc_int128_cnt)
571 {
572 if(is_signed)
574 else
576 }
577 else if(bv_cnt)
578 {
579 // explicitly-given expression for width
581 type.set(ID_size, bv_width);
582 }
583 else if(floatbv_cnt)
584 {
585 type.id(ID_custom_floatbv);
586 type.set(ID_size, bv_width);
587 type.set(ID_f, fraction_width);
588 }
589 else if(fixedbv_cnt)
590 {
591 type.id(ID_custom_fixedbv);
592 type.set(ID_size, bv_width);
593 type.set(ID_f, fraction_width);
594 }
595 else if(short_cnt)
596 {
597 if(long_cnt || char_cnt)
598 {
599 log.error().source_location = source_location;
600 log.error() << "conflicting type modifiers" << messaget::eom;
601 throw 0;
602 }
603
604 if(is_signed)
606 else
608 }
609 else if(long_cnt==0)
610 {
611 if(is_signed)
612 type=signed_int_type();
613 else
614 type=unsigned_int_type();
615 }
616 else if(long_cnt==1)
617 {
618 if(is_signed)
620 else
622 }
623 else if(long_cnt==2)
624 {
625 if(is_signed)
627 else
629 }
630 else
631 {
632 log.error().source_location = source_location;
633 log.error() << "illegal type modifier for integer type" << messaget::eom;
634 throw 0;
635 }
636 }
637
639 set_attributes(type);
640}
641
644{
646 {
649 new_type.add_source_location()=vector_size.source_location();
650 type=new_type;
651 }
652
653 if(complex_cnt)
654 {
655 // These take more or less arbitrary subtypes.
657 new_type.add_source_location()=source_location;
658 type.swap(new_type);
659 }
660}
661
664{
666 {
668 new_type.add_subtype() = type;
669 type.swap(new_type);
670 }
671
672 c_qualifiers.write(type);
673
674 if(packed)
675 type.set(ID_C_packed, true);
676
677 if(aligned)
679}
ANSI-C Language Conversion.
configt config
Definition config.cpp:25
floatbv_typet float_type()
Definition c_types.cpp:177
signedbv_typet signed_long_int_type()
Definition c_types.cpp:72
signedbv_typet signed_char_type()
Definition c_types.cpp:134
unsignedbv_typet unsigned_int_type()
Definition c_types.cpp:36
unsignedbv_typet unsigned_long_long_int_type()
Definition c_types.cpp:93
unsignedbv_typet unsigned_long_int_type()
Definition c_types.cpp:86
signedbv_typet signed_int_type()
Definition c_types.cpp:22
unsignedbv_typet unsigned_char_type()
Definition c_types.cpp:127
bitvector_typet char_type()
Definition c_types.cpp:106
signedbv_typet signed_long_long_int_type()
Definition c_types.cpp:79
floatbv_typet long_double_type()
Definition c_types.cpp:193
typet c_bool_type()
Definition c_types.cpp:100
floatbv_typet double_type()
Definition c_types.cpp:185
signedbv_typet signed_short_int_type()
Definition c_types.cpp:29
unsignedbv_typet unsigned_short_int_type()
Definition c_types.cpp:43
const code_with_contract_typet & to_code_with_contract_type(const typet &type)
Cast a typet to a code_with_contract_typet.
Definition c_types.h:467
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
virtual void read_rec(const typet &type)
c_storage_spect c_storage_spec
exprt::operandst c_ensures
virtual void write(typet &type)
message_handlert & message_handler
virtual void set_attributes(typet &type) const
Add qualifiers and GCC attributes onto type.
exprt::operandst c_requires
source_locationt source_location
exprt::operandst c_assigns
virtual void build_type_with_subtype(typet &type) const
Build a vector or complex type with type as subtype.
std::list< typet > other
virtual void write(typet &src) const
bool is_transparent_union
Complex numbers made of pair of given subtype.
Definition std_types.h:1133
struct configt::ansi_ct ansi_c
A constant literal expression.
Definition std_expr.h:3117
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
operandst & operands()
Definition expr.h:94
const source_locationt & source_location() const
Definition expr.h:231
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:482
const irept & find(const irep_idt &name) const
Definition irep.cpp:93
const irep_idt & get(const irep_idt &name) const
Definition irep.cpp:44
void set(const irep_idt &name, const irep_idt &value)
Definition irep.h:412
void clear()
Definition irep.h:444
bool is_not_nil() const
Definition irep.h:372
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
Class that provides messages with a built-in verbosity 'level'.
Definition message.h:154
static eomt eom
Definition message.h:289
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
Type with a single subtype.
Definition type.h:180
The type of an expression, extends irept.
Definition type.h:29
const source_locationt & source_location() const
Definition type.h:72
bool has_subtype() const
Definition type.h:64
floatbv_typet gcc_float32_type()
Definition gcc_types.cpp:21
floatbv_typet gcc_float16_type()
Definition gcc_types.cpp:13
floatbv_typet gcc_float64_type()
Definition gcc_types.cpp:39
signedbv_typet gcc_signed_int128_type()
Definition gcc_types.cpp:82
floatbv_typet gcc_float32x_type()
Definition gcc_types.cpp:30
floatbv_typet gcc_float64x_type()
Definition gcc_types.cpp:48
floatbv_typet gcc_float128x_type()
Definition gcc_types.cpp:66
unsignedbv_typet gcc_unsigned_int128_type()
Definition gcc_types.cpp:75
floatbv_typet gcc_float128_type()
Definition gcc_types.cpp:57
double log(double x)
Definition math.c:2449
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:426
Pre-defined types.
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
const string_constantt & to_string_constant(const exprt &expr)
const type_with_subtypest & to_type_with_subtypes(const typet &type)
Definition type.h:252
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition type.h:208
bool is_signed(const typet &t)
Convenience function – is the type signed?
Definition util.cpp:45