Update type of procdesc and closure expression to contain information about capture variable mode

Summary:
We update the type of captured variables to include information about capture mode (`ByReference` or `ByValue`) both for procdesc attributes and the closure expression.

For lambda: closure expression now contains correct capture mode for capture variables. Procdesc still does not contain information about captured variables which we will address in the next diff.

For objc blocks: at the moment all captured variables have mode `ByReference`. Added TODOs to fix this.

Reviewed By: jvillard

Differential Revision: D22572054

fbshipit-source-id: 4c88678ee
master
Daiva Naudziuniene 4 years ago committed by Facebook GitHub Bot
parent 9b5820bf32
commit 50d659b750

@ -21,8 +21,10 @@ let pp_etlist fmt etl =
let pp_var_list fmt etl = let pp_var_list fmt etl =
List.iter etl ~f:(fun (id, ty) -> List.iter etl ~f:(fun (id, ty, mode) ->
Format.fprintf fmt " %a:%a" Mangled.pp id (Typ.pp_full Pp.text) ty ) Format.fprintf fmt " [%s]%a:%a"
(Pvar.string_of_capture_mode mode)
Mangled.pp id (Typ.pp_full Pp.text) ty )
let pp_local_list fmt etl = List.iter ~f:(Procdesc.pp_local fmt) etl let pp_local_list fmt etl = List.iter ~f:(Procdesc.pp_local fmt) etl

@ -18,7 +18,7 @@ type ident_ = Ident.t
let compare_ident_ x y = Ident.compare y x let compare_ident_ x y = Ident.compare y x
type closure = {name: Procname.t; captured_vars: (t * Pvar.t * Typ.t) list} type closure = {name: Procname.t; captured_vars: (t * Pvar.t * Typ.t * Pvar.capture_mode) list}
(** This records information about a [sizeof(typ)] expression. (** This records information about a [sizeof(typ)] expression.
@ -184,7 +184,7 @@ let fold_captured ~f exp acc =
fold_captured_ e1 captured_acc |> fold_captured_ e2 fold_captured_ e1 captured_acc |> fold_captured_ e2
| Closure {captured_vars} -> | Closure {captured_vars} ->
List.fold captured_vars List.fold captured_vars
~f:(fun acc (captured_exp, _, _) -> f acc captured_exp) ~f:(fun acc (captured_exp, _, _, _) -> f acc captured_exp)
~init:captured_acc ~init:captured_acc
| Const _ | Lvar _ | Var _ | Sizeof _ -> | Const _ | Lvar _ | Var _ | Sizeof _ ->
captured_acc captured_acc
@ -249,12 +249,14 @@ let rec pp_ pe pp_t f e =
subtype subtype
and pp_captured_var pe pp_t f (exp, var, typ) = and pp_captured_var pe pp_t f (exp, var, typ, mode) =
match exp with match exp with
| Lvar evar when Pvar.equal var evar -> | Lvar evar when Pvar.equal var evar ->
(Pvar.pp pe) f var (Pvar.pp pe) f var
| _ -> | _ ->
F.fprintf f "(%a %a:%a)" (pp_ pe pp_t) exp (Pvar.pp pe) var (Typ.pp pe) typ F.fprintf f "([%s]%a %a:%a)"
(Pvar.string_of_capture_mode mode)
(pp_ pe pp_t) exp (Pvar.pp pe) var (Typ.pp pe) typ
let pp_printenv ~print_types pe f e = let pp_printenv ~print_types pe f e =
@ -323,7 +325,7 @@ let rec gen_free_vars =
| Cast (_, e) | Exn e | Lfield (e, _, _) | Sizeof {dynamic_length= Some e} | UnOp (_, e, _) -> | Cast (_, e) | Exn e | Lfield (e, _, _) | Sizeof {dynamic_length= Some e} | UnOp (_, e, _) ->
gen_free_vars e gen_free_vars e
| Closure {captured_vars} -> | Closure {captured_vars} ->
ISequence.gen_sequence_list captured_vars ~f:(fun (e, _, _) -> gen_free_vars e) ISequence.gen_sequence_list captured_vars ~f:(fun (e, _, _, _) -> gen_free_vars e)
| Const (Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cclass _) | Lvar _ | Sizeof {dynamic_length= None} | Const (Cint _ | Cfun _ | Cstr _ | Cfloat _ | Cclass _) | Lvar _ | Sizeof {dynamic_length= None}
-> ->
return () return ()
@ -347,7 +349,7 @@ let rec gen_program_vars =
| BinOp (_, e1, e2) | Lindex (e1, e2) -> | BinOp (_, e1, e2) | Lindex (e1, e2) ->
gen_program_vars e1 >>= fun () -> gen_program_vars e2 gen_program_vars e1 >>= fun () -> gen_program_vars e2
| Closure {captured_vars} -> | Closure {captured_vars} ->
ISequence.gen_sequence_list captured_vars ~f:(fun (e, _, _) -> gen_program_vars e) ISequence.gen_sequence_list captured_vars ~f:(fun (e, _, _, _) -> gen_program_vars e)
let program_vars e = Sequence.Generator.run (gen_program_vars e) let program_vars e = Sequence.Generator.run (gen_program_vars e)
@ -363,7 +365,7 @@ let rec rename_pvars ~(f : string -> string) : t -> t =
| Exn e -> | Exn e ->
Exn (re e) Exn (re e)
| Closure {name; captured_vars} -> | Closure {name; captured_vars} ->
let captured_vars = List.map ~f:(function e, v, t -> (re e, rv v, t)) captured_vars in let captured_vars = List.map ~f:(function e, v, t, m -> (re e, rv v, t, m)) captured_vars in
Closure {name; captured_vars} Closure {name; captured_vars}
| Cast (t, e) -> | Cast (t, e) ->
Cast (t, re e) Cast (t, re e)

@ -13,7 +13,7 @@
open! IStd open! IStd
module F = Format module F = Format
type closure = {name: Procname.t; captured_vars: (t * Pvar.t * Typ.t) list} type closure = {name: Procname.t; captured_vars: (t * Pvar.t * Typ.t * Pvar.capture_mode) list}
(** This records information about a [sizeof(typ)] expression. (** This records information about a [sizeof(typ)] expression.

@ -39,7 +39,8 @@ let pp_var_data fmt {name; typ; modify_in_block} =
type t = type t =
{ access: PredSymb.access (** visibility access *) { access: PredSymb.access (** visibility access *)
; captured: (Mangled.t * Typ.t) list (** name and type of variables captured in blocks *) ; captured: (Mangled.t * Typ.t * Pvar.capture_mode) list
(** name and type of variables captured in blocks *)
; exceptions: string list (** exceptions thrown by the procedure *) ; exceptions: string list (** exceptions thrown by the procedure *)
; formals: (Mangled.t * Typ.t) list (** name and type of formal parameters *) ; formals: (Mangled.t * Typ.t) list (** name and type of formal parameters *)
; const_formals: int list (** list of indices of formals that are const-qualified *) ; const_formals: int list (** list of indices of formals that are const-qualified *)
@ -118,6 +119,13 @@ let pp_parameters =
Pp.semicolon_seq ~print_env:Pp.text_break (Pp.pair ~fst:Mangled.pp ~snd:(Typ.pp_full Pp.text)) Pp.semicolon_seq ~print_env:Pp.text_break (Pp.pair ~fst:Mangled.pp ~snd:(Typ.pp_full Pp.text))
let pp_captured_var fmt (var, typ, mode) =
F.fprintf fmt "(%a,@,%a,@,%s)" Mangled.pp var (Typ.pp_full Pp.text) typ
(Pvar.string_of_capture_mode mode)
let pp_captured = Pp.semicolon_seq ~print_env:Pp.text_break pp_captured_var
let pp f let pp f
({ access ({ access
; captured ; captured
@ -152,8 +160,8 @@ let pp f
translation_unit ; translation_unit ;
if not (PredSymb.equal_access default.access access) then if not (PredSymb.equal_access default.access access) then
F.fprintf f "; access= %a@," (Pp.of_string ~f:PredSymb.string_of_access) access ; F.fprintf f "; access= %a@," (Pp.of_string ~f:PredSymb.string_of_access) access ;
if not ([%compare.equal: (Mangled.t * Typ.t) list] default.captured captured) then if not ([%compare.equal: (Mangled.t * Typ.t * Pvar.capture_mode) list] default.captured captured)
F.fprintf f "; captured= [@[%a@]]@," pp_parameters captured ; then F.fprintf f "; captured= [@[%a@]]@," pp_captured captured ;
if not ([%compare.equal: string list] default.exceptions exceptions) then if not ([%compare.equal: string list] default.exceptions exceptions) then
F.fprintf f "; exceptions= [@[%a@]]@," F.fprintf f "; exceptions= [@[%a@]]@,"
(Pp.semicolon_seq ~print_env:Pp.text_break F.pp_print_string) (Pp.semicolon_seq ~print_env:Pp.text_break F.pp_print_string)

@ -21,7 +21,8 @@ type var_data =
type t = type t =
{ access: PredSymb.access (** visibility access *) { access: PredSymb.access (** visibility access *)
; captured: (Mangled.t * Typ.t) list (** name and type of variables captured in blocks *) ; captured: (Mangled.t * Typ.t * Pvar.capture_mode) list
(** name, type, and mode of variables captured in blocks and lambdas *)
; exceptions: string list (** exceptions thrown by the procedure *) ; exceptions: string list (** exceptions thrown by the procedure *)
; formals: (Mangled.t * Typ.t) list (** name and type of formal parameters *) ; formals: (Mangled.t * Typ.t) list (** name and type of formal parameters *)
; const_formals: int list (** list of indices of formals that are const-qualified *) ; const_formals: int list (** list of indices of formals that are const-qualified *)

@ -741,6 +741,15 @@ let pp_variable_list fmt etl =
etl etl
let pp_captured_list fmt etl =
List.iter
~f:(fun (id, ty, mode) ->
Format.fprintf fmt " [%s] %a:%a"
(Pvar.string_of_capture_mode mode)
Mangled.pp id (Typ.pp_full Pp.text) ty )
etl
let pp_objc_accessor fmt accessor = let pp_objc_accessor fmt accessor =
match accessor with match accessor with
| Some (ProcAttributes.Objc_getter field) -> | Some (ProcAttributes.Objc_getter field) ->
@ -760,7 +769,7 @@ let pp_signature fmt pdesc =
attributes.ProcAttributes.objc_accessor pp_variable_list (get_formals pdesc) pp_locals_list attributes.ProcAttributes.objc_accessor pp_variable_list (get_formals pdesc) pp_locals_list
(get_locals pdesc) ; (get_locals pdesc) ;
if not (List.is_empty (get_captured pdesc)) then if not (List.is_empty (get_captured pdesc)) then
Format.fprintf fmt ", Captured: %a" pp_variable_list (get_captured pdesc) ; Format.fprintf fmt ", Captured: %a" pp_captured_list (get_captured pdesc) ;
let method_annotation = attributes.ProcAttributes.method_annotation in let method_annotation = attributes.ProcAttributes.method_annotation in
( if not (Annot.Method.is_empty method_annotation) then ( if not (Annot.Method.is_empty method_annotation) then
let pname_string = Procname.to_string pname in let pname_string = Procname.to_string pname in
@ -792,9 +801,11 @@ let is_captured_pvar procdesc pvar =
| _ -> | _ ->
false false
in in
let pvar_matches_in_captured (name, _, _) = Mangled.equal name pvar_name in
let is_captured_var_objc_block = let is_captured_var_objc_block =
(* var is captured if the procedure is a objc block and the var is in the captured *) (* var is captured if the procedure is a objc block and the var is in the captured *)
Procname.is_objc_block procname && List.exists ~f:pvar_matches (get_captured procdesc) Procname.is_objc_block procname
&& List.exists ~f:pvar_matches_in_captured (get_captured procdesc)
in in
is_captured_var_cpp_lambda || is_captured_var_objc_block is_captured_var_cpp_lambda || is_captured_var_objc_block

@ -225,7 +225,7 @@ val get_attributes : t -> ProcAttributes.t
val set_attributes : t -> ProcAttributes.t -> unit val set_attributes : t -> ProcAttributes.t -> unit
val get_captured : t -> (Mangled.t * Typ.t) list val get_captured : t -> (Mangled.t * Typ.t * Pvar.capture_mode) list
(** Return name and type of block's captured variables *) (** Return name and type of block's captured variables *)
val get_exit_node : t -> Node.t val get_exit_node : t -> Node.t

@ -324,3 +324,7 @@ module Set = PrettyPrintable.MakePPSet (struct
let pp = pp Pp.text let pp = pp Pp.text
end) end)
type capture_mode = ByReference | ByValue [@@deriving compare]
let string_of_capture_mode = function ByReference -> "by ref" | ByValue -> "by value"

@ -171,3 +171,7 @@ val rename : f:(string -> string) -> t -> t
(** Sets of pvars. *) (** Sets of pvars. *)
module Set : PrettyPrintable.PPSet with type elt = t module Set : PrettyPrintable.PPSet with type elt = t
type capture_mode = ByReference | ByValue [@@deriving compare]
val string_of_capture_mode : capture_mode -> string

@ -212,7 +212,7 @@ let with_block_args_instrs resolved_pdesc substitutions =
let id = Ident.create_fresh_specialized_with_blocks Ident.knormal in let id = Ident.create_fresh_specialized_with_blocks Ident.knormal in
let pvar = Pvar.mk var resolved_pname in let pvar = Pvar.mk var resolved_pname in
( Var.of_id id ( Var.of_id id
, (Exp.Var id, pvar, typ) , (Exp.Var id, pvar, typ, Pvar.ByReference)
, Sil.Load {id; e= Exp.Lvar pvar; root_typ= typ; typ; loc} ) ) , Sil.Load {id; e= Exp.Lvar pvar; root_typ= typ; typ; loc} ) )
|> List.unzip3 |> List.unzip3
in in
@ -259,7 +259,7 @@ let with_block_args_instrs resolved_pdesc substitutions =
get_block_name_and_load_captured_vars_instrs block_var loc get_block_name_and_load_captured_vars_instrs block_var loc
in in
let call_instr = let call_instr =
let id_exps = List.map ~f:(fun (id, _, typ) -> (id, typ)) id_exp_typs in let id_exps = List.map ~f:(fun (id, _, typ, _) -> (id, typ)) id_exp_typs in
let converted_args = List.map ~f:(fun (exp, typ) -> (convert_exp exp, typ)) origin_args in let converted_args = List.map ~f:(fun (exp, typ) -> (convert_exp exp, typ)) origin_args in
Sil.Call Sil.Call
( return_ids ( return_ids
@ -304,7 +304,7 @@ let with_block_args callee_pdesc pname_with_block_args block_args =
| Some (cl : Exp.closure) -> | Some (cl : Exp.closure) ->
let formals_from_captured = let formals_from_captured =
List.map List.map
~f:(fun (_, var, typ) -> ~f:(fun (_, var, typ, _) ->
(* Here we create fresh names for the new formals, based on the names of the captured (* Here we create fresh names for the new formals, based on the names of the captured
variables annotated with the name of the caller method *) variables annotated with the name of the caller method *)
(Pvar.get_name_of_local_with_procname var, typ) ) (Pvar.get_name_of_local_with_procname var, typ) )

@ -547,7 +547,7 @@ and of_sil ~include_array_indexes ~f_resolve_id ~add_deref exp typ =
| Closure closure -> | Closure closure ->
let environment = let environment =
List.map List.map
~f:(fun (value, pvar, typ) -> ~f:(fun (value, pvar, typ, _) ->
(* TODO: this is a hack than can disappear once we have proper AccessExpressions (t23176430) *) (* TODO: this is a hack than can disappear once we have proper AccessExpressions (t23176430) *)
let typ' = let typ' =
match value with match value with

@ -928,10 +928,10 @@ let rec exp_sub_ids (f : subst_fun) exp =
if phys_equal e' e then exp else Exp.Exn e' if phys_equal e' e then exp else Exp.Exn e'
| Closure c -> | Closure c ->
let captured_vars = let captured_vars =
IList.map_changed ~equal:[%compare.equal: Exp.t * Pvar.t * Typ.t] IList.map_changed ~equal:[%compare.equal: Exp.t * Pvar.t * Typ.t * Pvar.capture_mode]
~f:(fun ((e, pvar, typ) as captured) -> ~f:(fun ((e, pvar, typ, mode) as captured) ->
let e' = exp_sub_ids f e in let e' = exp_sub_ids f e in
if phys_equal e' e then captured else (e', pvar, typ) ) if phys_equal e' e then captured else (e', pvar, typ, mode) )
c.captured_vars c.captured_vars
in in
if phys_equal captured_vars c.captured_vars then exp else Exp.Closure {c with captured_vars} if phys_equal captured_vars c.captured_vars then exp else Exp.Closure {c with captured_vars}

@ -673,7 +673,7 @@ module Normalize = struct
e e
| Closure c -> | Closure c ->
let captured_vars = let captured_vars =
List.map ~f:(fun (exp, pvar, typ) -> (eval exp, pvar, typ)) c.captured_vars List.map ~f:(fun (exp, pvar, typ, mode) -> (eval exp, pvar, typ, mode)) c.captured_vars
in in
Closure {c with captured_vars} Closure {c with captured_vars}
| Const _ -> | Const _ ->
@ -1399,12 +1399,12 @@ module Normalize = struct
match (hpred : Predicates.hpred) with match (hpred : Predicates.hpred) with
| Hpointsto (Exp.Lvar var, Eexp (Exp.Var id, _), _) -> | Hpointsto (Exp.Lvar var, Eexp (Exp.Var id, _), _) ->
IList.map_changed ~equal:phys_equal IList.map_changed ~equal:phys_equal
~f:(fun ((e_captured, var_captured, t) as captured_item) -> ~f:(fun ((e_captured, var_captured, t, mode) as captured_item) ->
match e_captured with match e_captured with
| Exp.Var id_captured -> | Exp.Var id_captured ->
if Ident.equal id id_captured && Pvar.equal var var_captured then captured_item if Ident.equal id id_captured && Pvar.equal var var_captured then captured_item
else if Ident.equal id id_captured then (e_captured, var, t) else if Ident.equal id id_captured then (e_captured, var, t, mode)
else if Pvar.equal var var_captured then (Exp.Var id, var_captured, t) else if Pvar.equal var var_captured then (Exp.Var id, var_captured, t, mode)
else captured_item else captured_item
| _ -> | _ ->
captured_item ) captured_item )
@ -2114,7 +2114,7 @@ let rec exp_captured_ren ren (e : Exp.t) : Exp.t =
Exn (exp_captured_ren ren e) Exn (exp_captured_ren ren e)
| Closure {name; captured_vars} -> | Closure {name; captured_vars} ->
let captured_vars' = let captured_vars' =
List.map ~f:(fun (e, v, t) -> (exp_captured_ren ren e, v, t)) captured_vars List.map ~f:(fun (e, v, t, m) -> (exp_captured_ren ren e, v, t, m)) captured_vars
in in
Closure {name; captured_vars= captured_vars'} Closure {name; captured_vars= captured_vars'}
| Const _ -> | Const _ ->

@ -1289,7 +1289,7 @@ let check_call_to_objc_block_error tenv pdesc prop fun_exp loc =
| Some (_, Exp.Lvar pvar) -> | Some (_, Exp.Lvar pvar) ->
(* pvar is the block *) (* pvar is the block *)
let name = Pvar.get_name pvar in let name = Pvar.get_name pvar in
List.exists ~f:(fun (cn, _) -> Mangled.equal name cn) (Procdesc.get_captured pdesc) List.exists ~f:(fun (cn, _, _) -> Mangled.equal name cn) (Procdesc.get_captured pdesc)
| _ -> | _ ->
false false
in in

@ -119,7 +119,7 @@ let get_cycle_blocks root_node exp =
match exp with match exp with
| Exp.Closure {name; captured_vars} -> | Exp.Closure {name; captured_vars} ->
List.find_map List.find_map
~f:(fun (e, var, typ) -> ~f:(fun (e, var, typ, _) ->
match typ.Typ.desc with match typ.Typ.desc with
| Typ.Tptr (_, Typ.Pk_objc_weak) | Typ.Tptr (_, Typ.Pk_objc_unsafe_unretained) -> | Typ.Tptr (_, Typ.Pk_objc_weak) | Typ.Tptr (_, Typ.Pk_objc_unsafe_unretained) ->
None None

@ -1108,7 +1108,7 @@ let rec sym_exec
| Exp.Closure c -> | Exp.Closure c ->
let proc_exp = Exp.Const (Const.Cfun c.name) in let proc_exp = Exp.Const (Const.Cfun c.name) in
let proc_exp' = Prop.exp_normalize_prop tenv prop_ proc_exp in let proc_exp' = Prop.exp_normalize_prop tenv prop_ proc_exp in
let par' = List.map ~f:(fun (id_exp, _, typ) -> (id_exp, typ)) c.captured_vars in let par' = List.map ~f:(fun (id_exp, _, typ, _) -> (id_exp, typ)) c.captured_vars in
Sil.Call (ret, proc_exp', par' @ par, loc, call_flags) Sil.Call (ret, proc_exp', par' @ par, loc, call_flags)
| _ -> | _ ->
Sil.Call (ret, exp', par, loc, call_flags) Sil.Call (ret, exp', par, loc, call_flags)

@ -34,7 +34,7 @@ let get_extended_args_for_method_with_block_analysis act_params =
match act_param with match act_param with
| Exp.Closure cl, _, _ -> | Exp.Closure cl, _, _ ->
let captured = let captured =
List.map ~f:(fun (exp, var, typ) -> (exp, Some var, typ)) cl.captured_vars List.map ~f:(fun (exp, var, typ, _) -> (exp, Some var, typ)) cl.captured_vars
in in
append_no_duplicates_vars all_args captured append_no_duplicates_vars all_args captured
| _ -> | _ ->

@ -173,7 +173,7 @@ let check_expr_for_array_access :
| Exp.Cast (_, e) -> | Exp.Cast (_, e) ->
check_sub_expr e cond_set check_sub_expr e cond_set
| Exp.Closure {captured_vars} -> | Exp.Closure {captured_vars} ->
List.fold captured_vars ~init:cond_set ~f:(fun cond_set (e, _, _) -> List.fold captured_vars ~init:cond_set ~f:(fun cond_set (e, _, _, _) ->
check_sub_expr e cond_set ) check_sub_expr e cond_set )
| Exp.Var _ | Exp.Lvar _ | Exp.Const _ | Exp.Sizeof _ -> | Exp.Var _ | Exp.Lvar _ | Exp.Const _ | Exp.Sizeof _ ->
cond_set cond_set
@ -226,7 +226,7 @@ let rec check_expr_for_integer_overflow integer_type_widths pname exp location m
|> check_expr_for_integer_overflow integer_type_widths pname e1 location mem |> check_expr_for_integer_overflow integer_type_widths pname e1 location mem
|> check_expr_for_integer_overflow integer_type_widths pname e2 location mem |> check_expr_for_integer_overflow integer_type_widths pname e2 location mem
| Exp.Closure {captured_vars} -> | Exp.Closure {captured_vars} ->
List.fold captured_vars ~init:cond_set ~f:(fun cond_set (e, _, _) -> List.fold captured_vars ~init:cond_set ~f:(fun cond_set (e, _, _, _) ->
check_expr_for_integer_overflow integer_type_widths pname e location mem cond_set ) check_expr_for_integer_overflow integer_type_widths pname e location mem cond_set )
| Exp.Var _ | Exp.Const _ | Exp.Lvar _ | Exp.Sizeof {dynamic_length= None} -> | Exp.Var _ | Exp.Const _ | Exp.Lvar _ | Exp.Sizeof {dynamic_length= None} ->
cond_set cond_set

@ -151,7 +151,7 @@ module TransferFunctions = struct
let pvar_name = Pvar.get_name pvar in let pvar_name = Pvar.get_name pvar in
Pvar.is_self pvar Pvar.is_self pvar
&& List.exists && List.exists
~f:(fun (captured, typ) -> Mangled.equal captured pvar_name && Typ.is_strong_pointer typ) ~f:(fun (captured, typ, _) -> Mangled.equal captured pvar_name && Typ.is_strong_pointer typ)
attributes.ProcAttributes.captured attributes.ProcAttributes.captured
@ -159,7 +159,7 @@ module TransferFunctions = struct
let is_captured_strong_self attributes pvar = let is_captured_strong_self attributes pvar =
(not (Pvar.is_self pvar)) (not (Pvar.is_self pvar))
&& List.exists && List.exists
~f:(fun (captured, typ) -> ~f:(fun (captured, typ, _) ->
Typ.is_strong_pointer typ Typ.is_strong_pointer typ
&& Mangled.equal captured (Pvar.get_name pvar) && Mangled.equal captured (Pvar.get_name pvar)
&& String.is_suffix ~suffix:"self" (String.lowercase (Mangled.to_string captured)) ) && String.is_suffix ~suffix:"self" (String.lowercase (Mangled.to_string captured)) )
@ -168,7 +168,7 @@ module TransferFunctions = struct
let is_captured_weak_self attributes pvar = let is_captured_weak_self attributes pvar =
List.exists List.exists
~f:(fun (captured, typ) -> ~f:(fun (captured, typ, _) ->
Mangled.equal captured (Pvar.get_name pvar) Mangled.equal captured (Pvar.get_name pvar)
&& String.is_substring ~substring:"self" (String.lowercase (Mangled.to_string captured)) && String.is_substring ~substring:"self" (String.lowercase (Mangled.to_string captured))
&& Typ.is_weak_pointer typ ) && Typ.is_weak_pointer typ )
@ -270,7 +270,7 @@ module TransferFunctions = struct
actual "use" of the captured variable in the source program though, and causes false actual "use" of the captured variable in the source program though, and causes false
positives. Here we remove the ids from the domain when that id is being added to a closure. *) positives. Here we remove the ids from the domain when that id is being added to a closure. *)
let remove_ids_in_closures_from_domain (domain : Domain.t) (instr : Sil.instr) = let remove_ids_in_closures_from_domain (domain : Domain.t) (instr : Sil.instr) =
let remove_id_in_closures_from_domain vars ((exp : Exp.t), _, _) = let remove_id_in_closures_from_domain vars ((exp : Exp.t), _, _, _) =
match exp with Var id -> Vars.remove id vars | _ -> vars match exp with Var id -> Vars.remove id vars | _ -> vars
in in
let do_exp vars (exp : Exp.t) = let do_exp vars (exp : Exp.t) =

@ -216,10 +216,15 @@ let create_local_procdesc ?(set_objc_accessor_attr = false) trans_unit_ctx cfg t
let formals = let formals =
List.map ~f:(fun ({name; typ} : CMethodSignature.param_type) -> (name, typ)) all_params List.map ~f:(fun ({name; typ} : CMethodSignature.param_type) -> (name, typ)) all_params
in in
let captured_mangled = List.map ~f:(fun (var, t) -> (Pvar.get_name var, t)) captured in let captured_mangled =
List.map ~f:(fun (var, t, mode) -> (Pvar.get_name var, t, mode)) captured
in
(* Captured variables for blocks are treated as parameters *) (* Captured variables for blocks are treated as parameters *)
let formals = captured_mangled @ formals in let captured_as_formals = List.map ~f:(fun (var, t, _) -> (var, t)) captured_mangled in
let const_formals = get_const_params_indices ~shift:(List.length captured_mangled) all_params in let formals = captured_as_formals @ formals in
let const_formals =
get_const_params_indices ~shift:(List.length captured_as_formals) all_params
in
let source_range = ms.CMethodSignature.loc in let source_range = ms.CMethodSignature.loc in
L.(debug Capture Verbose) L.(debug Capture Verbose)
"@\nCreating a new procdesc for function: '%a'@\n@." Procname.pp proc_name ; "@\nCreating a new procdesc for function: '%a'@\n@." Procname.pp proc_name ;

@ -31,7 +31,7 @@ val create_local_procdesc :
-> Tenv.t -> Tenv.t
-> CMethodSignature.t -> CMethodSignature.t
-> Clang_ast_t.stmt list -> Clang_ast_t.stmt list
-> (Pvar.t * Typ.t) list -> (Pvar.t * Typ.t * Pvar.capture_mode) list
-> bool -> bool
val create_external_procdesc : val create_external_procdesc :

@ -8,7 +8,7 @@
open! IStd open! IStd
type block_data = type block_data =
{ captured_vars: (Pvar.t * Typ.t) list { captured_vars: (Pvar.t * Typ.t * Pvar.capture_mode) list
; context: CContext.t ; context: CContext.t
; passed_as_noescape_block_to: Procname.t option ; passed_as_noescape_block_to: Procname.t option
; procname: Procname.t ; procname: Procname.t

@ -291,10 +291,10 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
(** Given a captured var, return the instruction to assign it to a temp *) (** Given a captured var, return the instruction to assign it to a temp *)
let assign_captured_var loc (cvar, typ) = let assign_captured_var loc (cvar, typ, mode) =
let id = Ident.create_fresh Ident.knormal in let id = Ident.create_fresh Ident.knormal in
let instr = Sil.Load {id; e= Exp.Lvar cvar; root_typ= typ; typ; loc} in let instr = Sil.Load {id; e= Exp.Lvar cvar; root_typ= typ; typ; loc} in
((Exp.Var id, cvar, typ), instr) ((Exp.Var id, cvar, typ, mode), instr)
let closure_trans closure_pname captured_vars context stmt_info expr_info = let closure_trans closure_pname captured_vars context stmt_info expr_info =
@ -2833,11 +2833,15 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
CType_decl.CProcname.from_decl decl ~tenv:context.tenv ~block_return_type:return_type CType_decl.CProcname.from_decl decl ~tenv:context.tenv ~block_return_type:return_type
~outer_proc ~outer_proc
in in
let captured_vars = let captured_vars_no_mode =
CVar_decl.captured_vars_from_block_info context stmt_info.Clang_ast_t.si_source_range CVar_decl.captured_vars_from_block_info context stmt_info.Clang_ast_t.si_source_range
block_decl_info.Clang_ast_t.bdi_captured_variables block_decl_info.Clang_ast_t.bdi_captured_variables
in in
let passed_as_noescape_block_to = trans_state.passed_as_noescape_block_to in let passed_as_noescape_block_to = trans_state.passed_as_noescape_block_to in
(* TODO: set correct capture mode *)
let captured_vars =
List.map captured_vars_no_mode ~f:(fun (var, typ) -> (var, typ, Pvar.ByReference))
in
let res = closure_trans procname captured_vars context stmt_info expr_info in let res = closure_trans procname captured_vars context stmt_info expr_info in
let block_data = let block_data =
Some Some
@ -2870,14 +2874,16 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
CFrontend_errors.incorrect_assumption __POS__ stmt_info.Clang_ast_t.si_source_range CFrontend_errors.incorrect_assumption __POS__ stmt_info.Clang_ast_t.si_source_range
"Capture-init statement without var decl" "Capture-init statement without var decl"
in in
let translate_normal_capture ~is_by_ref ((pvar, typ) as pvar_typ) let translate_normal_capture mode (pvar, typ) (trans_results_acc, captured_vars_acc) =
(trans_results_acc, captured_vars_acc) =
let loc = let loc =
CLocation.location_of_stmt_info context.translation_unit_context.source_file stmt_info CLocation.location_of_stmt_info context.translation_unit_context.source_file stmt_info
in in
if is_by_ref then (trans_results_acc, (Exp.Lvar pvar, pvar, typ) :: captured_vars_acc) match mode with
else | Pvar.ByReference ->
let ((exp, _, typ) as exp_pvar_typ), instr = assign_captured_var loc pvar_typ in (trans_results_acc, (Exp.Lvar pvar, pvar, typ, mode) :: captured_vars_acc)
| Pvar.ByValue ->
let pvar_typ_mode = (pvar, typ, mode) in
let ((exp, _, typ, _) as exp_pvar_typ), instr = assign_captured_var loc pvar_typ_mode in
let trans_results = mk_trans_result (exp, typ) {empty_control with instrs= [instr]} in let trans_results = mk_trans_result (exp, typ) {empty_control with instrs= [instr]} in
(trans_results :: trans_results_acc, exp_pvar_typ :: captured_vars_acc) (trans_results :: trans_results_acc, exp_pvar_typ :: captured_vars_acc)
in in
@ -2899,27 +2905,28 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
| `LCK_StarThis (* [*this] is special syntax for capturing current object by value *) -> | `LCK_StarThis (* [*this] is special syntax for capturing current object by value *) ->
false false
in in
let mode = if is_by_ref then Pvar.ByReference else Pvar.ByValue in
match (lci_captured_var, lci_init_captured_vardecl) with match (lci_captured_var, lci_init_captured_vardecl) with
| Some captured_var_decl_ref, Some init_decl -> ( | Some captured_var_decl_ref, Some init_decl -> (
(* capture and init *) (* capture and init *)
match get_captured_pvar_typ captured_var_decl_ref with match get_captured_pvar_typ captured_var_decl_ref with
| Some pvar_typ -> | Some ((pvar, typ) as pvar_typ) ->
( translate_capture_init pvar_typ init_decl :: trans_results_acc ( translate_capture_init pvar_typ init_decl :: trans_results_acc
, (Exp.Lvar (fst pvar_typ), fst pvar_typ, snd pvar_typ) :: captured_vars_acc ) , (Exp.Lvar pvar, pvar, typ, mode) :: captured_vars_acc )
| None -> | None ->
(trans_results_acc, captured_vars_acc) ) (trans_results_acc, captured_vars_acc) )
| Some captured_var_decl_ref, None -> ( | Some captured_var_decl_ref, None -> (
(* just capture *) (* just capture *)
match get_captured_pvar_typ captured_var_decl_ref with match get_captured_pvar_typ captured_var_decl_ref with
| Some pvar_typ -> | Some pvar_typ ->
translate_normal_capture ~is_by_ref pvar_typ acc translate_normal_capture mode pvar_typ acc
| None -> | None ->
(trans_results_acc, captured_vars_acc) ) (trans_results_acc, captured_vars_acc) )
| None, None -> | None, None ->
if lci_capture_this then if lci_capture_this then
(* captured [this] *) (* captured [this] *)
let this_typ = get_this_pvar_typ stmt_info context in let this_typ = get_this_pvar_typ stmt_info context in
translate_normal_capture ~is_by_ref this_typ acc translate_normal_capture mode this_typ acc
else acc else acc
| None, Some _ -> | None, Some _ ->
CFrontend_errors.incorrect_assumption __POS__ stmt_info.Clang_ast_t.si_source_range CFrontend_errors.incorrect_assumption __POS__ stmt_info.Clang_ast_t.si_source_range

@ -101,6 +101,7 @@ let sil_var_of_captured_var context source_range procname decl_ref =
in in
match (var_opt, typ_opt) with match (var_opt, typ_opt) with
| Some var, Some typ -> | Some var, Some typ ->
(* TODO: set correct capture mode *)
Some (var, typ) Some (var, typ)
| None, None -> | None, None ->
None None

@ -72,9 +72,9 @@ module Closures = struct
List.rev_filter_map captured List.rev_filter_map captured
~f:(fun (captured_as, (address_captured, trace_captured), mode) -> ~f:(fun (captured_as, (address_captured, trace_captured), mode) ->
match mode with match mode with
| `ByValue -> | Pvar.ByValue ->
None None
| `ByReference -> | Pvar.ByReference ->
let new_trace = ValueHistory.Capture {captured_as; location} :: trace_captured in let new_trace = ValueHistory.Capture {captured_as; location} :: trace_captured in
Some (address_captured, new_trace) ) Some (address_captured, new_trace) )
in in
@ -114,12 +114,8 @@ let eval location exp0 astate =
| Closure {name; captured_vars} -> | Closure {name; captured_vars} ->
let+ astate, rev_captured = let+ astate, rev_captured =
List.fold_result captured_vars ~init:(astate, []) List.fold_result captured_vars ~init:(astate, [])
~f:(fun (astate, rev_captured) (capt_exp, captured_as, _) -> ~f:(fun (astate, rev_captured) (capt_exp, captured_as, _, mode) ->
let+ astate, addr_trace = eval capt_exp astate in let+ astate, addr_trace = eval capt_exp astate in
let mode =
(* HACK: the frontend follows this discipline *)
match (capt_exp : Exp.t) with Lvar _ -> `ByReference | _ -> `ByValue
in
(astate, (captured_as, addr_trace, mode) :: rev_captured) ) (astate, (captured_as, addr_trace, mode) :: rev_captured) )
in in
Closures.record location name (List.rev rev_captured) astate Closures.record location name (List.rev rev_captured) astate

@ -16,7 +16,9 @@ let tests =
let int_ptr_typ = Typ.mk (Tptr (int_typ, Pk_pointer)) in let int_ptr_typ = Typ.mk (Tptr (int_typ, Pk_pointer)) in
let fun_ptr_typ = Typ.mk (Tptr (Typ.mk Tfun, Pk_pointer)) in let fun_ptr_typ = Typ.mk (Tptr (Typ.mk Tfun, Pk_pointer)) in
let closure_exp captureds = let closure_exp captureds =
let mk_captured_var str = (Exp.Var (ident_of_str str), pvar_of_str str, int_ptr_typ) in let mk_captured_var str =
(Exp.Var (ident_of_str str), pvar_of_str str, int_ptr_typ, Pvar.ByReference)
in
let captured_vars = List.map ~f:mk_captured_var captureds in let captured_vars = List.map ~f:mk_captured_var captureds in
let closure = {Exp.name= dummy_procname; captured_vars} in let closure = {Exp.name= dummy_procname; captured_vars} in
Exp.Closure closure Exp.Closure closure

@ -15,7 +15,9 @@ let tests =
let assert_empty = invariant "{ }" in let assert_empty = invariant "{ }" in
let fun_ptr_typ = Typ.mk (Tptr (Typ.mk Tfun, Pk_pointer)) in let fun_ptr_typ = Typ.mk (Tptr (Typ.mk Tfun, Pk_pointer)) in
let closure_exp captured_pvars = let closure_exp captured_pvars =
let mk_captured_var str = (Exp.Var (ident_of_str str), pvar_of_str str, dummy_typ) in let mk_captured_var str =
(Exp.Var (ident_of_str str), pvar_of_str str, dummy_typ, Pvar.ByReference)
in
let captured_vars = List.map ~f:mk_captured_var captured_pvars in let captured_vars = List.map ~f:mk_captured_var captured_pvars in
let closure = {Exp.name= dummy_procname; captured_vars} in let closure = {Exp.name= dummy_procname; captured_vars} in
Exp.Closure closure Exp.Closure closure

@ -121,7 +121,7 @@ digraph cfg {
"normal_capture#5533029764254319855.11493b249dddd657790695e287170b84_2" [label="2: Exit normal_capture \n " color=yellow style=filled] "normal_capture#5533029764254319855.11493b249dddd657790695e287170b84_2" [label="2: Exit normal_capture \n " color=yellow style=filled]
"normal_capture#5533029764254319855.11493b249dddd657790695e287170b84_3" [label="3: Return Stmt \n VARIABLE_DECLARED(0$?%__sil_tmpSIL_materialize_temp__n$0:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10); [line 31, column 10]\n n$6=*&x:int [line 31, column 10]\n n$5=*&y:int [line 31, column 10]\n *&0$?%__sil_tmpSIL_materialize_temp__n$0:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10=(_fun_normal_capture::lambda_shared_lambda_lambda1.cpp:31:10::operator(),(n$6 &x:int),(n$5 &y:int)) [line 31, column 10]\n n$7=_fun_normal_capture::lambda_shared_lambda_lambda1.cpp:31:10::operator()(&0$?%__sil_tmpSIL_materialize_temp__n$0:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10&) [line 31, column 10]\n _=*&0$?%__sil_tmpSIL_materialize_temp__n$0:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10 [line 31, column 37]\n n$2=_fun_normal_capture::lambda_shared_lambda_lambda1.cpp:31:10::~(&0$?%__sil_tmpSIL_materialize_temp__n$0:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10*) injected [line 31, column 37]\n *&return:int=n$7 [line 31, column 3]\n " shape="box"] "normal_capture#5533029764254319855.11493b249dddd657790695e287170b84_3" [label="3: Return Stmt \n VARIABLE_DECLARED(0$?%__sil_tmpSIL_materialize_temp__n$0:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10); [line 31, column 10]\n n$6=*&x:int [line 31, column 10]\n n$5=*&y:int [line 31, column 10]\n *&0$?%__sil_tmpSIL_materialize_temp__n$0:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10=(_fun_normal_capture::lambda_shared_lambda_lambda1.cpp:31:10::operator(),([by value]n$6 &x:int),([by value]n$5 &y:int)) [line 31, column 10]\n n$7=_fun_normal_capture::lambda_shared_lambda_lambda1.cpp:31:10::operator()(&0$?%__sil_tmpSIL_materialize_temp__n$0:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10&) [line 31, column 10]\n _=*&0$?%__sil_tmpSIL_materialize_temp__n$0:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10 [line 31, column 37]\n n$2=_fun_normal_capture::lambda_shared_lambda_lambda1.cpp:31:10::~(&0$?%__sil_tmpSIL_materialize_temp__n$0:normal_capture::lambda_shared_lambda_lambda1.cpp:31:10*) injected [line 31, column 37]\n *&return:int=n$7 [line 31, column 3]\n " shape="box"]
"normal_capture#5533029764254319855.11493b249dddd657790695e287170b84_3" -> "normal_capture#5533029764254319855.11493b249dddd657790695e287170b84_2" ; "normal_capture#5533029764254319855.11493b249dddd657790695e287170b84_3" -> "normal_capture#5533029764254319855.11493b249dddd657790695e287170b84_2" ;
@ -144,7 +144,7 @@ digraph cfg {
"struct_capture#7773507847510274281.f3db763dc0b20b24ec397f7802254c90_3" -> "struct_capture#7773507847510274281.f3db763dc0b20b24ec397f7802254c90_2" ; "struct_capture#7773507847510274281.f3db763dc0b20b24ec397f7802254c90_3" -> "struct_capture#7773507847510274281.f3db763dc0b20b24ec397f7802254c90_2" ;
"struct_capture#7773507847510274281.f3db763dc0b20b24ec397f7802254c90_4" [label="4: DeclStmt \n VARIABLE_DECLARED(f:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12); [line 77, column 3]\n VARIABLE_DECLARED(0$?%__sil_tmpSIL_materialize_temp__n$9:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12); [line 77, column 12]\n n$14=*&x:SomeStruct [line 77, column 12]\n n$13=*&y:SomeStruct [line 77, column 12]\n *&0$?%__sil_tmpSIL_materialize_temp__n$9:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12=(_fun_struct_capture::lambda_shared_lambda_lambda1.cpp:77:12::operator(),(n$14 &x:SomeStruct),(n$13 &y:SomeStruct)) [line 77, column 12]\n n$15=_fun_struct_capture::lambda_shared_lambda_lambda1.cpp:77:12::(&f:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12*,&0$?%__sil_tmpSIL_materialize_temp__n$9:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12&) [line 77, column 12]\n _=*&0$?%__sil_tmpSIL_materialize_temp__n$9:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12 [line 77, column 41]\n n$11=_fun_struct_capture::lambda_shared_lambda_lambda1.cpp:77:12::~(&0$?%__sil_tmpSIL_materialize_temp__n$9:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12*) injected [line 77, column 41]\n " shape="box"] "struct_capture#7773507847510274281.f3db763dc0b20b24ec397f7802254c90_4" [label="4: DeclStmt \n VARIABLE_DECLARED(f:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12); [line 77, column 3]\n VARIABLE_DECLARED(0$?%__sil_tmpSIL_materialize_temp__n$9:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12); [line 77, column 12]\n n$14=*&x:SomeStruct [line 77, column 12]\n n$13=*&y:SomeStruct [line 77, column 12]\n *&0$?%__sil_tmpSIL_materialize_temp__n$9:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12=(_fun_struct_capture::lambda_shared_lambda_lambda1.cpp:77:12::operator(),([by value]n$14 &x:SomeStruct),([by value]n$13 &y:SomeStruct)) [line 77, column 12]\n n$15=_fun_struct_capture::lambda_shared_lambda_lambda1.cpp:77:12::(&f:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12*,&0$?%__sil_tmpSIL_materialize_temp__n$9:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12&) [line 77, column 12]\n _=*&0$?%__sil_tmpSIL_materialize_temp__n$9:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12 [line 77, column 41]\n n$11=_fun_struct_capture::lambda_shared_lambda_lambda1.cpp:77:12::~(&0$?%__sil_tmpSIL_materialize_temp__n$9:struct_capture::lambda_shared_lambda_lambda1.cpp:77:12*) injected [line 77, column 41]\n " shape="box"]
"struct_capture#7773507847510274281.f3db763dc0b20b24ec397f7802254c90_4" -> "struct_capture#7773507847510274281.f3db763dc0b20b24ec397f7802254c90_3" ; "struct_capture#7773507847510274281.f3db763dc0b20b24ec397f7802254c90_4" -> "struct_capture#7773507847510274281.f3db763dc0b20b24ec397f7802254c90_3" ;
@ -197,7 +197,7 @@ digraph cfg {
"capture_star_this#Capture#(2506493005619132138).63fd6aa2a7efbd48dc1a62c0c2bd2161_3" -> "capture_star_this#Capture#(2506493005619132138).63fd6aa2a7efbd48dc1a62c0c2bd2161_2" ; "capture_star_this#Capture#(2506493005619132138).63fd6aa2a7efbd48dc1a62c0c2bd2161_3" -> "capture_star_this#Capture#(2506493005619132138).63fd6aa2a7efbd48dc1a62c0c2bd2161_2" ;
"capture_star_this#Capture#(2506493005619132138).63fd6aa2a7efbd48dc1a62c0c2bd2161_4" [label="4: DeclStmt \n VARIABLE_DECLARED(lambda:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19); [line 55, column 5]\n VARIABLE_DECLARED(0$?%__sil_tmpSIL_materialize_temp__n$3:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19); [line 55, column 19]\n n$7=*&this:Capture* [line 55, column 19]\n *&0$?%__sil_tmpSIL_materialize_temp__n$3:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19=(_fun_Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19::operator(),(n$7 &this:Capture*)) [line 55, column 19]\n n$8=_fun_Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19::(&lambda:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19*,&0$?%__sil_tmpSIL_materialize_temp__n$3:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19&) [line 55, column 19]\n _=*&0$?%__sil_tmpSIL_materialize_temp__n$3:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19 [line 57, column 5]\n n$5=_fun_Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19::~(&0$?%__sil_tmpSIL_materialize_temp__n$3:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19*) injected [line 57, column 5]\n " shape="box"] "capture_star_this#Capture#(2506493005619132138).63fd6aa2a7efbd48dc1a62c0c2bd2161_4" [label="4: DeclStmt \n VARIABLE_DECLARED(lambda:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19); [line 55, column 5]\n VARIABLE_DECLARED(0$?%__sil_tmpSIL_materialize_temp__n$3:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19); [line 55, column 19]\n n$7=*&this:Capture* [line 55, column 19]\n *&0$?%__sil_tmpSIL_materialize_temp__n$3:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19=(_fun_Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19::operator(),([by value]n$7 &this:Capture*)) [line 55, column 19]\n n$8=_fun_Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19::(&lambda:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19*,&0$?%__sil_tmpSIL_materialize_temp__n$3:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19&) [line 55, column 19]\n _=*&0$?%__sil_tmpSIL_materialize_temp__n$3:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19 [line 57, column 5]\n n$5=_fun_Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19::~(&0$?%__sil_tmpSIL_materialize_temp__n$3:Capture::capture_star_this::lambda_shared_lambda_lambda1.cpp:55:19*) injected [line 57, column 5]\n " shape="box"]
"capture_star_this#Capture#(2506493005619132138).63fd6aa2a7efbd48dc1a62c0c2bd2161_4" -> "capture_star_this#Capture#(2506493005619132138).63fd6aa2a7efbd48dc1a62c0c2bd2161_3" ; "capture_star_this#Capture#(2506493005619132138).63fd6aa2a7efbd48dc1a62c0c2bd2161_4" -> "capture_star_this#Capture#(2506493005619132138).63fd6aa2a7efbd48dc1a62c0c2bd2161_3" ;

@ -34,7 +34,7 @@ digraph cfg {
"main.fad58de7366495db4650cfefac2fcd61_5" -> "main.fad58de7366495db4650cfefac2fcd61_4" ; "main.fad58de7366495db4650cfefac2fcd61_5" -> "main.fad58de7366495db4650cfefac2fcd61_4" ;
"objc_blockA.capture_1(class A,class D).8e9a52049a11f3e729d697583cda7110_1" [label="1: Start objc_blockA.capture_1\nFormals: self:A* d:D*\nLocals: \nCaptured: self:A* \n " color=yellow style=filled] "objc_blockA.capture_1(class A,class D).8e9a52049a11f3e729d697583cda7110_1" [label="1: Start objc_blockA.capture_1\nFormals: self:A* d:D*\nLocals: \nCaptured: [by ref]self:A* \n " color=yellow style=filled]
"objc_blockA.capture_1(class A,class D).8e9a52049a11f3e729d697583cda7110_1" -> "objc_blockA.capture_1(class A,class D).8e9a52049a11f3e729d697583cda7110_3" ; "objc_blockA.capture_1(class A,class D).8e9a52049a11f3e729d697583cda7110_1" -> "objc_blockA.capture_1(class A,class D).8e9a52049a11f3e729d697583cda7110_3" ;
@ -52,7 +52,7 @@ digraph cfg {
"capture#A#instance.d411336575e4bf632a1828f5f5979726_2" [label="2: Exit A.capture \n " color=yellow style=filled] "capture#A#instance.d411336575e4bf632a1828f5f5979726_2" [label="2: Exit A.capture \n " color=yellow style=filled]
"capture#A#instance.d411336575e4bf632a1828f5f5979726_3" [label="3: Message Call: sHandler: \n n$3=*&self:A* [line 45, column 4]\n n$4=*n$3._b:B* [line 45, column 4]\n n$0=*&self:A* [line 45, column 16]\n n$5=_fun_B.sHandler:(n$4:B*,(_fun_objc_blockA.capture_1,(n$0 &self:A*)):_fn_(*)) block_params virtual [line 45, column 3]\n " shape="box"] "capture#A#instance.d411336575e4bf632a1828f5f5979726_3" [label="3: Message Call: sHandler: \n n$3=*&self:A* [line 45, column 4]\n n$4=*n$3._b:B* [line 45, column 4]\n n$0=*&self:A* [line 45, column 16]\n n$5=_fun_B.sHandler:(n$4:B*,(_fun_objc_blockA.capture_1,([by ref]n$0 &self:A*)):_fn_(*)) block_params virtual [line 45, column 3]\n " shape="box"]
"capture#A#instance.d411336575e4bf632a1828f5f5979726_3" -> "capture#A#instance.d411336575e4bf632a1828f5f5979726_2" ; "capture#A#instance.d411336575e4bf632a1828f5f5979726_3" -> "capture#A#instance.d411336575e4bf632a1828f5f5979726_2" ;

@ -6,7 +6,7 @@ codetoanalyze/objc/pulse/MemoryLeaks.m, MemoryLeaks.cg_path_create_with_rect_lea
codetoanalyze/objc/pulse/MemoryLeaks.m, MemoryLeaks.no_bridge_leak_bad, 1, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `CFLocaleCreate` (modelled),allocation part of the trace ends here,memory becomes unreachable here] codetoanalyze/objc/pulse/MemoryLeaks.m, MemoryLeaks.no_bridge_leak_bad, 1, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `CFLocaleCreate` (modelled),allocation part of the trace ends here,memory becomes unreachable here]
codetoanalyze/objc/pulse/MemoryLeaks.m, call_bridge_interproc_leak_ok_FP, 2, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `CFLocaleCreate` (modelled),allocation part of the trace ends here,memory becomes unreachable here] codetoanalyze/objc/pulse/MemoryLeaks.m, call_bridge_interproc_leak_ok_FP, 2, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `CFLocaleCreate` (modelled),allocation part of the trace ends here,memory becomes unreachable here]
codetoanalyze/objc/pulse/MemoryLeaks.m, call_cfrelease_interproc_leak_ok_FP, 2, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `CFLocaleCreate` (modelled),allocation part of the trace ends here,memory becomes unreachable here] codetoanalyze/objc/pulse/MemoryLeaks.m, call_cfrelease_interproc_leak_ok_FP, 2, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `CFLocaleCreate` (modelled),allocation part of the trace ends here,memory becomes unreachable here]
codetoanalyze/objc/pulse/MemoryLeaksInBlocks.m, block_captured_var_leak_bad, 3, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `malloc_no_fail` (modelled),allocation part of the trace ends here,memory becomes unreachable here] codetoanalyze/objc/pulse/MemoryLeaksInBlocks.m, block_captured_var_leak_bad, 6, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `malloc_no_fail` (modelled),allocation part of the trace ends here,memory becomes unreachable here]
codetoanalyze/objc/pulse/MemoryLeaksInBlocks.m, block_free_ok_FP, 3, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `malloc_no_fail` (modelled),allocation part of the trace ends here,memory becomes unreachable here] codetoanalyze/objc/pulse/MemoryLeaksInBlocks.m, block_free_ok_FP, 8, MEMORY_LEAK, no_bucket, ERROR, [allocation part of the trace starts here,allocated by call to `malloc_no_fail` (modelled),allocation part of the trace ends here,memory becomes unreachable here]
codetoanalyze/objc/pulse/use_after_free.m, PulseTest.use_after_free_simple_in_objc_method_bad:, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `x` of PulseTest.use_after_free_simple_in_objc_method_bad:,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,parameter `x` of PulseTest.use_after_free_simple_in_objc_method_bad:,invalid access occurs here] codetoanalyze/objc/pulse/use_after_free.m, PulseTest.use_after_free_simple_in_objc_method_bad:, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `x` of PulseTest.use_after_free_simple_in_objc_method_bad:,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,parameter `x` of PulseTest.use_after_free_simple_in_objc_method_bad:,invalid access occurs here]
codetoanalyze/objc/pulse/use_after_free.m, use_after_free_simple_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `x` of use_after_free_simple_bad,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,parameter `x` of use_after_free_simple_bad,invalid access occurs here] codetoanalyze/objc/pulse/use_after_free.m, use_after_free_simple_bad, 2, USE_AFTER_FREE, no_bucket, ERROR, [invalidation part of the trace starts here,parameter `x` of use_after_free_simple_bad,was invalidated by call to `free()`,use-after-lifetime part of the trace starts here,parameter `x` of use_after_free_simple_bad,invalid access occurs here]

@ -1,6 +1,6 @@
/* @generated */ /* @generated */
digraph cfg { digraph cfg {
"objc_blockBlockVar.blockPostBad_2.9b5fc6c216acf1eebade4e80598bd292_1" [label="1: Start objc_blockBlockVar.blockPostBad_2\nFormals: x:int*\nLocals: \nCaptured: x:int* \n " color=yellow style=filled] "objc_blockBlockVar.blockPostBad_2.9b5fc6c216acf1eebade4e80598bd292_1" [label="1: Start objc_blockBlockVar.blockPostBad_2\nFormals: x:int*\nLocals: \nCaptured: [by ref]x:int* \n " color=yellow style=filled]
"objc_blockBlockVar.blockPostBad_2.9b5fc6c216acf1eebade4e80598bd292_1" -> "objc_blockBlockVar.blockPostBad_2.9b5fc6c216acf1eebade4e80598bd292_3" ; "objc_blockBlockVar.blockPostBad_2.9b5fc6c216acf1eebade4e80598bd292_1" -> "objc_blockBlockVar.blockPostBad_2.9b5fc6c216acf1eebade4e80598bd292_3" ;
@ -11,7 +11,7 @@ digraph cfg {
"objc_blockBlockVar.blockPostBad_2.9b5fc6c216acf1eebade4e80598bd292_3" -> "objc_blockBlockVar.blockPostBad_2.9b5fc6c216acf1eebade4e80598bd292_2" ; "objc_blockBlockVar.blockPostBad_2.9b5fc6c216acf1eebade4e80598bd292_3" -> "objc_blockBlockVar.blockPostBad_2.9b5fc6c216acf1eebade4e80598bd292_2" ;
"objc_blockBlockVar.blockPostOk_3.860b502fd4305d26ee26104b0e266b62_1" [label="1: Start objc_blockBlockVar.blockPostOk_3\nFormals: x:int*\nLocals: \nCaptured: x:int* \n " color=yellow style=filled] "objc_blockBlockVar.blockPostOk_3.860b502fd4305d26ee26104b0e266b62_1" [label="1: Start objc_blockBlockVar.blockPostOk_3\nFormals: x:int*\nLocals: \nCaptured: [by ref]x:int* \n " color=yellow style=filled]
"objc_blockBlockVar.blockPostOk_3.860b502fd4305d26ee26104b0e266b62_1" -> "objc_blockBlockVar.blockPostOk_3.860b502fd4305d26ee26104b0e266b62_3" ; "objc_blockBlockVar.blockPostOk_3.860b502fd4305d26ee26104b0e266b62_1" -> "objc_blockBlockVar.blockPostOk_3.860b502fd4305d26ee26104b0e266b62_3" ;
@ -22,7 +22,7 @@ digraph cfg {
"objc_blockBlockVar.blockPostOk_3.860b502fd4305d26ee26104b0e266b62_3" -> "objc_blockBlockVar.blockPostOk_3.860b502fd4305d26ee26104b0e266b62_2" ; "objc_blockBlockVar.blockPostOk_3.860b502fd4305d26ee26104b0e266b62_3" -> "objc_blockBlockVar.blockPostOk_3.860b502fd4305d26ee26104b0e266b62_2" ;
"objc_blockBlockVar.capturedNoNullDeref_5.05728b28cff98ce99554f69b47154636_1" [label="1: Start objc_blockBlockVar.capturedNoNullDeref_5\nFormals: x:int*\nLocals: \nCaptured: x:int* \n " color=yellow style=filled] "objc_blockBlockVar.capturedNoNullDeref_5.05728b28cff98ce99554f69b47154636_1" [label="1: Start objc_blockBlockVar.capturedNoNullDeref_5\nFormals: x:int*\nLocals: \nCaptured: [by ref]x:int* \n " color=yellow style=filled]
"objc_blockBlockVar.capturedNoNullDeref_5.05728b28cff98ce99554f69b47154636_1" -> "objc_blockBlockVar.capturedNoNullDeref_5.05728b28cff98ce99554f69b47154636_3" ; "objc_blockBlockVar.capturedNoNullDeref_5.05728b28cff98ce99554f69b47154636_1" -> "objc_blockBlockVar.capturedNoNullDeref_5.05728b28cff98ce99554f69b47154636_3" ;
@ -33,7 +33,7 @@ digraph cfg {
"objc_blockBlockVar.capturedNoNullDeref_5.05728b28cff98ce99554f69b47154636_3" -> "objc_blockBlockVar.capturedNoNullDeref_5.05728b28cff98ce99554f69b47154636_2" ; "objc_blockBlockVar.capturedNoNullDeref_5.05728b28cff98ce99554f69b47154636_3" -> "objc_blockBlockVar.capturedNoNullDeref_5.05728b28cff98ce99554f69b47154636_2" ;
"objc_blockBlockVar.capturedNullDeref_4.b2398d8a441f4c0e3ff276c92e1e2c2b_1" [label="1: Start objc_blockBlockVar.capturedNullDeref_4\nFormals: x:int*\nLocals: \nCaptured: x:int* \n " color=yellow style=filled] "objc_blockBlockVar.capturedNullDeref_4.b2398d8a441f4c0e3ff276c92e1e2c2b_1" [label="1: Start objc_blockBlockVar.capturedNullDeref_4\nFormals: x:int*\nLocals: \nCaptured: [by ref]x:int* \n " color=yellow style=filled]
"objc_blockBlockVar.capturedNullDeref_4.b2398d8a441f4c0e3ff276c92e1e2c2b_1" -> "objc_blockBlockVar.capturedNullDeref_4.b2398d8a441f4c0e3ff276c92e1e2c2b_3" ; "objc_blockBlockVar.capturedNullDeref_4.b2398d8a441f4c0e3ff276c92e1e2c2b_1" -> "objc_blockBlockVar.capturedNullDeref_4.b2398d8a441f4c0e3ff276c92e1e2c2b_3" ;
@ -129,7 +129,7 @@ digraph cfg {
"blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_3" -> "blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_2" ; "blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_3" -> "blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_2" ;
"blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_4" [label="4: DeclStmt \n VARIABLE_DECLARED(my_block:_fn_(*)); [line 31, column 3]\n n$14=*&x:int* [line 31, column 28]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar.blockPostBad_2,(n$14 &x:int*)) [line 31, column 3]\n " shape="box"] "blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_4" [label="4: DeclStmt \n VARIABLE_DECLARED(my_block:_fn_(*)); [line 31, column 3]\n n$14=*&x:int* [line 31, column 28]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar.blockPostBad_2,([by ref]n$14 &x:int*)) [line 31, column 3]\n " shape="box"]
"blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_4" -> "blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_3" ; "blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_4" -> "blockPostBad#BlockVar#instance.60292f870cad8c1a5cefdbfe4194d6f9_3" ;
@ -148,7 +148,7 @@ digraph cfg {
"blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_3" -> "blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_2" ; "blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_3" -> "blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_2" ;
"blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_4" [label="4: DeclStmt \n VARIABLE_DECLARED(my_block:_fn_(*)); [line 40, column 3]\n n$19=*&x:int* [line 40, column 28]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar.blockPostOk_3,(n$19 &x:int*)) [line 40, column 3]\n " shape="box"] "blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_4" [label="4: DeclStmt \n VARIABLE_DECLARED(my_block:_fn_(*)); [line 40, column 3]\n n$19=*&x:int* [line 40, column 28]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar.blockPostOk_3,([by ref]n$19 &x:int*)) [line 40, column 3]\n " shape="box"]
"blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_4" -> "blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_3" ; "blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_4" -> "blockPostOk#BlockVar#instance.1bb64a946f8b169b31996644931ed82d_3" ;
@ -175,7 +175,7 @@ digraph cfg {
"capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_4" -> "capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_3" ; "capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_4" -> "capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_3" ;
"capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_5" [label="5: DeclStmt \n VARIABLE_DECLARED(my_block:_fn_(*)); [line 57, column 3]\n n$28=*&x:int* [line 57, column 27]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar.capturedNoNullDeref_5,(n$28 &x:int*)) [line 57, column 3]\n " shape="box"] "capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_5" [label="5: DeclStmt \n VARIABLE_DECLARED(my_block:_fn_(*)); [line 57, column 3]\n n$28=*&x:int* [line 57, column 27]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar.capturedNoNullDeref_5,([by ref]n$28 &x:int*)) [line 57, column 3]\n " shape="box"]
"capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_5" -> "capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_4" ; "capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_5" -> "capturedNoNullDeref#BlockVar#instance.ebe646baaabdc58144a5916780ee8c76_4" ;
@ -198,7 +198,7 @@ digraph cfg {
"capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_3" -> "capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_2" ; "capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_3" -> "capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_2" ;
"capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_4" [label="4: DeclStmt \n VARIABLE_DECLARED(my_block:_fn_(*)); [line 48, column 3]\n n$23=*&x:int* [line 48, column 27]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar.capturedNullDeref_4,(n$23 &x:int*)) [line 48, column 3]\n " shape="box"] "capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_4" [label="4: DeclStmt \n VARIABLE_DECLARED(my_block:_fn_(*)); [line 48, column 3]\n n$23=*&x:int* [line 48, column 27]\n *&my_block:_fn_(*)=(_fun_objc_blockBlockVar.capturedNullDeref_4,([by ref]n$23 &x:int*)) [line 48, column 3]\n " shape="box"]
"capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_4" -> "capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_3" ; "capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_4" -> "capturedNullDeref#BlockVar#instance.48c44f7ae26caf7a1ac522523ebac894_3" ;

@ -1,6 +1,6 @@
/* @generated */ /* @generated */
digraph cfg { digraph cfg {
"objc_blockB.f_1(class B).c1c611f4be5cea3fe56d67e34da1fffd_1" [label="1: Start objc_blockB.f_1\nFormals: self:B* const \nLocals: \nCaptured: self:B* const \n " color=yellow style=filled] "objc_blockB.f_1(class B).c1c611f4be5cea3fe56d67e34da1fffd_1" [label="1: Start objc_blockB.f_1\nFormals: self:B* const \nLocals: \nCaptured: [by ref]self:B* const \n " color=yellow style=filled]
"objc_blockB.f_1(class B).c1c611f4be5cea3fe56d67e34da1fffd_1" -> "objc_blockB.f_1(class B).c1c611f4be5cea3fe56d67e34da1fffd_3" ; "objc_blockB.f_1(class B).c1c611f4be5cea3fe56d67e34da1fffd_1" -> "objc_blockB.f_1(class B).c1c611f4be5cea3fe56d67e34da1fffd_3" ;
@ -33,7 +33,7 @@ digraph cfg {
"f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_3" -> "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_2" ; "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_3" -> "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_2" ;
"f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_4" [label="4: Message Call: foo:and: \n n$4=*&self:B* [line 23, column 10]\n n$5=*n$4.h:int [line 23, column 10]\n n$2=*&self:B* const [line 24, column 11]\n n$6=_fun_B.foo:and:(n$5:int,(_fun_objc_blockB.f_1,(n$2 &self:B* const )):_fn_(*)) block_params [line 23, column 3]\n " shape="box"] "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_4" [label="4: Message Call: foo:and: \n n$4=*&self:B* [line 23, column 10]\n n$5=*n$4.h:int [line 23, column 10]\n n$2=*&self:B* const [line 24, column 11]\n n$6=_fun_B.foo:and:(n$5:int,(_fun_objc_blockB.f_1,([by ref]n$2 &self:B* const )):_fn_(*)) block_params [line 23, column 3]\n " shape="box"]
"f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_4" -> "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_3" ; "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_4" -> "f#B#instance.f1371ff5e7f410d3df6a2e71ff0a814e_3" ;

@ -38,7 +38,7 @@ digraph cfg {
"main1.38f534a9576db7ec6ebcbca8c111f942_7" -> "main1.38f534a9576db7ec6ebcbca8c111f942_6" ; "main1.38f534a9576db7ec6ebcbca8c111f942_7" -> "main1.38f534a9576db7ec6ebcbca8c111f942_6" ;
"main1.38f534a9576db7ec6ebcbca8c111f942_8" [label="8: BinaryOperatorStmt: Assign \n n$9=*&x:int [line 16, column 14]\n *&addblock:_fn_(*)=(_fun_objc_blockmain1_2,(n$9 &x:int)) [line 16, column 3]\n " shape="box"] "main1.38f534a9576db7ec6ebcbca8c111f942_8" [label="8: BinaryOperatorStmt: Assign \n n$9=*&x:int [line 16, column 14]\n *&addblock:_fn_(*)=(_fun_objc_blockmain1_2,([by ref]n$9 &x:int)) [line 16, column 3]\n " shape="box"]
"main1.38f534a9576db7ec6ebcbca8c111f942_8" -> "main1.38f534a9576db7ec6ebcbca8c111f942_7" ; "main1.38f534a9576db7ec6ebcbca8c111f942_8" -> "main1.38f534a9576db7ec6ebcbca8c111f942_7" ;
@ -61,7 +61,7 @@ digraph cfg {
"objc_blockmain1_1.74199543de3b6a9a736f23ef5e45586a_3" -> "objc_blockmain1_1.74199543de3b6a9a736f23ef5e45586a_2" ; "objc_blockmain1_1.74199543de3b6a9a736f23ef5e45586a_3" -> "objc_blockmain1_1.74199543de3b6a9a736f23ef5e45586a_2" ;
"objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_1" [label="1: Start objc_blockmain1_2\nFormals: x:int c:int d:int\nLocals: bla:int add2:int addblock2:_fn_(*)\nCaptured: x:int \n " color=yellow style=filled] "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_1" [label="1: Start objc_blockmain1_2\nFormals: x:int c:int d:int\nLocals: bla:int add2:int addblock2:_fn_(*)\nCaptured: [by ref]x:int \n " color=yellow style=filled]
"objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_1" -> "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_6" ; "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_1" -> "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_6" ;
@ -76,7 +76,7 @@ digraph cfg {
"objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_4" -> "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_3" ; "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_4" -> "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_3" ;
"objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_5" [label="5: BinaryOperatorStmt: Assign \n n$15=*&x:int [line 21, column 17]\n n$16=*&bla:int [line 21, column 17]\n *&addblock2:_fn_(*)=(_fun_objc_blockobjc_blockmain1_2_3,(n$15 &x:int),(n$16 &bla:int)) [line 21, column 5]\n " shape="box"] "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_5" [label="5: BinaryOperatorStmt: Assign \n n$15=*&x:int [line 21, column 17]\n n$16=*&bla:int [line 21, column 17]\n *&addblock2:_fn_(*)=(_fun_objc_blockobjc_blockmain1_2_3,([by ref]n$15 &x:int),([by ref]n$16 &bla:int)) [line 21, column 5]\n " shape="box"]
"objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_5" -> "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_4" ; "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_5" -> "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_4" ;
@ -84,7 +84,7 @@ digraph cfg {
"objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_6" -> "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_5" ; "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_6" -> "objc_blockmain1_2.0d332204bbe33f46a9283d2c0df5700a_5" ;
"objc_blockobjc_blockmain1_2_3.0824f0806cf4ebad2920e9a12535d20e_1" [label="1: Start objc_blockobjc_blockmain1_2_3\nFormals: x:int bla:int z:int\nLocals: \nCaptured: x:int bla:int \n " color=yellow style=filled] "objc_blockobjc_blockmain1_2_3.0824f0806cf4ebad2920e9a12535d20e_1" [label="1: Start objc_blockobjc_blockmain1_2_3\nFormals: x:int bla:int z:int\nLocals: \nCaptured: [by ref]x:int [by ref]bla:int \n " color=yellow style=filled]
"objc_blockobjc_blockmain1_2_3.0824f0806cf4ebad2920e9a12535d20e_1" -> "objc_blockobjc_blockmain1_2_3.0824f0806cf4ebad2920e9a12535d20e_3" ; "objc_blockobjc_blockmain1_2_3.0824f0806cf4ebad2920e9a12535d20e_1" -> "objc_blockobjc_blockmain1_2_3.0824f0806cf4ebad2920e9a12535d20e_3" ;

@ -1,6 +1,6 @@
/* @generated */ /* @generated */
digraph cfg { digraph cfg {
"objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_1" [label="1: Start objc_blockBlock_no_args.m_1\nFormals: z:int\nLocals: \nCaptured: z:int \n " color=yellow style=filled] "objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_1" [label="1: Start objc_blockBlock_no_args.m_1\nFormals: z:int\nLocals: \nCaptured: [by ref]z:int \n " color=yellow style=filled]
"objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_1" -> "objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_3" ; "objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_1" -> "objc_blockBlock_no_args.m_1.4d7585adf186f5ddc971eca39c81e1b8_3" ;
@ -66,7 +66,7 @@ digraph cfg {
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_11" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_10" ; "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_11" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_10" ;
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_12" [label="12: BinaryOperatorStmt: Assign \n n$7=*&z:int [line 23, column 7]\n *&b:_fn_(*)=(_fun_objc_blockBlock_no_args.m_1,(n$7 &z:int)) [line 23, column 3]\n " shape="box"] "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_12" [label="12: BinaryOperatorStmt: Assign \n n$7=*&z:int [line 23, column 7]\n *&b:_fn_(*)=(_fun_objc_blockBlock_no_args.m_1,([by ref]n$7 &z:int)) [line 23, column 3]\n " shape="box"]
"m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_12" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_11" ; "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_12" -> "m#Block_no_args#instance.385f8c4982ef6acc28cdc868a8cd4272_11" ;

@ -1,6 +1,6 @@
/* @generated */ /* @generated */
digraph cfg { digraph cfg {
"objc_blockMy_manager.blockReleaseNoLeak_1(struct CGImage).d2039f8bbb0530575d5ff258d059d268_1" [label="1: Start objc_blockMy_manager.blockReleaseNoLeak_1\nFormals: newImage:CGImage* a:int\nLocals: \nCaptured: newImage:CGImage* \n " color=yellow style=filled] "objc_blockMy_manager.blockReleaseNoLeak_1(struct CGImage).d2039f8bbb0530575d5ff258d059d268_1" [label="1: Start objc_blockMy_manager.blockReleaseNoLeak_1\nFormals: newImage:CGImage* a:int\nLocals: \nCaptured: [by ref]newImage:CGImage* \n " color=yellow style=filled]
"objc_blockMy_manager.blockReleaseNoLeak_1(struct CGImage).d2039f8bbb0530575d5ff258d059d268_1" -> "objc_blockMy_manager.blockReleaseNoLeak_1(struct CGImage).d2039f8bbb0530575d5ff258d059d268_5" ; "objc_blockMy_manager.blockReleaseNoLeak_1(struct CGImage).d2039f8bbb0530575d5ff258d059d268_1" -> "objc_blockMy_manager.blockReleaseNoLeak_1(struct CGImage).d2039f8bbb0530575d5ff258d059d268_5" ;
@ -60,7 +60,7 @@ digraph cfg {
"blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_8" -> "blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_5" ; "blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_8" -> "blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_5" ;
"blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_8" -> "blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_6" ; "blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_8" -> "blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_6" ;
"blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_9" [label="9: BinaryOperatorStmt: Assign \n n$9=*&newImage:CGImage* [line 23, column 7]\n *&b:_fn_(*)=(_fun_objc_blockMy_manager.blockReleaseNoLeak_1,(n$9 &newImage:CGImage*)) [line 23, column 3]\n " shape="box"] "blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_9" [label="9: BinaryOperatorStmt: Assign \n n$9=*&newImage:CGImage* [line 23, column 7]\n *&b:_fn_(*)=(_fun_objc_blockMy_manager.blockReleaseNoLeak_1,([by ref]n$9 &newImage:CGImage*)) [line 23, column 3]\n " shape="box"]
"blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_9" -> "blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_8" ; "blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_9" -> "blockReleaseNoLeak#My_manager#instance.0c48f80f024250b18a529440f1313af6_8" ;

@ -44,7 +44,7 @@ digraph cfg {
"DispatchMain.f6461dbdaeaf9a114cbe40f5f72fbb3f_11" -> "DispatchMain.f6461dbdaeaf9a114cbe40f5f72fbb3f_10" ; "DispatchMain.f6461dbdaeaf9a114cbe40f5f72fbb3f_11" -> "DispatchMain.f6461dbdaeaf9a114cbe40f5f72fbb3f_10" ;
"objc_blockDispatchA.block_attribute_2(class DispatchA).fbb5956dc6c8f95a8f2ae751ac2b44a1_1" [label="1: Start objc_blockDispatchA.block_attribute_2\nFormals: a:DispatchA*\nLocals: \nCaptured: a:DispatchA* \n " color=yellow style=filled] "objc_blockDispatchA.block_attribute_2(class DispatchA).fbb5956dc6c8f95a8f2ae751ac2b44a1_1" [label="1: Start objc_blockDispatchA.block_attribute_2\nFormals: a:DispatchA*\nLocals: \nCaptured: [by ref]a:DispatchA* \n " color=yellow style=filled]
"objc_blockDispatchA.block_attribute_2(class DispatchA).fbb5956dc6c8f95a8f2ae751ac2b44a1_1" -> "objc_blockDispatchA.block_attribute_2(class DispatchA).fbb5956dc6c8f95a8f2ae751ac2b44a1_3" ; "objc_blockDispatchA.block_attribute_2(class DispatchA).fbb5956dc6c8f95a8f2ae751ac2b44a1_1" -> "objc_blockDispatchA.block_attribute_2(class DispatchA).fbb5956dc6c8f95a8f2ae751ac2b44a1_3" ;
@ -110,7 +110,7 @@ digraph cfg {
"block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_3" -> "block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_2" ; "block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_3" -> "block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_2" ;
"block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_4" [label="4: Call _fun__dispatch_once \n n$7=*&a:DispatchA* [line 37, column 24]\n n$9=_fun__dispatch_once(&#GB<codetoanalyze/objc/shared/block/dispatch.m>$DispatchA.block_attribute.once:long*,(_fun_objc_blockDispatchA.block_attribute_2,(n$7 &a:DispatchA*)):_fn_(*)) block_params [line 37, column 3]\n " shape="box"] "block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_4" [label="4: Call _fun__dispatch_once \n n$7=*&a:DispatchA* [line 37, column 24]\n n$9=_fun__dispatch_once(&#GB<codetoanalyze/objc/shared/block/dispatch.m>$DispatchA.block_attribute.once:long*,(_fun_objc_blockDispatchA.block_attribute_2,([by ref]n$7 &a:DispatchA*)):_fn_(*)) block_params [line 37, column 3]\n " shape="box"]
"block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_4" -> "block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_3" ; "block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_4" -> "block_attribute#DispatchA#class.df997e345dbf19ec3438c667c942e14a_3" ;

Loading…
Cancel
Save