Go to the documentation of this file.
15 #include <unordered_set>
37 const exprt &e = it->second;
39 if(e.
type().
id() != ID_array)
45 static_cast<exprt &
>(s) = e;
52 const exprt &expr)
const
59 const typet &type)
const
68 if(type.
id() == ID_c_enum_tag)
70 else if(type.
id()==ID_struct_tag)
72 else if(type.
id()==ID_union_tag)
80 const typet &type)
const
84 if(followed.
id()==ID_struct || followed.
id()==ID_union)
88 const std::string &tag=followed.
get_string(ID_tag);
102 const typet &subtype = c.type();
107 if(!c.get_base_name().empty())
120 else if(followed.
id()==ID_pointer)
134 exprt &conflict_path)
137 debug() <<
"<BEGIN DEPTH " << depth <<
">" <<
eom;
146 msg=
"type classes differ";
147 else if(t1.
id()==ID_pointer ||
153 if(conflict_path.
type().
id() == ID_pointer)
164 else if(t1.
id()==ID_pointer)
165 msg=
"pointer types differ";
167 msg=
"array types differ";
169 else if(t1.
id()==ID_struct ||
178 exprt conflict_path_before=conflict_path;
180 if(components1.size()!=components2.size())
182 msg=
"number of members is different (";
188 for(std::size_t i=0; i<components1.size(); ++i)
190 const typet &subtype1=components1[i].type();
191 const typet &subtype2=components2[i].type();
193 if(components1[i].get_name()!=components2[i].get_name())
196 msg+=
id2string(components1[i].get_name())+
'/';
197 msg+=
id2string(components2[i].get_name())+
')';
202 typedef std::unordered_set<typet, irep_hash> type_sett;
203 type_sett parent_types;
205 exprt e=conflict_path_before;
206 while(e.
id()==ID_dereference ||
210 parent_types.insert(e.
type());
211 if(e.
id() == ID_dereference)
213 else if(e.
id() == ID_member)
215 else if(e.
id() == ID_index)
221 conflict_path=conflict_path_before;
222 conflict_path.
type()=t1;
227 parent_types.find(t1)==parent_types.end())
237 msg=
"type of member "+
256 if(parent_types.find(t1)==parent_types.end())
262 else if(t1.
id()==ID_c_enum)
272 msg=
"enum value types are different (";
276 else if(members1.size()!=members2.size())
278 msg=
"number of enum members is different (";
284 for(std::size_t i=0; i<members1.size(); ++i)
293 else if(members1[i].get_value()!=members2[i].get_value())
296 msg+=
id2string(members1[i].get_value())+
'/';
297 msg+=
id2string(members2[i].get_value())+
')';
303 msg+=
"\nenum declarations at\n";
307 else if(t1.
id()==ID_code)
318 if(parameters1.size()!=parameters2.size())
320 msg=
"parameter counts differ (";
339 msg=
"return types differ";
343 for(std::size_t i=0; i<parameters1.size(); i++)
345 const typet &subtype1=parameters1[i].type();
346 const typet &subtype2=parameters2[i].type();
363 msg=
"parameter types differ";
371 msg=
"conflict on POD";
376 error() <<
"reason for conflict at "
385 debug() <<
"<END DEPTH " << depth <<
">" <<
eom;
392 const std::string &msg)
398 error() <<
"old definition in module '" << old_symbol.
module <<
"' "
401 error() <<
"new definition in module '" << new_symbol.
module <<
"' "
409 const std::string &msg)
413 warning() <<
"warning: " << msg <<
" \""
416 warning() <<
"old definition in module " << old_symbol.
module <<
" "
419 warning() <<
"new definition in module " << new_symbol.
module <<
" "
444 return new_identifier;
482 "implicit function declaration");
487 "implicit function declaration");
500 "ignoring conflicting implicit function declaration");
505 "implicit function declaration");
532 "function declaration conflicts with with weak definition");
546 "ignoring conflicting weak function declaration");
560 "ignoring conflicting function alias declaration");
571 "ignoring conflicting function declarations");
591 "conflicting parameter counts of function declarations");
600 std::string warn_msg;
602 typedef std::deque<std::pair<typet, typet> > conflictst;
603 conflictst conflicts;
609 code_typet::parameterst::const_iterator
619 std::make_pair(o_it->type(), n_it->type()));
628 "conflicting parameter counts of function declarations");
643 "conflicting parameter counts of function declarations");
652 while(!conflicts.empty())
659 if((t1.
id()==ID_empty || t2.
id()==ID_empty) &&
663 warn_msg=
"void/non-void return type conflict on function";
669 else if((t1.
id()==ID_pointer || t2.
id()==ID_pointer) &&
674 warn_msg=
"different pointer types in extern function";
679 else if((t1.
id()==ID_pointer || t2.
id()==ID_pointer) &&
684 warn_msg=
"pointer parameter types differ between "
685 "declaration and definition";
691 else if((t1.
id()==ID_union &&
692 (t1.
get_bool(ID_C_transparent_union) ||
693 conflicts.front().first.get_bool(ID_C_transparent_union))) ||
694 (t2.
id()==ID_union &&
695 (t2.
get_bool(ID_C_transparent_union) ||
696 conflicts.front().second.get_bool(ID_C_transparent_union))))
700 (t1.
get_bool(ID_C_transparent_union) ||
701 conflicts.front().first.get_bool(ID_C_transparent_union)) &&
706 const typet &src_type=t1.
id()==ID_union?t2:t1;
714 warn_msg=
"conflict on transparent union parameter in function";
728 warn_msg=
"non-pointer parameter types differ between "
729 "declaration and definition";
735 conflicts.pop_front();
738 if(!conflicts.empty())
743 conflicts.front().first,
744 conflicts.front().second);
749 "conflicting function declarations");
790 warning() <<
"function '" << old_symbol.
name <<
"' in module '"
792 <<
"' is shadowed by a definition in module '"
799 "duplicate definition of function");
812 t1.
id() == ID_struct_tag || t1.
id() == ID_union_tag ||
813 t1.
id() == ID_c_enum_tag)
817 if(info.
o_symbols.insert(identifier).second)
829 t2.
id() == ID_struct_tag || t2.
id() == ID_union_tag ||
830 t2.
id() == ID_c_enum_tag)
834 if(info.
n_symbols.insert(identifier).second)
845 else if(t1.
id()==ID_pointer && t2.
id()==ID_array)
851 else if(t1.
id()==ID_array && t2.
id()==ID_pointer)
886 else if(t1.
id()!=t2.
id())
892 if(t1.
id()==ID_pointer)
901 "conflicting pointer types for variable");
908 "conflicting pointer types for variable");
918 else if(t1.
id()==ID_array &&
931 else if(new_size.
is_nil() ||
946 "conflicting array sizes for variable");
955 else if(t1.
id()==ID_struct || t1.
id()==ID_union)
963 struct_union_typet::componentst::const_iterator
964 it1=components1.begin(), it2=components2.begin();
966 it1!=components1.end() && it2!=components2.end();
969 if(it1->get_name()!=it2->get_name() ||
973 if(it1!=components1.end() || it2!=components2.end())
1002 bool set_to_new =
false;
1015 if(old_type.
id()==ID_struct ||
1016 old_type.
id()==ID_union ||
1017 old_type.
id()==ID_array ||
1018 old_type.
id()==ID_c_enum)
1028 "conflicting types for variable");
1055 tmp_new=new_symbol.
value;
1068 warning() <<
"warning: conflicting initializers for"
1069 <<
" variable \"" << old_symbol.
name <<
"\"\n";
1070 warning() <<
"using old value in module " << old_symbol.
module <<
" "
1073 warning() <<
"ignoring new value in module " << new_symbol.
module <<
" "
1093 bool is_code_old_symbol=old_symbol.
type.
id()==ID_code;
1094 bool is_code_new_symbol=new_symbol.
type.
id()==ID_code;
1096 if(is_code_old_symbol!=is_code_new_symbol)
1101 "conflicting definition for symbol");
1107 if(is_code_old_symbol)
1132 "conflicting definition for symbol");
1138 if(old_symbol.
type==new_symbol.
type)
1142 old_symbol.
type.
id() == ID_struct &&
1144 new_symbol.
type.
id() == ID_struct &&
1153 old_symbol.
type.
id() == ID_struct &&
1155 new_symbol.
type.
id() == ID_struct &&
1163 old_symbol.
type.
id() == ID_union &&
1165 new_symbol.
type.
id() == ID_union &&
1174 old_symbol.
type.
id() == ID_union &&
1176 new_symbol.
type.
id() == ID_union &&
1183 if(old_symbol.
type.
id()==ID_array &&
1184 new_symbol.
type.
id()==ID_array &&
1212 "unexpected difference between type symbols");
1224 if(old_symbol.
type==new_symbol.
type)
1228 old_symbol.
type.
id() == ID_struct &&
1230 new_symbol.
type.
id() == ID_struct &&
1235 old_symbol.
type.
id() == ID_struct &&
1237 new_symbol.
type.
id() == ID_struct &&
1242 old_symbol.
type.
id() == ID_union &&
1244 new_symbol.
type.
id() == ID_union &&
1249 old_symbol.
type.
id() == ID_union &&
1251 new_symbol.
type.
id() == ID_union &&
1255 if(old_symbol.
type.
id()==ID_array &&
1256 new_symbol.
type.
id()==ID_array &&
1272 std::unordered_set<irep_idt> &needs_to_be_renamed)
1281 if(symbol_pair.second.is_type)
1287 for(
const auto &symbol_used : symbols_used)
1289 used_by[symbol_used].insert(symbol_pair.first);
1294 std::deque<irep_idt> queue(
1295 needs_to_be_renamed.begin(), needs_to_be_renamed.end());
1297 while(!queue.empty())
1302 const std::unordered_set<irep_idt> &u = used_by[id];
1304 for(
const auto &dep : u)
1305 if(needs_to_be_renamed.insert(dep).second)
1307 queue.push_back(dep);
1309 debug() <<
"LINKING: needs to be renamed (dependency): "
1317 const std::unordered_set<irep_idt> &needs_to_be_renamed)
1321 for(
const irep_idt &
id : needs_to_be_renamed)
1330 new_identifier=
rename(
id);
1332 new_symbol.
name=new_identifier;
1335 debug() <<
"LINKING: renaming " <<
id <<
" to "
1336 << new_identifier <<
eom;
1348 std::map<irep_idt, symbolt> src_symbols;
1352 symbolt symbol=named_symbol.second;
1357 src_symbols.emplace(named_symbol.first, std::move(symbol));
1361 std::unordered_set<irep_idt> collisions;
1363 for(
const auto &named_symbol : src_symbols)
1366 if(named_symbol.first!=named_symbol.second.name)
1379 collisions.insert(named_symbol.first);
1384 for(
const irep_idt &collision : collisions)
1387 symbolt &new_symbol=src_symbols.at(collision);
1398 if(!named_symbol.second.is_type &&
1399 !named_symbol.second.is_macro &&
1400 named_symbol.second.value.is_not_nil())
1416 std::unordered_set<irep_idt> needs_to_be_renamed;
1420 symbol_tablet::symbolst::const_iterator m_it =
1427 needs_to_be_renamed.insert(symbol_pair.first);
1429 debug() <<
"LINKING: needs to be renamed: " << symbol_pair.first <<
eom;
1450 dest_symbol_table, new_symbol_table, message_handler);
1452 return linking.typecheck_main();
bool needs_renaming_type(const symbolt &old_symbol, const symbolt &new_symbol)
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
bool adjust_object_type(const symbolt &old_symbol, const symbolt &new_symbol, bool &set_to_new)
const irep_idt & get_identifier() const
#define UNREACHABLE
This should be used to mark dead code.
const componentst & components() const
symbol_table_baset & src_symbol_table
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
bool has_ellipsis() const
std::string get_base_name(const std::string &in, bool strip_suffix)
cleans a filename from path and extension
static exprt conditional_cast(const exprt &expr, const typet &type)
bool needs_renaming(const symbolt &old_symbol, const symbolt &new_symbol)
const typet & subtype() const
std::string as_string() const
void find_type_and_expr_symbols(const exprt &src, find_symbols_sett &dest)
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
const symbolt & new_symbol
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
std::string type_to_name(const namespacet &ns, const irep_idt &identifier, const typet &type)
const irep_idt & display_name() const
Return language specific display name if present.
casting_replace_symbolt object_type_updates
The type of an expression, extends irept.
std::vector< parametert > parameterst
std::string type_to_string_verbose(const symbolt &symbol, const typet &type) const
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
typet type
Type of symbol.
Operator to dereference a pointer.
std::vector< c_enum_membert > memberst
static symbol_exprt typeless(const irep_idt &id)
Generate a symbol_exprt without a proper type.
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
std::string type_to_string(const irep_idt &identifier, const typet &type) const
void replace(const union_find_replacet &replace_map, string_not_contains_constraintt &constraint)
Unbounded, signed integers (mathematical integers, not bitvectors)
bool needs_renaming_non_type(const symbolt &old_symbol, const symbolt &new_symbol)
Base class for all expressions.
std::vector< componentt > componentst
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
Expression to hold a symbol (variable)
void link_warning(const symbolt &old_symbol, const symbolt &new_symbol, const std::string &msg)
void duplicate_code_symbol(symbolt &old_symbol, symbolt &new_symbol)
symbol_table_baset & main_symbol_table
const exprt & size() const
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
typet & type()
Return the type of the expression.
bool get_bool(const irep_namet &name) const
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
bool adjust_object_type_rec(const typet &type1, const typet &type2, adjust_type_infot &info)
std::unordered_map< irep_idt, std::unordered_set< irep_idt > > used_byt
mstreamt & result() const
const tag_typet & to_tag_type(const typet &type)
Cast a typet to a tag_typet.
static const typet & follow_tags_symbols(const namespacet &ns, const typet &type)
void do_type_dependencies(std::unordered_set< irep_idt > &)
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
const std::string & id2string(const irep_idt &d)
const exprt & compound() const
static bool failed(bool error_indicator)
source_locationt source_location
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
bool base_type_eq(const typet &type1, const typet &type2, const namespacet &ns)
Check types for equality across all levels of hierarchy.
bool linking(symbol_tablet &dest_symbol_table, symbol_tablet &new_symbol_table, message_handlert &message_handler)
const source_locationt & source_location() const
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
const irep_idt & get_identifier() const
optionalt< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
bool replace_symbol_expr(symbol_exprt &dest) const override
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
API to expression classes for Pointers.
const std::string & id_string() const
bool simplify(exprt &expr, const namespacet &ns)
exprt simplify_expr(exprt src, const namespacet &ns)
void duplicate_non_type_symbol(symbolt &old_symbol, symbolt &new_symbol)
const irep_idt & id() const
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
irep_idt rename(irep_idt)
void detailed_conflict_report_rec(const symbolt &old_symbol, const symbolt &new_symbol, const typet &type1, const typet &type2, unsigned depth, exprt &conflict_path)
void insert(const class symbol_exprt &old_expr, const exprt &new_expr)
Sets old_expr to be replaced by new_expr if we don't already have a replacement; otherwise does nothi...
void duplicate_object_symbol(symbolt &old_symbol, symbolt &new_symbol)
const parameterst & parameters() const
std::string expr_to_string(const irep_idt &identifier, const exprt &expr) const
rename_symbolt rename_symbol
void link_error(const symbolt &old_symbol, const symbolt &new_symbol, const std::string &msg)
bool is_zero() const
Return whether the expression is a constant representing 0.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
Extract member of struct or union.
const std::string & get_string(const irep_namet &name) const
exprt value
Initial value of symbol.
std::unordered_set< irep_idt > find_symbols_sett
void duplicate_type_symbol(symbolt &old_symbol, const symbolt &new_symbol)
source_locationt location
Source code location of definition of symbol.
const symbolst & symbols
Read-only field, used to look up symbols given their names.
void insert_expr(const irep_idt &old_id, const irep_idt &new_id)
void detailed_conflict_report(const symbolt &old_symbol, const symbolt &new_symbol, const typet &type1, const typet &type2)
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
std::unordered_set< irep_idt > renamed_ids
const typet & return_type() const
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
std::unordered_set< irep_idt > n_symbols
const symbolt & old_symbol
Semantic type conversion.
A constant literal expression.
irep_idt module
Name of module the symbol belongs to.
bool is_true(const literalt &l)
mstreamt & warning() const
bool is_incomplete() const
A struct/union may be incomplete.
std::unordered_set< irep_idt > o_symbols
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
irep_idt name
The unique identifier.
void insert_type(const irep_idt &old_id, const irep_idt &new_id)
void rename_symbols(const std::unordered_set< irep_idt > &needs_to_be_renamed)
const memberst & members() const