Skip to content

Commit af862d2

Browse files
Petr BauchPetr Bauch
Petr Bauch
authored and
Petr Bauch
committed
Symbol consistency between goto programs and symbol table
Iterate over all symbols in a goto program and for each one check that it is present in the symbol table as well. Includes a unit test for the check.
1 parent 62280d2 commit af862d2

File tree

7 files changed

+164
-4
lines changed

7 files changed

+164
-4
lines changed

src/goto-programs/goto_function.h

+53-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,59 @@ class goto_functiont
117117
/// reported via DATA_INVARIANT violations or exceptions.
118118
void validate(const namespacet &ns, const validation_modet vm) const
119119
{
120-
body.validate(ns, vm);
120+
auto type_symbol_finder =
121+
[&](const typet &t, const source_locationt &location) {
122+
irep_idt identifier = ID_nil;
123+
if(t.id() == ID_symbol_type)
124+
{
125+
identifier = to_symbol_type(t).get_identifier();
126+
}
127+
else if(
128+
t.id() == ID_c_enum_tag || t.id() == ID_struct_tag ||
129+
t.id() == ID_union_tag)
130+
{
131+
identifier = to_tag_type(t).get_identifier();
132+
}
133+
if(identifier != ID_nil)
134+
{
135+
const symbolt *symbol;
136+
if(location.is_nil())
137+
DATA_CHECK(
138+
!ns.lookup(identifier, symbol),
139+
id2string(identifier) + " not found");
140+
else
141+
DATA_CHECK_WITH_DIAGNOSTICS(
142+
!ns.lookup(identifier, symbol),
143+
id2string(identifier) + " not found",
144+
location);
145+
}
146+
};
147+
148+
auto expr_symbol_finder =
149+
[&](const exprt &e, const source_locationt &location) {
150+
forall_subtypes(it, e.type())
151+
{
152+
type_symbol_finder(*it, location);
153+
}
154+
if(e.id() == ID_symbol)
155+
{
156+
const symbolt *symbol;
157+
auto identifier = to_symbol_expr(e).get_identifier();
158+
DATA_CHECK_WITH_DIAGNOSTICS(
159+
!ns.lookup(identifier, symbol),
160+
id2string(identifier) + " not found",
161+
location);
162+
}
163+
};
164+
165+
body.validate(expr_symbol_finder, ns, vm);
166+
source_locationt nil_location;
167+
nil_location.make_nil();
168+
forall_subtypes(it, type)
169+
{
170+
type_symbol_finder(*it, nil_location);
171+
}
172+
121173
validate_full_type(type, ns, vm);
122174
}
123175
};

src/goto-programs/goto_program.cpp

+14
Original file line numberDiff line numberDiff line change
@@ -670,12 +670,24 @@ bool goto_programt::instructiont::equals(const instructiont &other) const
670670
}
671671

672672
void goto_programt::instructiont::validate(
673+
const std::function<void(const exprt &, const source_locationt &)>
674+
&symbol_finder,
673675
const namespacet &ns,
674676
const validation_modet vm) const
675677
{
676678
validate_full_code(code, ns, vm);
677679
validate_full_expr(guard, ns, vm);
678680

681+
const symbolt *symbol;
682+
DATA_CHECK_WITH_DIAGNOSTICS(
683+
!ns.lookup(function, symbol),
684+
id2string(function) + " not found",
685+
source_location);
686+
687+
auto expr_symbol_finder = [&](const exprt &e) {
688+
symbol_finder(e, source_location);
689+
};
690+
679691
switch(type)
680692
{
681693
case NO_INSTRUCTION_TYPE:
@@ -685,6 +697,7 @@ void goto_programt::instructiont::validate(
685697
case ASSUME:
686698
break;
687699
case ASSERT:
700+
guard.visit(expr_symbol_finder);
688701
break;
689702
case OTHER:
690703
break;
@@ -715,6 +728,7 @@ void goto_programt::instructiont::validate(
715728
case DEAD:
716729
break;
717730
case FUNCTION_CALL:
731+
code.visit(expr_symbol_finder);
718732
break;
719733
case THROW:
720734
break;

src/goto-programs/goto_program.h

+11-3
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,11 @@ class goto_programt
405405
///
406406
/// The validation mode indicates whether well-formedness check failures are
407407
/// reported via DATA_INVARIANT violations or exceptions.
408-
void validate(const namespacet &ns, const validation_modet vm) const;
408+
void validate(
409+
const std::function<void(const exprt &, const source_locationt &)>
410+
&symbol_finder,
411+
const namespacet &ns,
412+
const validation_modet vm) const;
409413
};
410414

411415
// Never try to change this to vector-we mutate the list while iterating
@@ -690,11 +694,15 @@ class goto_programt
690694
///
691695
/// The validation mode indicates whether well-formedness check failures are
692696
/// reported via DATA_INVARIANT violations or exceptions.
693-
void validate(const namespacet &ns, const validation_modet vm) const
697+
void validate(
698+
const std::function<void(const exprt &, const source_locationt &)>
699+
&symbol_finder,
700+
const namespacet &ns,
701+
const validation_modet vm) const
694702
{
695703
for(const instructiont &ins : instructions)
696704
{
697-
ins.validate(ns, vm);
705+
ins.validate(symbol_finder, ns, vm);
698706
}
699707
}
700708
};

src/util/expr.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,24 @@ void exprt::visit(const_expr_visitort &visitor) const
327327
}
328328
}
329329

330+
void exprt::visit(const std::function<void(const exprt &)> &f) const
331+
{
332+
std::stack<const exprt *> stack;
333+
334+
stack.push(this);
335+
336+
while(!stack.empty())
337+
{
338+
const exprt &expr = *stack.top();
339+
stack.pop();
340+
341+
f(expr);
342+
343+
forall_operands(it, expr)
344+
stack.push(&(*it));
345+
}
346+
}
347+
330348
depth_iteratort exprt::depth_begin()
331349
{ return depth_iteratort(*this); }
332350
depth_iteratort exprt::depth_end()

src/util/expr.h

+1
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ class exprt:public irept
309309
public:
310310
void visit(class expr_visitort &visitor);
311311
void visit(class const_expr_visitort &visitor) const;
312+
void visit(const std::function<void(const exprt &)> &f) const;
312313

313314
depth_iteratort depth_begin();
314315
depth_iteratort depth_end();

unit/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ SRC += analyses/ai/ai.cpp \
1616
analyses/does_remove_const/is_type_at_least_as_const_as.cpp \
1717
compound_block_locations.cpp \
1818
goto-programs/goto_trace_output.cpp \
19+
goto-programs/goto_program_table_consistency.cpp \
1920
interpreter/interpreter.cpp \
2021
json/json_parser.cpp \
2122
path_strategies.cpp \
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*******************************************************************\
2+
3+
Module: Unit tests for goto_program::validate
4+
Author: Diffblue Ltd.
5+
6+
\*******************************************************************/
7+
8+
#include <goto-programs/goto_function.h>
9+
#include <testing-utils/catch.hpp>
10+
#include <util/arith_tools.h>
11+
12+
SCENARIO(
13+
"Validation of consistent program/table pair",
14+
"[core][goto-programs][validate]")
15+
{
16+
GIVEN("A program with one assertion")
17+
{
18+
symbol_tablet symbol_table;
19+
const typet type = signedbv_typet(32);
20+
symbolt symbol;
21+
irep_idt symbol_name = "a";
22+
symbol.name = symbol_name;
23+
symbol_exprt varx(symbol_name, type);
24+
symbolt function_symbol;
25+
irep_idt function_name = "fun";
26+
function_symbol.name = function_name;
27+
28+
exprt val10 = from_integer(10, type);
29+
binary_relation_exprt x_le_10(varx, ID_le, val10);
30+
31+
goto_functiont goto_function;
32+
auto &instructions = goto_function.body.instructions;
33+
instructions.emplace_back(goto_program_instruction_typet::ASSERT);
34+
instructions.back().make_assertion(x_le_10);
35+
instructions.back().function = function_symbol.name;
36+
37+
symbol_table.insert(function_symbol);
38+
WHEN("Symbol table has the right symbol")
39+
{
40+
symbol_table.insert(symbol);
41+
const namespacet ns(symbol_table);
42+
THEN("The consistency check succeeds")
43+
{
44+
goto_function.validate(ns, validation_modet::INVARIANT);
45+
REQUIRE(true);
46+
}
47+
}
48+
WHEN("Symbol table does not have the symbol")
49+
{
50+
const namespacet ns(symbol_table);
51+
THEN("The consistency check fails")
52+
{
53+
bool caught = false;
54+
try
55+
{
56+
goto_function.validate(ns, validation_modet::EXCEPTION);
57+
}
58+
catch(incorrect_goto_program_exceptiont &e)
59+
{
60+
caught = true;
61+
}
62+
REQUIRE(caught);
63+
}
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)