@@ -1181,6 +1181,9 @@ struct
11811181 not is_alloc || (is_alloc && not (ctx.ask (Queries. IsHeapVar v)))
11821182
11831183 let query_invariant ctx context =
1184+ let keep_local = GobConfig. get_bool " ana.base.invariant.local" in
1185+ let keep_global = GobConfig. get_bool " ana.base.invariant.global" in
1186+
11841187 let cpa = ctx.local.BaseDomain. cpa in
11851188 let ask = Analyses. ask_of_ctx ctx in
11861189
@@ -1193,6 +1196,13 @@ struct
11931196 in
11941197 let module I = ValueDomain. ValueInvariant (Arg ) in
11951198
1199+ let var_filter v =
1200+ if is_global ask v then
1201+ keep_global
1202+ else
1203+ keep_local
1204+ in
1205+
11961206 let var_invariant ?offset v =
11971207 if not (InvariantCil. var_is_heap v) then
11981208 I. key_invariant v ?offset (Arg. find v)
@@ -1203,14 +1213,23 @@ struct
12031213 if Lval.Set. is_top context.Invariant. lvals then (
12041214 if ! earlyglobs || ThreadFlag. has_ever_been_multi ask then (
12051215 let cpa_invariant =
1206- CPA. fold (fun k v a ->
1207- if not (is_global ask k) then
1208- Invariant. (a && var_invariant k)
1209- else
1210- a
1211- ) cpa Invariant. none
1216+ if keep_local then (
1217+ CPA. fold (fun k v a ->
1218+ if not (is_global ask k) then
1219+ Invariant. (a && var_invariant k)
1220+ else
1221+ a
1222+ ) cpa Invariant. none
1223+ )
1224+ else
1225+ Invariant. none
1226+ in
1227+ let priv_vars =
1228+ if keep_global then
1229+ Priv. invariant_vars ask (priv_getg ctx.global) ctx.local
1230+ else
1231+ []
12121232 in
1213- let priv_vars = Priv. invariant_vars ask (priv_getg ctx.global) ctx.local in
12141233 let priv_invariant =
12151234 List. fold_left (fun acc v ->
12161235 Invariant. (var_invariant v && acc)
@@ -1220,15 +1239,18 @@ struct
12201239 )
12211240 else (
12221241 CPA. fold (fun k v a ->
1223- Invariant. (a && var_invariant k)
1242+ if var_filter k then
1243+ Invariant. (a && var_invariant k)
1244+ else
1245+ a
12241246 ) cpa Invariant. none
12251247 )
12261248 )
12271249 else (
12281250 Lval.Set. fold (fun k a ->
12291251 let i =
12301252 match k with
1231- | (Var v , offset ) when not (InvariantCil. var_is_heap v) ->
1253+ | (Var v , offset ) when var_filter v && not (InvariantCil. var_is_heap v) ->
12321254 (try I. key_invariant_lval v ~offset ~lval: k (Arg. find v) with Not_found -> Invariant. none)
12331255 | _ -> Invariant. none
12341256 in
@@ -1243,13 +1265,23 @@ struct
12431265 Invariant. none
12441266
12451267 let query_invariant_global ctx g =
1246- if GobConfig. get_bool " ana.base.invariant.enabled" && get_bool " exp.earlyglobs " then (
1268+ if GobConfig. get_bool " ana.base.invariant.enabled" && GobConfig. get_bool " ana.base.invariant.global " then (
12471269 (* Currently these global invariants are only sound with earlyglobs enabled for both single- and multi-threaded programs.
1248- Otherwise, the values of globals in single-threaded mode are not accounted for. *)
1249- (* TODO: account for single-threaded values without earlyglobs. *)
1270+ Otherwise, the values of globals in single-threaded mode are not accounted for.
1271+ They are also made sound without earlyglobs using the multithreaded mode ghost variable . *)
12501272 match g with
12511273 | `Left g' -> (* priv *)
1252- Priv. invariant_global (Analyses. ask_of_ctx ctx) (priv_getg ctx.global) g'
1274+ let inv = Priv. invariant_global (Analyses. ask_of_ctx ctx) (priv_getg ctx.global) g' in
1275+ if get_bool " exp.earlyglobs" then
1276+ inv
1277+ else (
1278+ if ctx.ask (GhostVarAvailable Multithreaded ) then (
1279+ let var = WitnessGhost. to_varinfo Multithreaded in
1280+ Invariant. (of_exp (UnOp (LNot , Lval (GoblintCil. var var), GoblintCil. intType)) || inv) [@ coverage off] (* bisect_ppx cannot handle redefined (||) *)
1281+ )
1282+ else
1283+ Invariant. none
1284+ )
12531285 | `Right _ -> (* thread return *)
12541286 Invariant. none
12551287 )
0 commit comments