Skip to content

Commit c668985

Browse files
Petr BauchPetr Bauch
authored andcommitted
Add checks that type identifiers are consistent
Moved the checking functions to goto_function to be more easily reusable. Added check for type variable inside goto_functions and all types in expressions in goto programs.
1 parent d0ba4d7 commit c668985

File tree

7 files changed

+91
-56
lines changed

7 files changed

+91
-56
lines changed

src/cbmc/cbmc_parse_options.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -515,10 +515,6 @@ 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-
522518
if(cmdline.isset("show-claims") || // will go away
523519
cmdline.isset("show-properties")) // use this one
524520
{
@@ -530,6 +526,12 @@ int cbmc_parse_optionst::doit()
530526
if(set_properties())
531527
return CPROVER_EXIT_SET_PROPERTIES_FAILED;
532528

529+
if(cmdline.isset("validate-goto-model"))
530+
{
531+
namespacet ns(goto_model.symbol_table);
532+
goto_model.validate(ns, validation_modet::INVARIANT);
533+
}
534+
533535
return bmct::do_language_agnostic_bmc(
534536
path_strategy_chooser, options, goto_model, ui_message_handler);
535537
}
@@ -976,6 +978,7 @@ void cbmc_parse_optionst::help()
976978
" --xml-ui use XML-formatted output\n"
977979
" --xml-interface bi-directional XML interface\n"
978980
" --json-ui use JSON-formatted output\n"
981+
" --validate-goto-model enables additional well-formedness checks on the goto program\n" // NOLINT(*)
979982
HELP_GOTO_TRACE
980983
HELP_FLUSH
981984
" --verbosity # verbosity level\n"

src/cbmc/cbmc_parse_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ class optionst;
7272
OPT_FLUSH \
7373
"(localize-faults)(localize-faults-method):" \
7474
OPT_GOTO_TRACE \
75+
"(validate-goto-model)" \
7576
"(claim):(show-claims)(floatbv)(all-claims)(all-properties)" // legacy, and will eventually disappear // NOLINT(whitespace/line_length)
7677
// clang-format on
7778

src/goto-programs/goto_function.h

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,62 @@ class goto_functiont
111111
return *this;
112112
}
113113

114-
bool
115-
check_internal_invariants(const symbol_tablet &table, messaget &msg) const
114+
/// Iterates over the functions inside the goto model and checks invariants
115+
/// in all of them. Prints out error message collected.
116+
/// \param table symbol table to be checked for consistency
117+
/// \param vm validation mode to be used for error reporting
118+
void validate(const symbol_tablet &table, const validation_modet &vm) const
116119
{
117-
return body.check_internal_invariants(table, msg);
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+
if(location.is_nil())
136+
DATA_CHECK(
137+
table.has_symbol(identifier), id2string(identifier) + " not found");
138+
else
139+
DATA_CHECK_WITH_DIAGNOSTICS(
140+
table.has_symbol(identifier),
141+
id2string(identifier) + " not found",
142+
location);
143+
}
144+
};
145+
146+
auto expr_symbol_finder =
147+
[&](const exprt &e, const source_locationt &location) {
148+
forall_subtypes(it, e.type())
149+
{
150+
type_symbol_finder(*it, location);
151+
}
152+
if(e.id() == ID_symbol)
153+
{
154+
auto identifier = to_symbol_expr(e).get_identifier();
155+
DATA_CHECK_WITH_DIAGNOSTICS(
156+
table.has_symbol(identifier),
157+
id2string(identifier) + " not found",
158+
location);
159+
}
160+
};
161+
162+
body.validate(expr_symbol_finder, vm);
163+
164+
source_locationt nil_location;
165+
nil_location.make_nil();
166+
forall_subtypes(it, type)
167+
{
168+
type_symbol_finder(*it, nil_location);
169+
}
118170
}
119171
};
120172

src/goto-programs/goto_model.h

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -99,17 +99,14 @@ class goto_modelt : public abstract_goto_modelt
9999

100100
/// Iterates over the functions inside the goto model and checks invariants
101101
/// 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
102+
/// \param ns namespace for the environment
103+
/// \param vm validation mode to be used for error reporting
104+
void validate(const namespacet &ns, const validation_modet &vm) const
105105
{
106-
bool found_violation = false;
107106
forall_goto_functions(it, goto_functions)
108107
{
109-
found_violation = found_violation ||
110-
it->second.check_internal_invariants(symbol_table, msg);
108+
it->second.validate(symbol_table, vm);
111109
}
112-
return found_violation;
113110
}
114111
};
115112

src/goto-programs/goto_program.cpp

Lines changed: 13 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -668,36 +668,27 @@ 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
671+
void goto_programt::instructiont::validate(
672+
const std::function<void(const exprt &, const source_locationt &)>
673+
&symbol_finder,
674+
const validation_modet &vm) const
674675
{
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-
}
676+
auto expr_symbol_finder = [&](const exprt &e) {
677+
symbol_finder(e, source_location);
684678
};
685679

686-
if(!table.has_symbol(function))
687-
id_collector.push_back(id2string(function));
688-
689680
switch(type)
690681
{
691682
case GOTO:
692683
case ASSUME:
693684
case ASSERT:
694-
guard.visit(symbol_finder);
685+
guard.visit(expr_symbol_finder);
695686
break;
696687
case ASSIGN:
697688
case DECL:
698689
case DEAD:
699690
case FUNCTION_CALL:
700-
code.visit(symbol_finder);
691+
code.visit(expr_symbol_finder);
701692
break;
702693
case OTHER:
703694
case SKIP:
@@ -714,17 +705,6 @@ bool goto_programt::instructiont::check_internal_invariants(
714705
case INCOMPLETE_GOTO:
715706
break;
716707
}
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;
728708
}
729709

730710
bool goto_programt::equals(const goto_programt &other) const
@@ -758,17 +738,15 @@ bool goto_programt::equals(const goto_programt &other) const
758738
return true;
759739
}
760740

761-
bool goto_programt::check_internal_invariants(
762-
const symbol_tablet &table,
763-
messaget &msg) const
741+
void goto_programt::validate(
742+
const std::function<void(const exprt &, const source_locationt &)>
743+
&symbol_finder,
744+
const validation_modet &vm) const
764745
{
765-
bool found_violation = false;
766746
forall_goto_program_instructions(it, (*this))
767747
{
768-
found_violation =
769-
found_violation || it->check_internal_invariants(table, msg);
748+
it->validate(symbol_finder, vm);
770749
}
771-
return found_violation;
772750
}
773751

774752
/// Outputs a string representation of a `goto_program_instruction_typet`

src/goto-programs/goto_program.h

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -402,11 +402,12 @@ class goto_programt
402402

403403
/// Iterate over code and guard and collect inconsistencies with symbol
404404
/// 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;
405+
/// \param symbol_finder function that locates symbols in a symbol table
406+
/// \param vm validation mode
407+
void validate(
408+
const std::function<void(const exprt &, const source_locationt &)>
409+
&symbol_finder,
410+
const validation_modet &vm) const;
410411
};
411412

412413
// Never try to change this to vector-we mutate the list while iterating
@@ -687,8 +688,10 @@ class goto_programt
687688
/// and relative jumps have the same distance.
688689
bool equals(const goto_programt &other) const;
689690

690-
bool
691-
check_internal_invariants(const symbol_tablet &table, messaget &msg) const;
691+
void validate(
692+
const std::function<void(const exprt &, const source_locationt &)>
693+
&symbol_finder,
694+
const validation_modet &vm) const;
692695
};
693696

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

src/util/expr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Author: Daniel Kroening, [email protected]
1010
#define CPROVER_UTIL_EXPR_H
1111

1212
#include "type.h"
13+
#include "validate.h"
1314

1415
#include <functional>
1516
#include <list>

0 commit comments

Comments
 (0)