-
Notifications
You must be signed in to change notification settings - Fork 75
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
Make meet in AddressDomain more precise #1468
base: master
Are you sure you want to change the base?
Changes from all commits
7186571
c1b7284
3eff22f
dc2a9c3
b7265e7
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 |
---|---|---|
|
@@ -182,16 +182,26 @@ module type MayEqualSetDomain = | |
sig | ||
include SetDomain.S | ||
val may_be_equal: elt -> elt -> bool | ||
val amenable_to_meet: elt -> elt -> bool | ||
Comment on lines
184
to
+185
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. I'm wondering if the two predicates could be combined into one more meaningful thing. Because I guess now there's supposed to be some kind of relationship between them, given that we only check them in certain order. Would this be the correct description? val same_sublattice: elt -> elt -> bool option
(** @return [Some true] if definitely in same sublattice, [Some false] if definitely not, [None] if unknown. *) 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. I'm skeptical here: So I think using lattice terminology here will be only confusing. For example what is difference between
So it once again boils down to the two properties above. 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. type eqinfo = Maybe | No | Meet
val may_be_equal: elt -> elt -> eqinfo One could do something like this but I don't think that is particularly nice. 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.
I agree and that's why I'm wondering if there is a less ad-hoc way to view these things. There are now two predicates who have 4 possible combined results for a pair of arguments, but only three cases are distinguished where the predicates are used. This makes me wonder about the order of these checks. If the previous implementation was sound, then checking Or if the case |
||
end | ||
|
||
module ProjectiveSetPairwiseMeet (E: Printable.S) (B: MayEqualSetDomain with type elt = E.t) (R: Representative with type elt = E.t): SetDomain.S with type elt = E.t = struct | ||
module ProjectiveSetPairwiseMeet (E: Lattice.S) (B: MayEqualSetDomain with type elt = E.t) (R: Representative with type elt = E.t): SetDomain.S with type elt = E.t = struct | ||
include ProjectiveSet (E) (B) (R) | ||
|
||
let meet m1 m2 = | ||
let meet_buckets b1 b2 acc = | ||
B.fold (fun e1 acc -> | ||
B.fold (fun e2 acc -> | ||
if B.may_be_equal e1 e2 then | ||
if B.amenable_to_meet e1 e2 then | ||
try | ||
let m = E.meet e1 e2 in | ||
if not (E.is_bot m) then | ||
add m acc | ||
else | ||
acc | ||
with Lattice.Uncomparable -> | ||
failwith (GobPretty.sprintf "amenable_to_meet %a %a returned true, but meet throws!" E.pretty e1 E.pretty e2) | ||
else if B.may_be_equal e1 e2 then | ||
add e1 (add e2 acc) | ||
else | ||
acc | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// PARAM: --set ana.base.privatization write | ||
#include<pthread.h> | ||
struct a { | ||
char* b; | ||
}; | ||
|
||
struct a *c; | ||
struct a h = {""}; | ||
struct a i = {"string"}; | ||
|
||
void* d(void* args) { | ||
struct a r; | ||
if (c->b) { | ||
__goblint_check(strlen(h.b) == 0); // Should also work for write! | ||
} | ||
} | ||
|
||
int main() { | ||
int top; | ||
|
||
if(top) { | ||
c = &h; | ||
} else { | ||
c = &i; | ||
} | ||
|
||
pthread_t t; | ||
pthread_create(&t, 0, d, 0); | ||
return 0; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
//PARAM: --enable ana.int.interval | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <time.h> | ||
|
||
int more_intricate() { | ||
int arr[20]; | ||
|
||
int top; | ||
|
||
int i = 2; | ||
int j = 8; | ||
if(top) { | ||
i = 8; | ||
j = 9; | ||
} | ||
|
||
int* imprecise1 = &arr[i]; // &arr[2..8] | ||
int* imprecise2 = &arr[j]; // &arr[8..9] | ||
|
||
if(imprecise1 == imprecise2) { | ||
__goblint_check(imprecise1 == &arr[8]); | ||
__goblint_check(imprecise2 == &arr[8]); //TODO (Refinement should happen in both directions!) | ||
} | ||
|
||
if(imprecise1 == &arr[j]) { | ||
__goblint_check(imprecise1 == &arr[8]); | ||
} | ||
|
||
} | ||
|
||
|
||
int main() { | ||
int arr[20]; | ||
|
||
int top; | ||
|
||
int i = 2; | ||
if(top) { | ||
i = 8; | ||
} | ||
|
||
int* imprecise = &arr[i]; | ||
|
||
if(imprecise == &arr[2]) { | ||
__goblint_check(imprecise == &arr[2]); | ||
sim642 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
more_intricate(); | ||
return 0; | ||
} |
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.
Don't the address set buckets already guarantee this to only be called in such cases because
Mval.top_indices
are the representatives?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.
Even if the buckets guarantee this already, this function can be called with two arbitrary addresses, so we can not just return true.
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.
That's true, although it could just be an implementation detail (like the buckets themselves are), which isn't exposed to the outside by the interface. Then such misuse would be impossible.