Skip to content

Commit dd7cd37

Browse files
committed
Filter generated assertions according to command-line settings
Turn into skip C/C++ goto checks that were previously generated, but are no longer expected as configured via the command line.
1 parent e14e33d commit dd7cd37

File tree

4 files changed

+164
-0
lines changed

4 files changed

+164
-0
lines changed

src/goto-instrument/goto_instrument_parse_options.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,6 +1329,7 @@ void goto_instrument_parse_optionst::instrument_goto_program()
13291329

13301330
// add generic checks, if needed
13311331
goto_check_c(options, goto_model, ui_message_handler);
1332+
remove_disabled_checks(options, goto_model);
13321333
transform_assertions_assumptions(options, goto_model);
13331334

13341335
// check for uninitalized local variables

src/goto-programs/goto_check.cpp

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Author: Daniel Kroening, [email protected]
1212
#include "goto_check.h"
1313

1414
#include <util/options.h>
15+
#include <util/prefix.h>
16+
#include <util/simplify_expr.h>
1517

1618
#include "goto_model.h"
1719
#include "remove_skip.h"
@@ -96,3 +98,161 @@ void transform_assertions_assumptions(
9698
enable_built_in_assertions,
9799
enable_assumptions);
98100
}
101+
102+
void remove_disabled_checks(const optionst &options, goto_modelt &goto_model)
103+
{
104+
// properties to keep
105+
const bool enable_bounds_check = options.get_bool_option("bounds-check");
106+
const bool enable_conversion_check =
107+
options.get_bool_option("conversion-check");
108+
const bool enable_div_by_zero_check =
109+
options.get_bool_option("div-by-zero-check");
110+
const bool enable_enum_range_check =
111+
options.get_bool_option("enum-range-check");
112+
const bool enable_float_overflow_check =
113+
options.get_bool_option("float-overflow-check");
114+
const bool enable_memory_leak_check =
115+
options.get_bool_option("memory-leak-check");
116+
const bool enable_nan_check = options.get_bool_option("nan-check");
117+
const bool enable_pointer_check = options.get_bool_option("pointer-check");
118+
const bool enable_pointer_overflow_check =
119+
options.get_bool_option("pointer-overflow-check");
120+
const bool enable_pointer_primitive_check =
121+
options.get_bool_option("pointer-primitive-check");
122+
const bool enable_signed_overflow_check =
123+
options.get_bool_option("signed-overflow-check");
124+
const bool enable_undefined_shift_check =
125+
options.get_bool_option("undefined-shift-check");
126+
const bool enable_unsigned_overflow_check =
127+
options.get_bool_option("unsigned-overflow-check");
128+
const auto error_labels = options.get_list_option("error-label");
129+
130+
// transformations retained on properties
131+
// const bool enable_simplify = options.get_bool_option("simplify");
132+
const bool enable_assert_to_assume =
133+
options.get_bool_option("assert-to-assume");
134+
// const bool retain_trivial = options.get_bool_option("retain-trivial-checks");
135+
136+
const std::unordered_map<irep_idt, bool> should_skip = {
137+
{"NaN", !enable_nan_check},
138+
{"array bounds", !enable_bounds_check},
139+
{"bit count", !enable_bounds_check},
140+
{"division-by-zero", !enable_div_by_zero_check},
141+
{"enum-range-check", !enable_enum_range_check},
142+
{"error label", error_labels.empty()}, // further evaluation is necessary
143+
{"memory-leak", !enable_memory_leak_check},
144+
{"overflow", false}, // further evaluation is necessary
145+
{"pointer arithmetic",
146+
!enable_pointer_check && !enable_pointer_overflow_check},
147+
{"pointer dereference", !enable_pointer_check},
148+
{"pointer primitives", !enable_pointer_primitive_check},
149+
{"pointer", !enable_pointer_check},
150+
{"undefined-shift", !enable_undefined_shift_check}};
151+
152+
const namespacet ns(goto_model.symbol_table);
153+
154+
for(auto &entry : goto_model.goto_functions.function_map)
155+
{
156+
bool added_skip = false;
157+
158+
for(auto &instruction : entry.second.body.instructions)
159+
{
160+
// TODO: we may have other code using __CPROVER_dead_object and therefore
161+
// cannot easily remove these assignments
162+
#if 0
163+
if(
164+
instruction.is_assign() && !enable_pointer_check &&
165+
!enable_pointer_primitive_check &&
166+
instruction.assign_lhs().id() == ID_symbol &&
167+
to_symbol_expr(instruction.assign_lhs()).get_identifier() ==
168+
CPROVER_PREFIX "dead_object")
169+
{
170+
instruction.turn_into_skip();
171+
added_skip = true;
172+
continue;
173+
}
174+
else
175+
#endif
176+
if(!instruction.is_assert())
177+
continue;
178+
179+
const irep_idt &property_class =
180+
instruction.source_location().get_property_class();
181+
auto entry_it = should_skip.find(property_class);
182+
bool skip = entry_it != should_skip.end() && entry_it->second;
183+
184+
if(!skip && property_class == "error label")
185+
{
186+
const std::string comment =
187+
id2string(instruction.source_location().get_comment());
188+
skip = true;
189+
for(const auto &l : error_labels)
190+
{
191+
if(comment == std::string("error label " + l))
192+
{
193+
skip = false;
194+
break;
195+
}
196+
}
197+
}
198+
else if(!skip && property_class == "overflow")
199+
{
200+
const std::string comment =
201+
id2string(instruction.source_location().get_comment());
202+
if(has_prefix(comment, "result of signed mod is not representable"))
203+
skip = !enable_signed_overflow_check;
204+
else if(has_prefix(comment, "arithmetic overflow on "))
205+
{
206+
const std::string op = comment.substr(23);
207+
if(has_prefix(op, "floating-point "))
208+
skip = !enable_float_overflow_check;
209+
else if(
210+
has_prefix(op, "signed type ") || has_prefix(op, "float to ") ||
211+
has_prefix(op, "signed to ") || has_prefix(op, "unsigned to "))
212+
{
213+
skip = !enable_conversion_check;
214+
}
215+
else if(has_prefix(op, "signed "))
216+
{
217+
// TODO: some of these checks may also have been generated via
218+
// enable_pointer_overflow_check
219+
skip = !enable_signed_overflow_check;
220+
}
221+
else if(has_prefix(op, "unsigned "))
222+
{
223+
// TODO: some of these checks may also have been generated via
224+
// enable_pointer_overflow_check
225+
skip = !enable_unsigned_overflow_check;
226+
}
227+
}
228+
}
229+
230+
if(skip)
231+
{
232+
instruction.turn_into_skip();
233+
added_skip = true;
234+
}
235+
else
236+
{
237+
if(enable_assert_to_assume)
238+
instruction.turn_into_assume();
239+
240+
// TODO: the following would also simplify assertions not generated by
241+
// goto_check_c
242+
#if 0
243+
if(enable_simplify)
244+
simplify(instruction.guard, ns);
245+
246+
if(!retain_trivial && instruction.guard.is_true())
247+
{
248+
instruction.turn_into_skip();
249+
added_skip = true;
250+
}
251+
#endif
252+
}
253+
}
254+
255+
if(added_skip)
256+
remove_skip(entry.second.body);
257+
}
258+
}

src/goto-programs/goto_check.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,6 @@ void transform_assertions_assumptions(
3030
const optionst &options,
3131
goto_programt &goto_program);
3232

33+
void remove_disabled_checks(const optionst &, goto_modelt &);
34+
3335
#endif // CPROVER_GOTO_PROGRAMS_GOTO_CHECK_H

src/goto-programs/process_goto_program.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ bool process_goto_program(
7676
// add generic checks
7777
log.status() << "Generic Property Instrumentation" << messaget::eom;
7878
goto_check_c(options, goto_model, log.get_message_handler());
79+
remove_disabled_checks(options, goto_model);
7980
transform_assertions_assumptions(options, goto_model);
8081

8182
// checks don't know about adjusted float expressions

0 commit comments

Comments
 (0)