21 #include <unordered_set>
25 if(type.
id() == ID_c_enum_tag)
27 else if(type.
id() == ID_struct_tag)
29 else if(type.
id() == ID_union_tag)
37 const typet &type)
const
41 if(followed.
id() == ID_struct || followed.
id() == ID_union)
43 std::string result = followed.
id_string();
45 const std::string &tag = followed.
get_string(ID_tag);
51 result +=
" (incomplete)";
59 const typet &subtype = c.type();
64 if(!c.get_base_name().empty())
77 else if(followed.
id() == ID_pointer)
95 bool conclusive =
false;
107 if(t1.
id() != t2.
id())
109 msg =
"type classes differ";
112 else if(t1.
id() == ID_pointer || t1.
id() == ID_array)
118 if(conflict_path.
type().
id() == ID_pointer)
129 else if(t1.
id() == ID_pointer)
130 msg =
"pointer types differ";
132 msg =
"array types differ";
134 else if(t1.
id() == ID_struct || t1.
id() == ID_union)
142 exprt conflict_path_before = conflict_path;
144 if(components1.size() != components2.size())
146 msg =
"number of members is different (";
153 for(std::size_t i = 0; i < components1.size(); ++i)
155 const typet &subtype1 = components1[i].type();
156 const typet &subtype2 = components2[i].type();
158 if(components1[i].get_name() != components2[i].get_name())
161 msg +=
id2string(components1[i].get_name()) +
'/';
162 msg +=
id2string(components2[i].get_name()) +
')';
165 else if(subtype1 != subtype2)
167 typedef std::unordered_set<typet, irep_hash> type_sett;
168 type_sett parent_types;
170 exprt e = conflict_path_before;
171 while(e.
id() == ID_dereference || e.
id() == ID_member ||
174 parent_types.insert(e.
type());
176 if(e.
id() == ID_dereference)
178 else if(e.
id() == ID_member)
180 else if(e.
id() == ID_index)
186 if(parent_types.find(subtype1) == parent_types.end())
188 conflict_path = conflict_path_before;
189 conflict_path.
type() = t1;
190 conflict_path =
member_exprt(conflict_path, components1[i]);
205 msg =
"type of member " +
id2string(components1[i].get_name()) +
206 " differs (recursive)";
215 else if(t1.
id() == ID_c_enum)
225 msg =
"enum value types are different (";
234 else if(members1.size() != members2.size())
236 msg =
"number of enum members is different (";
243 for(std::size_t i = 0; i < members1.size(); ++i)
252 else if(members1[i].get_value() != members2[i].get_value())
255 msg +=
id2string(members1[i].get_value()) +
'/';
256 msg +=
id2string(members2[i].get_value()) +
')';
265 msg +=
"\nenum declarations at\n";
269 else if(t1.
id() == ID_code)
278 if(parameters1.size() != parameters2.size())
280 msg =
"parameter counts differ (";
285 else if(return_type1 != return_type2)
302 msg =
"return types differ";
306 for(std::size_t i = 0; i < parameters1.size(); i++)
308 const typet &subtype1 = parameters1[i].type();
309 const typet &subtype2 = parameters2[i].type();
311 if(subtype1 != subtype2)
328 msg =
"parameter types differ";
338 msg =
"conflict on POD";
342 if(conclusive && !msg.empty())
348 log.error() <<
"reason for conflict at "
368 const std::string &msg)
373 log.error() << msg <<
" '" << old_symbol.
display_name() <<
"'" <<
'\n';
374 log.error() <<
"old definition in module '" << old_symbol.
module <<
"' "
377 log.error() <<
"new definition in module '" << new_symbol.
module <<
"' "
385 const std::string &msg)
388 log.warning().source_location = new_symbol.
location;
391 log.warning() <<
"old definition in module " << old_symbol.
module <<
" "
394 log.warning() <<
"new definition in module " << new_symbol.
module <<
" "
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
std::vector< c_enum_membert > memberst
std::vector< parametert > parameterst
const typet & return_type() const
const parameterst & parameters() const
A constant literal expression.
Operator to dereference a pointer.
Base class for all expressions.
typet & type()
Return the type of the expression.
Unbounded, signed integers (mathematical integers, not bitvectors)
const std::string & id_string() const
const irep_idt & id() const
const std::string & get_string(const irep_idt &name) const
message_handlert & message_handler
std::string type_to_string_verbose(const symbolt &symbol, const typet &type) const
void warning(const symbolt &old_symbol, const symbolt &new_symbol, const std::string &msg)
bool detailed_conflict_report_rec(const symbolt &old_symbol, const symbolt &new_symbol, const typet &type1, const typet &type2, unsigned depth, exprt &conflict_path)
Returns true iff the conflict report on a particular branch of the tree of types was a definitive res...
void error(const symbolt &old_symbol, const symbolt &new_symbol, const std::string &msg)
Extract member of struct or union.
const exprt & compound() const
Class that provides messages with a built-in verbosity 'level'.
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
std::string as_string() const
const componentst & components() const
std::vector< componentt > componentst
const irep_idt & display_name() const
Return language specific display name if present.
irep_idt module
Name of module the symbol belongs to.
source_locationt location
Source code location of definition of symbol.
irep_idt name
The unique identifier.
The type of an expression, extends irept.
const source_locationt & source_location() const
std::string get_base_name(const std::string &in, bool strip_suffix)
cleans a filename from path and extension
const std::string & id2string(const irep_idt &d)
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
static const typet & follow_tags_symbols(const namespacet &ns, const typet &type)
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
#define UNREACHABLE
This should be used to mark dead code.
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
const type_with_subtypet & to_type_with_subtype(const typet &type)