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