diff --git a/infer/src/IR/Mangled.ml b/infer/src/IR/Mangled.ml index aa8c6150eed..e6f31688fbd 100644 --- a/infer/src/IR/Mangled.ml +++ b/infer/src/IR/Mangled.ml @@ -41,6 +41,8 @@ let self = from_string "self" let is_self = function {plain= "self"} -> true | _ -> false +let is_artificial = function {plain= "__promise" | "__coro_frame"} -> true | _ -> false + let return_param = from_string "__return_param" let is_return_param = function {plain= "__return_param"} -> true | _ -> false diff --git a/infer/src/IR/Mangled.mli b/infer/src/IR/Mangled.mli index f59932a8c55..1e665da1990 100644 --- a/infer/src/IR/Mangled.mli +++ b/infer/src/IR/Mangled.mli @@ -39,6 +39,8 @@ val self : t [@@warning "-unused-value-declaration"] val is_self : t -> bool +val is_artificial : t -> bool + val return_param : t val is_return_param : t -> bool diff --git a/infer/src/IR/Pvar.ml b/infer/src/IR/Pvar.ml index 85f9d83a5a7..082c2d163e3 100644 --- a/infer/src/IR/Pvar.ml +++ b/infer/src/IR/Pvar.ml @@ -118,6 +118,8 @@ let is_this pvar = Mangled.is_this (get_name pvar) (** Check if a pvar is the special "self" var *) let is_self pvar = Mangled.is_self (get_name pvar) +let is_artificial pvar = Mangled.is_artificial (get_name pvar) + (** Check if the pvar is a return var *) let is_return pv = Mangled.equal (get_name pv) Ident.name_return diff --git a/infer/src/IR/Pvar.mli b/infer/src/IR/Pvar.mli index d01e57c3f69..8dd9fea1eb0 100644 --- a/infer/src/IR/Pvar.mli +++ b/infer/src/IR/Pvar.mli @@ -78,6 +78,9 @@ val is_this : t -> bool val is_self : t -> bool (** Check if a pvar is the special "self" var *) +val is_artificial : t -> bool +(** Check if a pvar is an artificial variable related coroutine, "__promise" or "__coro_frame" *) + val is_frontend_tmp : t -> bool (** return true if [pvar] is a temporary variable generated by the frontend *) diff --git a/infer/src/IR/Var.ml b/infer/src/IR/Var.ml index 80dd942a2d4..61fbb675d2f 100644 --- a/infer/src/IR/Var.ml +++ b/infer/src/IR/Var.ml @@ -47,6 +47,8 @@ let is_none = function LogicalVar id -> Ident.is_none id | _ -> false let is_this = function ProgramVar pv -> Pvar.is_this pv | LogicalVar _ -> false +let is_artificial = function ProgramVar pv -> Pvar.is_artificial pv | LogicalVar _ -> false + let get_all_vars_in_exp e = let acc = Exp.free_vars e |> Sequence.map ~f:of_id in Exp.program_vars e |> Sequence.map ~f:of_pvar |> Sequence.append acc diff --git a/infer/src/IR/Var.mli b/infer/src/IR/Var.mli index eceb5ab73d2..a98848c7c3d 100644 --- a/infer/src/IR/Var.mli +++ b/infer/src/IR/Var.mli @@ -42,6 +42,8 @@ val is_none : t -> bool val is_this : t -> bool +val is_artificial : t -> bool + val appears_in_source_code : t -> bool (** return true if this variable appears in source code (i.e., is not a LogicalVar or a frontend-generated ProgramVar) *) diff --git a/infer/src/backend/preanal.ml b/infer/src/backend/preanal.ml index 40d75233fba..81393746453 100644 --- a/infer/src/backend/preanal.ml +++ b/infer/src/backend/preanal.ml @@ -381,7 +381,9 @@ module Liveness = struct let is_local pvar = not (Liveness.is_always_in_scope proc_desc pvar) in let prepend_node_nullify_instructions loc pvars instrs = List.fold pvars ~init:instrs ~f:(fun instrs pvar -> - if is_local pvar then Sil.Metadata (Nullify (pvar, loc)) :: instrs else instrs ) + if is_local pvar && not (Pvar.is_artificial pvar) then + Sil.Metadata (Nullify (pvar, loc)) :: instrs + else instrs ) in let node_deadvars_instruction loc vars = let local_vars = @@ -399,6 +401,7 @@ module Liveness = struct let dead_vars, pvars_to_nullify = VarDomain.fold (fun var (dead_vars, pvars_to_nullify) -> + let dead_vars = if Var.is_artificial var then dead_vars else var :: dead_vars in let pvars_to_nullify = match Var.get_pvar var with | Some pvar when not (AddressTaken.Domain.mem pvar address_taken_vars) -> @@ -408,7 +411,7 @@ module Liveness = struct | _ -> pvars_to_nullify in - (var :: dead_vars, pvars_to_nullify) ) + (dead_vars, pvars_to_nullify) ) to_nullify ([], []) in let loc = Procdesc.Node.get_last_loc node in diff --git a/infer/src/pulse/Pulse.ml b/infer/src/pulse/Pulse.ml index 23d2cfeb6fb..895e634df78 100644 --- a/infer/src/pulse/Pulse.ml +++ b/infer/src/pulse/Pulse.ml @@ -310,7 +310,9 @@ module PulseTransferFunctions = struct if flags.cf_injected_destructor then match (callee_pname, actuals) with | Some (Procname.ObjC_Cpp pname), [(Exp.Lvar pvar, typ)] - when Pvar.is_local pvar && not (Procname.ObjC_Cpp.is_inner_destructor pname) -> + when Pvar.is_local pvar + && (not (Procname.ObjC_Cpp.is_inner_destructor pname)) + && not (Pvar.is_artificial pvar) -> (* ignore inner destructors, only trigger out of scope on the final destructor call *) Some (pvar, typ) | _ -> diff --git a/infer/src/pulse/PulseAbductiveDomain.ml b/infer/src/pulse/PulseAbductiveDomain.ml index c287694d2a1..54e1977bf90 100644 --- a/infer/src/pulse/PulseAbductiveDomain.ml +++ b/infer/src/pulse/PulseAbductiveDomain.ml @@ -972,7 +972,7 @@ module Internal = struct else None ) in match var with - | Var.ProgramVar pvar -> + | Var.ProgramVar pvar when not (Pvar.is_artificial pvar) -> get_local_typ_opt pvar |> Option.value_map ~default:acc ~f:(add_out_of_scope_attribute addr pvar location history acc)