CBMC
linking.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: ANSI-C Linking
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include "linking.h"
13 
14 #include <deque>
15 #include <unordered_set>
16 
17 #include <util/c_types.h>
18 #include <util/find_symbols.h>
20 #include <util/pointer_expr.h>
22 #include <util/simplify_expr.h>
23 #include <util/symbol_table.h>
24 
25 #include <langapi/language_util.h>
26 
27 #include "linking_class.h"
28 
30 {
31  expr_mapt::const_iterator it = expr_map.find(s.get_identifier());
32 
33  if(it == expr_map.end())
34  return true;
35 
36  const exprt &e = it->second;
37 
38  if(e.type().id() != ID_array)
39  {
40  typet type = s.type();
41  static_cast<exprt &>(s) = typecast_exprt::conditional_cast(e, type);
42  }
43  else
44  static_cast<exprt &>(s) = e;
45 
46  return false;
47 }
48 
50  const irep_idt &identifier,
51  const exprt &expr) const
52 {
53  return from_expr(ns, identifier, expr);
54 }
55 
57  const irep_idt &identifier,
58  const typet &type) const
59 {
60  return from_type(ns, identifier, type);
61 }
62 
63 static const typet &follow_tags_symbols(
64  const namespacet &ns,
65  const typet &type)
66 {
67  if(type.id() == ID_c_enum_tag)
68  return ns.follow_tag(to_c_enum_tag_type(type));
69  else if(type.id()==ID_struct_tag)
70  return ns.follow_tag(to_struct_tag_type(type));
71  else if(type.id()==ID_union_tag)
72  return ns.follow_tag(to_union_tag_type(type));
73  else
74  return type;
75 }
76 
78  const symbolt &symbol,
79  const typet &type) const
80 {
81  const typet &followed=follow_tags_symbols(ns, type);
82 
83  if(followed.id()==ID_struct || followed.id()==ID_union)
84  {
85  std::string result=followed.id_string();
86 
87  const std::string &tag=followed.get_string(ID_tag);
88  if(!tag.empty())
89  result+=" "+tag;
90 
91  if(to_struct_union_type(followed).is_incomplete())
92  {
93  result += " (incomplete)";
94  }
95  else
96  {
97  result += " {\n";
98 
99  for(const auto &c : to_struct_union_type(followed).components())
100  {
101  const typet &subtype = c.type();
102  result += " ";
103  result += type_to_string(symbol.name, subtype);
104  result += ' ';
105 
106  if(!c.get_base_name().empty())
107  result += id2string(c.get_base_name());
108  else
109  result += id2string(c.get_name());
110 
111  result += ";\n";
112  }
113 
114  result += '}';
115  }
116 
117  return result;
118  }
119  else if(followed.id()==ID_pointer)
120  {
121  return type_to_string_verbose(
122  symbol, to_pointer_type(followed).base_type()) +
123  " *";
124  }
125 
126  return type_to_string(symbol.name, type);
127 }
128 
130  const symbolt &old_symbol,
131  const symbolt &new_symbol,
132  const typet &type1,
133  const typet &type2,
134  unsigned depth,
135  exprt &conflict_path)
136 {
137  #ifdef DEBUG
138  debug() << "<BEGIN DEPTH " << depth << ">" << eom;
139  #endif
140 
141  std::string msg;
142 
143  const typet &t1=follow_tags_symbols(ns, type1);
144  const typet &t2=follow_tags_symbols(ns, type2);
145 
146  if(t1.id()!=t2.id())
147  msg="type classes differ";
148  else if(t1.id()==ID_pointer ||
149  t1.id()==ID_array)
150  {
151  if(
152  depth > 0 &&
153  to_type_with_subtype(t1).subtype() != to_type_with_subtype(t2).subtype())
154  {
155  if(conflict_path.type().id() == ID_pointer)
156  conflict_path = dereference_exprt(conflict_path);
157 
159  old_symbol,
160  new_symbol,
161  to_type_with_subtype(t1).subtype(),
162  to_type_with_subtype(t2).subtype(),
163  depth - 1,
164  conflict_path);
165  }
166  else if(t1.id()==ID_pointer)
167  msg="pointer types differ";
168  else
169  msg="array types differ";
170  }
171  else if(t1.id()==ID_struct ||
172  t1.id()==ID_union)
173  {
174  const struct_union_typet::componentst &components1=
176 
177  const struct_union_typet::componentst &components2=
179 
180  exprt conflict_path_before=conflict_path;
181 
182  if(components1.size()!=components2.size())
183  {
184  msg="number of members is different (";
185  msg+=std::to_string(components1.size())+'/';
186  msg+=std::to_string(components2.size())+')';
187  }
188  else
189  {
190  for(std::size_t i=0; i<components1.size(); ++i)
191  {
192  const typet &subtype1=components1[i].type();
193  const typet &subtype2=components2[i].type();
194 
195  if(components1[i].get_name()!=components2[i].get_name())
196  {
197  msg="names of member "+std::to_string(i)+" differ (";
198  msg+=id2string(components1[i].get_name())+'/';
199  msg+=id2string(components2[i].get_name())+')';
200  break;
201  }
202  else if(subtype1 != subtype2)
203  {
204  typedef std::unordered_set<typet, irep_hash> type_sett;
205  type_sett parent_types;
206 
207  exprt e=conflict_path_before;
208  while(e.id()==ID_dereference ||
209  e.id()==ID_member ||
210  e.id()==ID_index)
211  {
212  parent_types.insert(e.type());
213  if(e.id() == ID_dereference)
214  e = to_dereference_expr(e).pointer();
215  else if(e.id() == ID_member)
216  e = to_member_expr(e).compound();
217  else if(e.id() == ID_index)
218  e = to_index_expr(e).array();
219  else
220  UNREACHABLE;
221  }
222 
223  conflict_path=conflict_path_before;
224  conflict_path.type()=t1;
225  conflict_path=
226  member_exprt(conflict_path, components1[i]);
227 
228  if(depth>0 &&
229  parent_types.find(t1)==parent_types.end())
231  old_symbol,
232  new_symbol,
233  subtype1,
234  subtype2,
235  depth-1,
236  conflict_path);
237  else
238  {
239  msg="type of member "+
240  id2string(components1[i].get_name())+
241  " differs";
242  if(depth>0)
243  {
244  std::string msg_bak;
245  msg_bak.swap(msg);
246  symbol_exprt c = symbol_exprt::typeless(ID_C_this);
248  old_symbol,
249  new_symbol,
250  subtype1,
251  subtype2,
252  depth-1,
253  c);
254  msg.swap(msg_bak);
255  }
256  }
257 
258  if(parent_types.find(t1)==parent_types.end())
259  break;
260  }
261  }
262  }
263  }
264  else if(t1.id()==ID_c_enum)
265  {
266  const c_enum_typet::memberst &members1=
267  to_c_enum_type(t1).members();
268 
269  const c_enum_typet::memberst &members2=
270  to_c_enum_type(t2).members();
271 
272  if(
273  to_c_enum_type(t1).underlying_type() !=
274  to_c_enum_type(t2).underlying_type())
275  {
276  msg="enum value types are different (";
277  msg +=
278  type_to_string(old_symbol.name, to_c_enum_type(t1).underlying_type()) +
279  '/';
280  msg +=
281  type_to_string(new_symbol.name, to_c_enum_type(t2).underlying_type()) +
282  ')';
283  }
284  else if(members1.size()!=members2.size())
285  {
286  msg="number of enum members is different (";
287  msg+=std::to_string(members1.size())+'/';
288  msg+=std::to_string(members2.size())+')';
289  }
290  else
291  {
292  for(std::size_t i=0; i<members1.size(); ++i)
293  {
294  if(members1[i].get_base_name()!=members2[i].get_base_name())
295  {
296  msg="names of member "+std::to_string(i)+" differ (";
297  msg+=id2string(members1[i].get_base_name())+'/';
298  msg+=id2string(members2[i].get_base_name())+')';
299  break;
300  }
301  else if(members1[i].get_value()!=members2[i].get_value())
302  {
303  msg="values of member "+std::to_string(i)+" differ (";
304  msg+=id2string(members1[i].get_value())+'/';
305  msg+=id2string(members2[i].get_value())+')';
306  break;
307  }
308  }
309  }
310 
311  msg+="\nenum declarations at\n";
312  msg+=t1.source_location().as_string()+" and\n";
313  msg+=t1.source_location().as_string();
314  }
315  else if(t1.id()==ID_code)
316  {
317  const code_typet::parameterst &parameters1=
318  to_code_type(t1).parameters();
319 
320  const code_typet::parameterst &parameters2=
321  to_code_type(t2).parameters();
322 
323  const typet &return_type1=to_code_type(t1).return_type();
324  const typet &return_type2=to_code_type(t2).return_type();
325 
326  if(parameters1.size()!=parameters2.size())
327  {
328  msg="parameter counts differ (";
329  msg+=std::to_string(parameters1.size())+'/';
330  msg+=std::to_string(parameters2.size())+')';
331  }
332  else if(return_type1 != return_type2)
333  {
334  conflict_path=
335  index_exprt(conflict_path,
337 
338  if(depth>0)
340  old_symbol,
341  new_symbol,
342  return_type1,
343  return_type2,
344  depth-1,
345  conflict_path);
346  else
347  msg="return types differ";
348  }
349  else
350  {
351  for(std::size_t i=0; i<parameters1.size(); i++)
352  {
353  const typet &subtype1=parameters1[i].type();
354  const typet &subtype2=parameters2[i].type();
355 
356  if(subtype1 != subtype2)
357  {
358  conflict_path=
359  index_exprt(conflict_path,
361 
362  if(depth>0)
364  old_symbol,
365  new_symbol,
366  subtype1,
367  subtype2,
368  depth-1,
369  conflict_path);
370  else
371  msg="parameter types differ";
372 
373  break;
374  }
375  }
376  }
377  }
378  else
379  msg="conflict on POD";
380 
381  if(!msg.empty())
382  {
383  error() << '\n';
384  error() << "reason for conflict at "
385  << expr_to_string(irep_idt(), conflict_path) << ": " << msg << '\n';
386 
387  error() << '\n';
388  error() << type_to_string_verbose(old_symbol, t1) << '\n';
389  error() << type_to_string_verbose(new_symbol, t2) << '\n';
390  }
391 
392  #ifdef DEBUG
393  debug() << "<END DEPTH " << depth << ">" << eom;
394  #endif
395 }
396 
398  const symbolt &old_symbol,
399  const symbolt &new_symbol,
400  const std::string &msg)
401 {
402  error().source_location=new_symbol.location;
403 
404  error() << "error: " << msg << " '" << old_symbol.display_name() << "'"
405  << '\n';
406  error() << "old definition in module '" << old_symbol.module << "' "
407  << old_symbol.location << '\n'
408  << type_to_string_verbose(old_symbol) << '\n';
409  error() << "new definition in module '" << new_symbol.module << "' "
410  << new_symbol.location << '\n'
411  << type_to_string_verbose(new_symbol) << eom;
412 }
413 
415  const symbolt &old_symbol,
416  const symbolt &new_symbol,
417  const std::string &msg)
418 {
419  warning().source_location=new_symbol.location;
420 
421  warning() << "warning: " << msg << " \""
422  << old_symbol.display_name()
423  << "\"" << '\n';
424  warning() << "old definition in module " << old_symbol.module << " "
425  << old_symbol.location << '\n'
426  << type_to_string_verbose(old_symbol) << '\n';
427  warning() << "new definition in module " << new_symbol.module << " "
428  << new_symbol.location << '\n'
429  << type_to_string_verbose(new_symbol) << eom;
430 }
431 
433 {
434  unsigned cnt=0;
435 
436  while(true)
437  {
438  irep_idt new_identifier=
439  id2string(id)+"$link"+std::to_string(++cnt);
440 
441  if(main_symbol_table.symbols.find(new_identifier)!=
443  continue; // already in main symbol table
444 
445  if(!renamed_ids.insert(new_identifier).second)
446  continue; // used this for renaming already
447 
448  if(src_symbol_table.symbols.find(new_identifier)!=
450  continue; // used by some earlier linking call already
451 
452  return new_identifier;
453  }
454 }
455 
457  const symbolt &old_symbol,
458  const symbolt &new_symbol)
459 {
460  // We first take care of file-local non-type symbols.
461  // These are static functions, or static variables
462  // inside static function bodies.
463  if(new_symbol.is_file_local ||
464  old_symbol.is_file_local)
465  return true;
466 
467  return false;
468 }
469 
471  symbolt &old_symbol,
472  symbolt &new_symbol)
473 {
474  // Both are functions.
475  if(old_symbol.type != new_symbol.type)
476  {
477  const code_typet &old_t=to_code_type(old_symbol.type);
478  const code_typet &new_t=to_code_type(new_symbol.type);
479 
480  // if one of them was an implicit declaration then only conflicts on the
481  // return type are an error as we would end up with assignments with
482  // mismatching types; as we currently do not patch these by inserting type
483  // casts we need to fail hard
484  if(old_symbol.type.get_bool(ID_C_incomplete) && old_symbol.value.is_nil())
485  {
486  if(old_t.return_type() == new_t.return_type())
487  link_warning(old_symbol, new_symbol, "implicit function declaration");
488  else
489  link_error(
490  old_symbol,
491  new_symbol,
492  "implicit function declaration");
493 
494  old_symbol.type=new_symbol.type;
495  old_symbol.location=new_symbol.location;
496  old_symbol.is_weak=new_symbol.is_weak;
497  }
498  else if(
499  new_symbol.type.get_bool(ID_C_incomplete) && new_symbol.value.is_nil())
500  {
501  if(old_t.return_type() == new_t.return_type())
502  link_warning(
503  old_symbol,
504  new_symbol,
505  "ignoring conflicting implicit function declaration");
506  else
507  link_error(
508  old_symbol,
509  new_symbol,
510  "implicit function declaration");
511  }
512  // handle (incomplete) function prototypes
513  else if(
514  old_t.return_type() == new_t.return_type() &&
515  ((old_t.parameters().empty() && old_t.has_ellipsis() &&
516  old_symbol.value.is_nil()) ||
517  (new_t.parameters().empty() && new_t.has_ellipsis() &&
518  new_symbol.value.is_nil())))
519  {
520  if(old_t.parameters().empty() &&
521  old_t.has_ellipsis() &&
522  old_symbol.value.is_nil())
523  {
524  old_symbol.type=new_symbol.type;
525  old_symbol.location=new_symbol.location;
526  old_symbol.is_weak=new_symbol.is_weak;
527  }
528  }
529  // replace weak symbols
530  else if(old_symbol.is_weak)
531  {
532  if(new_symbol.value.is_nil())
533  link_warning(
534  old_symbol,
535  new_symbol,
536  "function declaration conflicts with with weak definition");
537  else
538  old_symbol.value.make_nil();
539  }
540  else if(new_symbol.is_weak)
541  {
542  if(new_symbol.value.is_nil() ||
543  old_symbol.value.is_not_nil())
544  {
545  new_symbol.value.make_nil();
546 
547  link_warning(
548  old_symbol,
549  new_symbol,
550  "ignoring conflicting weak function declaration");
551  }
552  }
553  // aliasing may alter the type
554  else if((new_symbol.is_macro &&
555  new_symbol.value.is_not_nil() &&
556  old_symbol.value.is_nil()) ||
557  (old_symbol.is_macro &&
558  old_symbol.value.is_not_nil() &&
559  new_symbol.value.is_nil()))
560  {
561  link_warning(
562  old_symbol,
563  new_symbol,
564  "ignoring conflicting function alias declaration");
565  }
566  // conflicting declarations without a definition, matching return
567  // types
568  else if(
569  old_t.return_type() == new_t.return_type() && old_symbol.value.is_nil() &&
570  new_symbol.value.is_nil())
571  {
572  link_warning(
573  old_symbol,
574  new_symbol,
575  "ignoring conflicting function declarations");
576 
577  if(old_t.parameters().size()<new_t.parameters().size())
578  {
579  old_symbol.type=new_symbol.type;
580  old_symbol.location=new_symbol.location;
581  old_symbol.is_weak=new_symbol.is_weak;
582  }
583  }
584  // mismatch on number of parameters is definitively an error
585  else if((old_t.parameters().size()<new_t.parameters().size() &&
586  new_symbol.value.is_not_nil() &&
587  !old_t.has_ellipsis()) ||
588  (old_t.parameters().size()>new_t.parameters().size() &&
589  old_symbol.value.is_not_nil() &&
590  !new_t.has_ellipsis()))
591  {
592  link_error(
593  old_symbol,
594  new_symbol,
595  "conflicting parameter counts of function declarations");
596 
597  // error logged, continue typechecking other symbols
598  return;
599  }
600  else
601  {
602  // the number of parameters matches, collect all the conflicts
603  // and see whether they can be cured
604  std::string warn_msg;
605  bool replace=false;
606  typedef std::deque<std::pair<typet, typet> > conflictst;
607  conflictst conflicts;
608 
609  if(old_t.return_type() != new_t.return_type())
610  conflicts.push_back(
611  std::make_pair(old_t.return_type(), new_t.return_type()));
612 
613  code_typet::parameterst::const_iterator
614  n_it=new_t.parameters().begin(),
615  o_it=old_t.parameters().begin();
616  for( ;
617  o_it!=old_t.parameters().end() &&
618  n_it!=new_t.parameters().end();
619  ++o_it, ++n_it)
620  {
621  if(o_it->type() != n_it->type())
622  conflicts.push_back(
623  std::make_pair(o_it->type(), n_it->type()));
624  }
625  if(o_it!=old_t.parameters().end())
626  {
627  if(!new_t.has_ellipsis() && old_symbol.value.is_not_nil())
628  {
629  link_error(
630  old_symbol,
631  new_symbol,
632  "conflicting parameter counts of function declarations");
633 
634  // error logged, continue typechecking other symbols
635  return;
636  }
637 
638  replace=new_symbol.value.is_not_nil();
639  }
640  else if(n_it!=new_t.parameters().end())
641  {
642  if(!old_t.has_ellipsis() && new_symbol.value.is_not_nil())
643  {
644  link_error(
645  old_symbol,
646  new_symbol,
647  "conflicting parameter counts of function declarations");
648 
649  // error logged, continue typechecking other symbols
650  return;
651  }
652 
653  replace=new_symbol.value.is_not_nil();
654  }
655 
656  while(!conflicts.empty())
657  {
658  const typet &t1=follow_tags_symbols(ns, conflicts.front().first);
659  const typet &t2=follow_tags_symbols(ns, conflicts.front().second);
660 
661  // void vs. non-void return type may be acceptable if the
662  // return value is never used
663  if((t1.id()==ID_empty || t2.id()==ID_empty) &&
664  (old_symbol.value.is_nil() || new_symbol.value.is_nil()))
665  {
666  if(warn_msg.empty())
667  warn_msg="void/non-void return type conflict on function";
668  replace=
669  new_symbol.value.is_not_nil() ||
670  (old_symbol.value.is_nil() && t2.id()==ID_empty);
671  }
672  // different pointer arguments without implementation may work
673  else if((t1.id()==ID_pointer || t2.id()==ID_pointer) &&
675  old_symbol.value.is_nil() && new_symbol.value.is_nil())
676  {
677  if(warn_msg.empty())
678  warn_msg="different pointer types in extern function";
679  }
680  // different pointer arguments with implementation - the
681  // implementation is always right, even though such code may
682  // be severely broken
683  else if((t1.id()==ID_pointer || t2.id()==ID_pointer) &&
685  old_symbol.value.is_nil()!=new_symbol.value.is_nil())
686  {
687  if(warn_msg.empty())
688  warn_msg="pointer parameter types differ between "
689  "declaration and definition";
690  replace=new_symbol.value.is_not_nil();
691  }
692  // transparent union with (or entirely without) implementation is
693  // ok -- this primarily helps all those people that don't get
694  // _GNU_SOURCE consistent
695  else if((t1.id()==ID_union &&
696  (t1.get_bool(ID_C_transparent_union) ||
697  conflicts.front().first.get_bool(ID_C_transparent_union))) ||
698  (t2.id()==ID_union &&
699  (t2.get_bool(ID_C_transparent_union) ||
700  conflicts.front().second.get_bool(ID_C_transparent_union))))
701  {
702  const bool use_old=
703  t1.id()==ID_union &&
704  (t1.get_bool(ID_C_transparent_union) ||
705  conflicts.front().first.get_bool(ID_C_transparent_union)) &&
706  new_symbol.value.is_nil();
707 
708  const union_typet &union_type=
709  to_union_type(t1.id()==ID_union?t1:t2);
710  const typet &src_type=t1.id()==ID_union?t2:t1;
711 
712  bool found=false;
713  for(const auto &c : union_type.components())
714  if(c.type() == src_type)
715  {
716  found=true;
717  if(warn_msg.empty())
718  warn_msg="conflict on transparent union parameter in function";
719  replace=!use_old;
720  }
721 
722  if(!found)
723  break;
724  }
725  // different non-pointer arguments with implementation - the
726  // implementation is always right, even though such code may
727  // be severely broken
728  else if(pointer_offset_bits(t1, ns)==pointer_offset_bits(t2, ns) &&
729  old_symbol.value.is_nil()!=new_symbol.value.is_nil())
730  {
731  if(warn_msg.empty())
732  warn_msg="non-pointer parameter types differ between "
733  "declaration and definition";
734  replace=new_symbol.value.is_not_nil();
735  }
736  else
737  break;
738 
739  conflicts.pop_front();
740  }
741 
742  if(!conflicts.empty())
743  {
745  old_symbol,
746  new_symbol,
747  conflicts.front().first,
748  conflicts.front().second);
749 
750  link_error(
751  old_symbol,
752  new_symbol,
753  "conflicting function declarations");
754 
755  // error logged, continue typechecking other symbols
756  return;
757  }
758  else
759  {
760  // warns about the first inconsistency
761  link_warning(old_symbol, new_symbol, warn_msg);
762 
763  if(replace)
764  {
765  old_symbol.type=new_symbol.type;
766  old_symbol.location=new_symbol.location;
767  }
768  }
769  }
770  }
771 
772  if(!new_symbol.value.is_nil())
773  {
774  if(old_symbol.value.is_nil())
775  {
776  // the one with body wins!
777  rename_symbol(new_symbol.value);
778  rename_symbol(new_symbol.type);
779  old_symbol.value=new_symbol.value;
780  old_symbol.type=new_symbol.type; // for parameter identifiers
781  old_symbol.is_weak=new_symbol.is_weak;
782  old_symbol.location=new_symbol.location;
783  old_symbol.is_macro=new_symbol.is_macro;
784  }
785  else if(to_code_type(old_symbol.type).get_inlined())
786  {
787  // ok, silently ignore
788  }
789  else if(old_symbol.type == new_symbol.type)
790  {
791  // keep the one in old_symbol -- libraries come last!
792  debug().source_location = new_symbol.location;
793 
794  debug() << "function '" << old_symbol.name << "' in module '"
795  << new_symbol.module
796  << "' is shadowed by a definition in module '"
797  << old_symbol.module << "'" << eom;
798  }
799  else
800  link_error(
801  old_symbol,
802  new_symbol,
803  "duplicate definition of function");
804  }
805 }
806 
808  const typet &t1,
809  const typet &t2,
810  adjust_type_infot &info)
811 {
812  if(t1 == t2)
813  return false;
814 
815  if(
816  t1.id() == ID_struct_tag || t1.id() == ID_union_tag ||
817  t1.id() == ID_c_enum_tag)
818  {
819  const irep_idt &identifier = to_tag_type(t1).get_identifier();
820 
821  if(info.o_symbols.insert(identifier).second)
822  {
823  bool result=
825  info.o_symbols.erase(identifier);
826 
827  return result;
828  }
829 
830  return false;
831  }
832  else if(
833  t2.id() == ID_struct_tag || t2.id() == ID_union_tag ||
834  t2.id() == ID_c_enum_tag)
835  {
836  const irep_idt &identifier = to_tag_type(t2).get_identifier();
837 
838  if(info.n_symbols.insert(identifier).second)
839  {
840  bool result=
842  info.n_symbols.erase(identifier);
843 
844  return result;
845  }
846 
847  return false;
848  }
849  else if(t1.id()==ID_pointer && t2.id()==ID_array)
850  {
851  info.set_to_new=true; // store new type
852 
853  return false;
854  }
855  else if(t1.id()==ID_array && t2.id()==ID_pointer)
856  {
857  // ignore
858  return false;
859  }
860  else if(
861  t1.id() == ID_struct && to_struct_type(t1).is_incomplete() &&
862  t2.id() == ID_struct && !to_struct_type(t2).is_incomplete())
863  {
864  info.set_to_new=true; // store new type
865 
866  return false;
867  }
868  else if(
869  t1.id() == ID_union && to_union_type(t1).is_incomplete() &&
870  t2.id() == ID_union && !to_union_type(t2).is_incomplete())
871  {
872  info.set_to_new = true; // store new type
873 
874  return false;
875  }
876  else if(
877  t1.id() == ID_struct && !to_struct_type(t1).is_incomplete() &&
878  t2.id() == ID_struct && to_struct_type(t2).is_incomplete())
879  {
880  // ignore
881  return false;
882  }
883  else if(
884  t1.id() == ID_union && !to_union_type(t1).is_incomplete() &&
885  t2.id() == ID_union && to_union_type(t2).is_incomplete())
886  {
887  // ignore
888  return false;
889  }
890  else if(t1.id()!=t2.id())
891  {
892  // type classes do not match and can't be fixed
893  return true;
894  }
895 
896  if(t1.id()==ID_pointer)
897  {
898  #if 0
899  bool s=info.set_to_new;
900  if(adjust_object_type_rec(t1.subtype(), t2.subtype(), info))
901  {
902  link_warning(
903  info.old_symbol,
904  info.new_symbol,
905  "conflicting pointer types for variable");
906  info.set_to_new=s;
907  }
908  #else
909  link_warning(
910  info.old_symbol,
911  info.new_symbol,
912  "conflicting pointer types for variable");
913  #endif
914 
915  if(info.old_symbol.is_extern && !info.new_symbol.is_extern)
916  {
917  info.set_to_new = true; // store new type
918  }
919 
920  return false;
921  }
922  else if(
923  t1.id() == ID_array &&
925  to_array_type(t1).element_type(), to_array_type(t2).element_type(), info))
926  {
927  // still need to compare size
928  const exprt &old_size=to_array_type(t1).size();
929  const exprt &new_size=to_array_type(t2).size();
930 
931  if((old_size.is_nil() && new_size.is_not_nil()) ||
932  (old_size.is_zero() && new_size.is_not_nil()) ||
933  info.old_symbol.is_weak)
934  {
935  info.set_to_new=true; // store new type
936  }
937  else if(new_size.is_nil() ||
938  new_size.is_zero() ||
939  info.new_symbol.is_weak)
940  {
941  // ok, we will use the old type
942  }
943  else
944  {
945  if(new_size.type() != old_size.type())
946  {
947  link_error(
948  info.old_symbol,
949  info.new_symbol,
950  "conflicting array sizes for variable");
951 
952  // error logged, continue typechecking other symbols
953  return true;
954  }
955 
956  equal_exprt eq(old_size, new_size);
957 
958  if(!simplify_expr(eq, ns).is_true())
959  {
960  link_error(
961  info.old_symbol,
962  info.new_symbol,
963  "conflicting array sizes for variable");
964 
965  // error logged, continue typechecking other symbols
966  return true;
967  }
968  }
969 
970  return false;
971  }
972  else if(t1.id()==ID_struct || t1.id()==ID_union)
973  {
974  const struct_union_typet::componentst &components1=
976 
977  const struct_union_typet::componentst &components2=
979 
980  struct_union_typet::componentst::const_iterator
981  it1=components1.begin(), it2=components2.begin();
982  for( ;
983  it1!=components1.end() && it2!=components2.end();
984  ++it1, ++it2)
985  {
986  if(it1->get_name()!=it2->get_name() ||
987  adjust_object_type_rec(it1->type(), it2->type(), info))
988  return true;
989  }
990  if(it1!=components1.end() || it2!=components2.end())
991  return true;
992 
993  return false;
994  }
995 
996  return true;
997 }
998 
1000  const symbolt &old_symbol,
1001  const symbolt &new_symbol,
1002  bool &set_to_new)
1003 {
1004  const typet &old_type=follow_tags_symbols(ns, old_symbol.type);
1005  const typet &new_type=follow_tags_symbols(ns, new_symbol.type);
1006 
1007  adjust_type_infot info(old_symbol, new_symbol);
1008  bool result=adjust_object_type_rec(old_type, new_type, info);
1009  set_to_new=info.set_to_new;
1010 
1011  return result;
1012 }
1013 
1015  symbolt &old_symbol,
1016  symbolt &new_symbol)
1017 {
1018  // both are variables
1019  bool set_to_new = false;
1020 
1021  if(old_symbol.type != new_symbol.type)
1022  {
1023  bool failed=
1024  adjust_object_type(old_symbol, new_symbol, set_to_new);
1025 
1026  if(failed)
1027  {
1028  const typet &old_type=follow_tags_symbols(ns, old_symbol.type);
1029 
1030  // provide additional diagnostic output for
1031  // struct/union/array/enum
1032  if(old_type.id()==ID_struct ||
1033  old_type.id()==ID_union ||
1034  old_type.id()==ID_array ||
1035  old_type.id()==ID_c_enum)
1037  old_symbol,
1038  new_symbol,
1039  old_symbol.type,
1040  new_symbol.type);
1041 
1042  link_error(
1043  old_symbol,
1044  new_symbol,
1045  "conflicting types for variable");
1046 
1047  // error logged, continue typechecking other symbols
1048  return;
1049  }
1050  else if(set_to_new)
1051  old_symbol.type=new_symbol.type;
1052 
1054  old_symbol.symbol_expr(), old_symbol.symbol_expr());
1055  }
1056 
1057  // care about initializers
1058 
1059  if(!new_symbol.value.is_nil())
1060  {
1061  if(old_symbol.value.is_nil() ||
1062  old_symbol.is_weak)
1063  {
1064  // new_symbol wins
1065  old_symbol.value=new_symbol.value;
1066  old_symbol.is_macro=new_symbol.is_macro;
1067  }
1068  else if(!new_symbol.is_weak)
1069  {
1070  // try simplifier
1071  exprt tmp_old=old_symbol.value,
1072  tmp_new=new_symbol.value;
1073 
1074  simplify(tmp_old, ns);
1075  simplify(tmp_new, ns);
1076 
1077  if(tmp_old == tmp_new)
1078  {
1079  // ok, the same
1080  }
1081  else
1082  {
1083  warning().source_location=new_symbol.location;
1084 
1085  warning() << "warning: conflicting initializers for"
1086  << " variable \"" << old_symbol.name << "\"\n";
1087  warning() << "using old value in module " << old_symbol.module << " "
1088  << old_symbol.value.find_source_location() << '\n'
1089  << expr_to_string(old_symbol.name, tmp_old) << '\n';
1090  warning() << "ignoring new value in module " << new_symbol.module << " "
1091  << new_symbol.value.find_source_location() << '\n'
1092  << expr_to_string(new_symbol.name, tmp_new) << eom;
1093  }
1094  }
1095  }
1096  else if(set_to_new && !old_symbol.value.is_nil())
1097  {
1098  // the type has been updated, now make sure that the initialising assignment
1099  // will have matching types
1100  old_symbol.value = typecast_exprt(old_symbol.value, old_symbol.type);
1101  }
1102 }
1103 
1105  symbolt &old_symbol,
1106  symbolt &new_symbol)
1107 {
1108  // we do not permit multiple contracts to be defined, or cases where only one
1109  // of the symbols is a contract
1110  if(old_symbol.is_property || new_symbol.is_property)
1111  link_error(old_symbol, new_symbol, "conflict on code contract");
1112 
1113  // see if it is a function or a variable
1114 
1115  bool is_code_old_symbol=old_symbol.type.id()==ID_code;
1116  bool is_code_new_symbol=new_symbol.type.id()==ID_code;
1117 
1118  if(is_code_old_symbol!=is_code_new_symbol)
1119  {
1120  link_error(
1121  old_symbol,
1122  new_symbol,
1123  "conflicting definition for symbol");
1124 
1125  // error logged, continue typechecking other symbols
1126  return;
1127  }
1128 
1129  if(is_code_old_symbol)
1130  duplicate_code_symbol(old_symbol, new_symbol);
1131  else
1132  duplicate_object_symbol(old_symbol, new_symbol);
1133 
1134  // care about flags
1135 
1136  if(old_symbol.is_extern && !new_symbol.is_extern)
1137  old_symbol.location=new_symbol.location;
1138 
1139  // it's enough that one isn't extern for the final one not to be
1140  old_symbol.is_extern=old_symbol.is_extern && new_symbol.is_extern;
1141 }
1142 
1144  symbolt &old_symbol,
1145  const symbolt &new_symbol)
1146 {
1147  assert(new_symbol.is_type);
1148 
1149  if(!old_symbol.is_type)
1150  {
1151  link_error(
1152  old_symbol,
1153  new_symbol,
1154  "conflicting definition for symbol");
1155 
1156  // error logged, continue typechecking other symbols
1157  return;
1158  }
1159 
1160  if(old_symbol.type==new_symbol.type)
1161  return;
1162 
1163  if(
1164  old_symbol.type.id() == ID_struct &&
1165  to_struct_type(old_symbol.type).is_incomplete() &&
1166  new_symbol.type.id() == ID_struct &&
1167  !to_struct_type(new_symbol.type).is_incomplete())
1168  {
1169  old_symbol.type=new_symbol.type;
1170  old_symbol.location=new_symbol.location;
1171  return;
1172  }
1173 
1174  if(
1175  old_symbol.type.id() == ID_struct &&
1176  !to_struct_type(old_symbol.type).is_incomplete() &&
1177  new_symbol.type.id() == ID_struct &&
1178  to_struct_type(new_symbol.type).is_incomplete())
1179  {
1180  // ok, keep old
1181  return;
1182  }
1183 
1184  if(
1185  old_symbol.type.id() == ID_union &&
1186  to_union_type(old_symbol.type).is_incomplete() &&
1187  new_symbol.type.id() == ID_union &&
1188  !to_union_type(new_symbol.type).is_incomplete())
1189  {
1190  old_symbol.type=new_symbol.type;
1191  old_symbol.location=new_symbol.location;
1192  return;
1193  }
1194 
1195  if(
1196  old_symbol.type.id() == ID_union &&
1197  !to_union_type(old_symbol.type).is_incomplete() &&
1198  new_symbol.type.id() == ID_union &&
1199  to_union_type(new_symbol.type).is_incomplete())
1200  {
1201  // ok, keep old
1202  return;
1203  }
1204 
1205  if(
1206  old_symbol.type.id() == ID_array && new_symbol.type.id() == ID_array &&
1207  to_array_type(old_symbol.type).element_type() ==
1208  to_array_type(new_symbol.type).element_type())
1209  {
1210  if(to_array_type(old_symbol.type).size().is_nil() &&
1211  to_array_type(new_symbol.type).size().is_not_nil())
1212  {
1213  to_array_type(old_symbol.type).size()=
1214  to_array_type(new_symbol.type).size();
1215  return;
1216  }
1217 
1218  if(to_array_type(new_symbol.type).size().is_nil() &&
1219  to_array_type(old_symbol.type).size().is_not_nil())
1220  {
1221  // ok, keep old
1222  return;
1223  }
1224  }
1225 
1227  old_symbol,
1228  new_symbol,
1229  old_symbol.type,
1230  new_symbol.type);
1231 
1232  link_error(
1233  old_symbol,
1234  new_symbol,
1235  "unexpected difference between type symbols");
1236 }
1237 
1239  const symbolt &old_symbol,
1240  const symbolt &new_symbol)
1241 {
1242  assert(new_symbol.is_type);
1243 
1244  if(!old_symbol.is_type)
1245  return true;
1246 
1247  if(old_symbol.type==new_symbol.type)
1248  return false;
1249 
1250  if(
1251  old_symbol.type.id() == ID_struct &&
1252  to_struct_type(old_symbol.type).is_incomplete() &&
1253  new_symbol.type.id() == ID_struct &&
1254  !to_struct_type(new_symbol.type).is_incomplete())
1255  return false; // not different
1256 
1257  if(
1258  old_symbol.type.id() == ID_struct &&
1259  !to_struct_type(old_symbol.type).is_incomplete() &&
1260  new_symbol.type.id() == ID_struct &&
1261  to_struct_type(new_symbol.type).is_incomplete())
1262  return false; // not different
1263 
1264  if(
1265  old_symbol.type.id() == ID_union &&
1266  to_union_type(old_symbol.type).is_incomplete() &&
1267  new_symbol.type.id() == ID_union &&
1268  !to_union_type(new_symbol.type).is_incomplete())
1269  return false; // not different
1270 
1271  if(
1272  old_symbol.type.id() == ID_union &&
1273  !to_union_type(old_symbol.type).is_incomplete() &&
1274  new_symbol.type.id() == ID_union &&
1275  to_union_type(new_symbol.type).is_incomplete())
1276  return false; // not different
1277 
1278  if(
1279  old_symbol.type.id() == ID_array && new_symbol.type.id() == ID_array &&
1280  to_array_type(old_symbol.type).element_type() ==
1281  to_array_type(new_symbol.type).element_type())
1282  {
1283  if(to_array_type(old_symbol.type).size().is_nil() &&
1284  to_array_type(new_symbol.type).size().is_not_nil())
1285  return false; // not different
1286 
1287  if(to_array_type(new_symbol.type).size().is_nil() &&
1288  to_array_type(old_symbol.type).size().is_not_nil())
1289  return false; // not different
1290  }
1291 
1292  return true; // different
1293 }
1294 
1296  std::unordered_set<irep_idt> &needs_to_be_renamed)
1297 {
1298  // Any type that uses a symbol that will be renamed also
1299  // needs to be renamed, and so on, until saturation.
1300 
1301  used_byt used_by;
1302 
1303  for(const auto &symbol_pair : src_symbol_table.symbols)
1304  {
1305  if(symbol_pair.second.is_type)
1306  {
1307  // find type and array-size symbols
1308  find_symbols_sett symbols_used;
1309  find_type_and_expr_symbols(symbol_pair.second.type, symbols_used);
1310 
1311  for(const auto &symbol_used : symbols_used)
1312  {
1313  used_by[symbol_used].insert(symbol_pair.first);
1314  }
1315  }
1316  }
1317 
1318  std::deque<irep_idt> queue(
1319  needs_to_be_renamed.begin(), needs_to_be_renamed.end());
1320 
1321  while(!queue.empty())
1322  {
1323  irep_idt id = queue.back();
1324  queue.pop_back();
1325 
1326  const std::unordered_set<irep_idt> &u = used_by[id];
1327 
1328  for(const auto &dep : u)
1329  if(needs_to_be_renamed.insert(dep).second)
1330  {
1331  queue.push_back(dep);
1332  #ifdef DEBUG
1333  debug() << "LINKING: needs to be renamed (dependency): "
1334  << dep << eom;
1335  #endif
1336  }
1337  }
1338 }
1339 
1340 std::unordered_map<irep_idt, irep_idt> linkingt::rename_symbols(
1341  const std::unordered_set<irep_idt> &needs_to_be_renamed)
1342 {
1343  std::unordered_map<irep_idt, irep_idt> new_identifiers;
1344  namespacet src_ns(src_symbol_table);
1345 
1346  for(const irep_idt &id : needs_to_be_renamed)
1347  {
1348  const symbolt &new_symbol = src_ns.lookup(id);
1349 
1350  irep_idt new_identifier;
1351 
1352  if(new_symbol.is_type)
1353  new_identifier=type_to_name(src_ns, id, new_symbol.type);
1354  else
1355  new_identifier=rename(id);
1356 
1357  new_identifiers.emplace(id, new_identifier);
1358 
1359 #ifdef DEBUG
1360  debug() << "LINKING: renaming " << id << " to "
1361  << new_identifier << eom;
1362 #endif
1363 
1364  if(new_symbol.is_type)
1365  rename_symbol.insert_type(id, new_identifier);
1366  else
1367  rename_symbol.insert_expr(id, new_identifier);
1368  }
1369 
1370  return new_identifiers;
1371 }
1372 
1374  const std::unordered_map<irep_idt, irep_idt> &new_identifiers)
1375 {
1376  std::map<irep_idt, symbolt> src_symbols;
1377  // First apply the renaming
1378  for(const auto &named_symbol : src_symbol_table.symbols)
1379  {
1380  symbolt symbol=named_symbol.second;
1381  // apply the renaming
1382  rename_symbol(symbol.type);
1383  rename_symbol(symbol.value);
1384  auto it = new_identifiers.find(named_symbol.first);
1385  if(it != new_identifiers.end())
1386  symbol.name = it->second;
1387 
1388  src_symbols.emplace(named_symbol.first, std::move(symbol));
1389  }
1390 
1391  // Move over all the non-colliding ones
1392  std::unordered_set<irep_idt> collisions;
1393 
1394  for(const auto &named_symbol : src_symbols)
1395  {
1396  // renamed?
1397  if(named_symbol.first!=named_symbol.second.name)
1398  {
1399  // new
1400  main_symbol_table.add(named_symbol.second);
1401  }
1402  else
1403  {
1404  if(!main_symbol_table.has_symbol(named_symbol.first))
1405  {
1406  // new
1407  main_symbol_table.add(named_symbol.second);
1408  }
1409  else
1410  collisions.insert(named_symbol.first);
1411  }
1412  }
1413 
1414  // Now do the collisions
1415  for(const irep_idt &collision : collisions)
1416  {
1417  symbolt &old_symbol = main_symbol_table.get_writeable_ref(collision);
1418  symbolt &new_symbol=src_symbols.at(collision);
1419 
1420  if(new_symbol.is_type)
1421  duplicate_type_symbol(old_symbol, new_symbol);
1422  else
1423  duplicate_non_type_symbol(old_symbol, new_symbol);
1424  }
1425 
1426  // Apply type updates to initializers
1427  for(const auto &named_symbol : main_symbol_table.symbols)
1428  {
1429  if(!named_symbol.second.is_type &&
1430  !named_symbol.second.is_macro &&
1431  named_symbol.second.value.is_not_nil())
1432  {
1434  main_symbol_table.get_writeable_ref(named_symbol.first).value);
1435  }
1436  }
1437 }
1438 
1440 {
1441  // We do this in three phases. We first figure out which symbols need to
1442  // be renamed, and then build the renaming, and finally apply this
1443  // renaming in the second pass over the symbol table.
1444 
1445  // PHASE 1: identify symbols to be renamed
1446 
1447  std::unordered_set<irep_idt> needs_to_be_renamed;
1448 
1449  for(const auto &symbol_pair : src_symbol_table.symbols)
1450  {
1451  symbol_tablet::symbolst::const_iterator m_it =
1452  main_symbol_table.symbols.find(symbol_pair.first);
1453 
1454  if(
1455  m_it != main_symbol_table.symbols.end() && // duplicate
1456  needs_renaming(m_it->second, symbol_pair.second))
1457  {
1458  needs_to_be_renamed.insert(symbol_pair.first);
1459  #ifdef DEBUG
1460  debug() << "LINKING: needs to be renamed: " << symbol_pair.first << eom;
1461  #endif
1462  }
1463  }
1464 
1465  // renaming types may trigger further renaming
1466  do_type_dependencies(needs_to_be_renamed);
1467 
1468  // PHASE 2: actually rename them
1469  auto new_identifiers = rename_symbols(needs_to_be_renamed);
1470 
1471  // PHASE 3: copy new symbols to main table
1472  copy_symbols(new_identifiers);
1473 }
1474 
1475 bool linking(
1476  symbol_tablet &dest_symbol_table,
1477  const symbol_tablet &new_symbol_table,
1478  message_handlert &message_handler)
1479 {
1480  linkingt linking(
1481  dest_symbol_table, new_symbol_table, message_handler);
1482 
1483  return linking.typecheck_main();
1484 }
linkingt::needs_renaming_type
bool needs_renaming_type(const symbolt &old_symbol, const symbolt &new_symbol)
Definition: linking.cpp:1238
to_union_tag_type
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition: c_types.h:202
linkingt::adjust_object_type
bool adjust_object_type(const symbolt &old_symbol, const symbolt &new_symbol, bool &set_to_new)
Definition: linking.cpp:999
tag_typet::get_identifier
const irep_idt & get_identifier() const
Definition: std_types.h:410
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:147
symbol_table_baset::has_symbol
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
Definition: symbol_table_base.h:87
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
pointer_offset_size.h
to_union_type
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition: c_types.h:162
code_typet::has_ellipsis
bool has_ellipsis() const
Definition: std_types.h:611
linkingt::adjust_type_infot
Definition: linking_class.h:89
get_base_name
std::string get_base_name(const std::string &in, bool strip_suffix)
cleans a filename from path and extension
Definition: get_base_name.cpp:16
typecast_exprt::conditional_cast
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2025
linkingt::needs_renaming
bool needs_renaming(const symbolt &old_symbol, const symbolt &new_symbol)
Definition: linking_class.h:56
symbol_tablet
The symbol table.
Definition: symbol_table.h:13
typet::subtype
const typet & subtype() const
Definition: type.h:50
source_locationt::as_string
std::string as_string() const
Definition: source_location.h:25
linking
bool linking(symbol_tablet &dest_symbol_table, const symbol_tablet &new_symbol_table, message_handlert &message_handler)
Merges the symbol table new_symbol_table into dest_symbol_table, renaming symbols from new_symbol_tab...
Definition: linking.cpp:1475
find_type_and_expr_symbols
void find_type_and_expr_symbols(const exprt &src, find_symbols_sett &dest)
Find identifiers of the sub expressions with id ID_symbol, considering both free and bound variables,...
Definition: find_symbols.cpp:283
symbolt::is_macro
bool is_macro
Definition: symbol.h:61
linkingt::typecheck
virtual void typecheck()
Definition: linking.cpp:1439
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
linkingt::adjust_type_infot::new_symbol
const symbolt & new_symbol
Definition: linking_class.h:101
to_struct_union_type
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition: std_types.h:214
to_dereference_expr
const dereference_exprt & to_dereference_expr(const exprt &expr)
Cast an exprt to a dereference_exprt.
Definition: pointer_expr.h:716
irept::make_nil
void make_nil()
Definition: irep.h:454
type_to_name
std::string type_to_name(const namespacet &ns, const irep_idt &identifier, const typet &type)
Definition: language_util.cpp:64
symbolt::display_name
const irep_idt & display_name() const
Return language specific display name if present.
Definition: symbol.h:55
linkingt::object_type_updates
casting_replace_symbolt object_type_updates
Definition: linking_class.h:45
typet
The type of an expression, extends irept.
Definition: type.h:28
code_typet::parameterst
std::vector< parametert > parameterst
Definition: std_types.h:541
linkingt::type_to_string_verbose
std::string type_to_string_verbose(const symbolt &symbol, const typet &type) const
Definition: linking.cpp:77
to_index_expr
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1478
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
dereference_exprt
Operator to dereference a pointer.
Definition: pointer_expr.h:659
c_enum_typet::memberst
std::vector< c_enum_membert > memberst
Definition: c_types.h:253
symbol_exprt::typeless
static symbol_exprt typeless(const irep_idt &id)
Generate a symbol_exprt without a proper type.
Definition: std_expr.h:132
to_c_enum_type
const c_enum_typet & to_c_enum_type(const typet &type)
Cast a typet to a c_enum_typet.
Definition: c_types.h:302
linkingt::type_to_string
std::string type_to_string(const irep_idt &identifier, const typet &type) const
Definition: linking.cpp:56
replace
void replace(const union_find_replacet &replace_map, string_not_contains_constraintt &constraint)
Definition: string_constraint.cpp:70
integer_typet
Unbounded, signed integers (mathematical integers, not bitvectors)
Definition: mathematical_types.h:21
linkingt::needs_renaming_non_type
bool needs_renaming_non_type(const symbolt &old_symbol, const symbolt &new_symbol)
Definition: linking.cpp:456
to_type_with_subtype
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:193
exprt
Base class for all expressions.
Definition: expr.h:55
struct_union_typet::componentst
std::vector< componentt > componentst
Definition: std_types.h:140
linkingt::rename_symbols
std::unordered_map< irep_idt, irep_idt > rename_symbols(const std::unordered_set< irep_idt > &needs_to_be_renamed)
Definition: linking.cpp:1340
namespace_baset::follow_tag
const union_typet & follow_tag(const union_tag_typet &) const
Follow type tag of union type.
Definition: namespace.cpp:63
from_type
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
Definition: language_util.cpp:51
replace_symbolt::expr_map
expr_mapt expr_map
Definition: replace_symbol.h:93
irep_idt
dstringt irep_idt
Definition: irep.h:37
to_string
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
Definition: string_constraint.cpp:58
messaget::eom
static eomt eom
Definition: message.h:297
symbol_exprt
Expression to hold a symbol (variable)
Definition: std_expr.h:112
equal_exprt
Equality.
Definition: std_expr.h:1305
linkingt::link_warning
void link_warning(const symbolt &old_symbol, const symbolt &new_symbol, const std::string &msg)
Definition: linking.cpp:414
linkingt::duplicate_code_symbol
void duplicate_code_symbol(symbolt &old_symbol, symbolt &new_symbol)
Definition: linking.cpp:470
linkingt::main_symbol_table
symbol_table_baset & main_symbol_table
Definition: linking_class.h:172
linkingt::copy_symbols
void copy_symbols(const std::unordered_map< irep_idt, irep_idt > &)
Definition: linking.cpp:1373
mathematical_types.h
array_typet::size
const exprt & size() const
Definition: std_types.h:800
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
namespacet::lookup
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
Definition: namespace.cpp:138
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
to_code_type
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:744
linkingt::adjust_object_type_rec
bool adjust_object_type_rec(const typet &type1, const typet &type2, adjust_type_infot &info)
Definition: linking.cpp:807
linkingt::used_byt
std::unordered_map< irep_idt, std::unordered_set< irep_idt > > used_byt
Definition: linking_class.h:178
messaget::result
mstreamt & result() const
Definition: message.h:409
messaget::error
mstreamt & error() const
Definition: message.h:399
find_symbols.h
to_tag_type
const tag_typet & to_tag_type(const typet &type)
Cast a typet to a tag_typet.
Definition: std_types.h:434
follow_tags_symbols
static const typet & follow_tags_symbols(const namespacet &ns, const typet &type)
Definition: linking.cpp:63
linkingt::do_type_dependencies
void do_type_dependencies(std::unordered_set< irep_idt > &)
Definition: linking.cpp:1295
symbol_table_baset::get_writeable_ref
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
Definition: symbol_table_base.h:121
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
member_exprt::compound
const exprt & compound() const
Definition: std_expr.h:2843
failed
static bool failed(bool error_indicator)
Definition: symtab2gb_parse_options.cpp:39
messaget::mstreamt::source_location
source_locationt source_location
Definition: message.h:247
to_c_enum_tag_type
const c_enum_tag_typet & to_c_enum_tag_type(const typet &type)
Cast a typet to a c_enum_tag_typet.
Definition: c_types.h:344
language_util.h
typet::source_location
const source_locationt & source_location() const
Definition: type.h:90
exprt::find_source_location
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition: expr.cpp:165
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
dereference_exprt::pointer
exprt & pointer()
Definition: pointer_expr.h:673
pointer_offset_bits
optionalt< mp_integer > pointer_offset_bits(const typet &type, const namespacet &ns)
Definition: pointer_offset_size.cpp:101
linkingt::src_symbol_table
const symbol_table_baset & src_symbol_table
Definition: linking_class.h:173
casting_replace_symbolt::replace_symbol_expr
bool replace_symbol_expr(symbol_exprt &dest) const override
Definition: linking.cpp:29
symbolt::symbol_expr
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
pointer_expr.h
irept::id_string
const std::string & id_string() const
Definition: irep.h:399
simplify
bool simplify(exprt &expr, const namespacet &ns)
Definition: simplify_expr.cpp:2926
to_pointer_type
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:79
simplify_expr
exprt simplify_expr(exprt src, const namespacet &ns)
Definition: simplify_expr.cpp:2931
irept::get_string
const std::string & get_string(const irep_idt &name) const
Definition: irep.h:409
linkingt
Definition: linking_class.h:28
linkingt::duplicate_non_type_symbol
void duplicate_non_type_symbol(symbolt &old_symbol, symbolt &new_symbol)
Definition: linking.cpp:1104
index_exprt::array
exprt & array()
Definition: std_expr.h:1440
linking.h
code_typet
Base type of functions.
Definition: std_types.h:538
irept::is_nil
bool is_nil() const
Definition: irep.h:376
irept::id
const irep_idt & id() const
Definition: irep.h:396
message_handlert
Definition: message.h:27
to_struct_tag_type
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:474
union_typet
The union type.
Definition: c_types.h:124
linkingt::detailed_conflict_report_rec
void detailed_conflict_report_rec(const symbolt &old_symbol, const symbolt &new_symbol, const typet &type1, const typet &type2, unsigned depth, exprt &conflict_path)
Definition: linking.cpp:129
replace_symbolt::insert
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...
Definition: replace_symbol.cpp:24
linkingt::duplicate_object_symbol
void duplicate_object_symbol(symbolt &old_symbol, symbolt &new_symbol)
Definition: linking.cpp:1014
code_typet::parameters
const parameterst & parameters() const
Definition: std_types.h:655
linkingt::expr_to_string
std::string expr_to_string(const irep_idt &identifier, const exprt &expr) const
Definition: linking.cpp:49
simplify_expr.h
linkingt::rename_symbol
rename_symbolt rename_symbol
Definition: linking_class.h:44
linkingt::link_error
void link_error(const symbolt &old_symbol, const symbolt &new_symbol, const std::string &msg)
Definition: linking.cpp:397
exprt::is_zero
bool is_zero() const
Return whether the expression is a constant representing 0.
Definition: expr.cpp:65
symbol_table_baset::add
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
Definition: symbol_table_base.cpp:18
member_exprt
Extract member of struct or union.
Definition: std_expr.h:2793
symbolt::value
exprt value
Initial value of symbol.
Definition: symbol.h:34
linking_class.h
symbolt::is_extern
bool is_extern
Definition: symbol.h:66
find_symbols_sett
std::unordered_set< irep_idt > find_symbols_sett
Definition: find_symbols.h:21
linkingt::adjust_type_infot::set_to_new
bool set_to_new
Definition: linking_class.h:102
linkingt::duplicate_type_symbol
void duplicate_type_symbol(symbolt &old_symbol, const symbolt &new_symbol)
Definition: linking.cpp:1143
symbolt::location
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
symbolt
Symbol table entry.
Definition: symbol.h:27
symbol_table_baset::symbols
const symbolst & symbols
Read-only field, used to look up symbols given their names.
Definition: symbol_table_base.h:30
symbolt::is_type
bool is_type
Definition: symbol.h:61
rename_symbolt::insert_expr
void insert_expr(const irep_idt &old_id, const irep_idt &new_id)
Definition: rename_symbol.h:31
linkingt::detailed_conflict_report
void detailed_conflict_report(const symbolt &old_symbol, const symbolt &new_symbol, const typet &type1, const typet &type2)
Definition: linking_class.h:142
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
linkingt::rename
irep_idt rename(const irep_idt &)
Definition: linking.cpp:432
code_typet::get_inlined
bool get_inlined() const
Definition: std_types.h:665
linkingt::renamed_ids
std::unordered_set< irep_idt > renamed_ids
Definition: linking_class.h:183
code_typet::return_type
const typet & return_type() const
Definition: std_types.h:645
to_member_expr
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2886
symbolt::is_file_local
bool is_file_local
Definition: symbol.h:66
messaget::debug
mstreamt & debug() const
Definition: message.h:429
linkingt::adjust_type_infot::n_symbols
std::unordered_set< irep_idt > n_symbols
Definition: linking_class.h:104
linkingt::adjust_type_infot::old_symbol
const symbolt & old_symbol
Definition: linking_class.h:100
index_exprt
Array index operator.
Definition: std_expr.h:1409
symbol_table.h
Author: Diffblue Ltd.
typecast_exprt
Semantic type conversion.
Definition: std_expr.h:2016
constant_exprt
A constant literal expression.
Definition: std_expr.h:2941
symbolt::module
irep_idt module
Name of module the symbol belongs to.
Definition: symbol.h:43
is_true
bool is_true(const literalt &l)
Definition: literal.h:198
messaget::warning
mstreamt & warning() const
Definition: message.h:404
linkingt::ns
namespacet ns
Definition: linking_class.h:175
struct_union_typet::is_incomplete
bool is_incomplete() const
A struct/union may be incomplete.
Definition: std_types.h:185
c_types.h
linkingt::adjust_type_infot::o_symbols
std::unordered_set< irep_idt > o_symbols
Definition: linking_class.h:103
from_expr
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
Definition: language_util.cpp:38
symbolt::is_weak
bool is_weak
Definition: symbol.h:67
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
rename_symbolt::insert_type
void insert_type(const irep_idt &old_id, const irep_idt &new_id)
Definition: rename_symbol.h:40
symbolt::is_property
bool is_property
Definition: symbol.h:62
irept::get_bool
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:58
c_enum_typet::members
const memberst & members() const
Definition: c_types.h:255
array_typet::element_type
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:785