Skip to content

Commit bed3526

Browse files
Generalize to arbitrary offsets
1 parent 8eb3d72 commit bed3526

File tree

2 files changed

+45
-25
lines changed

2 files changed

+45
-25
lines changed

src/analyses/baseInvariant.ml

Lines changed: 34 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ struct
8585

8686
let refine_lv man st c x c' pretty exp =
8787
let set' lval v st = set st (eval_lv ~man st lval) (Cilfacade.typeOfLval lval) ~lval_raw:lval v ~man in
88+
let default () =
89+
(* For accesses via pointers in complicated case, no refinement yet *)
90+
let old_val = eval_rv_lval_refine ~man st exp x in
91+
let old_val = map_oldval old_val (Cilfacade.typeOfLval x) in
92+
let v = apply_invariant ~old_val ~new_val:c' in
93+
if is_some_bot v then contra st
94+
else (
95+
if M.tracing then M.tracel "inv" "improve lval %a from %a to %a (c = %a, c' = %a)" d_lval x VD.pretty old_val VD.pretty v pretty c VD.pretty c';
96+
set' x v st
97+
)
98+
in
8899
match x with
89100
| Var var, o when refine_entire_var ->
90101
(* For variables, this is done at to the level of entire variables to benefit e.g. from disjunctive struct domains *)
@@ -100,23 +111,28 @@ struct
100111
if M.tracing then M.tracel "inv" "st from %a to %a" D.pretty st D.pretty r;
101112
r
102113
)
103-
| Mem (Lval lv), NoOffset ->
104-
let lvals = eval_lv ~man st x in
114+
| Mem (Lval lv), off ->
115+
let lvals = eval_lv ~man st (Mem (Lval lv), off) in
105116
let res = AD.fold (fun a acc ->
106-
if M.tracing then M.tracel "inv" "Consider case of lval %a = %a" d_lval lv VD.pretty (Address (AD.singleton a));
107-
let st = set' lv (Address (AD.singleton a)) st in
108-
let old_val = get ~man st (AD.singleton a) None in
109-
let old_val = VD.cast (Cilfacade.typeOfLval x) old_val in (* needed as the type of this pointer may be different *)
110-
(* this what I would originally have liked to do, but eval_rv_lval_refine uses queries and thus stale values *)
111-
(* let old_val = eval_rv_lval_refine ~man st exp x in *)
112-
let old_val = map_oldval old_val (Cilfacade.typeOfLval x) in
113-
let v = apply_invariant ~old_val ~new_val:c' in
114-
if is_some_bot v then
115-
D.join acc (try contra st with Analyses.Deadcode -> D.bot ())
116-
else (
117-
if M.tracing then M.tracel "inv" "improve lval %a from %a to %a (c = %a, c' = %a)" d_lval x VD.pretty old_val VD.pretty v pretty c VD.pretty c';
118-
D.join acc (set' x v st)
119-
)
117+
match a with
118+
| Addr (base, _) as orig ->
119+
let (a:VD.t) = Address (AD.singleton (AD.Addr.of_var base)) in
120+
if M.tracing then M.tracel "invo" "Consider case of lval %a = %a" d_lval lv VD.pretty a;
121+
let st = set' lv a st in
122+
let old_val = get ~man st (AD.singleton orig) None in
123+
let old_val = VD.cast (Cilfacade.typeOfLval x) old_val in (* needed as the type of this pointer may be different *)
124+
(* this what I would originally have liked to do, but eval_rv_lval_refine uses queries and thus stale values *)
125+
(* let old_val = eval_rv_lval_refine ~man st exp x in *)
126+
let old_val = map_oldval old_val (Cilfacade.typeOfLval x) in
127+
let v = apply_invariant ~old_val ~new_val:c' in
128+
if is_some_bot v then
129+
D.join acc (try contra st with Analyses.Deadcode -> D.bot ())
130+
else (
131+
if M.tracing then M.tracel "invo" "improve lval %a from %a to %a (c = %a, c' = %a)" d_lval x VD.pretty old_val VD.pretty v pretty c VD.pretty c';
132+
D.join acc (set' x v st)
133+
)
134+
| _ ->
135+
default ()
120136
) lvals (D.bot ())
121137
in
122138
if D.is_bot res then
@@ -125,15 +141,8 @@ struct
125141
res
126142
| Var _, _
127143
| Mem _, _ ->
128-
(* For accesses via pointers, not yet *)
129-
let old_val = eval_rv_lval_refine ~man st exp x in
130-
let old_val = map_oldval old_val (Cilfacade.typeOfLval x) in
131-
let v = apply_invariant ~old_val ~new_val:c' in
132-
if is_some_bot v then contra st
133-
else (
134-
if M.tracing then M.tracel "inv" "improve lval %a from %a to %a (c = %a, c' = %a)" d_lval x VD.pretty old_val VD.pretty v pretty c VD.pretty c';
135-
set' x v st
136-
)
144+
default ()
145+
137146

138147
let invariant_fallback man st exp tv =
139148
(* We use a recursive helper function so that x != 0 is false can be handled

tests/regression/27-inv_invariants/24-ptr.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,30 @@
33
int two = 2;
44
int three = 3;
55

6+
struct s { int content; };
7+
struct s twostruct = {2};
8+
struct s threestruct = {3};
9+
610
int main() {
711
int* ptr;
12+
struct s* ptrstruct;
813
int top;
914

1015
if(top) {
1116
ptr = &two;
17+
ptrstruct = &twostruct;
1218
} else {
1319
ptr = &three;
20+
ptrstruct = &threestruct;
1421
}
1522

1623
if(*ptr == 2) {
1724
__goblint_check(ptr == &two);
1825
}
1926

27+
if(ptrstruct->content == 2) {
28+
__goblint_check(ptrstruct == &twostruct);
29+
}
30+
2031
return 0;
2132
}

0 commit comments

Comments
 (0)