|
14 | 14 | #include <ostream>
|
15 | 15 | #include <iomanip>
|
16 | 16 |
|
| 17 | +#include <util/expr_iterator.h> |
| 18 | +#include <util/find_symbols.h> |
17 | 19 | #include <util/std_expr.h>
|
18 | 20 | #include <util/validate.h>
|
19 | 21 |
|
@@ -677,6 +679,45 @@ void goto_programt::instructiont::validate(
|
677 | 679 | validate_full_expr(guard, ns, vm);
|
678 | 680 |
|
679 | 681 | const symbolt *table_symbol;
|
| 682 | + DATA_CHECK_WITH_DIAGNOSTICS( |
| 683 | + vm, |
| 684 | + !ns.lookup(function, table_symbol), |
| 685 | + id2string(function) + " not found", |
| 686 | + source_location); |
| 687 | + |
| 688 | + auto expr_symbol_finder = [&](const exprt &e) { |
| 689 | + find_symbols_sett typetags; |
| 690 | + find_type_symbols(e.type(), typetags); |
| 691 | + find_symbols(e, typetags); |
| 692 | + const symbolt *symbol; |
| 693 | + for(const auto &identifier : typetags) |
| 694 | + { |
| 695 | + DATA_CHECK_WITH_DIAGNOSTICS( |
| 696 | + vm, |
| 697 | + !ns.lookup(identifier, symbol), |
| 698 | + id2string(identifier) + " not found", |
| 699 | + source_location); |
| 700 | + } |
| 701 | + }; |
| 702 | + |
| 703 | + auto ¤t_source_location = source_location; |
| 704 | + auto type_finder = |
| 705 | + [&ns, vm, &table_symbol, ¤t_source_location](const exprt &e) { |
| 706 | + if(e.id() == ID_symbol) |
| 707 | + { |
| 708 | + const auto &goto_symbol_expr = to_symbol_expr(e); |
| 709 | + const auto &goto_id = goto_symbol_expr.get_identifier(); |
| 710 | + |
| 711 | + if(!ns.lookup(goto_id, table_symbol)) |
| 712 | + DATA_CHECK_WITH_DIAGNOSTICS( |
| 713 | + vm, |
| 714 | + base_type_eq(goto_symbol_expr.type(), table_symbol->type, ns), |
| 715 | + id2string(goto_id) + " type inconsistency\n" + |
| 716 | + "goto program type: " + goto_symbol_expr.type().id_string() + |
| 717 | + "\n" + "symbol table type: " + table_symbol->type.id_string(), |
| 718 | + current_source_location); |
| 719 | + } |
| 720 | + }; |
680 | 721 |
|
681 | 722 | switch(type)
|
682 | 723 | {
|
@@ -708,6 +749,9 @@ void goto_programt::instructiont::validate(
|
708 | 749 | targets.empty(),
|
709 | 750 | "assert instruction should not have a target",
|
710 | 751 | source_location);
|
| 752 | + |
| 753 | + std::for_each(guard.depth_begin(), guard.depth_end(), expr_symbol_finder); |
| 754 | + std::for_each(guard.depth_begin(), guard.depth_end(), type_finder); |
711 | 755 | break;
|
712 | 756 | case OTHER:
|
713 | 757 | break;
|
@@ -772,6 +816,9 @@ void goto_programt::instructiont::validate(
|
772 | 816 | code.get_statement() == ID_function_call,
|
773 | 817 | "function call instruction should contain a call statement",
|
774 | 818 | source_location);
|
| 819 | + |
| 820 | + std::for_each(code.depth_begin(), code.depth_end(), expr_symbol_finder); |
| 821 | + std::for_each(code.depth_begin(), code.depth_end(), type_finder); |
775 | 822 | break;
|
776 | 823 | case THROW:
|
777 | 824 | break;
|
|
0 commit comments