@@ -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,17 +111,40 @@ struct
100111 if M. tracing then M. tracel " inv" " st from %a to %a" D. pretty st D. pretty r;
101112 r
102113 )
114+ | Mem (Lval lv ), off ->
115+ (* Underlying lvals (may have offsets themselves), e.g., for struct members NOT including any offset appended to outer Mem *)
116+ let lvals = eval_lv ~man st (Mem (Lval lv), NoOffset ) in
117+ (* Additional offset of value being refined in Addr Offset type *)
118+ let original_offset = convert_offset ~man st off in
119+ let res = AD. fold (fun base_a acc ->
120+ Option. bind acc (fun acc ->
121+ match base_a with
122+ | Addr _ ->
123+ let (lval_a:VD.t ) = Address (AD. singleton base_a) in
124+ if M. tracing then M. tracel " inv" " Consider case of lval %a = %a" d_lval lv VD. pretty lval_a;
125+ let st = set' lv lval_a st in
126+ let orig = AD.Addr. add_offset base_a original_offset in
127+ let old_val = get ~man st (AD. singleton orig) None in
128+ let old_val = VD. cast (Cilfacade. typeOfLval x) old_val in (* needed as the type of this pointer may be different *)
129+ (* this what I would originally have liked to do, but eval_rv_lval_refine uses queries and thus stale values *)
130+ (* let old_val = eval_rv_lval_refine ~man st exp x in *)
131+ let old_val = map_oldval old_val (Cilfacade. typeOfLval x) in
132+ let v = apply_invariant ~old_val ~new_val: c' in
133+ if is_some_bot v then
134+ Some (D. join acc (try contra st with Analyses. Deadcode -> D. bot () ))
135+ else (
136+ 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';
137+ Some (D. join acc (set' x v st))
138+ )
139+ | _ -> None
140+ )
141+ ) lvals (Some (D. bot () ))
142+ in
143+ BatOption. map_default_delayed (fun d -> if D. is_bot d then raise Analyses. Deadcode else d) default res
103144 | Var _, _
104145 | Mem _ , _ ->
105- (* For accesses via pointers, not yet *)
106- let old_val = eval_rv_lval_refine ~man st exp x in
107- let old_val = map_oldval old_val (Cilfacade. typeOfLval x) in
108- let v = apply_invariant ~old_val ~new_val: c' in
109- if is_some_bot v then contra st
110- else (
111- 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';
112- set' x v st
113- )
146+ default ()
147+
114148
115149 let invariant_fallback man st exp tv =
116150 (* We use a recursive helper function so that x != 0 is false can be handled
0 commit comments