CBMC
cpp_typecheck_type.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 <util/c_types.h>
13 #include <util/cprover_prefix.h>
15 #include <util/simplify_expr.h>
16 #include <util/source_location.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());
28  PRECONDITION(type.is_not_nil());
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  {
51  c_qualifierst qualifiers(type);
52 
53  cpp_namet cpp_name;
54  cpp_name.swap(type);
55 
56  exprt symbol_expr=resolve(
57  cpp_name,
60 
61  if(symbol_expr.id()!=ID_type)
62  {
64  error() << "expected type" << eom;
65  throw 0;
66  }
67 
68  type=symbol_expr.type();
69  PRECONDITION(type.is_not_nil());
70 
71  if(type.get_bool(ID_C_constant))
72  qualifiers.is_constant = true;
73 
74  // CPROVER extensions
75  irep_idt typedef_identifier = type.get(ID_C_typedef);
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  {
96  c_qualifierst qualifiers(type);
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 
117  typecheck_type(class_object);
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
128  code_typet::parametert a0(pointer_type(class_object));
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  {
147  typecheck_expr(size_expr);
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  {
165  typecheck_vector_type(type);
166  }
167  else if(type.id()==ID_code)
168  {
169  code_typet &code_type=to_code_type(type);
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  {
192  typecheck_enum_type(type);
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  {
229  typet tmp_type=
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 
237  cpp_typecheck_fargst fargs;
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  {
248  typecheck_type(tmp_type);
249  type=tmp_type;
250  }
251  }
252  else
253  {
254  typecheck_expr(e);
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));
261  typecheck_expr(e);
262 
263  if(e.type().id() == ID_c_bit_field)
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
281  type.id(ID_frontend_pointer);
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  {
293  PRECONDITION(type.has_subtype());
294  merged_typet as_parsed;
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
const exprt & size() const
Definition: std_types.h:840
const typet & underlying_type() const
Definition: c_types.h:30
virtual void write(typet &src) const override
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)
void set_base_name(const irep_idt &name)
Definition: std_types.h:629
Base type of functions.
Definition: std_types.h:583
std::vector< parametert > parameterst
Definition: std_types.h:585
const typet & return_type() const
Definition: std_types.h:689
const parameterst & parameters() const
Definition: std_types.h:699
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)
Definition: cpp_typecheck.h:71
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
bool empty() const
Definition: dstring.h:89
Base class for all expressions.
Definition: expr.h:56
const source_locationt & source_location() const
Definition: expr.h:231
typet & type()
Return the type of the expression.
Definition: expr.h:84
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:360
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:57
subt & get_sub()
Definition: irep.h:444
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:408
bool is_not_nil() const
Definition: irep.h:368
const irep_idt & id() const
Definition: irep.h:384
void swap(irept &irep)
Definition: irep.h:430
irept & add(const irep_idt &name)
Definition: irep.cpp:103
bool is_nil() const
Definition: irep.h:364
holds a combination of types
Definition: merged_type.h:16
source_locationt source_location
Definition: message.h:247
mstreamt & error() const
Definition: message.h:399
message_handlert & get_message_handler()
Definition: message.h:184
static eomt eom
Definition: message.h:297
Unbounded, signed rational numbers.
void move_to_subtypes(typet &type)
Move the provided type to the subtypes of this type.
Definition: type.cpp:25
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
source_locationt & add_source_location()
Definition: type.h:77
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.
Definition: pointer_expr.h:93
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