CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cpp_typecheck_enum_type.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: C++ Language Type Checking
4
5Author: Daniel Kroening, kroening@kroening.com
6
7\*******************************************************************/
8
11
12#include <util/arith_tools.h>
13#include <util/c_types.h>
14#include <util/config.h>
16
17#include <ansi-c/c_qualifiers.h>
18
19#include "cpp_enum_type.h"
20#include "cpp_typecheck.h"
21
23{
25
26 exprt &body=static_cast<exprt &>(c_enum_type.add(ID_body));
27 irept::subt &components=body.get_sub();
28
30
31 mp_integer i=0;
32
33 for(auto &component : components)
34 {
35 const irep_idt &name = component.get(ID_name);
36
37 if(component.find(ID_value).is_not_nil())
38 {
39 exprt &value = static_cast<exprt &>(component.add(ID_value));
40 typecheck_expr(value);
41 implicit_typecast(value, c_enum_type.underlying_type());
42 make_constant(value);
43 if(to_integer(to_constant_expr(value), i))
44 {
46 error() << "failed to produce integer for enum constant" << eom;
47 throw 0;
48 }
49 }
50
51 exprt value_expr = from_integer(i, c_enum_type.underlying_type());
52 value_expr.type()=enum_tag_type; // override type
53
54 symbolt symbol{
55 id2string(enum_symbol.name) + "::" + id2string(name),
57 enum_symbol.mode};
58 symbol.base_name=name;
59 symbol.value=value_expr;
60 symbol.location = static_cast<const source_locationt &>(
62 symbol.module=module;
63 symbol.is_macro=true;
64 symbol.is_file_local = true;
65 symbol.is_thread_local = true;
66
67 symbolt *new_symbol;
68 if(symbol_table.move(symbol, new_symbol))
69 {
70 error().source_location=symbol.location;
71 error() << "cpp_typecheckt::typecheck_enum_body: "
72 << "symbol_table.move() failed" << eom;
73 throw 0;
74 }
75
77 cpp_scopes.put_into_scope(*new_symbol);
78
80
81 ++i;
82 }
83}
84
86{
87 // first save qualifiers
89 qualifiers.read(type);
90
92 bool anonymous=!enum_type.has_tag();
93 irep_idt base_name;
94
96
97 if(anonymous)
98 {
99 // we fabricate a tag based on the enum constants contained
100 base_name=enum_type.generate_anon_tag();
101 }
102 else
103 {
104 const cpp_namet &tag=enum_type.tag();
105
107 template_args.make_nil();
108
110 resolver.resolve_scope(tag, base_name, template_args);
111 }
112
113 bool has_body=enum_type.has_body();
114 bool tag_only_declaration=enum_type.get_tag_only_declaration();
115
117 tag_scope(base_name, has_body, tag_only_declaration);
118
119 const irep_idt symbol_name=
120 dest_scope.prefix+"tag-"+id2string(base_name);
121
122 // check if we have it
123
124 symbol_table_baset::symbolst::const_iterator previous_symbol =
126
128 {
129 // we do!
130
131 const symbolt &symbol=previous_symbol->second;
132
133 if(has_body)
134 {
136 error() << "enum symbol '" << base_name << "' declared previously\n"
137 << "location of previous definition: " << symbol.location << eom;
138 throw 0;
139 }
140 }
141 else if(
142 has_body ||
144 {
145 std::string pretty_name=
147
148 // C++11 enumerations have an underlying type,
149 // which defaults to int.
150 // enums without underlying type may be 'packed'.
151 if(type.add_subtype().is_nil())
152 type.add_subtype() = signed_int_type();
153 else
154 {
155 typecheck_type(to_type_with_subtype(type).subtype());
156 if(
157 to_type_with_subtype(type).subtype().id() != ID_signedbv &&
158 to_type_with_subtype(type).subtype().id() != ID_unsignedbv &&
159 to_type_with_subtype(type).subtype().id() != ID_c_bool)
160 {
162 error() << "underlying type must be integral" << eom;
163 throw 0;
164 }
165 }
166
167 type_symbolt symbol{symbol_name, type, ID_cpp};
168 symbol.base_name=base_name;
169 symbol.value.make_nil();
170 symbol.location=type.source_location();
171 symbol.module=module;
172 symbol.pretty_name=pretty_name;
173
174 // move early, must be visible before doing body
175 symbolt *new_symbol;
176 if(symbol_table.move(symbol, new_symbol))
177 {
178 error().source_location=symbol.location;
179 error() << "cpp_typecheckt::typecheck_enum_type: "
180 << "symbol_table.move() failed" << eom;
181 throw 0;
182 }
183
184 // put into scope
187
189 scope_identifier.is_scope = true;
190
192
193 if(new_symbol->type.get_bool(ID_C_class))
195
196 if(has_body)
197 typecheck_enum_body(*new_symbol);
198 }
199 else
200 {
202 error() << "use of enum '" << base_name << "' without previous declaration"
203 << eom;
204 throw 0;
205 }
206
207 // create enum tag expression, and add the qualifiers
209 qualifiers.write(type);
210}
configt config
Definition config.cpp:25
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
bool to_integer(const constant_exprt &expr, mp_integer &int_value)
Convert a constant expression expr to an arbitrary-precision integer.
signedbv_typet signed_int_type()
Definition c_types.cpp:22
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition c_types.h:335
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
C enum tag type, i.e., c_enum_typet with an identifier.
Definition c_types.h:352
The type of C enums.
Definition c_types.h:239
symbol_table_baset & symbol_table
virtual void make_constant(exprt &expr)
struct configt::ansi_ct ansi_c
std::string prefix
Definition cpp_id.h:79
void go_to(cpp_idt &id)
Definition cpp_scopes.h:103
cpp_idt & put_into_scope(const symbolt &symbol, cpp_scopet &scope, bool is_friend=false)
cpp_scopet & current_scope()
Definition cpp_scopes.h:32
void typecheck_type(typet &) override
void typecheck_enum_type(typet &type)
void implicit_typecast(exprt &expr, const typet &type) override
cpp_scopet & tag_scope(const irep_idt &_base_name, bool has_body, bool tag_only_declaration)
void typecheck_expr(exprt &) override
void typecheck_enum_body(symbolt &symbol)
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
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition expr.cpp:147
bool get_bool(const irep_idt &name) const
Definition irep.cpp:57
subt & get_sub()
Definition irep.h:448
bool is_nil() const
Definition irep.h:368
source_locationt source_location
Definition message.h:239
mstreamt & error() const
Definition message.h:391
static eomt eom
Definition message.h:289
virtual bool move(symbolt &symbol, symbolt *&new_symbol)=0
const symbolst & symbols
Read-only field, used to look up symbols given their names.
Symbol table entry.
Definition symbol.h:28
source_locationt location
Source code location of definition of symbol.
Definition symbol.h:37
typet type
Type of symbol.
Definition symbol.h:31
Symbol table entry describing a data typeThis is a symbol generated as part of type checking.
Definition symbol.h:139
The type of an expression, extends irept.
Definition type.h:29
const source_locationt & source_location() const
Definition type.h:72
typet & add_subtype()
Definition type.h:53
C++ Language Type Checking.
const cpp_enum_typet & to_cpp_enum_type(const irept &irep)
C++ Language Type Checking.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition std_expr.cpp:97
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3172
Author: Diffblue Ltd.
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition type.h:208