1/*******************************************************************\
5Author: Daniel Kroening, kroening@kroening.com
7\*******************************************************************/
54 continue;
// already in main symbol table
57 continue;
// used this for renaming already
61 continue;
// used by some earlier linking call already
71 // We first take care of file-local non-type symbols.
72 // These are static functions, or static variables
73 // inside static function bodies.
88 // Both are functions.
89 if(old_symbol.
type != new_symbol.
type)
96 diag.warning(old_symbol, new_symbol,
"implicit function declaration");
108 "ignoring conflicting implicit function declaration");
110 // handle (incomplete) function prototypes
111 else if(((
old_t.parameters().empty() &&
old_t.has_ellipsis() &&
113 (
new_t.parameters().empty() &&
new_t.has_ellipsis() &&
116 if(
old_t.parameters().empty() &&
117 old_t.has_ellipsis() &&
125 // replace weak symbols
133 "function declaration conflicts with with weak definition");
148 "ignoring conflicting weak function declaration");
151 // aliasing may alter the type
162 "ignoring conflicting function alias declaration");
164 // conflicting declarations without a definition, matching return
169 old_symbol, new_symbol,
"ignoring conflicting function declarations");
171 if(
old_t.parameters().size()<
new_t.parameters().size())
178 // mismatch on number of parameters is definitively an error
179 else if((
old_t.parameters().size()<
new_t.parameters().size() &&
181 !
old_t.has_ellipsis()) ||
182 (
old_t.parameters().size()>
new_t.parameters().size() &&
184 !
new_t.has_ellipsis()))
189 "conflicting parameter counts of function declarations");
191 // error logged, continue typechecking other symbols
196 // the number of parameters matches, collect all the conflicts
197 // and see whether they can be cured
200 typedef std::deque<std::pair<typet, typet> >
conflictst;
203 if(
old_t.return_type() !=
new_t.return_type())
205 diag.warning(old_symbol, new_symbol,
"conflicting return types");
210 code_typet::parameterst::const_iterator
220 std::make_pair(
o_it->type(),
n_it->type()));
229 "conflicting parameter counts of function declarations");
231 // error logged, continue typechecking other symbols
244 "conflicting parameter counts of function declarations");
246 // error logged, continue typechecking other symbols
258 // different pointer arguments without implementation may work
265 warn_msg=
"different pointer types in extern function";
267 // different pointer arguments with implementation - the
268 // implementation is always right, even though such code may
269 // be severely broken
276 warn_msg=
"pointer parameter types differ between "
277 "declaration and definition";
282 // transparent union with (or entirely without) implementation is
283 // ok -- this primarily helps all those people that don't get
284 // _GNU_SOURCE consistent
308 warn_msg=
"conflict on transparent union parameter in function";
315 // different non-pointer arguments with implementation - the
316 // implementation is always right, even though such code may
317 // be severely broken
322 warn_msg=
"non-pointer parameter types differ between "
323 "declaration and definition";
334 diag.detailed_conflict_report(
340 diag.error(old_symbol, new_symbol,
"conflicting function declarations");
342 // error logged, continue typechecking other symbols
347 // warns about the first inconsistency
366 // the one with body wins!
370 old_symbol.
type=new_symbol.
type;
// for parameter identifiers
375 // replace any previous update
382 // ok, silently ignore
384 else if(old_symbol.
type == new_symbol.
type)
386 // keep the one in old_symbol -- libraries come last!
389 log.debug() <<
"function '" << old_symbol.
name <<
"' in module '"
391 <<
"' is shadowed by a definition in module '"
396 diag.error(old_symbol, new_symbol,
"duplicate definition of function");
415 if(
info.o_symbols.insert(identifier).second)
419 info.o_symbols.erase(identifier);
432 if(
info.n_symbols.insert(identifier).second)
436 info.n_symbols.erase(identifier);
445 info.set_to_new=
true;
// store new type
458 info.set_to_new=
true;
// store new type
466 info.set_to_new =
true;
// store new type
484 else if(
t1.id()!=
t2.id())
486 // type classes do not match and can't be fixed
494 bool s=
info.set_to_new;
500 "conflicting pointer types for variable");
507 "conflicting pointer types for variable");
510 if(
info.old_symbol.is_extern && !
info.new_symbol.is_extern)
512 info.set_to_new =
true;
// store new type
522 // still need to compare size
530 info.set_to_new=
true;
// store new type
534 // ok, we will use the old type
544 "conflicting array sizes for variable");
546 // error logged, continue typechecking other symbols
558 "conflicting array sizes for variable");
560 // error logged, continue typechecking other symbols
575 struct_union_typet::componentst::const_iterator
581 if(
it1->get_name()!=
it2->get_name() ||
604 set_to_new=
info.set_to_new;
613 // both are variables
614 bool set_to_new =
false;
616 if(old_symbol.
type != new_symbol.
type)
627 // provide additional diagnostic output for
628 // struct/union/array/enum
634 diag.detailed_conflict_report(
635 old_symbol, new_symbol, old_symbol.
type, new_symbol.
type);
638 diag.error(old_symbol, new_symbol,
"conflicting types for variable");
640 // error logged, continue typechecking other symbols
650 // care about initializers
677 log.warning().source_location = new_symbol.
location;
679 log.warning() <<
"conflicting initializers for"
686 log.warning() <<
"ignoring new value in module "
697 // the type has been updated, now make sure that the initialising assignment
698 // will have matching types
707 // we do not permit different contracts with the same name to be defined, or
708 // cases where only one of the symbols is a contract
712 old_symbol.
type != new_symbol.
type))
715 diag.error(old_symbol, new_symbol,
"conflict on code contract");
718 // see if it is a function or a variable
726 diag.error(old_symbol, new_symbol,
"conflicting definition for symbol");
728 // error logged, continue typechecking other symbols
742 // it's enough that one isn't extern for the final one not to be
755 diag.error(old_symbol, new_symbol,
"conflicting definition for symbol");
757 // error logged, continue typechecking other symbols
761 if(old_symbol.
type==new_symbol.
type)
829 diag.detailed_conflict_report(
830 old_symbol, new_symbol, old_symbol.
type, new_symbol.
type);
833 old_symbol, new_symbol,
"unexpected difference between type symbols");
845 if(old_symbol.
type==new_symbol.
type)
910 // Any type that uses a symbol that will be renamed also
911 // needs to be renamed, and so on, until saturation.
913 // X -> Y iff Y uses X for new symbol type IDs X and Y
914 std::unordered_map<irep_idt, std::unordered_set<irep_idt>>
used_by;
920 // find type and array-size symbols
931 std::deque<irep_idt> queue(
934 while(!queue.empty())
939 const std::unordered_set<irep_idt> &
u =
used_by[id];
941 for(
const auto &
dep :
u)
944 queue.push_back(
dep);
947 log.debug() <<
"LINKING: needs to be renamed (dependency): " <<
dep
994 // First apply the renaming
998 // apply the renaming
1003 symbol.
name = it->second;
1008 // Move over all the non-colliding ones
1031 // Now do the collisions
1043 // Apply type updates to initializers
1047 !it->second.is_type && !it->second.is_macro &&
1048 it->second.value.is_not_nil())
1060 // We do this in three phases. We first figure out which symbols need to
1061 // be renamed, and then build the renaming, and finally apply this
1062 // renaming in the second pass over the symbol table.
1064 // PHASE 1: identify symbols to be renamed
1070 symbol_table_baset::symbolst::const_iterator
m_it =
1084 if(
m_it->second.is_type)
1097 log.debug() <<
"LINKING: needs to be renamed: " <<
symbol_pair.first
1106 // rename within main symbol table
1120 // renaming types may trigger further renaming
1123 // PHASE 2: actually rename them
1126 // PHASE 3: copy new symbols to main table
1139 return linking.link(new_symbol_table);
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Base class for all expressions.
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
bool get_bool(const irep_idt &name) const
const irep_idt & id() const
std::unordered_map< irep_idt, irep_idt > rename_symbols(const symbol_table_baset &, const std::unordered_set< irep_idt > &needs_to_be_renamed)
void duplicate_non_type_symbol(symbolt &old_symbol, symbolt &new_symbol)
bool adjust_object_type(const symbolt &old_symbol, const symbolt &new_symbol, bool &set_to_new)
bool link(const symbol_table_baset &src_symbol_table)
Merges the symbol table src_symbol_table into main_symbol_table, renaming symbols from src_symbol_tab...
renamingt needs_renaming(const symbolt &old_symbol, const symbolt &new_symbol)
bool adjust_object_type_rec(const typet &type1, const typet &type2, adjust_type_infot &info)
rename_symbolt rename_main_symbol
void copy_symbols(const symbol_table_baset &, const std::unordered_map< irep_idt, irep_idt > &)
irep_idt rename(const symbol_table_baset &, const irep_idt &)
renamingt needs_renaming_type(const symbolt &old_symbol, const symbolt &new_symbol)
symbol_table_baset & main_symbol_table
renamingt needs_renaming_non_type(const symbolt &old_symbol, const symbolt &new_symbol)
void duplicate_object_symbol(symbolt &old_symbol, symbolt &new_symbol)
casting_replace_symbolt object_type_updates
std::unordered_set< irep_idt > renamed_ids
void duplicate_type_symbol(symbolt &old_symbol, const symbolt &new_symbol)
rename_symbolt rename_new_symbol
void duplicate_code_symbol(symbolt &old_symbol, symbolt &new_symbol)
message_handlert & message_handler
std::size_t get_message_count(unsigned level) const
Class that provides messages with a built-in verbosity 'level'.
static const commandt quote_begin
Start quoted text.
static const commandt quote_end
End quoted text.
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...
void insert_type(const irep_idt &old_id, const irep_idt &new_id)
void insert_expr(const irep_idt &old_id, const irep_idt &new_id)
std::size_t erase(const irep_idt &id)
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...
std::vector< componentt > componentst
The symbol table base class interface.
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
virtual std::pair< symbolt &, bool > insert(symbolt symbol)=0
Move or copy a new symbol to the symbol table.
virtual symbolt * get_writeable(const irep_idt &name)=0
Find a symbol in the symbol table for read-write access.
virtual void erase(const symbolst::const_iterator &entry)=0
Remove a symbol from the symbol table.
virtual iteratort begin()=0
const symbolst & symbols
Read-only field, used to look up symbols given their names.
virtual iteratort end()=0
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
source_locationt location
Source code location of definition of symbol.
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
typet type
Type of symbol.
irep_idt name
The unique identifier.
exprt value
Initial value of symbol.
Semantic type conversion.
The type of an expression, extends irept.
void find_type_and_expr_symbols(const exprt &src, find_symbols_sett &dest, const std::vector< irep_idt > &subs_to_find)
Find identifiers with id ID_symbol of the sub expressions and the subs with ID in subs_to_find consid...
std::unordered_set< irep_idt > find_symbols_sett
const std::string & id2string(const irep_idt &d)
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
std::string type_to_name(const namespacet &ns, const irep_idt &identifier, const typet &type)
static void do_type_dependencies(const symbol_table_baset &src_symbol_table, std::unordered_set< irep_idt > &needs_to_be_renamed, message_handlert &message_handler)
static const typet & follow_tags_symbols(const namespacet &ns, const typet &type)
bool linking(symbol_table_baset &dest_symbol_table, const symbol_table_baset &new_symbol_table, message_handlert &message_handler)
Merges the symbol table new_symbol_table into dest_symbol_table, renaming symbols from new_symbol_tab...
std::optional< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
bool simplify(exprt &expr, const namespacet &ns)
exprt simplify_expr(exprt src, const namespacet &ns)
#define CHECK_RETURN(CONDITION)
#define PRECONDITION(CONDITION)
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
const tag_typet & to_tag_type(const typet &type)
Cast a typet to a tag_typet.
void replace(const union_find_replacet &replace_map, string_not_contains_constraintt &constraint)
static bool failed(bool error_indicator)