diff --git a/infer/src/clang/cContext.ml b/infer/src/clang/cContext.ml index eb8cdb2b1..69368b120 100644 --- a/infer/src/clang/cContext.ml +++ b/infer/src/clang/cContext.ml @@ -30,17 +30,19 @@ type t = procdesc : Cfg.Procdesc.t; is_objc_method : bool; curr_class: curr_class; + has_return_param : bool; is_callee_expression : bool; outer_context : t option; (* in case of objc blocks, the context of the method containing the block *) mutable blocks_static_vars : ((Sil.pvar * Sil.typ) list) Procname.Map.t; } -let create_context tenv cg cfg procdesc curr_class is_objc_method context_opt = +let create_context tenv cg cfg procdesc curr_class ~has_return_param is_objc_method context_opt = { tenv = tenv; cg = cg; cfg = cfg; procdesc = procdesc; curr_class = curr_class; + has_return_param = has_return_param; is_callee_expression = false; is_objc_method = is_objc_method; outer_context = context_opt; diff --git a/infer/src/clang/cContext.mli b/infer/src/clang/cContext.mli index 198b97b14..c59d78562 100644 --- a/infer/src/clang/cContext.mli +++ b/infer/src/clang/cContext.mli @@ -25,6 +25,7 @@ type t = procdesc : Cfg.Procdesc.t; is_objc_method : bool; curr_class: curr_class; + has_return_param : bool; is_callee_expression : bool; outer_context : t option; (* in case of objc blocks, the context of the method containing the block *) mutable blocks_static_vars : ((Sil.pvar * Sil.typ) list) Procname.Map.t; @@ -53,7 +54,7 @@ val is_objc_method : t -> bool val get_tenv : t -> Sil.tenv val create_context : Sil.tenv -> Cg.t -> Cfg.cfg -> Cfg.Procdesc.t -> - curr_class -> bool -> t option -> t + curr_class -> has_return_param : bool -> bool -> t option -> t val create_curr_class : Sil.tenv -> string -> curr_class diff --git a/infer/src/clang/cMethod_decl.ml b/infer/src/clang/cMethod_decl.ml index d7dfda84e..e8555c6b3 100644 --- a/infer/src/clang/cMethod_decl.ml +++ b/infer/src/clang/cMethod_decl.ml @@ -30,7 +30,7 @@ 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 instrs is_objc_method + let add_method tenv cg cfg class_decl_opt procname instrs has_return_param is_objc_method captured_vars outer_context_opt extra_instrs = Printing.log_out @@ -41,7 +41,7 @@ struct if (Cfg.Procdesc.is_defined procdesc && not (model_exists procname)) then (let context = CContext.create_context tenv cg cfg procdesc class_decl_opt - is_objc_method outer_context_opt in + has_return_param is_objc_method outer_context_opt in let start_node = Cfg.Procdesc.get_start_node procdesc in let exit_node = Cfg.Procdesc.get_exit_node procdesc in Printing.log_out @@ -75,8 +75,9 @@ struct match 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 + let has_return_param = CMethod_signature.ms_has_return_param ms in if CMethod_trans.create_local_procdesc cfg tenv ms [body] captured_vars false then - add_method tenv cg cfg CContext.ContextNoCls procname [body] false + add_method tenv cg cfg CContext.ContextNoCls procname [body] has_return_param false captured_vars outer_context_opt extra_instrs | None -> () @@ -88,8 +89,10 @@ struct let is_instance = CMethod_signature.ms_is_instance ms in let procname = CMethod_signature.ms_get_name ms in let is_objc_inst_method = is_instance && is_objc in + let has_return_param = CMethod_signature.ms_has_return_param ms in if CMethod_trans.create_local_procdesc cfg tenv ms [body] [] is_objc_inst_method then - add_method tenv cg cfg curr_class procname [body] is_objc [] None extra_instrs + add_method tenv cg cfg curr_class procname [body] has_return_param is_objc [] + None extra_instrs | None -> () let process_one_method_decl tenv cg cfg curr_class dec = diff --git a/infer/src/clang/cMethod_signature.ml b/infer/src/clang/cMethod_signature.ml index 76102e4ef..624a449af 100644 --- a/infer/src/clang/cMethod_signature.ml +++ b/infer/src/clang/cMethod_signature.ml @@ -20,6 +20,7 @@ type method_signature = { _language : CFrontend_config.lang; _pointer_to_parent : Clang_ast_t.pointer option; _pointer_to_property_opt : Clang_ast_t.pointer option; (* If set then method is a getter/setter *) + _has_return_param : bool; } let ms_get_name ms = @@ -52,6 +53,9 @@ let ms_get_pointer_to_parent ms = let ms_get_pointer_to_property_opt ms = ms._pointer_to_property_opt +let ms_has_return_param ms = + ms._has_return_param + (* A method is a getter if it has a link to a property and *) (* it has 1 argument (this includes self) *) let ms_is_getter ms = @@ -65,7 +69,7 @@ let ms_is_setter ms = IList.length ms._args == 2 let make_ms procname args ret_type attributes loc is_instance lang pointer_to_parent - pointer_to_property_opt = + pointer_to_property_opt ~has_return_param = let meth_signature = { _name = procname; _args = args; @@ -76,6 +80,7 @@ let make_ms procname args ret_type attributes loc is_instance lang pointer_to_pa _language = lang; _pointer_to_parent = pointer_to_parent; _pointer_to_property_opt = pointer_to_property_opt; + _has_return_param = has_return_param; } in meth_signature diff --git a/infer/src/clang/cMethod_signature.mli b/infer/src/clang/cMethod_signature.mli index 692721b2d..0ed35b7a0 100644 --- a/infer/src/clang/cMethod_signature.mli +++ b/infer/src/clang/cMethod_signature.mli @@ -33,13 +33,16 @@ val ms_get_pointer_to_parent : method_signature -> Clang_ast_t.pointer option val ms_get_pointer_to_property_opt : method_signature -> Clang_ast_t.pointer option +val ms_has_return_param : method_signature -> bool + val ms_is_getter : method_signature -> bool val ms_is_setter : method_signature -> bool val make_ms : Procname.t -> (string * Clang_ast_t.type_ptr) list -> Clang_ast_t.type_ptr -> Clang_ast_t.attribute list -> Clang_ast_t.source_range -> bool -> CFrontend_config.lang - -> Clang_ast_t.pointer option -> Clang_ast_t.pointer option -> method_signature + -> Clang_ast_t.pointer option -> Clang_ast_t.pointer option -> has_return_param : bool + -> method_signature val replace_name_ms : method_signature -> Procname.t -> method_signature diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 1dece3624..3253c8438 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -102,24 +102,25 @@ let get_parameters tenv function_method_decl_info = 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_return_param tenv function_method_decl_info +(** get return type of the function and whether function has return parameter *) let get_return_type 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 - Ast_expressions.create_void_type - else return_type_ptr + Ast_expressions.create_void_type, true + else return_type_ptr, false let build_method_signature tenv decl_info procname function_method_decl_info is_anonym_block parent_pointer pointer_to_property_opt = let source_range = decl_info.Clang_ast_t.di_source_range in - let tp = get_return_type tenv function_method_decl_info in + let tp, has_return_param = get_return_type tenv function_method_decl_info in let is_instance_method = is_instance_method 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 lang = get_language function_method_decl_info in CMethod_signature.make_ms procname parameters tp attributes source_range is_instance_method lang parent_pointer - pointer_to_property_opt + pointer_to_property_opt ~has_return_param let get_assume_not_null_calls param_decls = let do_one_param decl = match decl with @@ -436,7 +437,7 @@ let get_method_for_frontend_checks cfg cg tenv class_name decl_info = | None -> let ms_type_ptr = Clang_ast_types.pointer_to_type_ptr (Ast_utils.get_invalid_pointer ()) in let ms = CMethod_signature.make_ms proc_name [] ms_type_ptr [] source_range false - CFrontend_config.OBJC None None in + CFrontend_config.OBJC None None false in let body = [Clang_ast_t.CompoundStmt (stmt_info, [])] in ignore (create_local_procdesc cfg tenv ms body [] false); let pdesc = Option.get (Cfg.Procdesc.find_from_name cfg proc_name) in diff --git a/infer/src/clang/cTrans_models.ml b/infer/src/clang/cTrans_models.ml index b02de21d4..d00fba525 100644 --- a/infer/src/clang/cTrans_models.ml +++ b/infer/src/clang/cTrans_models.ml @@ -127,7 +127,7 @@ let get_predefined_ms_method condition class_name method_name method_kind mk_pro | Some procname -> procname | None -> mk_procname class_name method_name method_kind in let ms = CMethod_signature.make_ms procname arguments return_type attributes - (Ast_expressions.dummy_source_range ()) false lang None None in + (Ast_expressions.dummy_source_range ()) false lang None None false in Some ms else None