diff --git a/infer/src/backend/errdesc.ml b/infer/src/backend/errdesc.ml index 71a820971..4e8b05aab 100644 --- a/infer/src/backend/errdesc.ml +++ b/infer/src/backend/errdesc.ml @@ -208,6 +208,7 @@ let pvar_is_frontend_tmp pvar = (** Find the Letderef instruction used to declare normal variable [id], and return the expression dereferenced to initialize [id] *) let rec _find_normal_variable_letderef (seen : Sil.ExpSet.t) node id : Sil.dexp option = + let is_infer = Config.analyzer = Some Infer in let find_declaration node = function | Sil.Letderef (id0, e, _, _) when Ident.equal id id0 -> if verbose @@ -237,8 +238,14 @@ let rec _find_normal_variable_letderef (seen : Sil.ExpSet.t) node id : Sil.dexp else let unNone = function Some x -> x | None -> assert false in IList.map unNone args_dexpo in - Some (Sil.Dretcall (fun_dexp, args_dexp, loc, call_flags)) + | Sil.Set (Sil.Lvar pvar, _, Sil.Var id0, _) when is_infer && Ident.equal id id0 -> + (* this case is a hack to make bucketing continue to work in the presence of copy + propagation. previously, we would have code like: + n1 = foo(); x = n1; n2 = x; n2.toString(), but copy-propagation will optimize this to: + n1 = foo(); x = n1; n1.toString(). This case allows us to recognize the association + between n1 and x. Eradicate/checkers don't use copy-prop, so they don't need this. *) + Some (Sil.Dpvar pvar) | _ -> None in let res = find_in_node_or_preds node find_declaration in if verbose && res == None