Skip to content

Commit f08e23b

Browse files
authored
Merge pull request #3123 from danpoe/feature/well-formedness-checking
Skeleton for well-formedness checking of goto models [blocks: #3118, #3147, #3188, #3191, #3187, #3193]
2 parents d3d3cdb + d638ea7 commit f08e23b

31 files changed

+1024
-40
lines changed

src/cbmc/cbmc_parse_options.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -530,6 +530,11 @@ int cbmc_parse_optionst::doit()
530530
if(set_properties())
531531
return CPROVER_EXIT_SET_PROPERTIES_FAILED;
532532

533+
if(cmdline.isset("validate-goto-model"))
534+
{
535+
goto_model.validate(validation_modet::INVARIANT);
536+
}
537+
533538
return bmct::do_language_agnostic_bmc(
534539
path_strategy_chooser, options, goto_model, ui_message_handler);
535540
}
@@ -977,6 +982,8 @@ void cbmc_parse_optionst::help()
977982
" --xml-ui use XML-formatted output\n"
978983
" --xml-interface bi-directional XML interface\n"
979984
" --json-ui use JSON-formatted output\n"
985+
// NOLINTNEXTLINE(whitespace/line_length)
986+
HELP_VALIDATE
980987
HELP_GOTO_TRACE
981988
HELP_FLUSH
982989
" --verbosity # verbosity level\n"

src/cbmc/cbmc_parse_options.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ Author: Daniel Kroening, [email protected]
1212
#ifndef CPROVER_CBMC_CBMC_PARSE_OPTIONS_H
1313
#define CPROVER_CBMC_CBMC_PARSE_OPTIONS_H
1414

15-
#include <util/ui_message.h>
1615
#include <util/parse_options.h>
1716
#include <util/timestamper.h>
17+
#include <util/ui_message.h>
18+
#include <util/validation_interface.h>
1819

1920
#include <langapi/language.h>
2021

@@ -73,6 +74,7 @@ class optionst;
7374
OPT_FLUSH \
7475
"(localize-faults)(localize-faults-method):" \
7576
OPT_GOTO_TRACE \
77+
OPT_VALIDATE \
7678
"(claim):(show-claims)(floatbv)(all-claims)(all-properties)" // legacy, and will eventually disappear // NOLINT(whitespace/line_length)
7779
// clang-format on
7880

src/goto-analyzer/goto_analyzer_parse_options.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,11 @@ int goto_analyzer_parse_optionst::doit()
406406
if(process_goto_program(options))
407407
return CPROVER_EXIT_INTERNAL_ERROR;
408408

409+
if(cmdline.isset("validate-goto-model"))
410+
{
411+
goto_model.validate(validation_modet::INVARIANT);
412+
}
413+
409414
// show it?
410415
if(cmdline.isset("show-symbol-table"))
411416
{
@@ -875,6 +880,7 @@ void goto_analyzer_parse_optionst::help()
875880
HELP_GOTO_CHECK
876881
"\n"
877882
"Other options:\n"
883+
HELP_VALIDATE
878884
" --version show version and exit\n"
879885
HELP_FLUSH
880886
HELP_TIMESTAMP

src/goto-analyzer/goto_analyzer_parse_options.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,10 @@ Author: Daniel Kroening, [email protected]
101101
#ifndef CPROVER_GOTO_ANALYZER_GOTO_ANALYZER_PARSE_OPTIONS_H
102102
#define CPROVER_GOTO_ANALYZER_GOTO_ANALYZER_PARSE_OPTIONS_H
103103

104-
#include <util/ui_message.h>
105104
#include <util/parse_options.h>
106105
#include <util/timestamper.h>
106+
#include <util/ui_message.h>
107+
#include <util/validation_interface.h>
107108

108109
#include <langapi/language.h>
109110

@@ -148,6 +149,7 @@ class optionst;
148149
"(show)(verify)(simplify):" \
149150
"(location-sensitive)(concurrent)" \
150151
"(no-simplify-slicing)" \
152+
OPT_VALIDATE \
151153
// clang-format on
152154

153155
class goto_analyzer_parse_optionst:

src/goto-instrument/goto_instrument_parse_options.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,27 @@ int goto_instrument_parse_optionst::doit()
125125

126126
get_goto_program();
127127

128+
{
129+
const bool validate_only = cmdline.isset("validate-goto-binary");
130+
131+
if(validate_only || cmdline.isset("validate-goto-model"))
132+
{
133+
goto_model.validate(validation_modet::EXCEPTION);
134+
135+
if(validate_only)
136+
{
137+
return CPROVER_EXIT_SUCCESS;
138+
}
139+
}
140+
}
141+
128142
instrument_goto_program();
129143

144+
if(cmdline.isset("validate-goto-model"))
145+
{
146+
goto_model.validate(validation_modet::INVARIANT);
147+
}
148+
130149
{
131150
bool unwind_given=cmdline.isset("unwind");
132151
bool unwindset_given=cmdline.isset("unwindset");
@@ -1572,6 +1591,10 @@ void goto_instrument_parse_optionst::help()
15721591
" --show-local-safe-pointers show pointer expressions that are trivially dominated by a not-null check\n" // NOLINT(*)
15731592
" --show-safe-dereferences show pointer expressions that are trivially dominated by a not-null check\n" // NOLINT(*)
15741593
" *and* used as a dereference operand\n" // NOLINT(*)
1594+
HELP_VALIDATE
1595+
// NOLINTNEXTLINE(whitespace/line_length)
1596+
" --validate-goto-binary check the well-formedness of the passed in goto\n"
1597+
" binary and then exit\n"
15751598
"\n"
15761599
"Safety checks:\n"
15771600
" --no-assertions ignore user assertions\n"

src/goto-instrument/goto_instrument_parse_options.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ Author: Daniel Kroening, [email protected]
1212
#ifndef CPROVER_GOTO_INSTRUMENT_GOTO_INSTRUMENT_PARSE_OPTIONS_H
1313
#define CPROVER_GOTO_INSTRUMENT_GOTO_INSTRUMENT_PARSE_OPTIONS_H
1414

15-
#include <util/ui_message.h>
1615
#include <util/parse_options.h>
1716
#include <util/timestamper.h>
17+
#include <util/ui_message.h>
18+
#include <util/validation_interface.h>
1819

1920
#include <goto-programs/class_hierarchy.h>
2021
#include <goto-programs/goto_functions.h>
@@ -101,6 +102,8 @@ Author: Daniel Kroening, [email protected]
101102
OPT_GOTO_PROGRAM_STATS \
102103
"(show-local-safe-pointers)(show-safe-dereferences)" \
103104
OPT_REPLACE_CALLS \
105+
"(validate-goto-binary)" \
106+
OPT_VALIDATE \
104107
// empty last line
105108

106109
// clang-format on

src/goto-programs/goto_function.h

+10
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,16 @@ class goto_functiont
110110
parameter_identifiers = std::move(other.parameter_identifiers);
111111
return *this;
112112
}
113+
114+
/// Check that the goto function is well-formed
115+
///
116+
/// The validation mode indicates whether well-formedness check failures are
117+
/// reported via DATA_INVARIANT violations or exceptions.
118+
void validate(const namespacet &ns, const validation_modet vm) const
119+
{
120+
body.validate(ns, vm);
121+
validate_full_type(type, ns, vm);
122+
}
113123
};
114124

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

src/goto-programs/goto_functions.h

+13
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,19 @@ class goto_functionst
117117

118118
std::vector<function_mapt::const_iterator> sorted() const;
119119
std::vector<function_mapt::iterator> sorted();
120+
121+
/// Check that the goto functions are well-formed
122+
///
123+
/// The validation mode indicates whether well-formedness check failures are
124+
/// reported via DATA_INVARIANT violations or exceptions.
125+
void validate(const namespacet &ns, const validation_modet vm) const
126+
{
127+
for(const auto &entry : function_map)
128+
{
129+
const goto_functiont &goto_function = entry.second;
130+
goto_function.validate(ns, vm);
131+
}
132+
}
120133
};
121134

122135
#define Forall_goto_functions(it, functions) \

src/goto-programs/goto_model.h

+12
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,18 @@ class goto_modelt : public abstract_goto_modelt
8989
return goto_functions.function_map.find(id) !=
9090
goto_functions.function_map.end();
9191
}
92+
93+
/// Check that the goto model is well-formed
94+
///
95+
/// The validation mode indicates whether well-formedness check failures are
96+
/// reported via DATA_INVARIANT violations or exceptions.
97+
void validate(const validation_modet vm) const
98+
{
99+
symbol_table.validate();
100+
101+
const namespacet ns(symbol_table);
102+
goto_functions.validate(ns, vm);
103+
}
92104
};
93105

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

src/goto-programs/goto_program.cpp

+57
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Author: Daniel Kroening, [email protected]
1515
#include <iomanip>
1616

1717
#include <util/std_expr.h>
18+
#include <util/validate.h>
1819

1920
#include <langapi/language_util.h>
2021

@@ -668,6 +669,62 @@ bool goto_programt::instructiont::equals(const instructiont &other) const
668669
// clang-format on
669670
}
670671

672+
void goto_programt::instructiont::validate(
673+
const namespacet &ns,
674+
const validation_modet vm) const
675+
{
676+
validate_full_code(code, ns, vm);
677+
validate_full_expr(guard, ns, vm);
678+
679+
switch(type)
680+
{
681+
case NO_INSTRUCTION_TYPE:
682+
break;
683+
case GOTO:
684+
break;
685+
case ASSUME:
686+
break;
687+
case ASSERT:
688+
break;
689+
case OTHER:
690+
break;
691+
case SKIP:
692+
break;
693+
case START_THREAD:
694+
break;
695+
case END_THREAD:
696+
break;
697+
case LOCATION:
698+
break;
699+
case END_FUNCTION:
700+
break;
701+
case ATOMIC_BEGIN:
702+
break;
703+
case ATOMIC_END:
704+
break;
705+
case RETURN:
706+
break;
707+
case ASSIGN:
708+
DATA_CHECK(
709+
code.get_statement() == ID_assign,
710+
"assign instruction should contain an assign statement");
711+
DATA_CHECK(targets.empty(), "assign instruction should not have a target");
712+
break;
713+
case DECL:
714+
break;
715+
case DEAD:
716+
break;
717+
case FUNCTION_CALL:
718+
break;
719+
case THROW:
720+
break;
721+
case CATCH:
722+
break;
723+
case INCOMPLETE_GOTO:
724+
break;
725+
}
726+
}
727+
671728
bool goto_programt::equals(const goto_programt &other) const
672729
{
673730
if(instructions.size() != other.instructions.size())

src/goto-programs/goto_program.h

+22-2
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ Author: Daniel Kroening, [email protected]
2020

2121
#include <util/invariant.h>
2222
#include <util/namespace.h>
23-
#include <util/symbol_table.h>
2423
#include <util/source_location.h>
25-
#include <util/std_expr.h>
2624
#include <util/std_code.h>
25+
#include <util/std_expr.h>
26+
#include <util/symbol_table.h>
27+
28+
enum class validation_modet;
2729

2830
/// The type of an instruction in a GOTO program.
2931
enum goto_program_instruction_typet
@@ -398,6 +400,12 @@ class goto_programt
398400
/// only be evaluated in the context of a goto_programt (see
399401
/// goto_programt::equals).
400402
bool equals(const instructiont &other) const;
403+
404+
/// Check that the instruction is well-formed
405+
///
406+
/// The validation mode indicates whether well-formedness check failures are
407+
/// reported via DATA_INVARIANT violations or exceptions.
408+
void validate(const namespacet &ns, const validation_modet vm) const;
401409
};
402410

403411
// Never try to change this to vector-we mutate the list while iterating
@@ -677,6 +685,18 @@ 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+
/// Check that the goto program is well-formed
690+
///
691+
/// The validation mode indicates whether well-formedness check failures are
692+
/// reported via DATA_INVARIANT violations or exceptions.
693+
void validate(const namespacet &ns, const validation_modet vm) const
694+
{
695+
for(const instructiont &ins : instructions)
696+
{
697+
ins.validate(ns, vm);
698+
}
699+
}
680700
};
681701

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

src/goto-programs/initialize_goto_model.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ goto_modelt initialize_goto_model(
165165
goto_model.goto_functions,
166166
message_handler);
167167

168+
if(cmdline.isset("validate-goto-model"))
169+
{
170+
goto_model.validate(validation_modet::EXCEPTION);
171+
}
172+
168173
// stupid hack
169174
config.set_object_bits_from_symbol_table(
170175
goto_model.symbol_table);

src/util/Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ SRC = arith_tools.cpp \
9696
union_find.cpp \
9797
union_find_replace.cpp \
9898
unwrap_nested_exception.cpp \
99+
validate_code.cpp \
100+
validate_expressions.cpp \
101+
validate_types.cpp \
99102
version.cpp \
100103
xml.cpp \
101104
xml_expr.cpp \

src/util/exception_utils.cpp

+11-13
Original file line numberDiff line numberDiff line change
@@ -55,25 +55,23 @@ std::string deserialization_exceptiont::what() const
5555
}
5656

5757
incorrect_goto_program_exceptiont::incorrect_goto_program_exceptiont(
58-
std::string message,
59-
source_locationt source_location)
60-
: message(std::move(message)), source_location(std::move(source_location))
58+
std::string message)
59+
: message(std::move(message))
6160
{
61+
source_location.make_nil();
6262
}
6363

6464
std::string incorrect_goto_program_exceptiont::what() const
6565
{
66-
if(source_location.is_nil())
67-
return message;
68-
else
69-
return message + " (at: " + source_location.as_string() + ")";
70-
}
66+
std::string ret(message);
7167

72-
incorrect_goto_program_exceptiont::incorrect_goto_program_exceptiont(
73-
std::string message)
74-
: message(std::move(message))
75-
{
76-
source_location.make_nil();
68+
if(!source_location.is_nil())
69+
ret += " (at: " + source_location.as_string() + ")";
70+
71+
if(!diagnostics.empty())
72+
ret += "\n" + diagnostics;
73+
74+
return ret;
7775
}
7876

7977
unsupported_operation_exceptiont::unsupported_operation_exceptiont(

0 commit comments

Comments
 (0)