Add return parameter to functions returning structs

Summary:
public
Introduce additional parameter for functions returning struct types - instead of returning it, populate output parameter.
This diff just changes method signature, there are more coming

Reviewed By: jberdine

Differential Revision: D2864842

fb-gh-sync-id: 52fc12c
master
Andrzej Kotulski 9 years ago committed by facebook-github-bot-7
parent 18668a41ce
commit 58be5d0eb0

@ -33,6 +33,8 @@ let self = "self"
let this = "this" let this = "this"
let return_param = "__return_param"
let alloc = "alloc" let alloc = "alloc"
let malloc = "malloc" let malloc = "malloc"

@ -53,6 +53,8 @@ val self : string
val this : string val this : string
val return_param : string
val nsstring_cl : string val nsstring_cl : string
val nsobject_cl : string val nsobject_cl : string

@ -71,7 +71,7 @@ struct
| Some (outer_context, _, _, captured_vars) -> captured_vars, Some outer_context | Some (outer_context, _, _, captured_vars) -> captured_vars, Some outer_context
| None -> [], None in | None -> [], None in
let ms, body_opt, extra_instrs = let ms, body_opt, extra_instrs =
CMethod_trans.method_signature_of_decl func_decl block_data_opt in CMethod_trans.method_signature_of_decl tenv func_decl block_data_opt in
match body_opt with match body_opt with
| Some body -> (* Only in the case the function declaration has a defined body we create a procdesc *) | 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 let procname = CMethod_signature.ms_get_name ms in
@ -82,7 +82,7 @@ struct
let process_method_decl tenv cg cfg curr_class meth_decl ~is_objc = let process_method_decl tenv cg cfg curr_class meth_decl ~is_objc =
let ms, body_opt, extra_instrs = let ms, body_opt, extra_instrs =
CMethod_trans.method_signature_of_decl meth_decl None in CMethod_trans.method_signature_of_decl tenv meth_decl None in
match body_opt with match body_opt with
| Some body -> | Some body ->
let is_instance = CMethod_signature.ms_is_instance ms in let is_instance = CMethod_signature.ms_is_instance ms in

@ -41,6 +41,13 @@ let is_instance_method function_method_decl_info =
| ObjC_Meth_decl_info (method_decl_info, _) -> | ObjC_Meth_decl_info (method_decl_info, _) ->
method_decl_info.Clang_ast_t.omdi_is_instance_method method_decl_info.Clang_ast_t.omdi_is_instance_method
let get_original_return_type function_method_decl_info =
match function_method_decl_info with
| Func_decl_info (_, typ, _)
| Cpp_Meth_decl_info (_, _, _, typ)
| Block_decl_info (_, typ, _) -> CTypes.return_type_of_function_type typ
| ObjC_Meth_decl_info (method_decl_info, _) -> method_decl_info.Clang_ast_t.omdi_result_type
let get_class_param function_method_decl_info = let get_class_param function_method_decl_info =
if (is_instance_method function_method_decl_info) then if (is_instance_method function_method_decl_info) then
match function_method_decl_info with match function_method_decl_info with
@ -53,6 +60,19 @@ let get_class_param function_method_decl_info =
| _ -> [] | _ -> []
else [] else []
let should_add_return_param return_type =
match return_type with
| Sil.Tstruct _ -> false (* will return true once everything is in place *)
| _ -> false
let get_return_param tenv function_method_decl_info =
let return_type_ptr = get_original_return_type function_method_decl_info in
let return_typ = CTypes_decl.type_ptr_to_sil_type tenv return_type_ptr in
if should_add_return_param return_typ then
[(CFrontend_config.return_param, Ast_expressions.create_pointer_type return_type_ptr)]
else
[]
let get_param_decls function_method_decl_info = let get_param_decls function_method_decl_info =
match function_method_decl_info with match function_method_decl_info with
| Func_decl_info (function_decl_info, _, _) | Func_decl_info (function_decl_info, _, _)
@ -68,30 +88,33 @@ let get_language function_method_decl_info =
| ObjC_Meth_decl_info _ -> CFrontend_config.OBJC | ObjC_Meth_decl_info _ -> CFrontend_config.OBJC
| Block_decl_info _ -> CFrontend_config.OBJC | Block_decl_info _ -> CFrontend_config.OBJC
let get_parameters function_method_decl_info = (** Returns parameters of a function/method. They will have following order:
1. self/this parameter (optional, only for methods)
2. normal parameters
3. return parameter (optional) *)
let get_parameters tenv function_method_decl_info =
let par_to_ms_par par = let par_to_ms_par par =
match par with match par with
| Clang_ast_t.ParmVarDecl (decl_info, name_info, type_ptr, var_decl_info) -> | Clang_ast_t.ParmVarDecl (decl_info, name_info, type_ptr, var_decl_info) ->
let name = name_info.Clang_ast_t.ni_name in let name = name_info.Clang_ast_t.ni_name in
(name, type_ptr) (name, type_ptr)
| _ -> assert false in | _ -> assert false in
let pars = IList.map par_to_ms_par (get_param_decls function_method_decl_info) in let pars = IList.map par_to_ms_par (get_param_decls function_method_decl_info) in
get_class_param function_method_decl_info @ pars get_class_param function_method_decl_info @ pars @ get_return_param tenv function_method_decl_info
let get_return_type function_method_decl_info = let get_return_type tenv function_method_decl_info =
match function_method_decl_info with let return_type_ptr = get_original_return_type function_method_decl_info in
| Func_decl_info (_, typ, _) let return_typ = CTypes_decl.type_ptr_to_sil_type tenv return_type_ptr in
| Cpp_Meth_decl_info (_, _, _, typ) if should_add_return_param return_typ then
| Block_decl_info (_, typ, _) -> CTypes.return_type_of_function_type typ Ast_expressions.create_void_type
| ObjC_Meth_decl_info (method_decl_info, _) -> method_decl_info.Clang_ast_t.omdi_result_type else return_type_ptr
let build_method_signature decl_info procname function_method_decl_info is_anonym_block let build_method_signature tenv decl_info procname function_method_decl_info is_anonym_block
parent_pointer pointer_to_property_opt = parent_pointer pointer_to_property_opt =
let source_range = decl_info.Clang_ast_t.di_source_range in let source_range = decl_info.Clang_ast_t.di_source_range in
let tp = get_return_type function_method_decl_info in let tp = get_return_type tenv function_method_decl_info in
let is_instance_method = is_instance_method function_method_decl_info in let is_instance_method = is_instance_method function_method_decl_info in
let parameters = get_parameters function_method_decl_info in let parameters = get_parameters tenv function_method_decl_info in
let attributes = decl_info.Clang_ast_t.di_attributes in let attributes = decl_info.Clang_ast_t.di_attributes in
let lang = get_language function_method_decl_info in let lang = get_language function_method_decl_info in
CMethod_signature.make_ms CMethod_signature.make_ms
@ -111,7 +134,7 @@ let get_init_list_instrs method_decl_info =
let create_custom_instr construct_instr = `CXXConstructorInit construct_instr in let create_custom_instr construct_instr = `CXXConstructorInit construct_instr in
IList.map create_custom_instr method_decl_info.Clang_ast_t.xmdi_cxx_ctor_initializers IList.map create_custom_instr method_decl_info.Clang_ast_t.xmdi_cxx_ctor_initializers
let method_signature_of_decl meth_decl block_data_opt = let method_signature_of_decl tenv meth_decl block_data_opt =
let open Clang_ast_t in let open Clang_ast_t in
match meth_decl, block_data_opt with match meth_decl, block_data_opt with
| FunctionDecl (decl_info, name_info, tp, fdi), _ -> | FunctionDecl (decl_info, name_info, tp, fdi), _ ->
@ -120,7 +143,7 @@ let method_signature_of_decl meth_decl block_data_opt =
let func_decl = Func_decl_info (fdi, tp, language) in let func_decl = Func_decl_info (fdi, tp, language) in
let function_info = Some (decl_info, fdi) in let function_info = Some (decl_info, fdi) in
let procname = General_utils.mk_procname_from_function name function_info tp language in let procname = General_utils.mk_procname_from_function name function_info tp language in
let ms = build_method_signature decl_info procname func_decl false None None in let ms = build_method_signature tenv decl_info procname func_decl false None None in
let extra_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in let extra_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in
ms, fdi.Clang_ast_t.fdi_body, extra_instrs ms, fdi.Clang_ast_t.fdi_body, extra_instrs
| CXXMethodDecl (decl_info, name_info, tp, fdi, mdi), _ | CXXMethodDecl (decl_info, name_info, tp, fdi, mdi), _
@ -131,7 +154,7 @@ let method_signature_of_decl meth_decl block_data_opt =
let procname = General_utils.mk_procname_from_cpp_method class_name method_name tp in let procname = General_utils.mk_procname_from_cpp_method class_name method_name tp in
let method_decl = Cpp_Meth_decl_info (fdi, mdi, class_name, tp) in let method_decl = Cpp_Meth_decl_info (fdi, mdi, class_name, tp) in
let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in
let ms = build_method_signature decl_info procname method_decl false parent_pointer let ms = build_method_signature tenv decl_info procname method_decl false parent_pointer
None in None in
let non_null_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in let non_null_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in
let init_list_instrs = get_init_list_instrs mdi in (* it will be empty for methods *) let init_list_instrs = get_init_list_instrs mdi in (* it will be empty for methods *)
@ -148,22 +171,22 @@ let method_signature_of_decl meth_decl block_data_opt =
match mdi.Clang_ast_t.omdi_property_decl with match mdi.Clang_ast_t.omdi_property_decl with
| Some decl_ref -> Some decl_ref.Clang_ast_t.dr_decl_pointer | Some decl_ref -> Some decl_ref.Clang_ast_t.dr_decl_pointer
| None -> None in | None -> None in
let ms = build_method_signature decl_info procname method_decl false let ms = build_method_signature tenv decl_info procname method_decl false
parent_pointer pointer_to_property_opt in parent_pointer pointer_to_property_opt in
let extra_instrs = get_assume_not_null_calls mdi.omdi_parameters in let extra_instrs = get_assume_not_null_calls mdi.omdi_parameters in
ms, mdi.omdi_body, extra_instrs ms, mdi.omdi_body, extra_instrs
| BlockDecl (decl_info, bdi), Some (outer_context, tp, procname, _) -> | BlockDecl (decl_info, bdi), Some (outer_context, tp, procname, _) ->
let func_decl = Block_decl_info (bdi, tp, outer_context) in let func_decl = Block_decl_info (bdi, tp, outer_context) in
let ms = build_method_signature decl_info procname func_decl true None None in let ms = build_method_signature tenv decl_info procname func_decl true None None in
let extra_instrs = get_assume_not_null_calls bdi.bdi_parameters in let extra_instrs = get_assume_not_null_calls bdi.bdi_parameters in
ms, bdi.bdi_body, extra_instrs ms, bdi.bdi_body, extra_instrs
| _ -> raise Invalid_declaration | _ -> raise Invalid_declaration
let method_signature_of_pointer pointer = let method_signature_of_pointer tenv pointer =
try try
match Ast_utils.get_decl pointer with match Ast_utils.get_decl pointer with
| Some meth_decl -> | Some meth_decl ->
let ms, _, _ = method_signature_of_decl meth_decl None in let ms, _, _ = method_signature_of_decl tenv meth_decl None in
Some ms Some ms
| None -> None | None -> None
with Invalid_declaration -> None with Invalid_declaration -> None
@ -207,10 +230,10 @@ let get_superclass_curr_class context =
| CContext.ContextProtocol _ -> assert false | CContext.ContextProtocol _ -> assert false
(* Gets the class name from a method signature found by clang, if search is successful *) (* Gets the class name from a method signature found by clang, if search is successful *)
let get_class_name_method_call_from_clang obj_c_message_expr_info = let get_class_name_method_call_from_clang tenv obj_c_message_expr_info =
match obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer with match obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer with
| Some pointer -> | Some pointer ->
(match method_signature_of_pointer pointer with (match method_signature_of_pointer tenv pointer with
| Some ms -> | Some ms ->
let class_name = Procname.c_get_class (CMethod_signature.ms_get_name ms) in let class_name = Procname.c_get_class (CMethod_signature.ms_get_name ms) in
Some class_name Some class_name
@ -385,7 +408,7 @@ let create_external_procdesc cfg proc_name is_objc_inst_method type_opt =
let create_procdesc_with_pointer context pointer class_name_opt name tp = let create_procdesc_with_pointer context pointer class_name_opt name tp =
let open CContext in let open CContext in
match method_signature_of_pointer pointer with match method_signature_of_pointer context.tenv pointer with
| Some callee_ms -> | Some callee_ms ->
ignore (create_local_procdesc context.cfg context.tenv callee_ms [] [] false); ignore (create_local_procdesc context.cfg context.tenv callee_ms [] [] false);
CMethod_signature.ms_get_name callee_ms CMethod_signature.ms_get_name callee_ms

@ -20,6 +20,8 @@ type method_call_type =
| MCNoVirtual | MCNoVirtual
| MCStatic | MCStatic
val should_add_return_param : Sil.typ -> bool
val create_local_procdesc : Cfg.cfg -> Sil.tenv -> CMethod_signature.method_signature -> val create_local_procdesc : Cfg.cfg -> Sil.tenv -> CMethod_signature.method_signature ->
Clang_ast_t.stmt list -> (Sil.pvar * Sil.typ) list -> bool -> bool Clang_ast_t.stmt list -> (Sil.pvar * Sil.typ) list -> bool -> bool
@ -31,12 +33,14 @@ val get_objc_method_data : Clang_ast_t.obj_c_message_expr_info ->
val get_class_name_method_call_from_receiver_kind : CContext.t -> val get_class_name_method_call_from_receiver_kind : CContext.t ->
Clang_ast_t.obj_c_message_expr_info -> (Sil.exp * Sil.typ) list -> string Clang_ast_t.obj_c_message_expr_info -> (Sil.exp * Sil.typ) list -> string
val get_class_name_method_call_from_clang : Clang_ast_t.obj_c_message_expr_info -> string option val get_class_name_method_call_from_clang : Sil.tenv -> Clang_ast_t.obj_c_message_expr_info ->
string option
val method_signature_of_decl : Clang_ast_t.decl -> CModule_type.block_data option -> val method_signature_of_decl : Sil.tenv -> Clang_ast_t.decl -> CModule_type.block_data option ->
CMethod_signature.method_signature * Clang_ast_t.stmt option * CModule_type.instr_type list CMethod_signature.method_signature * Clang_ast_t.stmt option * CModule_type.instr_type list
val method_signature_of_pointer : Clang_ast_t.pointer -> CMethod_signature.method_signature option val method_signature_of_pointer : Sil.tenv -> Clang_ast_t.pointer ->
CMethod_signature.method_signature option
val get_method_name_from_clang : Sil.tenv -> CMethod_signature.method_signature option -> val get_method_name_from_clang : Sil.tenv -> CMethod_signature.method_signature option ->
CMethod_signature.method_signature option CMethod_signature.method_signature option

@ -43,7 +43,7 @@ struct
let method_kind = Procname.objc_method_kind_of_bool is_instance in let method_kind = Procname.objc_method_kind_of_bool is_instance in
let ms_opt = let ms_opt =
match method_pointer_opt with match method_pointer_opt with
| Some pointer -> CMethod_trans.method_signature_of_pointer pointer | Some pointer -> CMethod_trans.method_signature_of_pointer context.tenv pointer
| None -> None in | None -> None in
let procname = let procname =
match CMethod_trans.get_method_name_from_clang context.tenv ms_opt with match CMethod_trans.get_method_name_from_clang context.tenv ms_opt with
@ -418,7 +418,7 @@ struct
Printing.log_out "!!!!! Dealing with method '%s' @." method_name; Printing.log_out "!!!!! Dealing with method '%s' @." method_name;
let method_typ = CTypes_decl.type_ptr_to_sil_type context.tenv type_ptr in let method_typ = CTypes_decl.type_ptr_to_sil_type context.tenv type_ptr in
let is_instance_method = let is_instance_method =
match CMethod_trans.method_signature_of_pointer decl_ptr with match CMethod_trans.method_signature_of_pointer context.tenv decl_ptr with
| Some ms -> CMethod_signature.ms_is_instance ms | Some ms -> CMethod_signature.ms_is_instance ms
| _ -> true in (* might happen for methods that are not exported yet (some templates). *) | _ -> true in (* might happen for methods that are not exported yet (some templates). *)
let extra_exps = if is_instance_method then ( let extra_exps = if is_instance_method then (
@ -833,8 +833,8 @@ struct
else if (selector = CFrontend_config.alloc) || (selector = CFrontend_config.new_str) then else if (selector = CFrontend_config.alloc) || (selector = CFrontend_config.new_str) then
match receiver_kind with match receiver_kind with
| `Class type_ptr -> | `Class type_ptr ->
let class_opt = let class_opt = CMethod_trans.get_class_name_method_call_from_clang context.tenv
CMethod_trans.get_class_name_method_call_from_clang obj_c_message_expr_info in obj_c_message_expr_info in
Some (new_or_alloc_trans trans_state_pri sil_loc si type_ptr class_opt selector) Some (new_or_alloc_trans trans_state_pri sil_loc si type_ptr class_opt selector)
| _ -> None | _ -> None
(* assertions *) (* assertions *)

Loading…
Cancel
Save