Skip to content

Commit 4a47b9d

Browse files
Petr BauchPetr Bauch
Petr Bauch
authored and
Petr Bauch
committed
Symbol consistency between goto programs and symbol table
Introduce a chain of methods that (at the lowest level) iterate over all symbols in a goto program and for each one check that it is present in the symbol table as well. On the lower levels, the methods collect inconsistency messages and print them to error output. On the top level, e.g. cbmc-parser, they return a Boolean value to be caught by an invariant check.
1 parent d63fb7a commit 4a47b9d

File tree

7 files changed

+99
-0
lines changed

7 files changed

+99
-0
lines changed

src/cbmc/cbmc_parse_options.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,10 @@ int cbmc_parse_optionst::doit()
515515
if(get_goto_program_ret!=-1)
516516
return get_goto_program_ret;
517517

518+
INVARIANT(
519+
goto_model.check_id_consistency_symbol_table(),
520+
"identifier inconsistency between goto program and symbol table");
521+
518522
if(cmdline.isset("show-claims") || // will go away
519523
cmdline.isset("show-properties")) // use this one
520524
{

src/goto-programs/goto_function.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,13 @@ class goto_functiont
110110
parameter_identifiers = std::move(other.parameter_identifiers);
111111
return *this;
112112
}
113+
114+
void check_id_consistency_symbol_table(
115+
const symbol_tablet &table,
116+
std::vector<std::string> &message_collector) const
117+
{
118+
body.check_id_consistency_symbol_table(table, message_collector);
119+
}
113120
};
114121

115122
void get_local_identifiers(const goto_functiont &, std::set<irep_idt> &dest);

src/goto-programs/goto_model.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ Author: Daniel Kroening, [email protected]
1818
#include "abstract_goto_model.h"
1919
#include "goto_functions.h"
2020

21+
#include <iostream>
22+
2123
// A model is a pair consisting of a symbol table
2224
// and the CFGs for the functions.
2325

@@ -95,6 +97,29 @@ class goto_modelt : public abstract_goto_modelt
9597
return goto_functions.function_map.find(id) !=
9698
goto_functions.function_map.end();
9799
}
100+
101+
/// Iterates over the symbols in this goto-model and checks that each one is
102+
/// present in the symbol table.
103+
/// \return true if no inconsistency was found
104+
bool check_id_consistency_symbol_table() const
105+
{
106+
std::vector<std::string> message_collector;
107+
forall_goto_functions(it, goto_functions)
108+
{
109+
it->second.check_id_consistency_symbol_table(
110+
symbol_table, message_collector);
111+
}
112+
if(!message_collector.empty())
113+
{
114+
std::cerr << "Error messages collected while checking the goto "
115+
"program/symbol table\n consistency:\n";
116+
for(const auto &m : message_collector)
117+
std::cerr << m << std::endl;
118+
return false;
119+
}
120+
else
121+
return true;
122+
}
98123
};
99124

100125
/// Class providing the abstract GOTO model interface onto an unrelated

src/goto-programs/goto_program.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,28 @@ bool goto_programt::instructiont::equals(const instructiont &other) const
668668
// clang-format on
669669
}
670670

671+
void goto_programt::instructiont::check_id_consistency_symbol_table(
672+
const symbol_tablet &table,
673+
std::vector<std::string> &message_collector) const
674+
{
675+
auto symbol_finder = [&](const exprt &e) {
676+
if(e.id() == ID_symbol)
677+
{
678+
auto symbol_expr = to_symbol_expr(e);
679+
if(!table.has_symbol(symbol_expr.get_identifier()))
680+
message_collector.push_back(
681+
id2string(symbol_expr.get_identifier()) + " not found");
682+
}
683+
};
684+
685+
code.visit(symbol_finder);
686+
if(!table.has_symbol(function))
687+
{
688+
message_collector.push_back("function id not found");
689+
}
690+
guard.visit(symbol_finder);
691+
}
692+
671693
bool goto_programt::equals(const goto_programt &other) const
672694
{
673695
if(instructions.size() != other.instructions.size())
@@ -699,6 +721,16 @@ bool goto_programt::equals(const goto_programt &other) const
699721
return true;
700722
}
701723

724+
void goto_programt::check_id_consistency_symbol_table(
725+
const symbol_tablet &table,
726+
std::vector<std::string> &message_collector) const
727+
{
728+
forall_goto_program_instructions(it, (*this))
729+
{
730+
it->check_id_consistency_symbol_table(table, message_collector);
731+
}
732+
}
733+
702734
/// Outputs a string representation of a `goto_program_instruction_typet`
703735
std::ostream &operator<<(std::ostream &out, goto_program_instruction_typet t)
704736
{

src/goto-programs/goto_program.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,14 @@ class goto_programt
398398
/// only be evaluated in the context of a goto_programt (see
399399
/// goto_programt::equals).
400400
bool equals(const instructiont &other) const;
401+
402+
/// Iterate over code and guard and collect inconsistencies with symbol
403+
/// table.
404+
/// \param table the symbol table
405+
/// \param message_collector container to store the error messages
406+
void check_id_consistency_symbol_table(
407+
const symbol_tablet &table,
408+
std::vector<std::string> &message_collector) const;
401409
};
402410

403411
// Never try to change this to vector-we mutate the list while iterating
@@ -677,6 +685,10 @@ class goto_programt
677685
/// the same number of instructions, each pair of instructions compares equal,
678686
/// and relative jumps have the same distance.
679687
bool equals(const goto_programt &other) const;
688+
689+
void check_id_consistency_symbol_table(
690+
const symbol_tablet &table,
691+
std::vector<std::string> &message_collector) const;
680692
};
681693

682694
/// Get control-flow successors of a given instruction. The instruction is

src/util/expr.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,24 @@ void exprt::visit(const_expr_visitort &visitor) const
322322
}
323323
}
324324

325+
void exprt::visit(const std::function<void(const exprt &)> &f) const
326+
{
327+
std::stack<const exprt *> stack;
328+
329+
stack.push(this);
330+
331+
while(!stack.empty())
332+
{
333+
const exprt &expr = *stack.top();
334+
stack.pop();
335+
336+
f(expr);
337+
338+
forall_operands(it, expr)
339+
stack.push(&(*it));
340+
}
341+
}
342+
325343
depth_iteratort exprt::depth_begin()
326344
{ return depth_iteratort(*this); }
327345
depth_iteratort exprt::depth_end()

src/util/expr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ class exprt:public irept
224224
public:
225225
void visit(class expr_visitort &visitor);
226226
void visit(class const_expr_visitort &visitor) const;
227+
void visit(const std::function<void(const exprt &)> &f) const;
227228

228229
depth_iteratort depth_begin();
229230
depth_iteratort depth_end();

0 commit comments

Comments
 (0)