CBMC
Loading...
Searching...
No Matches
linking.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: ANSI-C Linking
4
5Author: 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>
21
23
24#include "linking_diagnostics.h"
25
26#include <deque>
27
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
44{
45 unsigned cnt=0;
46
47 while(true)
48 {
50 id2string(id)+"$link"+std::to_string(++cnt);
51
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)
76 else if(old_symbol.is_file_local)
78 else
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;
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=
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";
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
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,
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
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 {
572 to_struct_union_type(t1).components();
573
575 to_struct_union_type(t2).components();
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);
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
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
722 {
724 diag.error(old_symbol, new_symbol, "conflicting definition for symbol");
725
726 // error logged, continue typechecking other symbols
727 return;
728 }
729
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)
842
843 if(old_symbol.type==new_symbol.type)
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
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
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(
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
952std::unordered_map<irep_idt, irep_idt> linkingt::rename_symbols(
954 const std::unordered_set<irep_idt> &needs_to_be_renamed)
955{
956 std::unordered_map<irep_idt, irep_idt> new_identifiers;
958
959 for(const irep_idt &id : needs_to_be_renamed)
960 {
961 const symbolt &new_symbol = src_ns.lookup(id);
962
964
965 if(new_symbol.is_type)
966 new_identifier=type_to_name(src_ns, id, new_symbol.type);
967 else
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)
980 else
982 }
983
984 return new_identifiers;
985}
986
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
1016 }
1017 else
1018 {
1020 {
1021 // new
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 {
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
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 =
1070
1071 if(m_it != main_symbol_table.symbols.end())
1072 {
1073 // duplicate
1074 switch(needs_renaming(m_it->second, symbol_pair.second))
1075 {
1077 break;
1079 {
1080 symbolt renamed_symbol = m_it->second;
1082 if(m_it->second.is_type)
1084 else
1088 break;
1089 }
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);
1110 if(!unmodified)
1111 {
1114 *sym_ptr = std::move(tmp);
1115 }
1116 }
1117
1118 // renaming types may trigger further renaming
1120
1121 // PHASE 2: actually rename them
1123
1124 // PHASE 3: copy new symbols to main table
1126
1128}
1129
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 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 union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition c_types.h:184
const union_tag_typet & to_union_tag_type(const typet &type)
Cast a typet to a union_tag_typet.
Definition c_types.h:224
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Base type of functions.
Definition std_types.h:583
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:1366
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 get_bool(const irep_idt &name) const
Definition irep.cpp:57
bool is_not_nil() const
Definition irep.h:372
void make_nil()
Definition irep.h:446
const irep_idt & id() const
Definition irep.h:388
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)
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
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
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
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:49
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
void insert_type(const irep_idt &old_id, const irep_idt &new_id)
void insert_expr(const irep_idt &old_id, const irep_idt &new_id)
std::size_t erase(const irep_idt &id)
void insert(const class symbol_exprt &old_expr, const exprt &new_expr)
Sets old_expr to be replaced by new_expr if we don't already have a replacement; otherwise does nothi...
std::vector< componentt > componentst
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 std::pair< symbolt &, bool > insert(symbolt symbol)=0
Move or copy a new symbol to the symbol table.
virtual symbolt * get_writeable(const irep_idt &name)=0
Find a symbol in the symbol table for read-write access.
virtual void erase(const symbolst::const_iterator &entry)=0
Remove a symbol from the symbol table.
virtual iteratort begin()=0
const symbolst & symbols
Read-only field, used to look up symbols given their names.
virtual iteratort end()=0
bool has_symbol(const irep_idt &name) const
Check whether a symbol exists in the symbol table.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
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
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
Semantic type conversion.
Definition std_expr.h:2073
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
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:2449
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 code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
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 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 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)
Author: Diffblue Ltd.
static bool failed(bool error_indicator)