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 =
List.iter etl ~f:(fun (id, ty) ->
Format.fprintf fmt " %a:%a" Mangled.pp id (Typ.pp_full Pp.text) ty )
List.iter etl ~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 )
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
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.
@ -184,7 +184,7 @@ let fold_captured ~f exp acc =
fold_captured_ e1 captured_acc |> fold_captured_ e2
| Closure {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
| Const _ | Lvar _ | Var _ | Sizeof _ ->
captured_acc
@ -249,12 +249,14 @@ let rec pp_ pe pp_t f e =
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
| Lvar evar when Pvar.equal var evar ->
(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 =
@ -323,7 +325,7 @@ let rec gen_free_vars =
| Cast (_, e) | Exn e | Lfield (e, _, _) | Sizeof {dynamic_length= Some e} | UnOp (_, e, _) ->
gen_free_vars e
| 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}
->
return ()
@ -347,7 +349,7 @@ let rec gen_program_vars =
| BinOp (_, e1, e2) | Lindex (e1, e2) ->
gen_program_vars e1 >>= fun () -> gen_program_vars e2
| 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)
@ -363,7 +365,7 @@ let rec rename_pvars ~(f : string -> string) : t -> t =
| Exn e ->
Exn (re e)
| 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}
| Cast (t, e) ->
Cast (t, re e)

@ -13,7 +13,7 @@
open! IStd
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.

@ -39,7 +39,8 @@ let pp_var_data fmt {name; typ; modify_in_block} =
type t =
{ 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 *)
; 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 *)
@ -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))
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
({ access
; captured
@ -152,8 +160,8 @@ let pp f
translation_unit ;
if not (PredSymb.equal_access default.access access) then
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
F.fprintf f "; captured= [@[%a@]]@," pp_parameters captured ;
if not ([%compare.equal: (Mangled.t * Typ.t * Pvar.capture_mode) list] default.captured captured)
then F.fprintf f "; captured= [@[%a@]]@," pp_captured captured ;
if not ([%compare.equal: string list] default.exceptions exceptions) then
F.fprintf f "; exceptions= [@[%a@]]@,"
(Pp.semicolon_seq ~print_env:Pp.text_break F.pp_print_string)

@ -21,7 +21,8 @@ type var_data =
type t =
{ 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 *)
; 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 *)

@ -741,6 +741,15 @@ let pp_variable_list fmt 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 =
match accessor with
| 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
(get_locals pdesc) ;
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
( if not (Annot.Method.is_empty method_annotation) then
let pname_string = Procname.to_string pname in
@ -792,9 +801,11 @@ let is_captured_pvar procdesc pvar =
| _ ->
false
in
let pvar_matches_in_captured (name, _, _) = Mangled.equal name pvar_name in
let is_captured_var_objc_block =
(* 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
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 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 *)
val get_exit_node : t -> Node.t

@ -324,3 +324,7 @@ module Set = PrettyPrintable.MakePPSet (struct
let pp = pp Pp.text
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. *)
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 pvar = Pvar.mk var resolved_pname in
( 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} ) )
|> List.unzip3
in
@ -259,7 +259,7 @@ let with_block_args_instrs resolved_pdesc substitutions =
get_block_name_and_load_captured_vars_instrs block_var loc
in
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
Sil.Call
( return_ids
@ -304,7 +304,7 @@ let with_block_args callee_pdesc pname_with_block_args block_args =
| Some (cl : Exp.closure) ->
let formals_from_captured =
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
variables annotated with the name of the caller method *)
(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 ->
let environment =
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) *)
let typ' =
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'
| Closure c ->
let captured_vars =
IList.map_changed ~equal:[%compare.equal: Exp.t * Pvar.t * Typ.t]
~f:(fun ((e, pvar, typ) as captured) ->
IList.map_changed ~equal:[%compare.equal: Exp.t * Pvar.t * Typ.t * Pvar.capture_mode]
~f:(fun ((e, pvar, typ, mode) as captured) ->
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
in
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
| Closure c ->
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
Closure {c with captured_vars}
| Const _ ->
@ -1399,12 +1399,12 @@ module Normalize = struct
match (hpred : Predicates.hpred) with
| Hpointsto (Exp.Lvar var, Eexp (Exp.Var id, _), _) ->
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
| Exp.Var id_captured ->
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 Pvar.equal var var_captured then (Exp.Var id, var_captured, 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, mode)
else 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)
| Closure {name; 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
Closure {name; captured_vars= captured_vars'}
| Const _ ->

@ -1289,7 +1289,7 @@ let check_call_to_objc_block_error tenv pdesc prop fun_exp loc =
| Some (_, Exp.Lvar pvar) ->
(* pvar is the block *)
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
in

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

@ -1108,7 +1108,7 @@ let rec sym_exec
| Exp.Closure c ->
let proc_exp = Exp.Const (Const.Cfun c.name) 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, exp', par, loc, call_flags)

@ -34,7 +34,7 @@ let get_extended_args_for_method_with_block_analysis act_params =
match act_param with
| Exp.Closure cl, _, _ ->
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
append_no_duplicates_vars all_args captured
| _ ->

@ -173,7 +173,7 @@ let check_expr_for_array_access :
| Exp.Cast (_, e) ->
check_sub_expr e cond_set
| 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 )
| Exp.Var _ | Exp.Lvar _ | Exp.Const _ | Exp.Sizeof _ ->
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 e2 location mem
| 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 )
| Exp.Var _ | Exp.Const _ | Exp.Lvar _ | Exp.Sizeof {dynamic_length= None} ->
cond_set

@ -151,7 +151,7 @@ module TransferFunctions = struct
let pvar_name = Pvar.get_name pvar in
Pvar.is_self pvar
&& 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
@ -159,7 +159,7 @@ module TransferFunctions = struct
let is_captured_strong_self attributes pvar =
(not (Pvar.is_self pvar))
&& List.exists
~f:(fun (captured, typ) ->
~f:(fun (captured, typ, _) ->
Typ.is_strong_pointer typ
&& Mangled.equal captured (Pvar.get_name pvar)
&& 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 =
List.exists
~f:(fun (captured, typ) ->
~f:(fun (captured, typ, _) ->
Mangled.equal captured (Pvar.get_name pvar)
&& String.is_substring ~substring:"self" (String.lowercase (Mangled.to_string captured))
&& 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
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_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
in
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 =
List.map ~f:(fun ({name; typ} : CMethodSignature.param_type) -> (name, typ)) all_params
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 *)
let formals = captured_mangled @ formals in
let const_formals = get_const_params_indices ~shift:(List.length captured_mangled) all_params in
let captured_as_formals = List.map ~f:(fun (var, t, _) -> (var, t)) captured_mangled 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
L.(debug Capture Verbose)
"@\nCreating a new procdesc for function: '%a'@\n@." Procname.pp proc_name ;

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

@ -8,7 +8,7 @@
open! IStd
type block_data =
{ captured_vars: (Pvar.t * Typ.t) list
{ captured_vars: (Pvar.t * Typ.t * Pvar.capture_mode) list
; context: CContext.t
; passed_as_noescape_block_to: Procname.t option
; 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 *)
let assign_captured_var loc (cvar, typ) =
let assign_captured_var loc (cvar, typ, mode) =
let id = Ident.create_fresh Ident.knormal 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 =
@ -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
~outer_proc
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
block_decl_info.Clang_ast_t.bdi_captured_variables
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 block_data =
Some
@ -2870,16 +2874,18 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
CFrontend_errors.incorrect_assumption __POS__ stmt_info.Clang_ast_t.si_source_range
"Capture-init statement without var decl"
in
let translate_normal_capture ~is_by_ref ((pvar, typ) as pvar_typ)
(trans_results_acc, captured_vars_acc) =
let translate_normal_capture mode (pvar, typ) (trans_results_acc, captured_vars_acc) =
let loc =
CLocation.location_of_stmt_info context.translation_unit_context.source_file stmt_info
in
if is_by_ref then (trans_results_acc, (Exp.Lvar pvar, pvar, typ) :: captured_vars_acc)
else
let ((exp, _, typ) as exp_pvar_typ), instr = assign_captured_var loc pvar_typ 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)
match mode with
| Pvar.ByReference ->
(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
(trans_results :: trans_results_acc, exp_pvar_typ :: captured_vars_acc)
in
let translate_captured
{Clang_ast_t.lci_captured_var; lci_init_captured_vardecl; lci_capture_this; lci_capture_kind}
@ -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 *) ->
false
in
let mode = if is_by_ref then Pvar.ByReference else Pvar.ByValue in
match (lci_captured_var, lci_init_captured_vardecl) with
| Some captured_var_decl_ref, Some init_decl -> (
(* capture and init *)
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
, (Exp.Lvar (fst pvar_typ), fst pvar_typ, snd pvar_typ) :: captured_vars_acc )
, (Exp.Lvar pvar, pvar, typ, mode) :: captured_vars_acc )
| None ->
(trans_results_acc, captured_vars_acc) )
| Some captured_var_decl_ref, None -> (
(* just capture *)
match get_captured_pvar_typ captured_var_decl_ref with
| Some pvar_typ ->
translate_normal_capture ~is_by_ref pvar_typ acc
translate_normal_capture mode pvar_typ acc
| None ->
(trans_results_acc, captured_vars_acc) )
| None, None ->
if lci_capture_this then
(* captured [this] *)
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
| None, Some _ ->
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
match (var_opt, typ_opt) with
| Some var, Some typ ->
(* TODO: set correct capture mode *)
Some (var, typ)
| None, None ->
None

@ -72,9 +72,9 @@ module Closures = struct
List.rev_filter_map captured
~f:(fun (captured_as, (address_captured, trace_captured), mode) ->
match mode with
| `ByValue ->
| Pvar.ByValue ->
None
| `ByReference ->
| Pvar.ByReference ->
let new_trace = ValueHistory.Capture {captured_as; location} :: trace_captured in
Some (address_captured, new_trace) )
in
@ -114,12 +114,8 @@ let eval location exp0 astate =
| Closure {name; captured_vars} ->
let+ astate, rev_captured =
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 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) )
in
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 fun_ptr_typ = Typ.mk (Tptr (Typ.mk Tfun, Pk_pointer)) in
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 closure = {Exp.name= dummy_procname; captured_vars} in
Exp.Closure closure

@ -15,7 +15,9 @@ let tests =
let assert_empty = invariant "{ }" in
let fun_ptr_typ = Typ.mk (Tptr (Typ.mk Tfun, Pk_pointer)) in
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 closure = {Exp.name= dummy_procname; captured_vars} in
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_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" ;
@ -144,7 +144,7 @@ digraph cfg {
"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" ;
@ -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_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" ;

@ -34,7 +34,7 @@ digraph cfg {
"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" ;
@ -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_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" ;

@ -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, 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/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_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_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, 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, 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 */
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" ;
@ -11,7 +11,7 @@ digraph cfg {
"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" ;
@ -22,7 +22,7 @@ digraph cfg {
"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" ;
@ -33,7 +33,7 @@ digraph cfg {
"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" ;
@ -129,7 +129,7 @@ digraph cfg {
"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" ;
@ -148,7 +148,7 @@ digraph cfg {
"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" ;
@ -175,7 +175,7 @@ digraph cfg {
"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" ;
@ -198,7 +198,7 @@ digraph cfg {
"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" ;

@ -1,6 +1,6 @@
/* @generated */
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" ;
@ -33,7 +33,7 @@ digraph cfg {
"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" ;

@ -38,7 +38,7 @@ digraph cfg {
"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" ;
@ -61,7 +61,7 @@ digraph cfg {
"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" ;
@ -76,7 +76,7 @@ digraph cfg {
"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" ;
@ -84,7 +84,7 @@ digraph cfg {
"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" ;

@ -1,6 +1,6 @@
/* @generated */
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" ;
@ -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_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" ;

@ -1,6 +1,6 @@
/* @generated */
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" ;
@ -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_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" ;

@ -44,7 +44,7 @@ digraph cfg {
"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" ;
@ -110,7 +110,7 @@ digraph cfg {
"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" ;

Loading…
Cancel
Save