Skip to content

Commit efb95a6

Browse files
Petr BauchPetr Bauch
authored andcommitted
Type consistency between goto programs and symbol table
This first commit is just PR #3118 to reuse the common structure of checking this kind of consistency.
1 parent d63fb7a commit efb95a6

File tree

7 files changed

+129
-0
lines changed

7 files changed

+129
-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_internal_invariants(*this),
520+
"goto program internal invariants failed");
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: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,12 @@ class goto_functiont
110110
parameter_identifiers = std::move(other.parameter_identifiers);
111111
return *this;
112112
}
113+
114+
bool
115+
check_internal_invariants(const symbol_tablet &table, messaget &msg) const
116+
{
117+
return body.check_internal_invariants(table, msg);
118+
}
113119
};
114120

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

src/goto-programs/goto_model.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include <util/symbol_table.h>
1616
#include <util/journalling_symbol_table.h>
17+
#include <util/message.h>
1718

1819
#include "abstract_goto_model.h"
1920
#include "goto_functions.h"
@@ -95,6 +96,21 @@ class goto_modelt : public abstract_goto_modelt
9596
return goto_functions.function_map.find(id) !=
9697
goto_functions.function_map.end();
9798
}
99+
100+
/// Iterates over the functions inside the goto model and checks invariants
101+
/// in all of them. Prints out error message collected.
102+
/// \param msg message instance to collect errors
103+
/// \return true if any violation was found
104+
bool check_internal_invariants(messaget &msg) const
105+
{
106+
bool found_violation = false;
107+
forall_goto_functions(it, goto_functions)
108+
{
109+
found_violation = found_violation ||
110+
it->second.check_internal_invariants(symbol_table, msg);
111+
}
112+
return found_violation;
113+
}
98114
};
99115

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

src/goto-programs/goto_program.cpp

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

671+
bool goto_programt::instructiont::check_internal_invariants(
672+
const symbol_tablet &table,
673+
messaget &msg) const
674+
{
675+
bool found_violation = false;
676+
std::vector<std::string> id_collector;
677+
auto symbol_finder = [&](const exprt &e) {
678+
if(e.id() == ID_symbol)
679+
{
680+
auto symbol_expr = to_symbol_expr(e);
681+
if(!table.has_symbol(symbol_expr.get_identifier()))
682+
id_collector.push_back(id2string(symbol_expr.get_identifier()));
683+
}
684+
};
685+
686+
if(!table.has_symbol(function))
687+
id_collector.push_back(id2string(function));
688+
689+
switch(type)
690+
{
691+
case GOTO:
692+
case ASSUME:
693+
case ASSERT:
694+
guard.visit(symbol_finder);
695+
break;
696+
case ASSIGN:
697+
case DECL:
698+
case DEAD:
699+
case FUNCTION_CALL:
700+
code.visit(symbol_finder);
701+
break;
702+
case OTHER:
703+
case SKIP:
704+
case LOCATION:
705+
case END_FUNCTION:
706+
case START_THREAD:
707+
case END_THREAD:
708+
case ATOMIC_BEGIN:
709+
case ATOMIC_END:
710+
case RETURN:
711+
case THROW:
712+
case CATCH:
713+
case NO_INSTRUCTION_TYPE:
714+
case INCOMPLETE_GOTO:
715+
break;
716+
}
717+
718+
if(!id_collector.empty())
719+
{
720+
for(const auto &id : id_collector)
721+
{
722+
msg.error() << id << " not found (" << source_location << ")"
723+
<< messaget::eom;
724+
}
725+
found_violation = true;
726+
}
727+
return found_violation;
728+
}
729+
671730
bool goto_programt::equals(const goto_programt &other) const
672731
{
673732
if(instructions.size() != other.instructions.size())
@@ -699,6 +758,19 @@ bool goto_programt::equals(const goto_programt &other) const
699758
return true;
700759
}
701760

761+
bool goto_programt::check_internal_invariants(
762+
const symbol_tablet &table,
763+
messaget &msg) const
764+
{
765+
bool found_violation = false;
766+
forall_goto_program_instructions(it, (*this))
767+
{
768+
found_violation =
769+
found_violation || it->check_internal_invariants(table, msg);
770+
}
771+
return found_violation;
772+
}
773+
702774
/// Outputs a string representation of a `goto_program_instruction_typet`
703775
std::ostream &operator<<(std::ostream &out, goto_program_instruction_typet t)
704776
{

src/goto-programs/goto_program.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Author: Daniel Kroening, [email protected]
2424
#include <util/source_location.h>
2525
#include <util/std_expr.h>
2626
#include <util/std_code.h>
27+
#include <util/message.h>
2728

2829
/// The type of an instruction in a GOTO program.
2930
enum goto_program_instruction_typet
@@ -398,6 +399,14 @@ class goto_programt
398399
/// only be evaluated in the context of a goto_programt (see
399400
/// goto_programt::equals).
400401
bool equals(const instructiont &other) const;
402+
403+
/// Iterate over code and guard and collect inconsistencies with symbol
404+
/// table.
405+
/// \param table the symbol table
406+
/// \param msg container to store the error messages
407+
/// \return true if any violation was found
408+
bool
409+
check_internal_invariants(const symbol_tablet &table, messaget &msg) const;
401410
};
402411

403412
// Never try to change this to vector-we mutate the list while iterating
@@ -677,6 +686,9 @@ class goto_programt
677686
/// the same number of instructions, each pair of instructions compares equal,
678687
/// and relative jumps have the same distance.
679688
bool equals(const goto_programt &other) const;
689+
690+
bool
691+
check_internal_invariants(const symbol_tablet &table, messaget &msg) 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)