[clang] Use the map of pointers to find method declarations and build method signatures

Summary:
Use the map of pointers to find method declarations and build method signatures.
Remove the need for having an extra map for method signatures (and remove that map).
master
Dulma Rodriguez 9 years ago
parent 001e6a7c8f
commit 3cddd0489c

@ -29,7 +29,7 @@ let rec translate_one_declaration tenv cg cfg namespace parent_dec dec =
let open Clang_ast_t in let open Clang_ast_t in
match dec with match dec with
| FunctionDecl(di, name_info, qt, fdecl_info) -> | FunctionDecl(di, name_info, qt, fdecl_info) ->
CMethod_declImpl.function_decl tenv cfg cg namespace dec None CContext.ContextNoCls CMethod_declImpl.function_decl tenv cfg cg namespace dec None
| TypedefDecl (decl_info, name_info, opt_type, _, typedef_decl_info) -> | TypedefDecl (decl_info, name_info, opt_type, _, typedef_decl_info) ->
let name = name_info.Clang_ast_t.ni_name in let name = name_info.Clang_ast_t.ni_name in
CTypes_decl.do_typedef_declaration tenv namespace CTypes_decl.do_typedef_declaration tenv namespace
@ -124,7 +124,6 @@ let init_global_state source_file =
DB.current_source := source_file; DB.current_source := source_file;
DB.Results_dir.init (); DB.Results_dir.init ();
Ident.reset_name_generator (); Ident.reset_name_generator ();
CMethod_signature.reset_map ();
CGlobal_vars.reset_map (); CGlobal_vars.reset_map ();
CFrontend_config.global_translation_unit_decls := []; CFrontend_config.global_translation_unit_decls := [];
ObjcProperty_decl.reset_property_table (); ObjcProperty_decl.reset_property_table ();

@ -19,8 +19,7 @@ module type CMethod_decl = sig
Clang_ast_t.decl list -> unit Clang_ast_t.decl list -> unit
val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> Clang_ast_t.decl -> val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> Clang_ast_t.decl ->
(Clang_ast_t.qual_type * bool * Procname.t * (Mangled.t * Sil.typ * bool) list) option -> CModule_type.block_data option -> unit
CContext.curr_class -> unit
val process_getter_setter : CContext.t -> Procname.t -> bool val process_getter_setter : CContext.t -> Procname.t -> bool
end end
@ -90,32 +89,32 @@ struct
CMethod_trans.create_external_procdesc cfg procname is_objc_method None; CMethod_trans.create_external_procdesc cfg procname is_objc_method None;
() ()
let function_decl tenv cfg cg namespace func_decl block_data_opt curr_class = let function_decl tenv cfg cg namespace func_decl block_data_opt =
Printing.log_out "\nResetting the goto_labels hashmap...\n"; Printing.log_out "\nResetting the goto_labels hashmap...\n";
CTrans_utils.GotoLabel.reset_all_labels (); (* C Language Std 6.8.6.1-1 *) CTrans_utils.GotoLabel.reset_all_labels (); (* C Language Std 6.8.6.1-1 *)
let is_anonym_block, captured_vars, curr_class =
match block_data_opt with
| Some (_, _, _, captured_vars, curr_class) -> 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
let ms, body_opt, param_decls = let ms, body_opt, param_decls =
CMethod_trans.method_signature_of_decl curr_class func_decl block_data_opt in CMethod_trans.method_signature_of_decl class_name func_decl block_data_opt in
match method_body_to_translate ms body_opt with 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 *) | 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
let is_anonym_block, captured_vars =
match block_data_opt with
| Some (_, _, _, captured_vars) -> true, captured_vars
| None -> false, [] in
if CMethod_trans.create_local_procdesc cfg tenv ms [body] captured_vars false then 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_instance = CMethod_signature.ms_is_instance ms in
let is_objc_method = is_anonym_block in let is_objc_method = is_anonym_block in
let curr_class = if is_anonym_block then curr_class else CContext.ContextNoCls in
let attributes = CMethod_signature.ms_get_attributes ms in let attributes = CMethod_signature.ms_get_attributes ms in
CMethod_signature.add ms;
add_method tenv cg cfg curr_class procname namespace [body] is_objc_method is_instance add_method tenv cg cfg curr_class procname namespace [body] is_objc_method is_instance
captured_vars is_anonym_block param_decls attributes captured_vars is_anonym_block param_decls attributes
| None -> CMethod_signature.add ms | None -> ()
let process_method_decl tenv cg cfg namespace curr_class meth_decl ~is_objc = let process_method_decl tenv cg cfg namespace curr_class meth_decl ~is_objc =
let class_name = Some (CContext.get_curr_class_name curr_class) in
let ms, body_opt, param_decls = let ms, body_opt, param_decls =
CMethod_trans.method_signature_of_decl curr_class meth_decl None in CMethod_trans.method_signature_of_decl class_name meth_decl None in
CMethod_signature.add ms;
match method_body_to_translate ms body_opt with match method_body_to_translate ms 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

@ -14,8 +14,7 @@ module CMethod_decl_funct(T: CModule_type.CTranslation) : sig
Clang_ast_t.decl list -> unit Clang_ast_t.decl list -> unit
val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> Clang_ast_t.decl -> val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> Clang_ast_t.decl ->
(Clang_ast_t.qual_type * bool * Procname.t * (Mangled.t * Sil.typ * bool) list) option -> CModule_type.block_data option -> unit
CContext.curr_class -> unit
val process_getter_setter : CContext.t -> Procname.t -> bool val process_getter_setter : CContext.t -> Procname.t -> bool
@ -26,8 +25,7 @@ module type CMethod_decl = sig
Clang_ast_t.decl list -> unit Clang_ast_t.decl list -> unit
val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> Clang_ast_t.decl -> val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> Clang_ast_t.decl ->
(Clang_ast_t.qual_type * bool * Procname.t * (Mangled.t * Sil.typ * bool) list) option -> CModule_type.block_data option -> unit
CContext.curr_class -> unit
val process_getter_setter : CContext.t -> Procname.t -> bool val process_getter_setter : CContext.t -> Procname.t -> bool
end end

@ -41,10 +41,6 @@ let ms_is_instance ms =
let ms_is_generated ms = let ms_is_generated ms =
ms._is_generated ms._is_generated
type methodMap = method_signature Procname.Map.t
let methodMap = ref Procname.Map.empty
let make_ms procname args ret_type attributes loc is_instance is_generated = let make_ms procname args ret_type attributes loc is_instance is_generated =
let meth_signature = { let meth_signature = {
_name = procname; _name = procname;
@ -64,13 +60,3 @@ let ms_to_string ms =
"Method "^(Procname.to_string ms._name)^gen^" "^ "Method "^(Procname.to_string ms._name)^gen^" "^
(Utils.list_to_string (fun (s1, s2, _) -> s1^", "^s2) ms._args)^"->"^ms._ret_type^" "^ (Utils.list_to_string (fun (s1, s2, _) -> s1^", "^s2) ms._args)^"->"^ms._ret_type^" "^
Clang_ast_j.string_of_source_range ms._loc Clang_ast_j.string_of_source_range ms._loc
let find ms =
Procname.Map.find ms !methodMap
let add ms =
try ignore (find ms._name)
with Not_found -> methodMap := Procname.Map.add ms._name ms !methodMap
let reset_map () =
methodMap := Procname.Map.empty

@ -12,12 +12,6 @@
type method_signature type method_signature
val add : method_signature -> unit
val find : Procname.t -> method_signature
val reset_map : unit -> unit
val ms_get_name : method_signature -> Procname.t val ms_get_name : method_signature -> Procname.t
val ms_get_args : method_signature -> (string * string * Clang_ast_t.stmt option) list val ms_get_args : method_signature -> (string * string * Clang_ast_t.stmt option) list

@ -15,6 +15,8 @@ open CFrontend_utils
module L = Logging module L = Logging
exception Invalid_declaration
(** When the methoc call is MCStatic, means that it is a class method. *) (** When the methoc call is MCStatic, means that it is a class method. *)
(** When it is MCVirtual, it means that it is an instance method and that *) (** When it is MCVirtual, it means that it is an instance method and that *)
(** the method to be called will be determined at runtime. If it is MCNoVirtual *) (** the method to be called will be determined at runtime. If it is MCNoVirtual *)
@ -84,25 +86,23 @@ let build_method_signature decl_info procname function_method_decl_info is_insta
let attributes = decl_info.Clang_ast_t.di_attributes in let attributes = decl_info.Clang_ast_t.di_attributes in
CMethod_signature.make_ms procname parameters qt attributes source_range is_instance_method is_generated CMethod_signature.make_ms procname parameters qt attributes source_range is_instance_method is_generated
let method_signature_of_decl curr_class meth_decl block_data_opt = let method_signature_of_decl class_name_opt 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, class_name_opt with
| FunctionDecl (decl_info, name_info, qt, fdi), _ -> | FunctionDecl (decl_info, name_info, qt, fdi), _, _ ->
let name = name_info.ni_name in let name = name_info.ni_name in
let func_decl = Func_decl_info (fdi, CTypes.get_type qt) in let func_decl = Func_decl_info (fdi, CTypes.get_type qt) in
let procname = General_utils.mk_procname_from_function name (CTypes.get_type qt) in let procname = General_utils.mk_procname_from_function name (CTypes.get_type qt) in
let ms = build_method_signature decl_info procname func_decl false false false in let ms = build_method_signature decl_info procname func_decl false false false in
ms, fdi.Clang_ast_t.fdi_body, fdi.Clang_ast_t.fdi_parameters ms, fdi.Clang_ast_t.fdi_body, fdi.Clang_ast_t.fdi_parameters
| CXXMethodDecl (decl_info, name_info, qt, fdi), _ -> | CXXMethodDecl (decl_info, name_info, qt, fdi), _, Some class_name ->
let class_name = CContext.get_curr_class_name curr_class in
let method_name = name_info.Clang_ast_t.ni_name in let method_name = name_info.Clang_ast_t.ni_name in
let typ = CTypes.get_type qt in let typ = CTypes.get_type qt in
let procname = General_utils.mk_procname_from_cpp_method class_name method_name typ in let procname = General_utils.mk_procname_from_cpp_method class_name method_name typ in
let method_decl = Cpp_Meth_decl_info (fdi, class_name, typ) in let method_decl = Cpp_Meth_decl_info (fdi, class_name, typ) in
let ms = build_method_signature decl_info procname method_decl false false false in let ms = build_method_signature decl_info procname method_decl false false false in
ms, fdi.Clang_ast_t.fdi_body, fdi.Clang_ast_t.fdi_parameters ms, fdi.Clang_ast_t.fdi_body, fdi.Clang_ast_t.fdi_parameters
| ObjCMethodDecl (decl_info, name_info, mdi), _ -> | ObjCMethodDecl (decl_info, name_info, mdi), _, Some class_name ->
let class_name = CContext.get_curr_class_name curr_class in
let method_name = name_info.ni_name in let method_name = name_info.ni_name in
let is_instance = mdi.omdi_is_instance_method in let is_instance = mdi.omdi_is_instance_method in
let method_kind = Procname.objc_method_kind_of_bool is_instance in let method_kind = Procname.objc_method_kind_of_bool is_instance in
@ -112,11 +112,20 @@ let method_signature_of_decl curr_class meth_decl block_data_opt =
let ms = build_method_signature decl_info procname method_decl false false is_generated in let ms = build_method_signature decl_info procname method_decl false false is_generated in
ms, mdi.omdi_body, mdi.omdi_parameters ms, mdi.omdi_body, mdi.omdi_parameters
| BlockDecl (decl_info, decl_list, decl_context_info, bdi), | BlockDecl (decl_info, decl_list, decl_context_info, bdi),
Some (qt, is_instance, procname, _) -> Some (qt, is_instance, procname, _, _), _ ->
let func_decl = Block_decl_info (bdi, CTypes.get_type qt) in let func_decl = Block_decl_info (bdi, CTypes.get_type qt) in
let ms = build_method_signature decl_info procname func_decl is_instance true false in let ms = build_method_signature decl_info procname func_decl is_instance true false in
ms, bdi.bdi_body, bdi.bdi_parameters ms, bdi.bdi_body, bdi.bdi_parameters
|_ -> assert false | _ -> raise Invalid_declaration
let method_signature_of_pointer class_name_opt pointer =
try
match Ast_utils.get_decl pointer with
| Some meth_decl ->
let ms, _, _ = method_signature_of_decl class_name_opt meth_decl None in
Some ms
| None -> None
with Invalid_declaration -> None
let get_superclass_curr_class context = let get_superclass_curr_class context =
let retrive_super cname super_opt = let retrive_super cname super_opt =
@ -140,20 +149,21 @@ let get_superclass_curr_class context =
let get_class_selector_instance context obj_c_message_expr_info act_params = let get_class_selector_instance context obj_c_message_expr_info act_params =
let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in
let pointer = obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer in
match obj_c_message_expr_info.Clang_ast_t.omei_receiver_kind with match obj_c_message_expr_info.Clang_ast_t.omei_receiver_kind with
| `Class qt -> (CTypes.get_type qt, selector, MCStatic) | `Class qt -> (CTypes.get_type qt, selector, pointer, MCStatic)
| `Instance -> | `Instance ->
(match act_params with (match act_params with
| (instance_obj, Sil.Tptr(t, _)):: _ | (instance_obj, Sil.Tptr(t, _)):: _
| (instance_obj, t):: _ -> | (instance_obj, t):: _ ->
(CTypes.classname_of_type t, selector, MCVirtual) (CTypes.classname_of_type t, selector, pointer, MCVirtual)
| _ -> assert false) | _ -> assert false)
| `SuperInstance -> | `SuperInstance ->
let superclass = get_superclass_curr_class context in let superclass = get_superclass_curr_class context in
(superclass, selector, MCNoVirtual) (superclass, selector, pointer, MCNoVirtual)
| `SuperClass -> | `SuperClass ->
let superclass = get_superclass_curr_class context in let superclass = get_superclass_curr_class context in
(superclass, selector, MCStatic) (superclass, selector, pointer, MCStatic)
let get_formal_parameters tenv ms = let get_formal_parameters tenv ms =
let rec defined_parameters pl = let rec defined_parameters pl =

@ -28,10 +28,11 @@ val create_external_procdesc : Cfg.cfg -> Procname.t -> bool -> (Sil.typ * Sil.t
val captured_vars_from_block_info : CContext.t -> Clang_ast_t.block_captured_variable list -> (Mangled.t * Sil.typ * bool) list val captured_vars_from_block_info : CContext.t -> Clang_ast_t.block_captured_variable list -> (Mangled.t * Sil.typ * bool) list
val get_class_selector_instance : CContext.t -> Clang_ast_t.obj_c_message_expr_info -> (Sil.exp * Sil.typ) list val get_class_selector_instance : CContext.t -> Clang_ast_t.obj_c_message_expr_info -> (Sil.exp * Sil.typ) list
-> (string * string * method_call_type) -> (string * string * Clang_ast_t.pointer option * method_call_type)
val should_create_procdesc : Cfg.cfg -> Procname.t -> bool -> bool -> bool val should_create_procdesc : Cfg.cfg -> Procname.t -> bool -> bool -> bool
val method_signature_of_decl : CContext.curr_class -> Clang_ast_t.decl -> val method_signature_of_decl : string option -> Clang_ast_t.decl -> CModule_type.block_data option ->
(Clang_ast_t.qual_type * bool * Procname.t * 'a list) option ->
CMethod_signature.method_signature * Clang_ast_t.stmt option * Clang_ast_t.decl list CMethod_signature.method_signature * Clang_ast_t.stmt option * Clang_ast_t.decl list
val method_signature_of_pointer : string option -> Clang_ast_t.pointer -> CMethod_signature.method_signature option

@ -7,6 +7,8 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*) *)
type block_data = Clang_ast_t.qual_type * bool * Procname.t * (Mangled.t * Sil.typ * bool) list * CContext.curr_class
module type CTranslation = module type CTranslation =
sig sig
val instructions_trans : CContext.t -> Clang_ast_t.stmt list -> Cfg.Node.t -> Cfg.Node.t list val instructions_trans : CContext.t -> Clang_ast_t.stmt list -> Cfg.Node.t -> Cfg.Node.t list
@ -15,8 +17,7 @@ end
module type CMethod_declaration = module type CMethod_declaration =
sig sig
val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> Clang_ast_t.decl -> val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> Clang_ast_t.decl ->
(Clang_ast_t.qual_type * bool * Procname.t * (Mangled.t * Sil.typ * bool) list) option -> block_data option -> unit
CContext.curr_class -> unit
val process_getter_setter : CContext.t -> Procname.t -> bool val process_getter_setter : CContext.t -> Procname.t -> bool
end end

@ -35,10 +35,11 @@ struct
(*Returns the procname and whether is instance, according to the selector *) (*Returns the procname and whether is instance, according to the selector *)
(* information and according to the method signature *) (* information and according to the method signature *)
let get_callee_objc_method context obj_c_message_expr_info act_params = let get_callee_objc_method context obj_c_message_expr_info act_params =
let (class_name, method_name, mc_type) = let (class_name, method_name, method_pointer_opt, mc_type) =
CMethod_trans.get_class_selector_instance context obj_c_message_expr_info act_params in CMethod_trans.get_class_selector_instance context obj_c_message_expr_info act_params in
let is_instance = mc_type != CMethod_trans.MCStatic in let is_instance = mc_type != CMethod_trans.MCStatic in
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 callee_pn = General_utils.mk_procname_from_objc_method class_name method_name method_kind in
let open CContext in let open CContext in
match CTrans_models.get_predefined_model_method_signature class_name method_name match CTrans_models.get_predefined_model_method_signature class_name method_name
General_utils.mk_procname_from_objc_method with General_utils.mk_procname_from_objc_method with
@ -46,16 +47,19 @@ struct
ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv ms [] [] is_instance); ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv ms [] [] is_instance);
CMethod_signature.ms_get_name ms, CMethod_trans.MCNoVirtual CMethod_signature.ms_get_name ms, CMethod_trans.MCNoVirtual
| None -> | None ->
let procname = General_utils.mk_procname_from_objc_method class_name method_name method_kind in let found_method =
try match method_pointer_opt with
let callee_ms = CMethod_signature.find procname in | Some pointer ->
if not (M.process_getter_setter context procname) then (match CMethod_trans.method_signature_of_pointer (Some class_name) pointer with
(ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv callee_ms [] [] is_instance)); | Some callee_ms ->
procname, mc_type if not (M.process_getter_setter context callee_pn) then
with Not_found -> (ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv callee_ms [] [] is_instance));
let callee_pn = General_utils.mk_procname_from_objc_method class_name method_name method_kind in true
| None -> false)
| None -> false in
if not found_method then
CMethod_trans.create_external_procdesc context.cfg callee_pn is_instance None; CMethod_trans.create_external_procdesc context.cfg callee_pn is_instance None;
callee_pn, mc_type callee_pn, mc_type
let add_autorelease_call context exp typ sil_loc = let add_autorelease_call context exp typ sil_loc =
let method_name = Procname.c_get_method (Cfg.Procdesc.get_proc_name context.CContext.procdesc) in let method_name = Procname.c_get_method (Cfg.Procdesc.get_proc_name context.CContext.procdesc) in
@ -295,6 +299,7 @@ struct
let typ = CTypes_decl.qual_type_to_sil_type context.tenv expr_info.Clang_ast_t.ei_qual_type in let typ = CTypes_decl.qual_type_to_sil_type context.tenv expr_info.Clang_ast_t.ei_qual_type in
let name = get_name_decl_ref_exp_info decl_ref_expr_info stmt_info in let name = get_name_decl_ref_exp_info decl_ref_expr_info stmt_info in
let procname = Cfg.Procdesc.get_proc_name context.procdesc in let procname = Cfg.Procdesc.get_proc_name context.procdesc in
let pointer = CTrans_utils.get_decl_pointer decl_ref_expr_info in
let is_function = let is_function =
match get_decl_kind decl_ref_expr_info with match get_decl_kind decl_ref_expr_info with
| `Function -> true | `Function -> true
@ -320,6 +325,11 @@ struct
| Some v -> | Some v ->
(General_utils.mk_procname_from_function name v, CTypes_decl.parse_func_type name v) (General_utils.mk_procname_from_function name v, CTypes_decl.parse_func_type name v)
| None -> (Procname.from_string_c_fun name, None) in | None -> (Procname.from_string_c_fun name, None) in
(match CMethod_trans.method_signature_of_pointer None pointer with
| Some callee_ms ->
ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv callee_ms [] [] false)
| None ->
CMethod_trans.create_external_procdesc context.cfg pname false None);
let address_of_function = not context.CContext.is_callee_expression in let address_of_function = not context.CContext.is_callee_expression in
(* If we are not translating a callee expression, then the address of the function is being taken.*) (* If we are not translating a callee expression, then the address of the function is being taken.*)
(* As e.g. in fun_ptr = foo; *) (* As e.g. in fun_ptr = foo; *)
@ -557,7 +567,7 @@ struct
(Procname.to_string pn) <> CFrontend_config.builtin_object_size (Procname.to_string pn) <> CFrontend_config.builtin_object_size
| _ -> true in | _ -> true in
let params_stmt = if should_translate_args then let params_stmt = if should_translate_args then
CTrans_utils.assign_default_params params_stmt callee_pname_opt ~is_cxx_method:false CTrans_utils.assign_default_params params_stmt None fun_exp_stmt ~is_cxx_method:false
else [] in else [] in
let res_trans_par = let res_trans_par =
let l = list_map (fun i -> exec_with_self_exception instruction trans_state_param i) params_stmt in let l = list_map (fun i -> exec_with_self_exception instruction trans_state_param i) params_stmt in
@ -602,11 +612,6 @@ struct
if not (SymExec.function_is_builtin callee_pname) then if not (SymExec.function_is_builtin callee_pname) then
begin begin
Cg.add_edge context.cg procname callee_pname; Cg.add_edge context.cg procname callee_pname;
try
let callee_ms = CMethod_signature.find callee_pname in
ignore (CMethod_trans.create_local_procdesc context.cfg context.tenv callee_ms [] [] false)
with Not_found ->
CMethod_trans.create_external_procdesc context.cfg callee_pname false None
end end
| None -> ()); | None -> ());
(match ret_id with (match ret_id with
@ -638,8 +643,8 @@ struct
let callee_pname = match sil_method with let callee_pname = match sil_method with
| Sil.Const (Sil.Cfun pn) -> pn | Sil.Const (Sil.Cfun pn) -> pn
| _ -> assert false (* method pointer not implemented, this shouldn't happen *) in | _ -> assert false (* method pointer not implemented, this shouldn't happen *) in
let class_name_opt = Some (Procname.c_get_class callee_pname) in
let params_stmt = CTrans_utils.assign_default_params params_stmt (Some callee_pname) ~is_cxx_method:true in let params_stmt = CTrans_utils.assign_default_params params_stmt class_name_opt fun_exp_stmt ~is_cxx_method:true in
(* As we may have nodes coming from different parameters we need to *) (* As we may have nodes coming from different parameters we need to *)
(* call instruction for each parameter and collect the results *) (* call instruction for each parameter and collect the results *)
(* afterwards. The 'instructions' function does not do that *) (* afterwards. The 'instructions' function does not do that *)
@ -668,12 +673,6 @@ struct
let result_trans_to_parent = let result_trans_to_parent =
PriorityNode.compute_results_to_parent trans_state_pri sil_loc nname si res_trans_tmp in PriorityNode.compute_results_to_parent trans_state_pri sil_loc nname si res_trans_tmp in
Cg.add_edge context.CContext.cg procname callee_pname; Cg.add_edge context.CContext.cg procname callee_pname;
let cfg = context.CContext.cfg in
(try
let callee_ms = CMethod_signature.find callee_pname in
ignore (CMethod_trans.create_local_procdesc cfg context.CContext.tenv callee_ms [] [] false)
with Not_found ->
CMethod_trans.create_external_procdesc cfg callee_pname false None);
match ret_id with match ret_id with
| [] -> { result_trans_to_parent with exps = [] } | [] -> { result_trans_to_parent with exps = [] }
| [ret_id'] -> { result_trans_to_parent with exps = [(Sil.Var ret_id', function_type)] } | [ret_id'] -> { result_trans_to_parent with exps = [(Sil.Var ret_id', function_type)] }
@ -709,7 +708,7 @@ struct
let l = list_map (fun i -> exec_with_self_exception instruction trans_state_param i) rest in let l = list_map (fun i -> exec_with_self_exception instruction trans_state_param i) rest in
obj_c_message_expr_info, collect_res_trans (fst_res_trans :: l) obj_c_message_expr_info, collect_res_trans (fst_res_trans :: l)
| [] -> obj_c_message_expr_info, empty_res_trans) in | [] -> obj_c_message_expr_info, empty_res_trans) in
let (class_type, _, _) = CMethod_trans.get_class_selector_instance context obj_c_message_expr_info res_trans_par.exps in let (class_type, _, _, _) = CMethod_trans.get_class_selector_instance context obj_c_message_expr_info res_trans_par.exps in
if (selector = CFrontend_config.class_method && CTypes.is_class method_type) then if (selector = CFrontend_config.class_method && CTypes.is_class method_type) then
raise (Self.SelfClassException class_type) raise (Self.SelfClassException class_type)
else if is_alloc_or_new then else if is_alloc_or_new then
@ -1764,9 +1763,8 @@ struct
let all_captured_vars = captured_vars @ static_vars in let all_captured_vars = captured_vars @ static_vars in
let ids_instrs = list_map assign_captured_var all_captured_vars in let ids_instrs = list_map assign_captured_var all_captured_vars in
let ids, instrs = list_split ids_instrs in let ids, instrs = list_split ids_instrs in
let block_data = (qual_type, context.is_instance, block_pname, all_captured_vars) in let block_data = (qual_type, context.is_instance, block_pname, all_captured_vars, context.curr_class) in
M.function_decl context.tenv context.cfg context.cg context.namespace decl M.function_decl context.tenv context.cfg context.cg context.namespace decl (Some block_data);
(Some block_data) context.curr_class;
Cfg.set_procname_priority context.cfg block_pname; Cfg.set_procname_priority context.cfg block_pname;
let captured_exps = list_map (fun id -> Sil.Var id) ids in let captured_exps = list_map (fun id -> Sil.Var id) ids in
let tu = Sil.Ctuple ((Sil.Const (Sil.Cfun block_pname)) :: captured_exps) in let tu = Sil.Ctuple ((Sil.Const (Sil.Cfun block_pname)) :: captured_exps) in

@ -571,6 +571,11 @@ let get_decl_kind decl_ref_expr_info =
| Some decl_ref -> decl_ref.Clang_ast_t.dr_kind | Some decl_ref -> decl_ref.Clang_ast_t.dr_kind
| None -> assert false | None -> assert false
let get_decl_pointer decl_ref_expr_info =
match decl_ref_expr_info.Clang_ast_t.drti_decl_ref with
| Some decl_ref -> decl_ref.Clang_ast_t.dr_decl_pointer
| None -> assert false
(* From the manual: A selector is in a certain selector family if, ignoring any leading underscores, *) (* From the manual: A selector is in a certain selector family if, ignoring any leading underscores, *)
(* the first component of the selector either consists entirely of the name of *) (* the first component of the selector either consists entirely of the name of *)
(* the method family or it begins with that followed by character other than lower case letter.*) (* the method family or it begins with that followed by character other than lower case letter.*)
@ -678,27 +683,43 @@ let is_dispatch_function stmt_list =
| _ -> None)) | _ -> None))
| _ -> None | _ -> None
let assign_default_params params_stmt callee_pname_opt ~is_cxx_method = let rec pointer_of_call_expr stmt =
match callee_pname_opt with let open Clang_ast_t in
match stmt with
| DeclRefExpr(_, _, _, decl_ref_expr_info) ->
Some (get_decl_pointer decl_ref_expr_info)
| MemberExpr(_, _, _, member_expr_info) ->
let decl_ref = member_expr_info.Clang_ast_t.mei_decl_ref in
Some decl_ref.Clang_ast_t.dr_decl_pointer
| _ ->
match snd (Clang_ast_proj.get_stmt_tuple stmt) with
| [stmt] -> pointer_of_call_expr stmt
| _ -> None
let assign_default_params params_stmt class_name_opt stmt ~is_cxx_method =
match pointer_of_call_expr stmt with
| Some pointer ->
(match CMethod_trans.method_signature_of_pointer class_name_opt pointer with
| Some callee_ms ->
(let args = CMethod_signature.ms_get_args callee_ms in
let args = if is_cxx_method then match args with _::tl -> tl | _ -> assert false
else args in
let replace_default_arg param =
match param with
| Clang_ast_t.CXXDefaultArgExpr _, (_, _, Some default_instr) ->
default_instr
| instr, _ -> instr in
try
let params_args = list_combine params_stmt args in
list_map replace_default_arg params_args
with Invalid_argument _ ->
(* list_combine failed because of different list lengths *)
Printing.log_err "Param count doesn't match %s\n"
(Procname.to_string (CMethod_signature.ms_get_name callee_ms));
params_stmt)
| None -> params_stmt)
| None -> params_stmt | None -> params_stmt
| Some callee_pname ->
try
let callee_ms = CMethod_signature.find callee_pname in
let args = CMethod_signature.ms_get_args callee_ms in
let args = if is_cxx_method then match args with _::tl -> tl | _ -> assert false
else args in
let params_args = list_combine params_stmt args in
let replace_default_arg param =
match param with
| Clang_ast_t.CXXDefaultArgExpr _, (_, _, Some default_instr) -> default_instr
| instr, _ -> instr in
list_map replace_default_arg params_args
with
| Invalid_argument _ ->
(* list_combine failed because of different list lengths *)
Printing.log_err "Param count doesn't match %s\n" (Procname.to_string callee_pname);
params_stmt
| Not_found -> params_stmt
let is_block_enumerate_function mei = let is_block_enumerate_function mei =
mei.Clang_ast_t.omei_selector = CFrontend_config.enumerateObjectsUsingBlock mei.Clang_ast_t.omei_selector = CFrontend_config.enumerateObjectsUsingBlock

@ -70,6 +70,8 @@ val get_name_decl_ref_exp_info : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.s
val get_decl_kind : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.decl_kind val get_decl_kind : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.decl_kind
val get_decl_pointer : Clang_ast_t.decl_ref_expr_info -> Clang_ast_t.pointer
val is_enumeration_constant : Clang_ast_t.stmt -> bool val is_enumeration_constant : Clang_ast_t.stmt -> bool
val is_member_exp : Clang_ast_t.stmt -> bool val is_member_exp : Clang_ast_t.stmt -> bool
@ -203,7 +205,7 @@ val is_logical_negation_of_int : Sil.tenv -> Clang_ast_t.expr_info -> Clang_ast_
val is_dispatch_function : Clang_ast_t.stmt list -> int option val is_dispatch_function : Clang_ast_t.stmt list -> int option
val assign_default_params : Clang_ast_t.stmt list -> Procname.t option -> val assign_default_params : Clang_ast_t.stmt list -> string option -> Clang_ast_t.stmt ->
is_cxx_method:bool -> Clang_ast_t.stmt list is_cxx_method:bool -> Clang_ast_t.stmt list
val is_block_enumerate_function : Clang_ast_t.obj_c_message_expr_info -> bool val is_block_enumerate_function : Clang_ast_t.obj_c_message_expr_info -> bool

Loading…
Cancel
Save