Adding an outer context to the context in case of blocks

Reviewed By: @ddino

Differential Revision: D2526315

fb-gh-sync-id: 89a6d3f
master
Dulma Rodriguez 9 years ago committed by facebook-github-bot-7
parent 5a7399f8cb
commit e49d9d6f4d

@ -35,14 +35,15 @@ type t =
cfg : Cfg.cfg;
procdesc : Cfg.Procdesc.t;
is_objc_method : bool;
is_instance : bool;
curr_class: curr_class;
is_callee_expression : bool;
namespace: string option; (* contains the name of the namespace if we are in the scope of one*)
mutable local_vars : (Mangled.t * Sil.typ * bool) list; (* (name, type, is_static flag) *)
mutable captured_vars : (Mangled.t * Sil.typ * bool) list; (* (name, type, is_static flag) *)
mutable local_vars_stack : varMap;
mutable local_vars_pointer : pointerVarMap
mutable local_vars_pointer : pointerVarMap;
outer_context : t option; (* in case of objc blocks, the context of the method containing the block *)
mutable blocks : Procname.t list (* List of blocks defined in this method *)
}
module LocalVars =
@ -141,17 +142,17 @@ struct
try
Some (fst (lookup_var_locals context procname var_name))
with Stack.Empty ->
try
Some (fst (lookup_var_globals context procname var_name))
with Not_found ->
if is_captured_var context var_name then
try (* if it's a captured variable we need to look at the parameters list*)
Some (fst (lookup_var_formals context procname var_name))
with Not_found ->
Printing.log_err "Variable %s not found!!\n%!" var_name;
print_locals context;
None
else None
try
Some (fst (lookup_var_globals context procname var_name))
with Not_found ->
if is_captured_var context var_name then
try (* if it's a captured variable we need to look at the parameters list*)
Some (fst (lookup_var_formals context procname var_name))
with Not_found ->
Printing.log_err "Variable %s not found!!\n%!" var_name;
print_locals context;
None
else None
else if (kind = `ParmVar) then
try
Some (fst (lookup_var_formals context procname var_name))
@ -217,7 +218,7 @@ struct
end
let create_context tenv cg cfg procdesc ns curr_class is_objc_method cv is_instance =
let create_context tenv cg cfg procdesc ns curr_class is_objc_method cv outer_context_opt =
{ tenv = tenv;
cg = cg;
cfg = cfg;
@ -225,12 +226,13 @@ let create_context tenv cg cfg procdesc ns curr_class is_objc_method cv is_insta
curr_class = curr_class;
is_callee_expression = false;
is_objc_method = is_objc_method;
is_instance = is_instance;
namespace = ns;
local_vars = [];
captured_vars = cv;
local_vars_stack = StringMap.empty;
local_vars_pointer = StringMap.empty
local_vars_pointer = StringMap.empty;
outer_context = outer_context_opt;
blocks = []
}
let get_cfg context = context.cfg
@ -241,9 +243,24 @@ let get_tenv context = context.tenv
let get_procdesc context = context.procdesc
let is_objc_method context = context.is_objc_method
let rec is_objc_method context =
match context.outer_context with
| Some outer_context -> is_objc_method outer_context
| None -> context.is_objc_method
let rec is_objc_instance context =
match context.outer_context with
| Some outer_context -> is_objc_instance outer_context
| None ->
let attrs = Cfg.Procdesc.get_attributes context.procdesc in
attrs.ProcAttributes.is_objc_instance_method
let rec get_curr_class context =
match context.curr_class, context.outer_context with
| ContextNoCls, Some outer_context ->
get_curr_class outer_context
| _ -> context.curr_class
let get_curr_class context = context.curr_class
let get_curr_class_name curr_class =
match curr_class with
@ -299,3 +316,9 @@ let create_curr_class tenv class_name =
ContextCls (class_name, Some superclass, protocols)
| [] -> ContextCls (class_name, None, []))
| _ -> assert false
let rec add_block context block =
context.blocks <- block :: context.blocks;
match context.outer_context with
| Some outer_context -> add_block outer_context block
| None -> ()

@ -27,14 +27,15 @@ type t =
cfg : Cfg.cfg;
procdesc : Cfg.Procdesc.t;
is_objc_method : bool;
is_instance : bool;
curr_class: curr_class;
is_callee_expression : bool;
namespace: string option; (* contains the name of the namespace if we are in the scope of one*)
mutable local_vars : (Mangled.t * Sil.typ * bool) list; (* (name, type, is_static flag) *)
mutable captured_vars : (Mangled.t * Sil.typ * bool) list; (* (name, type, is_static flag) *)
mutable local_vars_stack : varMap;
mutable local_vars_pointer : pointerVarMap
mutable local_vars_pointer : pointerVarMap;
outer_context : t option; (* in case of objc blocks, the context of the method containing the block *)
mutable blocks : Procname.t list (* List of blocks defined in this method *)
}
module LocalVars :
@ -71,6 +72,10 @@ val is_objc_method : t -> bool
val get_tenv : t -> Sil.tenv
val create_context : Sil.tenv -> Cg.t -> Cfg.cfg -> Cfg.Procdesc.t ->
string option -> curr_class -> bool -> (Mangled.t * Sil.typ * bool) list -> bool -> t
string option -> curr_class -> bool -> (Mangled.t * Sil.typ * bool) list -> t option -> t
val create_curr_class : Sil.tenv -> string -> curr_class
val add_block : t -> Procname.t -> unit
val is_objc_instance : t -> bool

@ -51,7 +51,7 @@ let enum_decl name tenv cfg cg namespace type_ptr decl_list opt_type =
Printing.log_out "ADDING: EnumDecl '%s'\n" name;
let context' =
CContext.create_context tenv cg cfg !global_procdesc namespace CContext.ContextNoCls
false [] false in
false [] None in
let enum_constants = get_enum_constants context' decl_list 0 in
let name = (match opt_type with (* If the type is defined it's of the kind "enum name" and we take that.*)
| `Type s -> s

@ -38,8 +38,9 @@ struct
Specs.summary_exists_in_models procname && not !CFrontend_config.models_mode
(* Translates the method/function's body into nodes of the cfg. *)
let add_method tenv cg cfg class_decl_opt procname namespace instrs is_objc_method is_instance
captured_vars is_anonym_block extra_instrs =
let add_method tenv cg cfg class_decl_opt procname namespace instrs is_objc_method
captured_vars outer_context_opt extra_instrs =
Printing.log_out
"\n\n>>---------- ADDING METHOD: '%s' ---------<<\n@." (Procname.to_string procname);
try
@ -48,7 +49,7 @@ struct
if (Cfg.Procdesc.is_defined procdesc && not (model_exists procname)) then
(let context =
CContext.create_context tenv cg cfg procdesc namespace class_decl_opt
is_objc_method captured_vars is_instance in
is_objc_method captured_vars outer_context_opt in
CVar_decl.get_fun_locals context instrs;
let local_vars = list_map (fun (n, t, _) -> n, t) context.CContext.local_vars in
let start_node = Cfg.Procdesc.get_start_node procdesc in
@ -59,6 +60,7 @@ struct
"\n\n>>---------- Start translating body of function: '%s' ---------<<\n@."
(Procname.to_string procname);
let meth_body_nodes = T.instructions_trans context instrs extra_instrs exit_node in
let is_anonym_block = Option.is_some outer_context_opt in
if (not is_anonym_block) then CContext.LocalVars.reset_block ();
Cfg.Node.set_succs_exn start_node meth_body_nodes [];
Cg.add_node (CContext.get_cg context) (Cfg.Procdesc.get_proc_name procdesc))
@ -77,24 +79,18 @@ struct
let function_decl tenv cfg cg namespace func_decl block_data_opt =
Printing.log_out "\nResetting the goto_labels hashmap...\n";
CTrans_utils.GotoLabel.reset_all_labels (); (* C Language Std 6.8.6.1-1 *)
let is_anonym_block, captured_vars, curr_class =
let captured_vars, outer_context_opt =
match block_data_opt with
| Some (context, _, _, captured_vars) ->
let curr_class = context.CContext.curr_class in
true, captured_vars, curr_class
| None -> false, [], CContext.ContextNoCls in
let class_name =
if curr_class = CContext.ContextNoCls then None else Some (CContext.get_curr_class_name curr_class) in
| Some (outer_context, _, _, captured_vars) -> captured_vars, Some outer_context
| None -> [], None in
let ms, body_opt, extra_instrs =
CMethod_trans.method_signature_of_decl class_name func_decl block_data_opt in
CMethod_trans.method_signature_of_decl None func_decl block_data_opt in
match method_body_to_translate ms body_opt with
| Some body -> (* Only in the case the function declaration has a defined body we create a procdesc *)
let procname = CMethod_signature.ms_get_name ms in
if CMethod_trans.create_local_procdesc cfg tenv ms [body] captured_vars false then
let is_instance = CMethod_signature.ms_is_instance ms in
let is_objc_method = is_anonym_block in
add_method tenv cg cfg curr_class procname namespace [body] is_objc_method is_instance
captured_vars is_anonym_block extra_instrs
add_method tenv cg cfg CContext.ContextNoCls procname namespace [body] false
captured_vars outer_context_opt extra_instrs
| None -> ()
let process_method_decl tenv cg cfg namespace curr_class meth_decl ~is_objc =
@ -106,8 +102,7 @@ struct
let is_instance = CMethod_signature.ms_is_instance ms in
let procname = CMethod_signature.ms_get_name ms in
if CMethod_trans.create_local_procdesc cfg tenv ms [body] [] is_instance then
add_method tenv cg cfg curr_class procname namespace [body] is_objc is_instance [] false
extra_instrs
add_method tenv cg cfg curr_class procname namespace [body] is_objc [] None extra_instrs
| None -> ()
let rec process_one_method_decl tenv cg cfg curr_class namespace dec =

@ -35,11 +35,10 @@ type function_method_decl_info =
let is_instance_method function_method_decl_info =
match function_method_decl_info with
| Func_decl_info (function_decl_info, _, _) -> false
| Func_decl_info _ | Block_decl_info _ -> false
| Cpp_Meth_decl_info _ -> true
| ObjC_Meth_decl_info (method_decl_info, _) ->
method_decl_info.Clang_ast_t.omdi_is_instance_method
| Block_decl_info (_, _, context) -> context.CContext.is_instance
let get_class_param function_method_decl_info =
if (is_instance_method function_method_decl_info) then
@ -135,8 +134,8 @@ let method_signature_of_decl class_name_opt meth_decl block_data_opt =
let extra_instrs = get_assume_not_null_calls ms mdi.omdi_parameters in
ms, mdi.omdi_body, extra_instrs
| BlockDecl (decl_info, decl_list, decl_context_info, bdi),
Some (context, tp, procname, _), _ ->
let func_decl = Block_decl_info (bdi, tp, context) in
Some (outer_context, tp, procname, _), _ ->
let func_decl = Block_decl_info (bdi, tp, outer_context) in
let ms = build_method_signature decl_info procname func_decl true false in
let extra_instrs = get_assume_not_null_calls ms bdi.bdi_parameters in
ms, bdi.bdi_body, extra_instrs
@ -228,7 +227,7 @@ let captured_vars_from_block_info context cvl =
(match dr.Clang_ast_t.dr_name, dr.Clang_ast_t.dr_type_ptr with
| Some name_info, _ ->
let n = name_info.Clang_ast_t.ni_name in
if n = CFrontend_config.self && not context.CContext.is_instance then []
if n = CFrontend_config.self && not (CContext.is_objc_instance context) then []
else
(let procdesc_formals = Cfg.Procdesc.get_formals context.CContext.procdesc in
(Printing.log_err "formals are %s@." (Utils.list_to_string (fun (x, _) -> x) procdesc_formals));

@ -348,11 +348,12 @@ struct
let e = Sil.Lvar pvar in
let exps =
if Self.is_var_self pvar (CContext.is_objc_method context) then
let curr_class = CContext.get_curr_class context in
if (CTypes.is_class typ) then
raise (Self.SelfClassException (CContext.get_curr_class_name trans_state.context.curr_class))
raise (Self.SelfClassException (CContext.get_curr_class_name curr_class))
else
let typ = CTypes.add_pointer_to_typ
(CTypes_decl.get_type_curr_class context.tenv (CContext.get_curr_class context)) in
(CTypes_decl.get_type_curr_class context.tenv curr_class) in
[(e, typ)]
else [(e, typ)] in
Printing.log_out "\n\n PVAR ='%s'\n\n" (Sil.pvar_to_string pvar);
@ -1769,6 +1770,7 @@ struct
let ids_instrs = list_map assign_captured_var all_captured_vars in
let ids, instrs = list_split ids_instrs in
let block_data = (context, type_ptr, block_pname, all_captured_vars) in
CContext.add_block context block_pname;
M.function_decl context.tenv context.cfg context.cg context.namespace decl (Some block_data);
Cfg.set_procname_priority context.cfg block_pname;
let captured_exps = list_map (fun id -> Sil.Var id) ids in

Loading…
Cancel
Save