CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cpp_typecheck_type.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 <util/c_types.h>
13#include <util/cprover_prefix.h>
15#include <util/simplify_expr.h>
17
18#include <ansi-c/c_qualifiers.h>
19#include <ansi-c/merged_type.h>
20
21#include "cpp_convert_type.h"
22#include "cpp_typecheck.h"
23#include "cpp_typecheck_fargs.h"
24
26{
27 PRECONDITION(!type.id().empty());
29
30 try
31 {
33 }
34
35 catch(const char *err)
36 {
38 error() << err << eom;
39 throw 0;
40 }
41
42 catch(const std::string &err)
43 {
45 error() << err << eom;
46 throw 0;
47 }
48
49 if(type.id()==ID_cpp_name)
50 {
52
54 cpp_name.swap(type);
55
56 exprt symbol_expr=resolve(
60
61 if(symbol_expr.id()!=ID_type)
62 {
64 error() << "expected type" << eom;
65 throw 0;
66 }
67
68 type=symbol_expr.type();
70
71 if(type.get_bool(ID_C_constant))
72 qualifiers.is_constant = true;
73
74 // CPROVER extensions
76 if(typedef_identifier == CPROVER_PREFIX "rational")
77 {
78 type = rational_typet();
79 type.add_source_location() = symbol_expr.source_location();
80 }
81 else if(typedef_identifier == CPROVER_PREFIX "integer")
82 {
83 type = integer_typet();
84 type.add_source_location() = symbol_expr.source_location();
85 }
86
87 qualifiers.write(type);
88 }
89 else if(type.id()==ID_struct ||
90 type.id()==ID_union)
91 {
93 }
94 else if(type.id()==ID_pointer)
95 {
97
98 // the pointer/reference might have a qualifier,
99 // but do subtype first
100 typecheck_type(to_pointer_type(type).base_type());
101
102 // Check if it is a pointer-to-member
103 if(type.find(ID_to_member).is_not_nil())
104 {
105 // these can point either to data members or member functions
106 // of a class
107
108 typet &class_object = static_cast<typet &>(type.add(ID_to_member));
109
110 if(class_object.id()==ID_cpp_name)
111 {
113 class_object.get_sub().back().id() == "::", "scope suffix expected");
114 class_object.get_sub().pop_back();
115 }
116
118
119 // there may be parameters if this is a pointer to member function
120 if(to_pointer_type(type).base_type().id() == ID_code)
121 {
122 code_typet::parameterst &parameters =
123 to_code_type(to_pointer_type(type).base_type()).parameters();
124
125 if(parameters.empty() || !parameters.front().get_this())
126 {
127 // Add 'this' to the parameters
129 a0.set_base_name(ID_this);
130 a0.set_this();
131 parameters.insert(parameters.begin(), a0);
132 }
133 }
134 }
135
136 if(type.get_bool(ID_C_constant))
137 qualifiers.is_constant = true;
138
139 qualifiers.write(type);
140 }
141 else if(type.id()==ID_array)
142 {
143 exprt &size_expr=to_array_type(type).size();
144
145 if(size_expr.is_not_nil())
146 {
148 simplify(size_expr, *this);
149 }
150
151 typecheck_type(to_array_type(type).element_type());
152
153 if(to_array_type(type).element_type().get_bool(ID_C_constant))
154 type.set(ID_C_constant, true);
155
156 if(to_array_type(type).element_type().get_bool(ID_C_volatile))
157 type.set(ID_C_volatile, true);
158 }
159 else if(type.id()==ID_vector)
160 {
161 // already done
162 }
163 else if(type.id() == ID_frontend_vector)
164 {
166 }
167 else if(type.id()==ID_code)
168 {
170 typecheck_type(code_type.return_type());
171
172 code_typet::parameterst &parameters=code_type.parameters();
173
174 for(auto &param : parameters)
175 {
176 typecheck_type(param.type());
177
178 // see if there is a default value
179 if(param.has_default_value())
180 {
181 typecheck_expr(param.default_value());
182 implicit_typecast(param.default_value(), param.type());
183 }
184 }
185 }
186 else if(type.id()==ID_template)
187 {
188 typecheck_type(to_template_type(type).subtype());
189 }
190 else if(type.id()==ID_c_enum)
191 {
193 }
194 else if(type.id()==ID_c_enum_tag)
195 {
196 }
197 else if(type.id()==ID_c_bit_field)
198 {
200 }
201 else if(
202 type.id() == ID_unsignedbv || type.id() == ID_signedbv ||
203 type.id() == ID_bool || type.id() == ID_c_bool || type.id() == ID_floatbv ||
204 type.id() == ID_fixedbv || type.id() == ID_empty)
205 {
206 }
207 else if(type.id() == ID_struct_tag)
208 {
209 }
210 else if(type.id() == ID_union_tag)
211 {
212 }
213 else if(type.id()==ID_constructor ||
214 type.id()==ID_destructor)
215 {
216 }
217 else if(type.id()=="cpp-cast-operator")
218 {
219 }
220 else if(type.id()=="cpp-template-type")
221 {
222 }
223 else if(type.id()==ID_typeof)
224 {
225 exprt e=static_cast<const exprt &>(type.find(ID_expr_arg));
226
227 if(e.is_nil())
228 {
230 static_cast<const typet &>(type.find(ID_type_arg));
231
232 if(tmp_type.id()==ID_cpp_name)
233 {
234 // this may be ambiguous -- it can be either a type or
235 // an expression
236
238
239 exprt symbol_expr=resolve(
240 to_cpp_name(static_cast<const irept &>(tmp_type)),
242 fargs);
243
244 type=symbol_expr.type();
245 }
246 else
247 {
249 type=tmp_type;
250 }
251 }
252 else
253 {
255 type=e.type();
256 }
257 }
258 else if(type.id()==ID_decltype)
259 {
260 exprt e=static_cast<const exprt &>(type.find(ID_expr_arg));
262
263 if(e.type().id() == ID_c_bit_field)
264 type = to_c_bit_field_type(e.type()).underlying_type();
265 else
266 type = e.type();
267 }
268 else if(type.id()==ID_unassigned)
269 {
270 // ignore, for template parameter guessing
271 }
272 else if(type.id()==ID_template_class_instance)
273 {
274 // ok (internally generated)
275 }
276 else if(type.id()==ID_block_pointer)
277 {
278 // This is an Apple extension for lambda-like constructs.
279 // http://thirdcog.eu/pwcblocks/
280 // we just treat them as references to functions
282 typecheck_type(type);
283 }
284 else if(type.id()==ID_nullptr)
285 {
286 }
287 else if(type.id()==ID_already_typechecked)
288 {
290 }
291 else if(type.id() == ID_gcc_attribute_mode)
292 {
295 as_parsed.move_to_subtypes(to_type_with_subtype(type).subtype());
296 type.get_sub().clear();
297 as_parsed.move_to_subtypes(type);
298 type.swap(as_parsed);
299
301 }
302 else if(type.id() == ID_complex)
303 {
304 // already done
305 }
306 else
307 {
309 error() << "unexpected cpp type: " << type.pretty() << eom;
310 throw 0;
311 }
312
313 CHECK_RETURN(type.is_not_nil());
314}
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:235
const c_bit_field_typet & to_c_bit_field_type(const typet &type)
Cast a typet to a c_bit_field_typet.
Definition c_types.h:80
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
virtual void typecheck_vector_type(typet &type)
virtual void typecheck_c_bit_field_type(c_bit_field_typet &type)
virtual void typecheck_type(typet &type)
Base type of functions.
Definition std_types.h:583
std::vector< parametert > parameterst
Definition std_types.h:586
void typecheck_type(typet &) override
void typecheck_enum_type(typet &type)
void implicit_typecast(exprt &expr, const typet &type) override
void typecheck_compound_type(struct_union_typet &) override
void typecheck_expr(exprt &) override
exprt resolve(const cpp_namet &cpp_name, const cpp_typecheck_resolvet::wantt want, const cpp_typecheck_fargst &fargs, bool fail_with_exception=true)
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
typet & type()
Return the type of the expression.
Definition expr.h:84
const source_locationt & source_location() const
Definition expr.h:231
Unbounded, signed integers (mathematical integers, not bitvectors)
There are a large number of kinds of tree structured or tree-like data in CPROVER.
Definition irep.h:364
bool get_bool(const irep_idt &name) const
Definition irep.cpp:57
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
bool is_not_nil() const
Definition irep.h:372
subt & get_sub()
Definition irep.h:448
void swap(irept &irep)
Definition irep.h:434
const irep_idt & id() const
Definition irep.h:388
irept & add(const irep_idt &name)
Definition irep.cpp:103
bool is_nil() const
Definition irep.h:368
holds a combination of types
Definition merged_type.h:16
source_locationt source_location
Definition message.h:239
mstreamt & error() const
Definition message.h:391
message_handlert & get_message_handler()
Definition message.h:183
static eomt eom
Definition message.h:289
Unbounded, signed rational numbers.
The type of an expression, extends irept.
Definition type.h:29
source_locationt & add_source_location()
Definition type.h:77
const source_locationt & source_location() const
Definition type.h:72
bool has_subtype() const
Definition type.h:64
void cpp_convert_plain_type(typet &type, message_handlert &message_handler)
C++ Language Conversion.
cpp_namet & to_cpp_name(irept &cpp_name)
Definition cpp_name.h:148
template_typet & to_template_type(typet &type)
C++ Language Type Checking.
C++ Language Type Checking.
#define CPROVER_PREFIX
void err(int eval, const char *fmt,...)
Definition err.c:13
Mathematical types.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
bool simplify(exprt &expr, const namespacet &ns)
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define PRECONDITION(CONDITION)
Definition invariant.h:463
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition std_types.h:214
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition type.h:208