Skip to content

Commit 73ebbb4

Browse files
authored
Merge pull request #3585 from peterschrammel/all-properties-verifier
All-properties verifier [depends: 3584, blocks: 3794]
2 parents ce577d8 + c61ca64 commit 73ebbb4

File tree

3 files changed

+184
-0
lines changed

3 files changed

+184
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*******************************************************************\
2+
3+
Module: Goto Verifier for Verifying all Properties
4+
5+
Author: Daniel Kroening, Peter Schrammel
6+
7+
\*******************************************************************/
8+
9+
/// \file
10+
/// Goto Verifier for Verifying all Properties
11+
12+
#ifndef CPROVER_GOTO_CHECKER_ALL_PROPERTIES_VERIFIER_H
13+
#define CPROVER_GOTO_CHECKER_ALL_PROPERTIES_VERIFIER_H
14+
15+
#include "goto_verifier.h"
16+
17+
#include "incremental_goto_checker.h"
18+
#include "properties.h"
19+
#include "report_util.h"
20+
21+
template <class incremental_goto_checkerT>
22+
class all_properties_verifiert : public goto_verifiert
23+
{
24+
public:
25+
all_properties_verifiert(
26+
const optionst &options,
27+
ui_message_handlert &ui_message_handler,
28+
abstract_goto_modelt &goto_model)
29+
: goto_verifiert(options, ui_message_handler),
30+
goto_model(goto_model),
31+
incremental_goto_checker(options, ui_message_handler, goto_model)
32+
{
33+
properties = initialize_properties(goto_model);
34+
}
35+
36+
resultt operator()() override
37+
{
38+
// have we got anything to check? otherwise we return PASS
39+
if(!has_properties_to_check(properties))
40+
return resultt::PASS;
41+
42+
while(incremental_goto_checker(properties) !=
43+
incremental_goto_checkert::resultt::DONE)
44+
{
45+
// loop until we are done
46+
}
47+
return determine_result(properties);
48+
}
49+
50+
void report() override
51+
{
52+
output_properties(properties, ui_message_handler);
53+
output_overall_result(determine_result(properties), ui_message_handler);
54+
}
55+
56+
protected:
57+
abstract_goto_modelt &goto_model;
58+
incremental_goto_checkerT incremental_goto_checker;
59+
};
60+
61+
#endif // CPROVER_GOTO_CHECKER_ALL_PROPERTIES_VERIFIER_H

src/goto-checker/properties.cpp

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,116 @@ count_properties(const propertiest &properties, property_statust status)
144144
}
145145
return count;
146146
}
147+
148+
bool is_property_to_check(property_statust status)
149+
{
150+
return status == property_statust::NOT_CHECKED ||
151+
status == property_statust::UNKNOWN;
152+
}
153+
154+
bool has_properties_to_check(const propertiest &properties)
155+
{
156+
for(const auto &property_pair : properties)
157+
{
158+
if(is_property_to_check(property_pair.second.status))
159+
return true;
160+
}
161+
return false;
162+
}
163+
164+
/// Update with the preference order
165+
/// 1. old non-UNKNOWN/non-NOT_CHECKED status
166+
/// 2. new non-UNKNOWN/non-NOT_CHECKED status
167+
/// 3. UNKNOWN
168+
/// 4. NOT_CHECKED
169+
/// Suitable for updating property status
170+
property_statust &operator|=(property_statust &a, property_statust const &b)
171+
{
172+
// non-monotonic use is likely a bug
173+
PRECONDITION(
174+
a == property_statust::NOT_CHECKED ||
175+
(a == property_statust::UNKNOWN && b != property_statust::NOT_CHECKED) ||
176+
a == b);
177+
switch(a)
178+
{
179+
case property_statust::NOT_CHECKED:
180+
case property_statust::UNKNOWN:
181+
a = b;
182+
return a;
183+
case property_statust::ERROR:
184+
case property_statust::PASS:
185+
case property_statust::NOT_REACHABLE:
186+
case property_statust::FAIL:
187+
return a;
188+
}
189+
UNREACHABLE;
190+
}
191+
192+
/// Update with the preference order
193+
/// 1. ERROR
194+
/// 2. FAIL
195+
/// 3. UNKNOWN
196+
/// 4. NOT_CHECKED
197+
/// 5. NOT_REACHABLE
198+
/// 6. PASS
199+
/// Suitable for computing overall results
200+
property_statust &operator&=(property_statust &a, property_statust const &b)
201+
{
202+
switch(a)
203+
{
204+
case property_statust::ERROR:
205+
a = b;
206+
return a;
207+
case property_statust::FAIL:
208+
a = (b == property_statust::ERROR ? b : a);
209+
return a;
210+
case property_statust::UNKNOWN:
211+
a = (b == property_statust::ERROR || b == property_statust::FAIL ? b : a);
212+
return a;
213+
case property_statust::NOT_CHECKED:
214+
a =
215+
(b != property_statust::PASS && b != property_statust::NOT_REACHABLE ? b
216+
: a);
217+
return a;
218+
case property_statust::NOT_REACHABLE:
219+
a = (b != property_statust::PASS ? b : a);
220+
return a;
221+
case property_statust::PASS:
222+
a = (b == property_statust::PASS ? a : b);
223+
return a;
224+
}
225+
UNREACHABLE;
226+
}
227+
228+
/// Determines the overall result corresponding from the given properties
229+
/// That is PASS if all properties are PASS or NOT_CHECKED,
230+
/// FAIL if at least one property is FAIL and no property is ERROR,
231+
/// UNKNOWN if no property is FAIL or ERROR and
232+
/// at least one property is UNKNOWN,
233+
/// ERROR if at least one property is error.
234+
resultt determine_result(const propertiest &properties)
235+
{
236+
property_statust status = property_statust::PASS;
237+
for(const auto &property_pair : properties)
238+
{
239+
status &= property_pair.second.status;
240+
}
241+
switch(status)
242+
{
243+
case property_statust::NOT_CHECKED:
244+
// If we have unchecked properties then we don't know.
245+
return resultt::UNKNOWN;
246+
case property_statust::UNKNOWN:
247+
return resultt::UNKNOWN;
248+
case property_statust::NOT_REACHABLE:
249+
// If a property is not reachable then overall it's still a PASS.
250+
return resultt::PASS;
251+
case property_statust::PASS:
252+
return resultt::PASS;
253+
case property_statust::FAIL:
254+
return resultt::FAIL;
255+
case property_statust::ERROR:
256+
return resultt::ERROR;
257+
}
258+
UNREACHABLE;
259+
}

src/goto-checker/properties.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,14 @@ int result_to_exit_code(resultt result);
8989
/// Return the number of properties with given \p status
9090
std::size_t count_properties(const propertiest &, property_statust);
9191

92+
/// Return true if the status is NOT_CHECKED or UNKNOWN
93+
bool is_property_to_check(property_statust);
94+
95+
/// Return true if there as a property with NOT_CHECKED or UNKNOWN status
96+
bool has_properties_to_check(const propertiest &properties);
97+
98+
property_statust &operator|=(property_statust &, property_statust const &);
99+
property_statust &operator&=(property_statust &, property_statust const &);
100+
resultt determine_result(const propertiest &properties);
101+
92102
#endif // CPROVER_GOTO_CHECKER_PROPERTIES_H

0 commit comments

Comments
 (0)