Skip to content

Commit 13f0398

Browse files
Petr BauchPetr Bauch
Petr Bauch
authored and
Petr Bauch
committed
Type consistency between goto programs and symbol table
This first commit is just PR diffblue#3118 to reuse the common structure of checking this kind of consistency.
1 parent 251245e commit 13f0398

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
@@ -516,6 +516,10 @@ int cbmc_parse_optionst::doit()
516516
if(get_goto_program_ret!=-1)
517517
return get_goto_program_ret;
518518

519+
INVARIANT(
520+
!goto_model.check_internal_invariants(*this),
521+
"goto program internal invariants failed");
522+
519523
if(cmdline.isset("show-claims") || // will go away
520524
cmdline.isset("show-properties")) // use this one
521525
{

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
@@ -184,6 +184,7 @@ class exprt:public irept
184184
public:
185185
void visit(class expr_visitort &visitor);
186186
void visit(class const_expr_visitort &visitor) const;
187+
void visit(const std::function<void(const exprt &)> &f) const;
187188

188189
depth_iteratort depth_begin();
189190
depth_iteratort depth_end();

0 commit comments

Comments
 (0)