[clang] Refactor of creating method signatures. First step to use the map of pointers to find method declarations.

Summary:
Refactor of creating method signatures. First step to use the map of pointers to find method declarations.
The idea is to have a function that creates a method signature from a declaration, later we can get the declaration from a pointer
and use this function to retrieve the method signature.

(authored by @dulmarod)
master
Jules Villard 10 years ago
parent ca2699842d
commit 85b0ef7266

@ -29,8 +29,7 @@ let rec translate_one_declaration tenv cg cfg namespace dec =
let should_translate_enum = CLocation.should_translate_enum source_range in
match dec with
| FunctionDecl(di, name_info, qt, fdecl_info) ->
let name = name_info.Clang_ast_t.ni_name in
CMethod_declImpl.function_decl tenv cfg cg namespace false di name qt fdecl_info [] None CContext.ContextNoCls
CMethod_declImpl.function_decl tenv cfg cg namespace dec None CContext.ContextNoCls
| TypedefDecl (decl_info, name_info, opt_type, _, typedef_decl_info) ->
let name = name_info.Clang_ast_t.ni_name in
CTypes_decl.do_typedef_declaration tenv namespace
@ -94,8 +93,8 @@ let rec translate_one_declaration tenv cg cfg namespace dec =
(* Translates a file by translating the ast into a cfg. *)
let compute_icfg tenv source_file ast =
match ast with
| TranslationUnitDecl(_, decl_list, _, _) ->
CFrontend_config.global_translation_unit_decls:= decl_list;
| Clang_ast_t.TranslationUnitDecl(_, decl_list, _, _) ->
CFrontend_config.global_translation_unit_decls := decl_list;
Printing.log_out "\n Start creating icfg\n";
let cg = Cg.create () in
let cfg = Cfg.Node.create_cfg () in

@ -20,8 +20,9 @@ module type CMethod_decl = sig
val process_methods : Sil.tenv -> Cg.t -> Cfg.cfg -> CContext.curr_class -> string option ->
Clang_ast_t.decl list -> unit
val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> bool -> Clang_ast_t.decl_info ->
string -> Clang_ast_t.qual_type -> Clang_ast_t.function_decl_info -> (Mangled.t * Sil.typ * bool) list -> Procname.t option -> CContext.curr_class -> unit
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 ->
CContext.curr_class -> unit
val process_getter_setter : CContext.t -> Procname.t -> bool
end
@ -29,68 +30,13 @@ end
module CMethod_decl_funct(T: CModule_type.CTranslation) : CMethod_decl =
struct
let method_body_to_translate di ms body =
let method_body_to_translate ms body =
match body with
| Some body ->
if not (CLocation.should_translate_lib (CMethod_signature.ms_get_loc ms))
then None else Some body
| None -> body
type function_method_decl_info =
| Func_decl_info of Clang_ast_t.function_decl_info * string
| Meth_decl_info of Clang_ast_t.obj_c_method_decl_info * string
let is_instance_method function_method_decl_info is_instance is_anonym_block =
if is_anonym_block then is_instance
else (
match function_method_decl_info with
| Func_decl_info (function_decl_info, _) -> false
| Meth_decl_info (method_decl_info, _) ->
method_decl_info.Clang_ast_t.omdi_is_instance_method)
let get_parameters function_method_decl_info =
let par_to_ms_par par =
match par with
| ParmVarDecl(decl_info, name_info, qtype, var_decl_info) ->
let name = name_info.Clang_ast_t.ni_name in
Printing.log_out "Adding param '%s' " name;
Printing.log_out "with pointer %s@." decl_info.Clang_ast_t.di_pointer;
(name, CTypes.get_type qtype, var_decl_info.vdi_init_expr)
| _ -> assert false in
match function_method_decl_info with
| Func_decl_info (function_decl_info, _) ->
list_map par_to_ms_par function_decl_info.Clang_ast_t.fdi_parameters
| Meth_decl_info (method_decl_info, class_name) ->
let pars = list_map par_to_ms_par method_decl_info.Clang_ast_t.omdi_parameters in
if (is_instance_method function_method_decl_info false false) then
("self", class_name, None):: pars
else pars
let get_return_type function_method_decl_info =
match function_method_decl_info with
| Func_decl_info (_, qt) -> qt
| Meth_decl_info (method_decl_info, _) ->
let qt = method_decl_info.Clang_ast_t.omdi_result_type in
CTypes.get_type qt
let build_method_signature decl_info procname function_method_decl_info is_instance is_anonym_block is_generated =
let source_range = decl_info.Clang_ast_t.di_source_range in
let qt = get_return_type function_method_decl_info in
let is_instance_method = is_instance_method function_method_decl_info is_instance is_anonym_block in
let parameters = get_parameters function_method_decl_info 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
let create_function_signature di fdecl_info name qt is_instance anonym_block_opt =
let procname, is_anonym_block =
match anonym_block_opt with
| Some block -> block, true
| None -> CMethod_trans.mk_procname_from_function name (CTypes.get_type qt), false in
let ms = build_method_signature di procname
(Func_decl_info (fdecl_info, CTypes.get_type qt)) is_instance is_anonym_block false in
(match method_body_to_translate di ms fdecl_info.Clang_ast_t.fdi_body with
| Some body -> Some body, ms
| None -> None, ms)
let model_exists procname =
Specs.summary_exists_in_models procname && not !CFrontend_config.models_mode
@ -147,58 +93,55 @@ struct
CMethod_trans.create_external_procdesc cfg procname is_objc_method None;
()
let function_decl tenv cfg cg namespace is_instance di name qt fdecl_info captured_vars anonym_block_opt curr_class =
Printing.log_out "\nFound FunctionDecl '%s'. Processing...\n" name;
let function_decl tenv cfg cg namespace func_decl block_data_opt curr_class =
Printing.log_out "\nResetting the goto_labels hashmap...\n";
CTrans_utils.GotoLabel.reset_all_labels (); (* C Language Std 6.8.6.1-1 *)
match create_function_signature di fdecl_info name qt is_instance anonym_block_opt with
| Some body, ms -> (* Only in the case the function declaration has a defined body we create a procdesc *)
let ms, body_opt, param_decls =
CMethod_trans.method_signature_of_decl curr_class 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
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
let is_instance = CMethod_signature.ms_is_instance ms in
let is_anonym_block = Option.is_some anonym_block_opt 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
CMethod_signature.add ms;
add_method tenv cg cfg curr_class procname namespace [body] is_objc_method is_instance
captured_vars is_anonym_block fdecl_info.Clang_ast_t.fdi_parameters attributes
| None, ms -> CMethod_signature.add ms
let process_objc_method_decl tenv cg cfg namespace curr_class decl_info name_info method_decl_info =
let class_name = CContext.get_curr_class_name curr_class in
let method_name = name_info.Clang_ast_t.ni_name in
let is_instance = method_decl_info.Clang_ast_t.omdi_is_instance_method in
let method_kind = Procname.objc_method_kind_of_bool is_instance in
let procname = CMethod_trans.mk_procname_from_method class_name method_name method_kind in
let method_decl = Meth_decl_info (method_decl_info, class_name) in
let is_generated = Ast_utils.is_generated name_info in
let ms = build_method_signature decl_info procname method_decl false false is_generated in
Printing.log_out " ....Processing implementation for method '%s'\n" (Procname.to_string procname);
captured_vars is_anonym_block param_decls attributes
| None -> CMethod_signature.add ms
let process_objc_method_decl tenv cg cfg namespace curr_class meth_decl =
let ms, body_opt, param_decls =
CMethod_trans.method_signature_of_decl curr_class meth_decl None in
CMethod_signature.add ms;
(match method_body_to_translate decl_info ms method_decl_info.Clang_ast_t.omdi_body with
| Some body ->
let is_instance = CMethod_signature.ms_is_instance ms in
let attributes = CMethod_signature.ms_get_attributes 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] true is_instance [] false
method_decl_info.Clang_ast_t.omdi_parameters attributes
| None -> ())
match method_body_to_translate ms body_opt with
| Some body ->
let is_instance = CMethod_signature.ms_is_instance ms in
let attributes = CMethod_signature.ms_get_attributes 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] true is_instance [] false
param_decls attributes
| None -> ()
let rec process_one_method_decl tenv cg cfg curr_class namespace dec =
match dec with
| ObjCMethodDecl(decl_info, name_info, method_decl_info) ->
process_objc_method_decl tenv cg cfg namespace curr_class decl_info name_info method_decl_info
| ObjCPropertyImplDecl(decl_info, property_impl_decl_info) ->
| ObjCMethodDecl (decl_info, name_info, method_decl_info) ->
process_objc_method_decl tenv cg cfg namespace curr_class dec
| ObjCPropertyImplDecl (decl_info, property_impl_decl_info) ->
let pname = Ast_utils.property_name property_impl_decl_info in
Printing.log_out "ADDING: ObjCPropertyImplDecl for property '%s' " pname;
let getter_setter = ObjcProperty_decl.make_getter_setter curr_class decl_info pname in
list_iter (process_one_method_decl tenv cg cfg curr_class namespace) getter_setter
| EmptyDecl _ | ObjCIvarDecl _ | ObjCPropertyDecl _ -> ()
| d -> Printing.log_err
"\nWARNING: found Method Declaration '%s' skipped. NEED TO BE FIXED\n\n" (Ast_utils.string_of_decl d);
| _ ->
Printing.log_stats
"\nWARNING: found Method Declaration '%s' skipped. NEED TO BE FIXED\n\n" (Ast_utils.string_of_decl dec);
()
let process_methods tenv cg cfg curr_class namespace decl_list =

@ -13,8 +13,9 @@ module CMethod_decl_funct(T: CModule_type.CTranslation) : sig
val process_methods : Sil.tenv -> Cg.t -> Cfg.cfg -> CContext.curr_class -> string option ->
Clang_ast_t.decl list -> unit
val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> bool -> Clang_ast_t.decl_info ->
string -> Clang_ast_t.qual_type -> Clang_ast_t.function_decl_info -> (Mangled.t * Sil.typ * bool) list -> Procname.t option -> CContext.curr_class -> unit
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 ->
CContext.curr_class -> unit
val process_getter_setter : CContext.t -> Procname.t -> bool
@ -24,8 +25,9 @@ module type CMethod_decl = sig
val process_methods : Sil.tenv -> Cg.t -> Cfg.cfg -> CContext.curr_class -> string option ->
Clang_ast_t.decl list -> unit
val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> bool -> Clang_ast_t.decl_info ->
string -> Clang_ast_t.qual_type -> Clang_ast_t.function_decl_info -> (Mangled.t * Sil.typ * bool) list -> Procname.t option -> CContext.curr_class -> unit
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 ->
CContext.curr_class -> unit
val process_getter_setter : CContext.t -> Procname.t -> bool
end

@ -13,9 +13,19 @@
open Utils
open CFrontend_utils
open CContext
open Clang_ast_t
module L = Logging
let mk_procname_from_function name type_name =
let type_name_crc = CRC.crc16 type_name in
Procname.mangled_c_fun name type_name_crc
let mk_procname_from_method class_name method_name method_kind =
let mangled = Procname.mangled_of_objc_method_kind method_kind in
Procname.mangled_c_method class_name method_name mangled
(** 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 *)
(** the method to be called will be determined at runtime. If it is MCNoVirtual *)
@ -26,13 +36,79 @@ type method_call_type =
| MCNoVirtual
| MCStatic
let mk_procname_from_function name type_name =
let type_name_crc = CRC.crc16 type_name in
Procname.mangled_c_fun name type_name_crc
type function_method_decl_info =
| Func_decl_info of Clang_ast_t.function_decl_info * string
| Meth_decl_info of Clang_ast_t.obj_c_method_decl_info * string
| Block_decl_info of Clang_ast_t.block_decl_info * string
let is_instance_method function_method_decl_info is_instance =
match function_method_decl_info with
| Func_decl_info (function_decl_info, _) -> false
| Meth_decl_info (method_decl_info, _) ->
method_decl_info.Clang_ast_t.omdi_is_instance_method
| Block_decl_info (block_decl_info, _) -> is_instance
let get_parameters function_method_decl_info =
let par_to_ms_par par =
match par with
| ParmVarDecl(decl_info, name_info, qtype, var_decl_info) ->
let name = name_info.Clang_ast_t.ni_name in
Printing.log_out "Adding param '%s' " name;
Printing.log_out "with pointer %s@." decl_info.Clang_ast_t.di_pointer;
(name, CTypes.get_type qtype, var_decl_info.vdi_init_expr)
| _ -> assert false in
match function_method_decl_info with
| Func_decl_info (function_decl_info, _) ->
list_map par_to_ms_par function_decl_info.Clang_ast_t.fdi_parameters
| Meth_decl_info (method_decl_info, class_name) ->
let pars = list_map par_to_ms_par method_decl_info.Clang_ast_t.omdi_parameters in
if (is_instance_method function_method_decl_info false) then
("self", class_name, None):: pars
else pars
| Block_decl_info (block_decl_info, _) ->
list_map par_to_ms_par block_decl_info.Clang_ast_t.bdi_parameters
let get_return_type function_method_decl_info =
match function_method_decl_info with
| Func_decl_info (_, qt) -> qt
| Meth_decl_info (method_decl_info, _) ->
let qt = method_decl_info.Clang_ast_t.omdi_result_type in
CTypes.get_type qt
| Block_decl_info (_, qt) -> qt
let build_method_signature decl_info procname function_method_decl_info is_instance is_anonym_block is_generated =
let source_range = decl_info.Clang_ast_t.di_source_range in
let qt = get_return_type function_method_decl_info in
let is_instance_method = is_instance_method function_method_decl_info is_instance in
let parameters = get_parameters function_method_decl_info 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
let method_signature_of_decl curr_class meth_decl block_data_opt =
match meth_decl, block_data_opt with
| FunctionDecl(decl_info, name_info, qt, fdi), _ ->
let name = name_info.Clang_ast_t.ni_name in
let func_decl = Func_decl_info (fdi, CTypes.get_type qt) in
let procname = mk_procname_from_function name (CTypes.get_type qt) 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
| ObjCMethodDecl(decl_info, name_info, mdi), _ ->
let class_name = CContext.get_curr_class_name curr_class in
let method_name = name_info.Clang_ast_t.ni_name in
let is_instance = mdi.Clang_ast_t.omdi_is_instance_method in
let method_kind = Procname.objc_method_kind_of_bool is_instance in
let procname = mk_procname_from_method class_name method_name method_kind in
let method_decl = Meth_decl_info (mdi, class_name) in
let is_generated = Ast_utils.is_generated name_info in
let ms = build_method_signature decl_info procname method_decl false false is_generated in
ms, mdi.Clang_ast_t.omdi_body, mdi.Clang_ast_t.omdi_parameters
| BlockDecl(decl_info, decl_list, decl_context_info, bdi), Some (qt, is_instance, procname, _) ->
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
ms, bdi.Clang_ast_t.bdi_body, bdi.Clang_ast_t.bdi_parameters
|_ -> assert false
let mk_procname_from_method class_name method_name method_kind =
let mangled = Procname.mangled_of_objc_method_kind method_kind in
Procname.mangled_c_method class_name method_name mangled
let get_superclass_curr_class context =
let retrive_super cname super_opt =

@ -35,3 +35,7 @@ val get_class_selector_instance : CContext.t -> Clang_ast_t.obj_c_message_expr_i
-> (string * string * method_call_type)
val should_create_procdesc : Cfg.cfg -> Procname.t -> bool -> bool -> bool
val method_signature_of_decl : CContext.curr_class -> Clang_ast_t.decl ->
(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

@ -14,8 +14,9 @@ end
module type CMethod_declaration =
sig
val function_decl : Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> bool -> Clang_ast_t.decl_info ->
string -> Clang_ast_t.qual_type -> Clang_ast_t.function_decl_info -> (Mangled.t * Sil.typ * bool) list -> Procname.t option -> CContext.curr_class -> unit
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 ->
CContext.curr_class -> unit
val process_getter_setter : CContext.t -> Procname.t -> bool
end

@ -1617,33 +1617,33 @@ struct
let id = Ident.create_fresh Ident.knormal in
let instr = Sil.Letderef (id, Sil.Lvar (Sil.mk_pvar cvar procname), typ, loc) in
(id, instr) in
(match decl with
| BlockDecl(decl_info, decl_list, decl_context_info, block_decl_info) ->
let qual_type = expr_info.Clang_ast_t.ei_qual_type in
let block_pname = CFrontend_utils.General_utils.mk_fresh_block_procname procname in
let typ = CTypes_decl.qual_type_to_sil_type context.tenv qual_type in
(* We need to set the explicit dependency between the newly created block and the *)
(* defining procedure. We add an edge in the call graph.*)
Cg.add_edge context.cg procname block_pname;
let function_decl_info = CFrontend_utils.General_utils.mk_function_decl_info_from_block block_decl_info in
let static_locals = list_filter (fun (v, t, s) -> s = true) context.local_vars in
(*list_iter (fun (v, _, _) -> L.err "Static Locals %s@." (Mangled.to_string v)) static_locals;*)
let static_formals = list_filter (fun (v, t, s) -> s = true) context.captured_vars in
(*list_iter (fun (v, _, _) -> L.err "Formal Static %s@." (Mangled.to_string v)) static_formals;*)
let static_vars = static_locals @ static_formals in
let captured_vars =
(CMethod_trans.captured_vars_from_block_info context block_decl_info.Clang_ast_t.bdi_captured_variables) 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_split ids_instrs in
M.function_decl context.tenv context.cfg context.cg context.namespace context.is_instance decl_info
(Procname.to_string block_pname) qual_type function_decl_info all_captured_vars (Some block_pname) context.curr_class;
Cfg.set_procname_priority context.cfg block_pname;
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 alloc_block_instr, ids_block = allocate_block trans_state (Procname.to_string block_pname) all_captured_vars loc in
{ empty_res_trans with ids = ids_block @ ids; instrs = alloc_block_instr @ instrs; exps = [(Sil.Const tu, typ)]}
| _ -> assert false)
match decl with
| BlockDecl(decl_info, decl_list, decl_context_info, block_decl_info) ->
let qual_type = expr_info.Clang_ast_t.ei_qual_type in
let block_pname = CFrontend_utils.General_utils.mk_fresh_block_procname procname in
let typ = CTypes_decl.qual_type_to_sil_type context.tenv qual_type in
(* We need to set the explicit dependency between the newly created block and the *)
(* defining procedure. We add an edge in the call graph.*)
Cg.add_edge context.cg procname block_pname;
let static_locals = list_filter (fun (v, t, s) -> s = true) context.local_vars in
(*list_iter (fun (v, _, _) -> L.err "Static Locals %s@." (Mangled.to_string v)) static_locals;*)
let static_formals = list_filter (fun (v, t, s) -> s = true) context.captured_vars in
(*list_iter (fun (v, _, _) -> L.err "Formal Static %s@." (Mangled.to_string v)) static_formals;*)
let static_vars = static_locals @ static_formals in
let captured_vars =
(CMethod_trans.captured_vars_from_block_info context block_decl_info.Clang_ast_t.bdi_captured_variables) 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_split ids_instrs in
let block_data = (qual_type, context.is_instance, block_pname, all_captured_vars) in
M.function_decl context.tenv context.cfg context.cg context.namespace decl
(Some block_data) context.curr_class;
Cfg.set_procname_priority context.cfg block_pname;
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 alloc_block_instr, ids_block = allocate_block trans_state (Procname.to_string block_pname) all_captured_vars loc in
{ empty_res_trans with ids = ids_block @ ids; instrs = alloc_block_instr @ instrs; exps = [(Sil.Const tu, typ)]}
| _ -> assert false
and cxxNewExpr_trans trans_state stmt_info expr_info =
let context = trans_state.context in

Loading…
Cancel
Save