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(
527 (old_size.is_nil() && new_size.is_not_nil()) ||
528 (old_size == 0 && new_size.is_not_nil()) || info.old_symbol.is_weak)
529 {
530 info.set_to_new=true; // store new type
531 }
532 else if(new_size.is_nil() || new_size == 0 || info.new_symbol.is_weak)
533 {
534 // ok, we will use the old type
535 }
536 else
537 {
538 if(new_size.type() != old_size.type())
539 {
541 diag.error(
542 info.old_symbol,
543 info.new_symbol,
544 "conflicting array sizes for variable");
545
546 // error logged, continue typechecking other symbols
547 return true;
548 }
549
551
552 if(simplify_expr(eq, ns) != true)
553 {
555 diag.error(
556 info.old_symbol,
557 info.new_symbol,
558 "conflicting array sizes for variable");
559
560 // error logged, continue typechecking other symbols
561 return true;
562 }
563 }
564
565 return false;
566 }
567 else if(t1.id()==ID_struct || t1.id()==ID_union)
568 {
570 to_struct_union_type(t1).components();
571
573 to_struct_union_type(t2).components();
574
575 struct_union_typet::componentst::const_iterator
576 it1=components1.begin(), it2=components2.begin();
577 for( ;
578 it1!=components1.end() && it2!=components2.end();
579 ++it1, ++it2)
580 {
581 if(it1->get_name()!=it2->get_name() ||
582 adjust_object_type_rec(it1->type(), it2->type(), info))
583 return true;
584 }
585 if(it1!=components1.end() || it2!=components2.end())
586 return true;
587
588 return false;
589 }
590
591 return true;
592}
593
595 const symbolt &old_symbol,
596 const symbolt &new_symbol,
597 bool &set_to_new)
598{
599 const typet &old_type=follow_tags_symbols(ns, old_symbol.type);
600 const typet &new_type=follow_tags_symbols(ns, new_symbol.type);
601
602 adjust_type_infot info(old_symbol, new_symbol);
604 set_to_new=info.set_to_new;
605
606 return result;
607}
608
610 symbolt &old_symbol,
611 symbolt &new_symbol)
612{
613 // both are variables
614 bool set_to_new = false;
615
616 if(old_symbol.type != new_symbol.type)
617 {
618 bool failed=
619 adjust_object_type(old_symbol, new_symbol, set_to_new);
620
621 if(failed)
622 {
623 const typet &old_type=follow_tags_symbols(ns, old_symbol.type);
624
626
627 // provide additional diagnostic output for
628 // struct/union/array/enum
629 if(old_type.id()==ID_struct ||
630 old_type.id()==ID_union ||
631 old_type.id()==ID_array ||
632 old_type.id()==ID_c_enum)
633 {
634 diag.detailed_conflict_report(
635 old_symbol, new_symbol, old_symbol.type, new_symbol.type);
636 }
637
638 diag.error(old_symbol, new_symbol, "conflicting types for variable");
639
640 // error logged, continue typechecking other symbols
641 return;
642 }
643 else if(set_to_new)
644 old_symbol.type=new_symbol.type;
645
647 old_symbol.symbol_expr(), old_symbol.symbol_expr());
648 }
649
650 // care about initializers
651
652 if(!new_symbol.value.is_nil())
653 {
654 if(old_symbol.value.is_nil() ||
655 old_symbol.is_weak)
656 {
657 // new_symbol wins
658 old_symbol.value=new_symbol.value;
659 old_symbol.is_macro=new_symbol.is_macro;
660 }
661 else if(!new_symbol.is_weak)
662 {
663 // try simplifier
664 exprt tmp_old=old_symbol.value,
665 tmp_new=new_symbol.value;
666
669
670 if(tmp_old == tmp_new)
671 {
672 // ok, the same
673 }
674 else
675 {
677 log.warning().source_location = new_symbol.location;
678
679 log.warning() << "conflicting initializers for"
680 << " variable '" << old_symbol.name << "'\n";
681 log.warning() << "using old value in module " << old_symbol.module
682 << " " << old_symbol.value.find_source_location() << '\n'
683 << from_expr(ns, old_symbol.name, tmp_old) << '\n';
684 log.warning() << "ignoring new value in module " << new_symbol.module
685 << " " << new_symbol.value.find_source_location() << '\n'
686 << from_expr(ns, new_symbol.name, tmp_new)
687 << messaget::eom;
688 }
689 }
690 }
691 else if(set_to_new && !old_symbol.value.is_nil())
692 {
693 // the type has been updated, now make sure that the initialising assignment
694 // will have matching types
695 old_symbol.value = typecast_exprt(old_symbol.value, old_symbol.type);
696 }
697}
698
700 symbolt &old_symbol,
701 symbolt &new_symbol)
702{
703 // we do not permit different contracts with the same name to be defined, or
704 // cases where only one of the symbols is a contract
705 if(
706 old_symbol.is_property != new_symbol.is_property ||
707 (old_symbol.is_property && new_symbol.is_property &&
708 old_symbol.type != new_symbol.type))
709 {
711 diag.error(old_symbol, new_symbol, "conflict on code contract");
712 }
713
714 // see if it is a function or a variable
715
716 bool is_code_old_symbol=old_symbol.type.id()==ID_code;
717 bool is_code_new_symbol=new_symbol.type.id()==ID_code;
718
720 {
722 diag.error(old_symbol, new_symbol, "conflicting definition for symbol");
723
724 // error logged, continue typechecking other symbols
725 return;
726 }
727
729 duplicate_code_symbol(old_symbol, new_symbol);
730 else
731 duplicate_object_symbol(old_symbol, new_symbol);
732
733 // care about flags
734
735 if(old_symbol.is_extern && !new_symbol.is_extern)
736 old_symbol.location=new_symbol.location;
737
738 // it's enough that one isn't extern for the final one not to be
739 old_symbol.is_extern=old_symbol.is_extern && new_symbol.is_extern;
740}
741
743 symbolt &old_symbol,
744 const symbolt &new_symbol)
745{
746 PRECONDITION(new_symbol.is_type);
747
748 if(!old_symbol.is_type)
749 {
751 diag.error(old_symbol, new_symbol, "conflicting definition for symbol");
752
753 // error logged, continue typechecking other symbols
754 return;
755 }
756
757 if(old_symbol.type==new_symbol.type)
758 return;
759
760 if(
761 old_symbol.type.id() == ID_struct &&
762 to_struct_type(old_symbol.type).is_incomplete() &&
763 new_symbol.type.id() == ID_struct &&
764 !to_struct_type(new_symbol.type).is_incomplete())
765 {
766 old_symbol.type=new_symbol.type;
767 old_symbol.location=new_symbol.location;
768 return;
769 }
770
771 if(
772 old_symbol.type.id() == ID_struct &&
773 !to_struct_type(old_symbol.type).is_incomplete() &&
774 new_symbol.type.id() == ID_struct &&
775 to_struct_type(new_symbol.type).is_incomplete())
776 {
777 // ok, keep old
778 return;
779 }
780
781 if(
782 old_symbol.type.id() == ID_union &&
783 to_union_type(old_symbol.type).is_incomplete() &&
784 new_symbol.type.id() == ID_union &&
785 !to_union_type(new_symbol.type).is_incomplete())
786 {
787 old_symbol.type=new_symbol.type;
788 old_symbol.location=new_symbol.location;
789 return;
790 }
791
792 if(
793 old_symbol.type.id() == ID_union &&
794 !to_union_type(old_symbol.type).is_incomplete() &&
795 new_symbol.type.id() == ID_union &&
796 to_union_type(new_symbol.type).is_incomplete())
797 {
798 // ok, keep old
799 return;
800 }
801
802 if(
803 old_symbol.type.id() == ID_array && new_symbol.type.id() == ID_array &&
804 to_array_type(old_symbol.type).element_type() ==
805 to_array_type(new_symbol.type).element_type())
806 {
807 if(to_array_type(old_symbol.type).size().is_nil() &&
808 to_array_type(new_symbol.type).size().is_not_nil())
809 {
810 to_array_type(old_symbol.type).size()=
811 to_array_type(new_symbol.type).size();
812 return;
813 }
814
815 if(to_array_type(new_symbol.type).size().is_nil() &&
816 to_array_type(old_symbol.type).size().is_not_nil())
817 {
818 // ok, keep old
819 return;
820 }
821 }
822
824
825 diag.detailed_conflict_report(
826 old_symbol, new_symbol, old_symbol.type, new_symbol.type);
827
828 diag.error(
829 old_symbol, new_symbol, "unexpected difference between type symbols");
830}
831
833 const symbolt &old_symbol,
834 const symbolt &new_symbol)
835{
836 PRECONDITION(new_symbol.is_type);
837
838 if(!old_symbol.is_type)
840
841 if(old_symbol.type==new_symbol.type)
843
844 if(
845 old_symbol.type.id() == ID_struct &&
846 to_struct_type(old_symbol.type).is_incomplete() &&
847 new_symbol.type.id() == ID_struct &&
848 !to_struct_type(new_symbol.type).is_incomplete())
849 {
850 return renamingt::NO_RENAMING; // not different
851 }
852
853 if(
854 old_symbol.type.id() == ID_struct &&
855 !to_struct_type(old_symbol.type).is_incomplete() &&
856 new_symbol.type.id() == ID_struct &&
857 to_struct_type(new_symbol.type).is_incomplete())
858 {
859 return renamingt::NO_RENAMING; // not different
860 }
861
862 if(
863 old_symbol.type.id() == ID_union &&
864 to_union_type(old_symbol.type).is_incomplete() &&
865 new_symbol.type.id() == ID_union &&
866 !to_union_type(new_symbol.type).is_incomplete())
867 {
868 return renamingt::NO_RENAMING; // not different
869 }
870
871 if(
872 old_symbol.type.id() == ID_union &&
873 !to_union_type(old_symbol.type).is_incomplete() &&
874 new_symbol.type.id() == ID_union &&
875 to_union_type(new_symbol.type).is_incomplete())
876 {
877 return renamingt::NO_RENAMING; // not different
878 }
879
880 if(
881 old_symbol.type.id() == ID_array && new_symbol.type.id() == ID_array &&
882 to_array_type(old_symbol.type).element_type() ==
883 to_array_type(new_symbol.type).element_type())
884 {
885 if(to_array_type(old_symbol.type).size().is_nil() &&
886 to_array_type(new_symbol.type).size().is_not_nil())
887 {
888 return renamingt::NO_RENAMING; // not different
889 }
890
891 if(to_array_type(new_symbol.type).size().is_nil() &&
892 to_array_type(old_symbol.type).size().is_not_nil())
893 {
894 return renamingt::NO_RENAMING; // not different
895 }
896 }
897
898 return renamingt::RENAME_NEW; // different
899}
900
903 std::unordered_set<irep_idt> &needs_to_be_renamed,
904 message_handlert &message_handler)
905{
906 // Any type that uses a symbol that will be renamed also
907 // needs to be renamed, and so on, until saturation.
908
909 // X -> Y iff Y uses X for new symbol type IDs X and Y
910 std::unordered_map<irep_idt, std::unordered_set<irep_idt>> used_by;
911
912 for(const auto &symbol_pair : src_symbol_table.symbols)
913 {
914 if(symbol_pair.second.is_type)
915 {
916 // find type and array-size symbols
919
920 for(const auto &symbol_used : symbols_used)
921 {
922 used_by[symbol_used].insert(symbol_pair.first);
923 }
924 }
925 }
926
927 std::deque<irep_idt> queue(
929
930 while(!queue.empty())
931 {
932 irep_idt id = queue.back();
933 queue.pop_back();
934
935 const std::unordered_set<irep_idt> &u = used_by[id];
936
937 for(const auto &dep : u)
938 if(needs_to_be_renamed.insert(dep).second)
939 {
940 queue.push_back(dep);
941 #ifdef DEBUG
942 messaget log{message_handler};
943 log.debug() << "LINKING: needs to be renamed (dependency): " << dep
944 << messaget::eom;
945#endif
946 }
947 }
948}
949
950std::unordered_map<irep_idt, irep_idt> linkingt::rename_symbols(
952 const std::unordered_set<irep_idt> &needs_to_be_renamed)
953{
954 std::unordered_map<irep_idt, irep_idt> new_identifiers;
956
957 for(const irep_idt &id : needs_to_be_renamed)
958 {
959 const symbolt &new_symbol = src_ns.lookup(id);
960
962
963 if(new_symbol.is_type)
964 new_identifier=type_to_name(src_ns, id, new_symbol.type);
965 else
967
968 new_identifiers.emplace(id, new_identifier);
969
970#ifdef DEBUG
972 log.debug() << "LINKING: renaming " << id << " to " << new_identifier
973 << messaget::eom;
974#endif
975
976 if(new_symbol.is_type)
978 else
980 }
981
982 return new_identifiers;
983}
984
987 const std::unordered_map<irep_idt, irep_idt> &new_identifiers)
988{
989 std::map<irep_idt, symbolt> src_symbols;
990 // First apply the renaming
991 for(const auto &named_symbol : src_symbol_table.symbols)
992 {
993 symbolt symbol=named_symbol.second;
994 // apply the renaming
995 rename_new_symbol(symbol.type);
996 rename_new_symbol(symbol.value);
997 auto it = new_identifiers.find(named_symbol.first);
998 if(it != new_identifiers.end())
999 symbol.name = it->second;
1000
1001 src_symbols.emplace(named_symbol.first, std::move(symbol));
1002 }
1003
1004 // Move over all the non-colliding ones
1005 std::unordered_set<irep_idt> collisions;
1006
1007 for(const auto &named_symbol : src_symbols)
1008 {
1009 // renamed?
1010 if(named_symbol.first!=named_symbol.second.name)
1011 {
1012 // new
1014 }
1015 else
1016 {
1018 {
1019 // new
1021 }
1022 else
1023 collisions.insert(named_symbol.first);
1024 }
1025 }
1026
1027 // Now do the collisions
1028 for(const irep_idt &collision : collisions)
1029 {
1031 symbolt &new_symbol=src_symbols.at(collision);
1032
1033 if(new_symbol.is_type)
1034 duplicate_type_symbol(old_symbol, new_symbol);
1035 else
1036 duplicate_non_type_symbol(old_symbol, new_symbol);
1037 }
1038
1039 // Apply type updates to initializers
1040 for(auto it = main_symbol_table.begin(); it != main_symbol_table.end(); ++it)
1041 {
1042 if(
1043 !it->second.is_type && !it->second.is_macro &&
1044 it->second.value.is_not_nil())
1045 {
1046 object_type_updates(it.get_writeable_symbol().value);
1047 }
1048 }
1049}
1050
1052{
1053 const unsigned errors_before =
1055
1056 // We do this in three phases. We first figure out which symbols need to
1057 // be renamed, and then build the renaming, and finally apply this
1058 // renaming in the second pass over the symbol table.
1059
1060 // PHASE 1: identify symbols to be renamed
1061
1062 std::unordered_set<irep_idt> needs_to_be_renamed;
1063
1064 for(const auto &symbol_pair : src_symbol_table.symbols)
1065 {
1066 symbol_table_baset::symbolst::const_iterator m_it =
1068
1069 if(m_it != main_symbol_table.symbols.end())
1070 {
1071 // duplicate
1072 switch(needs_renaming(m_it->second, symbol_pair.second))
1073 {
1075 break;
1077 {
1078 symbolt renamed_symbol = m_it->second;
1080 if(m_it->second.is_type)
1082 else
1086 break;
1087 }
1089 {
1090 needs_to_be_renamed.insert(symbol_pair.first);
1091#ifdef DEBUG
1093 log.debug() << "LINKING: needs to be renamed: " << symbol_pair.first
1094 << messaget::eom;
1095#endif
1096 break;
1097 }
1098 }
1099 }
1100 }
1101
1102 // rename within main symbol table
1103 for(auto &symbol_pair : main_symbol_table)
1104 {
1105 symbolt tmp = symbol_pair.second;
1106 bool unmodified = rename_main_symbol(tmp.value);
1108 if(!unmodified)
1109 {
1112 *sym_ptr = std::move(tmp);
1113 }
1114 }
1115
1116 // renaming types may trigger further renaming
1118
1119 // PHASE 2: actually rename them
1121
1122 // PHASE 3: copy new symbols to main table
1124
1126}
1127
1130 const symbol_table_baset &new_symbol_table,
1131 message_handlert &message_handler)
1132{
1133 linkingt linking(dest_symbol_table, message_handler);
1134
1135 return linking.link(new_symbol_table);
1136}
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:57
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition expr.cpp:68
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:950
void duplicate_non_type_symbol(symbolt &old_symbol, symbolt &new_symbol)
Definition linking.cpp:699
bool adjust_object_type(const symbolt &old_symbol, const symbolt &new_symbol, bool &set_to_new)
Definition linking.cpp:594
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:1051
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:985
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:832
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:609
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:742
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:901
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:1128
ANSI-C Linking.
ANSI-C Linking.
ANSI-C Linking.
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)