-
Notifications
You must be signed in to change notification settings - Fork 275
Explicit nondet initialisation #35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a007615
9d44f13
673e789
e606e4f
c5574b6
efc5608
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
KNOWNBUG | ||
CORE | ||
main.c | ||
|
||
^EXIT=10$ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
KNOWNBUG | ||
CORE | ||
main.c | ||
|
||
^EXIT=0$ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
typedef struct _pair | ||
{ | ||
int x; | ||
int y; | ||
} pair; | ||
|
||
int __VERIFIER_nondet_int(); | ||
|
||
int main (void) | ||
{ | ||
pair p1 = { .x = 0, .y = __VERIFIER_nondet_int() }; | ||
pair p2 = {}; | ||
p2.x = __VERIFIER_nondet_int(); | ||
|
||
__CPROVER_assert(p1.x == p2.y, "true by constant propagation"); | ||
|
||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
CORE | ||
main.c | ||
|
||
^EXIT=0$ | ||
^SIGNAL=0$ | ||
^VERIFICATION SUCCESSFUL$ | ||
^Generated 1 VCC\(s\), 0 remaining after simplification$ | ||
-- | ||
^warning: ignoring |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,24 @@ | ||
CORE | ||
main.c | ||
<<<<<<< HEAD | ||
|
||
^EXIT=0$ | ||
^SIGNAL=0$ | ||
^VERIFICATION SUCCESSFUL$ | ||
-- | ||
^warning: ignoring | ||
======= | ||
--trace | ||
test.a\[1ll?\]=1 \(00000000000000000000000000000001\)$ | ||
^EXIT=10$ | ||
^SIGNAL=0$ | ||
^VERIFICATION FAILED$ | ||
-- | ||
^warning: ignoring | ||
\(\?\) | ||
-- | ||
Earlier versions of non-deterministic initialisation would cause trace output | ||
including | ||
|
||
test.a[1l]={ .a={ 0, 1 }, .b=0 }.a[1l] (?) | ||
>>>>>>> 2846e8c... Explicitly initialise non-static objects with non-deterministic values |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
uint32_t some_global_var; | ||
int8_t other_global_var; | ||
|
||
int main(int argc, char *argv[]) | ||
int main() | ||
{ | ||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ Author: Daniel Kroening, [email protected] | |
#include "goto_symex.h" | ||
|
||
#include <util/simplify_expr.h> | ||
#include <util/zero_initializer.h> | ||
|
||
unsigned goto_symext::dynamic_counter=0; | ||
|
||
|
@@ -27,3 +28,31 @@ nondet_symbol_exprt symex_nondet_generatort::operator()(typet &type) | |
nondet_symbol_exprt new_expr(identifier, type); | ||
return new_expr; | ||
} | ||
<<<<<<< HEAD | ||
======= | ||
|
||
void goto_symext::replace_nondet(exprt &expr) | ||
{ | ||
if(expr.id()==ID_side_effect && | ||
expr.get(ID_statement)==ID_nondet) | ||
{ | ||
exprt nondet = nondet_initializer( | ||
expr.type(), expr.source_location(), ns, log.get_message_handler()); | ||
|
||
// recursively replace nondet fields in structs or arrays | ||
if(nondet.id() != ID_side_effect) | ||
{ | ||
replace_nondet(nondet); | ||
expr.swap(nondet); | ||
return; | ||
} | ||
|
||
nondet_symbol_exprt new_expr = build_symex_nondet(expr.type()); | ||
new_expr.add_source_location()=expr.source_location(); | ||
expr.swap(new_expr); | ||
} | ||
else | ||
Forall_operands(it, expr) | ||
replace_nondet(*it); | ||
} | ||
>>>>>>> 2846e8c... Explicitly initialise non-static objects with non-deterministic values |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,8 +15,6 @@ Author: Daniel Kroening, [email protected] | |
|
||
#include <util/std_expr.h> | ||
|
||
#include <pointer-analysis/add_failed_symbols.h> | ||
|
||
#include <analyses/dirty.h> | ||
|
||
void goto_symext::symex_decl(statet &state) | ||
|
@@ -45,6 +43,7 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr) | |
state.rename(ssa.type(), l1_identifier, ns); | ||
ssa.update_type(); | ||
|
||
<<<<<<< HEAD | ||
// in case of pointers, put something into the value set | ||
if(ns.follow(expr.type()).id()==ID_pointer) | ||
{ | ||
|
@@ -76,6 +75,25 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr) | |
state.record_events=false; | ||
state.rename(ssa, ns); | ||
state.record_events=record_events; | ||
======= | ||
// L2 renaming | ||
// inlining may yield multiple declarations of the same identifier | ||
// within the same L1 context | ||
if(state.level2.current_names.find(l1_identifier)== | ||
state.level2.current_names.end()) | ||
state.level2.current_names[l1_identifier]=std::make_pair(ssa, 0); | ||
init_l1 = l1_identifier; | ||
|
||
// optimisation: skip non-deterministic initialisation if the next instruction | ||
// will take care of initialisation (but ensure int x=x; is handled properly) | ||
goto_programt::const_targett next = std::next(state.source.pc); | ||
if( | ||
next->is_assign() && to_code_assign(next->code).lhs() == expr && | ||
to_code_assign(next->code).rhs().is_constant()) | ||
{ | ||
return; | ||
} | ||
>>>>>>> 2846e8c... Explicitly initialise non-static objects with non-deterministic values | ||
|
||
// we hide the declaration of auxiliary variables | ||
// and if the statement itself is hidden | ||
|
@@ -84,10 +102,16 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr) | |
state.top().hidden_function || | ||
state.source.pc->source_location.get_hide(); | ||
|
||
target.decl( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Surprised the target doesn't get told of the declaration anymore? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a point worth considering, but really |
||
state.guard.as_expr(), | ||
side_effect_expr_nondett init(ssa.type()); | ||
replace_nondet(init); | ||
|
||
guardt guard; | ||
symex_assign_symbol( | ||
state, | ||
ssa, | ||
state.source, | ||
nil_exprt(), | ||
init, | ||
guard, | ||
hidden? | ||
symex_targett::assignment_typet::HIDDEN: | ||
symex_targett::assignment_typet::STATE); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is surprising -- the convention elsewhere seems to be that a nil value implies nondet init (for example, Java globals)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that maybe only the case in Java? The one place that takes care of initialising globals is
static_lifetime_init
, which will zero-initialise all symbols that don't have a value (unless they are markedextern
). Now of course the Java front-end had to do this in its very own way...