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>
17 #include <util/message.h>
19 #include <util/simplify_expr.h>
20 #include <util/symbol_table_base.h>
21 
22 #include <langapi/language_util.h>
23 
24 #include "linking_diagnostics.h"
25 
26 #include <deque>
27 
28 static const typet &follow_tags_symbols(
29  const namespacet &ns,
30  const typet &type)
31 {
32  if(type.id() == ID_c_enum_tag)
33  return ns.follow_tag(to_c_enum_tag_type(type));
34  else if(type.id()==ID_struct_tag)
35  return ns.follow_tag(to_struct_tag_type(type));
36  else if(type.id()==ID_union_tag)
37  return ns.follow_tag(to_union_tag_type(type));
38  else
39  return type;
40 }
41 
43 linkingt::rename(const symbol_table_baset &src_symbol_table, const irep_idt &id)
44 {
45  unsigned cnt=0;
46 
47  while(true)
48  {
49  irep_idt new_identifier=
50  id2string(id)+"$link"+std::to_string(++cnt);
51 
52  if(main_symbol_table.symbols.find(new_identifier)!=
54  continue; // already in main symbol table
55 
56  if(!renamed_ids.insert(new_identifier).second)
57  continue; // used this for renaming already
58 
59  if(src_symbol_table.symbols.find(new_identifier)!=
60  src_symbol_table.symbols.end())
61  continue; // used by some earlier linking call already
62 
63  return new_identifier;
64  }
65 }
66 
68  const symbolt &old_symbol,
69  const symbolt &new_symbol)
70 {
71  // We first take care of file-local non-type symbols.
72  // These are static functions, or static variables
73  // inside static function bodies.
74  if(new_symbol.is_file_local)
75  return renamingt::RENAME_NEW;
76  else if(old_symbol.is_file_local)
77  return renamingt::RENAME_OLD;
78  else
79  return renamingt::NO_RENAMING;
80 }
81 
83  symbolt &old_symbol,
84  symbolt &new_symbol)
85 {
87 
88  // Both are functions.
89  if(old_symbol.type != new_symbol.type)
90  {
91  const code_typet &old_t=to_code_type(old_symbol.type);
92  const code_typet &new_t=to_code_type(new_symbol.type);
93 
94  if(old_symbol.type.get_bool(ID_C_incomplete) && old_symbol.value.is_nil())
95  {
96  diag.warning(old_symbol, new_symbol, "implicit function declaration");
97 
98  old_symbol.type=new_symbol.type;
99  old_symbol.location=new_symbol.location;
100  old_symbol.is_weak=new_symbol.is_weak;
101  }
102  else if(
103  new_symbol.type.get_bool(ID_C_incomplete) && new_symbol.value.is_nil())
104  {
105  diag.warning(
106  old_symbol,
107  new_symbol,
108  "ignoring conflicting implicit function declaration");
109  }
110  // handle (incomplete) function prototypes
111  else if(((old_t.parameters().empty() && old_t.has_ellipsis() &&
112  old_symbol.value.is_nil()) ||
113  (new_t.parameters().empty() && new_t.has_ellipsis() &&
114  new_symbol.value.is_nil())))
115  {
116  if(old_t.parameters().empty() &&
117  old_t.has_ellipsis() &&
118  old_symbol.value.is_nil())
119  {
120  old_symbol.type=new_symbol.type;
121  old_symbol.location=new_symbol.location;
122  old_symbol.is_weak=new_symbol.is_weak;
123  }
124  }
125  // replace weak symbols
126  else if(old_symbol.is_weak)
127  {
128  if(new_symbol.value.is_nil())
129  {
130  diag.warning(
131  old_symbol,
132  new_symbol,
133  "function declaration conflicts with with weak definition");
134  }
135  else
136  old_symbol.value.make_nil();
137  }
138  else if(new_symbol.is_weak)
139  {
140  if(new_symbol.value.is_nil() ||
141  old_symbol.value.is_not_nil())
142  {
143  new_symbol.value.make_nil();
144 
145  diag.warning(
146  old_symbol,
147  new_symbol,
148  "ignoring conflicting weak function declaration");
149  }
150  }
151  // aliasing may alter the type
152  else if((new_symbol.is_macro &&
153  new_symbol.value.is_not_nil() &&
154  old_symbol.value.is_nil()) ||
155  (old_symbol.is_macro &&
156  old_symbol.value.is_not_nil() &&
157  new_symbol.value.is_nil()))
158  {
159  diag.warning(
160  old_symbol,
161  new_symbol,
162  "ignoring conflicting function alias declaration");
163  }
164  // conflicting declarations without a definition, matching return
165  // types
166  else if(old_symbol.value.is_nil() && new_symbol.value.is_nil())
167  {
168  diag.warning(
169  old_symbol, new_symbol, "ignoring conflicting function declarations");
170 
171  if(old_t.parameters().size()<new_t.parameters().size())
172  {
173  old_symbol.type=new_symbol.type;
174  old_symbol.location=new_symbol.location;
175  old_symbol.is_weak=new_symbol.is_weak;
176  }
177  }
178  // mismatch on number of parameters is definitively an error
179  else if((old_t.parameters().size()<new_t.parameters().size() &&
180  new_symbol.value.is_not_nil() &&
181  !old_t.has_ellipsis()) ||
182  (old_t.parameters().size()>new_t.parameters().size() &&
183  old_symbol.value.is_not_nil() &&
184  !new_t.has_ellipsis()))
185  {
186  diag.error(
187  old_symbol,
188  new_symbol,
189  "conflicting parameter counts of function declarations");
190 
191  // error logged, continue typechecking other symbols
192  return;
193  }
194  else
195  {
196  // the number of parameters matches, collect all the conflicts
197  // and see whether they can be cured
198  std::string warn_msg;
199  bool replace=false;
200  typedef std::deque<std::pair<typet, typet> > conflictst;
201  conflictst conflicts;
202 
203  if(old_t.return_type() != new_t.return_type())
204  {
205  diag.warning(old_symbol, new_symbol, "conflicting return types");
206 
207  conflicts.emplace_back(old_t.return_type(), new_t.return_type());
208  }
209 
210  code_typet::parameterst::const_iterator
211  n_it=new_t.parameters().begin(),
212  o_it=old_t.parameters().begin();
213  for( ;
214  o_it!=old_t.parameters().end() &&
215  n_it!=new_t.parameters().end();
216  ++o_it, ++n_it)
217  {
218  if(o_it->type() != n_it->type())
219  conflicts.push_back(
220  std::make_pair(o_it->type(), n_it->type()));
221  }
222  if(o_it!=old_t.parameters().end())
223  {
224  if(!new_t.has_ellipsis() && old_symbol.value.is_not_nil())
225  {
226  diag.error(
227  old_symbol,
228  new_symbol,
229  "conflicting parameter counts of function declarations");
230 
231  // error logged, continue typechecking other symbols
232  return;
233  }
234 
235  replace=new_symbol.value.is_not_nil();
236  }
237  else if(n_it!=new_t.parameters().end())
238  {
239  if(!old_t.has_ellipsis() && new_symbol.value.is_not_nil())
240  {
241  diag.error(
242  old_symbol,
243  new_symbol,
244  "conflicting parameter counts of function declarations");
245 
246  // error logged, continue typechecking other symbols
247  return;
248  }
249 
250  replace=new_symbol.value.is_not_nil();
251  }
252 
253  while(!conflicts.empty())
254  {
255  const typet &t1=follow_tags_symbols(ns, conflicts.front().first);
256  const typet &t2=follow_tags_symbols(ns, conflicts.front().second);
257 
258  // different pointer arguments without implementation may work
259  if(
260  (t1.id() == ID_pointer || t2.id() == ID_pointer) &&
262  old_symbol.value.is_nil() && new_symbol.value.is_nil())
263  {
264  if(warn_msg.empty())
265  warn_msg="different pointer types in extern function";
266  }
267  // different pointer arguments with implementation - the
268  // implementation is always right, even though such code may
269  // be severely broken
270  else if((t1.id()==ID_pointer || t2.id()==ID_pointer) &&
272  old_symbol.value.is_nil()!=new_symbol.value.is_nil())
273  {
274  if(warn_msg.empty())
275  {
276  warn_msg="pointer parameter types differ between "
277  "declaration and definition";
278  }
279 
280  replace=new_symbol.value.is_not_nil();
281  }
282  // transparent union with (or entirely without) implementation is
283  // ok -- this primarily helps all those people that don't get
284  // _GNU_SOURCE consistent
285  else if((t1.id()==ID_union &&
286  (t1.get_bool(ID_C_transparent_union) ||
287  conflicts.front().first.get_bool(ID_C_transparent_union))) ||
288  (t2.id()==ID_union &&
289  (t2.get_bool(ID_C_transparent_union) ||
290  conflicts.front().second.get_bool(ID_C_transparent_union))))
291  {
292  const bool use_old=
293  t1.id()==ID_union &&
294  (t1.get_bool(ID_C_transparent_union) ||
295  conflicts.front().first.get_bool(ID_C_transparent_union)) &&
296  new_symbol.value.is_nil();
297 
298  const union_typet &union_type=
299  to_union_type(t1.id()==ID_union?t1:t2);
300  const typet &src_type=t1.id()==ID_union?t2:t1;
301 
302  bool found=false;
303  for(const auto &c : union_type.components())
304  if(c.type() == src_type)
305  {
306  found=true;
307  if(warn_msg.empty())
308  warn_msg="conflict on transparent union parameter in function";
309  replace=!use_old;
310  }
311 
312  if(!found)
313  break;
314  }
315  // different non-pointer arguments with implementation - the
316  // implementation is always right, even though such code may
317  // be severely broken
318  else if(pointer_offset_bits(t1, ns)==pointer_offset_bits(t2, ns) &&
319  old_symbol.value.is_nil()!=new_symbol.value.is_nil())
320  {
321  if(warn_msg.empty())
322  warn_msg="non-pointer parameter types differ between "
323  "declaration and definition";
324  replace=new_symbol.value.is_not_nil();
325  }
326  else
327  break;
328 
329  conflicts.pop_front();
330  }
331 
332  if(!conflicts.empty())
333  {
334  diag.detailed_conflict_report(
335  old_symbol,
336  new_symbol,
337  conflicts.front().first,
338  conflicts.front().second);
339 
340  diag.error(old_symbol, new_symbol, "conflicting function declarations");
341 
342  // error logged, continue typechecking other symbols
343  return;
344  }
345  else
346  {
347  // warns about the first inconsistency
348  diag.warning(old_symbol, new_symbol, warn_msg);
349 
350  if(replace)
351  {
352  old_symbol.type=new_symbol.type;
353  old_symbol.location=new_symbol.location;
354  }
355  }
356  }
357 
359  old_symbol.symbol_expr(), old_symbol.symbol_expr());
360  }
361 
362  if(!new_symbol.value.is_nil())
363  {
364  if(old_symbol.value.is_nil())
365  {
366  // the one with body wins!
367  rename_new_symbol(new_symbol.value);
368  rename_new_symbol(new_symbol.type);
369  old_symbol.value=new_symbol.value;
370  old_symbol.type=new_symbol.type; // for parameter identifiers
371  old_symbol.is_weak=new_symbol.is_weak;
372  old_symbol.location=new_symbol.location;
373  old_symbol.is_macro=new_symbol.is_macro;
374 
375  // replace any previous update
376  object_type_updates.erase(old_symbol.name);
378  old_symbol.symbol_expr(), old_symbol.symbol_expr());
379  }
380  else if(to_code_type(old_symbol.type).get_inlined())
381  {
382  // ok, silently ignore
383  }
384  else if(old_symbol.type == new_symbol.type)
385  {
386  // keep the one in old_symbol -- libraries come last!
388  log.debug().source_location = new_symbol.location;
389  log.debug() << "function '" << old_symbol.name << "' in module '"
390  << new_symbol.module
391  << "' is shadowed by a definition in module '"
392  << old_symbol.module << "'" << messaget::eom;
393  }
394  else
395  {
396  diag.error(old_symbol, new_symbol, "duplicate definition of function");
397  }
398  }
399 }
400 
402  const typet &t1,
403  const typet &t2,
404  adjust_type_infot &info)
405 {
406  if(t1 == t2)
407  return false;
408 
409  if(
410  t1.id() == ID_struct_tag || t1.id() == ID_union_tag ||
411  t1.id() == ID_c_enum_tag)
412  {
413  const irep_idt &identifier = to_tag_type(t1).get_identifier();
414 
415  if(info.o_symbols.insert(identifier).second)
416  {
417  bool result=
419  info.o_symbols.erase(identifier);
420 
421  return result;
422  }
423 
424  return false;
425  }
426  else if(
427  t2.id() == ID_struct_tag || t2.id() == ID_union_tag ||
428  t2.id() == ID_c_enum_tag)
429  {
430  const irep_idt &identifier = to_tag_type(t2).get_identifier();
431 
432  if(info.n_symbols.insert(identifier).second)
433  {
434  bool result=
436  info.n_symbols.erase(identifier);
437 
438  return result;
439  }
440 
441  return false;
442  }
443  else if(t1.id()==ID_pointer && t2.id()==ID_array)
444  {
445  info.set_to_new=true; // store new type
446 
447  return false;
448  }
449  else if(t1.id()==ID_array && t2.id()==ID_pointer)
450  {
451  // ignore
452  return false;
453  }
454  else if(
455  t1.id() == ID_struct && to_struct_type(t1).is_incomplete() &&
456  t2.id() == ID_struct && !to_struct_type(t2).is_incomplete())
457  {
458  info.set_to_new=true; // store new type
459 
460  return false;
461  }
462  else if(
463  t1.id() == ID_union && to_union_type(t1).is_incomplete() &&
464  t2.id() == ID_union && !to_union_type(t2).is_incomplete())
465  {
466  info.set_to_new = true; // store new type
467 
468  return false;
469  }
470  else if(
471  t1.id() == ID_struct && !to_struct_type(t1).is_incomplete() &&
472  t2.id() == ID_struct && to_struct_type(t2).is_incomplete())
473  {
474  // ignore
475  return false;
476  }
477  else if(
478  t1.id() == ID_union && !to_union_type(t1).is_incomplete() &&
479  t2.id() == ID_union && to_union_type(t2).is_incomplete())
480  {
481  // ignore
482  return false;
483  }
484  else if(t1.id()!=t2.id())
485  {
486  // type classes do not match and can't be fixed
487  return true;
488  }
489 
490  if(t1.id()==ID_pointer)
491  {
493 #if 0
494  bool s=info.set_to_new;
495  if(adjust_object_type_rec(t1.subtype(), t2.subtype(), info))
496  {
497  diag.warning(
498  info.old_symbol,
499  info.new_symbol,
500  "conflicting pointer types for variable");
501  info.set_to_new=s;
502  }
503 #else
504  diag.warning(
505  info.old_symbol,
506  info.new_symbol,
507  "conflicting pointer types for variable");
508 #endif
509 
510  if(info.old_symbol.is_extern && !info.new_symbol.is_extern)
511  {
512  info.set_to_new = true; // store new type
513  }
514 
515  return false;
516  }
517  else if(
518  t1.id() == ID_array &&
520  to_array_type(t1).element_type(), to_array_type(t2).element_type(), info))
521  {
522  // still need to compare size
523  const exprt &old_size=to_array_type(t1).size();
524  const exprt &new_size=to_array_type(t2).size();
525 
526  if((old_size.is_nil() && new_size.is_not_nil()) ||
527  (old_size.is_zero() && new_size.is_not_nil()) ||
528  info.old_symbol.is_weak)
529  {
530  info.set_to_new=true; // store new type
531  }
532  else if(new_size.is_nil() ||
533  new_size.is_zero() ||
534  info.new_symbol.is_weak)
535  {
536  // ok, we will use the old type
537  }
538  else
539  {
540  if(new_size.type() != old_size.type())
541  {
543  diag.error(
544  info.old_symbol,
545  info.new_symbol,
546  "conflicting array sizes for variable");
547 
548  // error logged, continue typechecking other symbols
549  return true;
550  }
551 
552  equal_exprt eq(old_size, new_size);
553 
554  if(!simplify_expr(eq, ns).is_true())
555  {
557  diag.error(
558  info.old_symbol,
559  info.new_symbol,
560  "conflicting array sizes for variable");
561 
562  // error logged, continue typechecking other symbols
563  return true;
564  }
565  }
566 
567  return false;
568  }
569  else if(t1.id()==ID_struct || t1.id()==ID_union)
570  {
571  const struct_union_typet::componentst &components1=
573 
574  const struct_union_typet::componentst &components2=
576 
577  struct_union_typet::componentst::const_iterator
578  it1=components1.begin(), it2=components2.begin();
579  for( ;
580  it1!=components1.end() && it2!=components2.end();
581  ++it1, ++it2)
582  {
583  if(it1->get_name()!=it2->get_name() ||
584  adjust_object_type_rec(it1->type(), it2->type(), info))
585  return true;
586  }
587  if(it1!=components1.end() || it2!=components2.end())
588  return true;
589 
590  return false;
591  }
592 
593  return true;
594 }
595 
597  const symbolt &old_symbol,
598  const symbolt &new_symbol,
599  bool &set_to_new)
600 {
601  const typet &old_type=follow_tags_symbols(ns, old_symbol.type);
602  const typet &new_type=follow_tags_symbols(ns, new_symbol.type);
603 
604  adjust_type_infot info(old_symbol, new_symbol);
605  bool result=adjust_object_type_rec(old_type, new_type, info);
606  set_to_new=info.set_to_new;
607 
608  return result;
609 }
610 
612  symbolt &old_symbol,
613  symbolt &new_symbol)
614 {
615  // both are variables
616  bool set_to_new = false;
617 
618  if(old_symbol.type != new_symbol.type)
619  {
620  bool failed=
621  adjust_object_type(old_symbol, new_symbol, set_to_new);
622 
623  if(failed)
624  {
625  const typet &old_type=follow_tags_symbols(ns, old_symbol.type);
626 
628 
629  // provide additional diagnostic output for
630  // struct/union/array/enum
631  if(old_type.id()==ID_struct ||
632  old_type.id()==ID_union ||
633  old_type.id()==ID_array ||
634  old_type.id()==ID_c_enum)
635  {
636  diag.detailed_conflict_report(
637  old_symbol, new_symbol, old_symbol.type, new_symbol.type);
638  }
639 
640  diag.error(old_symbol, new_symbol, "conflicting types for variable");
641 
642  // error logged, continue typechecking other symbols
643  return;
644  }
645  else if(set_to_new)
646  old_symbol.type=new_symbol.type;
647 
649  old_symbol.symbol_expr(), old_symbol.symbol_expr());
650  }
651 
652  // care about initializers
653 
654  if(!new_symbol.value.is_nil())
655  {
656  if(old_symbol.value.is_nil() ||
657  old_symbol.is_weak)
658  {
659  // new_symbol wins
660  old_symbol.value=new_symbol.value;
661  old_symbol.is_macro=new_symbol.is_macro;
662  }
663  else if(!new_symbol.is_weak)
664  {
665  // try simplifier
666  exprt tmp_old=old_symbol.value,
667  tmp_new=new_symbol.value;
668 
669  simplify(tmp_old, ns);
670  simplify(tmp_new, ns);
671 
672  if(tmp_old == tmp_new)
673  {
674  // ok, the same
675  }
676  else
677  {
679  log.warning().source_location = new_symbol.location;
680 
681  log.warning() << "conflicting initializers for"
682  << " variable '" << old_symbol.name << "'\n";
683  log.warning() << "using old value in module " << old_symbol.module
684  << " " << old_symbol.value.find_source_location() << '\n'
685  << from_expr(ns, old_symbol.name, tmp_old) << '\n';
686  log.warning() << "ignoring new value in module " << new_symbol.module
687  << " " << new_symbol.value.find_source_location() << '\n'
688  << from_expr(ns, new_symbol.name, tmp_new)
689  << messaget::eom;
690  }
691  }
692  }
693  else if(set_to_new && !old_symbol.value.is_nil())
694  {
695  // the type has been updated, now make sure that the initialising assignment
696  // will have matching types
697  old_symbol.value = typecast_exprt(old_symbol.value, old_symbol.type);
698  }
699 }
700 
702  symbolt &old_symbol,
703  symbolt &new_symbol)
704 {
705  // we do not permit different contracts with the same name to be defined, or
706  // cases where only one of the symbols is a contract
707  if(
708  old_symbol.is_property != new_symbol.is_property ||
709  (old_symbol.is_property && new_symbol.is_property &&
710  old_symbol.type != new_symbol.type))
711  {
713  diag.error(old_symbol, new_symbol, "conflict on code contract");
714  }
715 
716  // see if it is a function or a variable
717 
718  bool is_code_old_symbol=old_symbol.type.id()==ID_code;
719  bool is_code_new_symbol=new_symbol.type.id()==ID_code;
720 
721  if(is_code_old_symbol!=is_code_new_symbol)
722  {
724  diag.error(old_symbol, new_symbol, "conflicting definition for symbol");
725 
726  // error logged, continue typechecking other symbols
727  return;
728  }
729 
730  if(is_code_old_symbol)
731  duplicate_code_symbol(old_symbol, new_symbol);
732  else
733  duplicate_object_symbol(old_symbol, new_symbol);
734 
735  // care about flags
736 
737  if(old_symbol.is_extern && !new_symbol.is_extern)
738  old_symbol.location=new_symbol.location;
739 
740  // it's enough that one isn't extern for the final one not to be
741  old_symbol.is_extern=old_symbol.is_extern && new_symbol.is_extern;
742 }
743 
745  symbolt &old_symbol,
746  const symbolt &new_symbol)
747 {
748  PRECONDITION(new_symbol.is_type);
749 
750  if(!old_symbol.is_type)
751  {
753  diag.error(old_symbol, new_symbol, "conflicting definition for symbol");
754 
755  // error logged, continue typechecking other symbols
756  return;
757  }
758 
759  if(old_symbol.type==new_symbol.type)
760  return;
761 
762  if(
763  old_symbol.type.id() == ID_struct &&
764  to_struct_type(old_symbol.type).is_incomplete() &&
765  new_symbol.type.id() == ID_struct &&
766  !to_struct_type(new_symbol.type).is_incomplete())
767  {
768  old_symbol.type=new_symbol.type;
769  old_symbol.location=new_symbol.location;
770  return;
771  }
772 
773  if(
774  old_symbol.type.id() == ID_struct &&
775  !to_struct_type(old_symbol.type).is_incomplete() &&
776  new_symbol.type.id() == ID_struct &&
777  to_struct_type(new_symbol.type).is_incomplete())
778  {
779  // ok, keep old
780  return;
781  }
782 
783  if(
784  old_symbol.type.id() == ID_union &&
785  to_union_type(old_symbol.type).is_incomplete() &&
786  new_symbol.type.id() == ID_union &&
787  !to_union_type(new_symbol.type).is_incomplete())
788  {
789  old_symbol.type=new_symbol.type;
790  old_symbol.location=new_symbol.location;
791  return;
792  }
793 
794  if(
795  old_symbol.type.id() == ID_union &&
796  !to_union_type(old_symbol.type).is_incomplete() &&
797  new_symbol.type.id() == ID_union &&
798  to_union_type(new_symbol.type).is_incomplete())
799  {
800  // ok, keep old
801  return;
802  }
803 
804  if(
805  old_symbol.type.id() == ID_array && new_symbol.type.id() == ID_array &&
806  to_array_type(old_symbol.type).element_type() ==
807  to_array_type(new_symbol.type).element_type())
808  {
809  if(to_array_type(old_symbol.type).size().is_nil() &&
810  to_array_type(new_symbol.type).size().is_not_nil())
811  {
812  to_array_type(old_symbol.type).size()=
813  to_array_type(new_symbol.type).size();
814  return;
815  }
816 
817  if(to_array_type(new_symbol.type).size().is_nil() &&
818  to_array_type(old_symbol.type).size().is_not_nil())
819  {
820  // ok, keep old
821  return;
822  }
823  }
824 
826 
827  diag.detailed_conflict_report(
828  old_symbol, new_symbol, old_symbol.type, new_symbol.type);
829 
830  diag.error(
831  old_symbol, new_symbol, "unexpected difference between type symbols");
832 }
833 
835  const symbolt &old_symbol,
836  const symbolt &new_symbol)
837 {
838  PRECONDITION(new_symbol.is_type);
839 
840  if(!old_symbol.is_type)
841  return renamingt::RENAME_NEW;
842 
843  if(old_symbol.type==new_symbol.type)
844  return renamingt::NO_RENAMING;
845 
846  if(
847  old_symbol.type.id() == ID_struct &&
848  to_struct_type(old_symbol.type).is_incomplete() &&
849  new_symbol.type.id() == ID_struct &&
850  !to_struct_type(new_symbol.type).is_incomplete())
851  {
852  return renamingt::NO_RENAMING; // not different
853  }
854 
855  if(
856  old_symbol.type.id() == ID_struct &&
857  !to_struct_type(old_symbol.type).is_incomplete() &&
858  new_symbol.type.id() == ID_struct &&
859  to_struct_type(new_symbol.type).is_incomplete())
860  {
861  return renamingt::NO_RENAMING; // not different
862  }
863 
864  if(
865  old_symbol.type.id() == ID_union &&
866  to_union_type(old_symbol.type).is_incomplete() &&
867  new_symbol.type.id() == ID_union &&
868  !to_union_type(new_symbol.type).is_incomplete())
869  {
870  return renamingt::NO_RENAMING; // not different
871  }
872 
873  if(
874  old_symbol.type.id() == ID_union &&
875  !to_union_type(old_symbol.type).is_incomplete() &&
876  new_symbol.type.id() == ID_union &&
877  to_union_type(new_symbol.type).is_incomplete())
878  {
879  return renamingt::NO_RENAMING; // not different
880  }
881 
882  if(
883  old_symbol.type.id() == ID_array && new_symbol.type.id() == ID_array &&
884  to_array_type(old_symbol.type).element_type() ==
885  to_array_type(new_symbol.type).element_type())
886  {
887  if(to_array_type(old_symbol.type).size().is_nil() &&
888  to_array_type(new_symbol.type).size().is_not_nil())
889  {
890  return renamingt::NO_RENAMING; // not different
891  }
892 
893  if(to_array_type(new_symbol.type).size().is_nil() &&
894  to_array_type(old_symbol.type).size().is_not_nil())
895  {
896  return renamingt::NO_RENAMING; // not different
897  }
898  }
899 
900  return renamingt::RENAME_NEW; // different
901 }
902 
904  const symbol_table_baset &src_symbol_table,
905  std::unordered_set<irep_idt> &needs_to_be_renamed,
906  message_handlert &message_handler)
907 {
908  // Any type that uses a symbol that will be renamed also
909  // needs to be renamed, and so on, until saturation.
910 
911  // X -> Y iff Y uses X for new symbol type IDs X and Y
912  std::unordered_map<irep_idt, std::unordered_set<irep_idt>> used_by;
913 
914  for(const auto &symbol_pair : src_symbol_table.symbols)
915  {
916  if(symbol_pair.second.is_type)
917  {
918  // find type and array-size symbols
919  find_symbols_sett symbols_used;
920  find_type_and_expr_symbols(symbol_pair.second.type, symbols_used);
921 
922  for(const auto &symbol_used : symbols_used)
923  {
924  used_by[symbol_used].insert(symbol_pair.first);
925  }
926  }
927  }
928 
929  std::deque<irep_idt> queue(
930  needs_to_be_renamed.begin(), needs_to_be_renamed.end());
931 
932  while(!queue.empty())
933  {
934  irep_idt id = queue.back();
935  queue.pop_back();
936 
937  const std::unordered_set<irep_idt> &u = used_by[id];
938 
939  for(const auto &dep : u)
940  if(needs_to_be_renamed.insert(dep).second)
941  {
942  queue.push_back(dep);
943  #ifdef DEBUG
944  messaget log{message_handler};
945  log.debug() << "LINKING: needs to be renamed (dependency): " << dep
946  << messaget::eom;
947 #endif
948  }
949  }
950 }
951 
952 std::unordered_map<irep_idt, irep_idt> linkingt::rename_symbols(
953  const symbol_table_baset &src_symbol_table,
954  const std::unordered_set<irep_idt> &needs_to_be_renamed)
955 {
956  std::unordered_map<irep_idt, irep_idt> new_identifiers;
957  namespacet src_ns(src_symbol_table);
958 
959  for(const irep_idt &id : needs_to_be_renamed)
960  {
961  const symbolt &new_symbol = src_ns.lookup(id);
962 
963  irep_idt new_identifier;
964 
965  if(new_symbol.is_type)
966  new_identifier=type_to_name(src_ns, id, new_symbol.type);
967  else
968  new_identifier = rename(src_symbol_table, id);
969 
970  new_identifiers.emplace(id, new_identifier);
971 
972 #ifdef DEBUG
974  log.debug() << "LINKING: renaming " << id << " to " << new_identifier
975  << messaget::eom;
976 #endif
977 
978  if(new_symbol.is_type)
979  rename_new_symbol.insert_type(id, new_identifier);
980  else
981  rename_new_symbol.insert_expr(id, new_identifier);
982  }
983 
984  return new_identifiers;
985 }
986 
988  const symbol_table_baset &src_symbol_table,
989  const std::unordered_map<irep_idt, irep_idt> &new_identifiers)
990 {
991  std::map<irep_idt, symbolt> src_symbols;
992  // First apply the renaming
993  for(const auto &named_symbol : src_symbol_table.symbols)
994  {
995  symbolt symbol=named_symbol.second;
996  // apply the renaming
997  rename_new_symbol(symbol.type);
998  rename_new_symbol(symbol.value);
999  auto it = new_identifiers.find(named_symbol.first);
1000  if(it != new_identifiers.end())
1001  symbol.name = it->second;
1002 
1003  src_symbols.emplace(named_symbol.first, std::move(symbol));
1004  }
1005 
1006  // Move over all the non-colliding ones
1007  std::unordered_set<irep_idt> collisions;
1008 
1009  for(const auto &named_symbol : src_symbols)
1010  {
1011  // renamed?
1012  if(named_symbol.first!=named_symbol.second.name)
1013  {
1014  // new
1015  main_symbol_table.add(named_symbol.second);
1016  }
1017  else
1018  {
1019  if(!main_symbol_table.has_symbol(named_symbol.first))
1020  {
1021  // new
1022  main_symbol_table.add(named_symbol.second);
1023  }
1024  else
1025  collisions.insert(named_symbol.first);
1026  }
1027  }
1028 
1029  // Now do the collisions
1030  for(const irep_idt &collision : collisions)
1031  {
1032  symbolt &old_symbol = main_symbol_table.get_writeable_ref(collision);
1033  symbolt &new_symbol=src_symbols.at(collision);
1034 
1035  if(new_symbol.is_type)
1036  duplicate_type_symbol(old_symbol, new_symbol);
1037  else
1038  duplicate_non_type_symbol(old_symbol, new_symbol);
1039  }
1040 
1041  // Apply type updates to initializers
1042  for(auto it = main_symbol_table.begin(); it != main_symbol_table.end(); ++it)
1043  {
1044  if(
1045  !it->second.is_type && !it->second.is_macro &&
1046  it->second.value.is_not_nil())
1047  {
1048  object_type_updates(it.get_writeable_symbol().value);
1049  }
1050  }
1051 }
1052 
1053 bool linkingt::link(const symbol_table_baset &src_symbol_table)
1054 {
1055  const unsigned errors_before =
1057 
1058  // We do this in three phases. We first figure out which symbols need to
1059  // be renamed, and then build the renaming, and finally apply this
1060  // renaming in the second pass over the symbol table.
1061 
1062  // PHASE 1: identify symbols to be renamed
1063 
1064  std::unordered_set<irep_idt> needs_to_be_renamed;
1065 
1066  for(const auto &symbol_pair : src_symbol_table.symbols)
1067  {
1068  symbol_table_baset::symbolst::const_iterator m_it =
1069  main_symbol_table.symbols.find(symbol_pair.first);
1070 
1071  if(m_it != main_symbol_table.symbols.end())
1072  {
1073  // duplicate
1074  switch(needs_renaming(m_it->second, symbol_pair.second))
1075  {
1076  case renamingt::NO_RENAMING:
1077  break;
1078  case renamingt::RENAME_OLD:
1079  {
1080  symbolt renamed_symbol = m_it->second;
1081  renamed_symbol.name = rename(src_symbol_table, symbol_pair.first);
1082  if(m_it->second.is_type)
1083  rename_main_symbol.insert_type(m_it->first, renamed_symbol.name);
1084  else
1085  rename_main_symbol.insert_expr(m_it->first, renamed_symbol.name);
1086  main_symbol_table.erase(m_it);
1087  main_symbol_table.insert(std::move(renamed_symbol));
1088  break;
1089  }
1090  case renamingt::RENAME_NEW:
1091  {
1092  needs_to_be_renamed.insert(symbol_pair.first);
1093 #ifdef DEBUG
1095  log.debug() << "LINKING: needs to be renamed: " << symbol_pair.first
1096  << messaget::eom;
1097 #endif
1098  break;
1099  }
1100  }
1101  }
1102  }
1103 
1104  // rename within main symbol table
1105  for(auto &symbol_pair : main_symbol_table)
1106  {
1107  symbolt tmp = symbol_pair.second;
1108  bool unmodified = rename_main_symbol(tmp.value);
1109  unmodified &= rename_main_symbol(tmp.type);
1110  if(!unmodified)
1111  {
1112  symbolt *sym_ptr = main_symbol_table.get_writeable(symbol_pair.first);
1113  CHECK_RETURN(sym_ptr);
1114  *sym_ptr = std::move(tmp);
1115  }
1116  }
1117 
1118  // renaming types may trigger further renaming
1119  do_type_dependencies(src_symbol_table, needs_to_be_renamed, message_handler);
1120 
1121  // PHASE 2: actually rename them
1122  auto new_identifiers = rename_symbols(src_symbol_table, needs_to_be_renamed);
1123 
1124  // PHASE 3: copy new symbols to main table
1125  copy_symbols(src_symbol_table, new_identifiers);
1126 
1127  return message_handler.get_message_count(messaget::M_ERROR) != errors_before;
1128 }
1129 
1130 bool linking(
1131  symbol_table_baset &dest_symbol_table,
1132  const symbol_table_baset &new_symbol_table,
1133  message_handlert &message_handler)
1134 {
1135  linkingt linking(dest_symbol_table, message_handler);
1136 
1137  return linking.link(new_symbol_table);
1138 }
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
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
Base type of functions.
Definition: std_types.h:583
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
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
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
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:57
bool is_not_nil() const
Definition: irep.h:372
const irep_idt & id() const
Definition: irep.h:388
void make_nil()
Definition: irep.h:446
bool is_nil() const
Definition: irep.h:368
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:952
void duplicate_non_type_symbol(symbolt &old_symbol, symbolt &new_symbol)
Definition: linking.cpp:701
bool adjust_object_type(const symbolt &old_symbol, const symbolt &new_symbol, bool &set_to_new)
Definition: linking.cpp:596
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:1053
renamingt needs_renaming(const symbolt &old_symbol, const symbolt &new_symbol)
Definition: linking_class.h:60
namespacet ns
bool adjust_object_type_rec(const typet &type1, const typet &type2, adjust_type_infot &info)
Definition: linking.cpp:401
rename_symbolt rename_main_symbol
Definition: linking_class.h:43
void copy_symbols(const symbol_table_baset &, const std::unordered_map< irep_idt, irep_idt > &)
Definition: linking.cpp:987
irep_idt rename(const symbol_table_baset &, const irep_idt &)
Definition: linking.cpp:43
renamingt needs_renaming_type(const symbolt &old_symbol, const symbolt &new_symbol)
Definition: linking.cpp:834
symbol_table_baset & main_symbol_table
renamingt needs_renaming_non_type(const symbolt &old_symbol, const symbolt &new_symbol)
Definition: linking.cpp:67
void duplicate_object_symbol(symbolt &old_symbol, symbolt &new_symbol)
Definition: linking.cpp:611
casting_replace_symbolt object_type_updates
Definition: linking_class.h:44
std::unordered_set< irep_idt > renamed_ids
void duplicate_type_symbol(symbolt &old_symbol, const symbolt &new_symbol)
Definition: linking.cpp:744
rename_symbolt rename_new_symbol
Definition: linking_class.h:43
void duplicate_code_symbol(symbolt &old_symbol, symbolt &new_symbol)
Definition: linking.cpp:82
message_handlert & message_handler
std::size_t get_message_count(unsigned level) const
Definition: message.h:55
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:154
@ M_ERROR
Definition: message.h:169
static eomt eom
Definition: message.h:289
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
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
std::size_t erase(const irep_idt &id)
void insert(const class symbol_exprt &old_expr, const exprt &new_expr)
Sets old_expr to be replaced by new_expr if we don't already have a replacement; otherwise does nothi...
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
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
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
The type of an expression, extends irept.
Definition: type.h:29
The union type.
Definition: c_types.h:147
void find_type_and_expr_symbols(const exprt &src, find_symbols_sett &dest, const std::vector< irep_idt > &subs_to_find)
Find identifiers with id ID_symbol of the sub expressions and the subs with ID in subs_to_find consid...
std::unordered_set< irep_idt > find_symbols_sett
Definition: find_symbols.h:20
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
std::string from_expr(const namespacet &ns, const irep_idt &identifier, const exprt &expr)
std::string type_to_name(const namespacet &ns, const irep_idt &identifier, const typet &type)
static void do_type_dependencies(const symbol_table_baset &src_symbol_table, std::unordered_set< irep_idt > &needs_to_be_renamed, message_handlert &message_handler)
Definition: linking.cpp:903
static const typet & follow_tags_symbols(const namespacet &ns, const typet &type)
Definition: linking.cpp:28
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:1130
ANSI-C Linking.
ANSI-C Linking.
ANSI-C Linking.
bool is_true(const literalt &l)
Definition: literal.h:198
double log(double x)
Definition: math.c:2776
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 PRECONDITION(CONDITION)
Definition: invariant.h:463
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)