[clang] Move mk_procname_ functions to separate module

Summary: procnames will depend on Typ.t soon and we need to go from `type_ptr` to `Typ.t` when creating procnames. `CType_decl` does this translation it can't depend on `mk_procname_` functions.

Reviewed By: jvillard

Differential Revision: D4620560

fbshipit-source-id: 9524178
master
Andrzej Kotulski 8 years ago committed by Facebook Github Bot
parent 04d96cb84b
commit 171083fbba

@ -0,0 +1,125 @@
(*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
let rec get_mangled_method_name function_decl_info method_decl_info =
(* For virtual methods return mangled name of the method from most base class
Go recursively until there is no method in any parent class. All names
of the same method need to be the same, otherwise dynamic dispatch won't
work. *)
let open Clang_ast_t in
match method_decl_info.xmdi_overriden_methods with
| [] -> function_decl_info.fdi_mangled_name
| base1_dr :: _ ->
(let base1 = match CAst_utils.get_decl base1_dr.dr_decl_pointer with
| Some b -> b
| _ -> assert false in
match base1 with
| CXXMethodDecl (_, _, _, fdi, mdi)
| CXXConstructorDecl (_, _, _, fdi, mdi)
| CXXConversionDecl (_, _, _, fdi, mdi)
| CXXDestructorDecl (_, _, _, fdi, mdi) ->
get_mangled_method_name fdi mdi
| _ -> assert false)
let mk_c_function translation_unit_context name function_decl_info_opt =
let file =
match function_decl_info_opt with
| Some (decl_info, function_decl_info) ->
(match function_decl_info.Clang_ast_t.fdi_storage_class with
| Some "static" ->
let file_opt = (fst decl_info.Clang_ast_t.di_source_range).Clang_ast_t.sl_file in
Option.value_map ~f:SourceFile.to_string ~default:"" file_opt
| _ -> "")
| None -> "" in
let mangled_opt = match function_decl_info_opt with
| Some (_, function_decl_info) -> function_decl_info.Clang_ast_t.fdi_mangled_name
| _ -> None in
let mangled_name = match mangled_opt with
| Some m when CGeneral_utils.is_cpp_translation translation_unit_context -> m
| _ -> "" in
let mangled = (Utils.string_crc_hex32 file) ^ mangled_name in
if String.is_empty file && String.is_empty mangled_name then
Procname.from_string_c_fun name
else
Procname.C (Procname.c name mangled)
let mk_cpp_method class_name method_name ?meth_decl mangled =
let method_kind = match meth_decl with
| Some (Clang_ast_t.CXXConstructorDecl (_, _, _, _, {xmdi_is_constexpr})) ->
Procname.CPPConstructor (mangled, xmdi_is_constexpr)
| _ ->
Procname.CPPMethod mangled in
Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name method_kind)
let block_procname_with_index defining_proc i =
Config.anonymous_block_prefix ^
(Procname.to_string defining_proc) ^
Config.anonymous_block_num_sep ^
(string_of_int i)
(* Global counter for anonymous block*)
let block_counter = ref 0
let get_next_block_pvar defining_proc =
let name = block_procname_with_index defining_proc (!block_counter +1) in
Pvar.mk_tmp name defining_proc
let reset_block_counter () =
block_counter := 0
let get_fresh_block_index () =
block_counter := !block_counter +1;
!block_counter
let mk_fresh_block_procname defining_proc =
let name = block_procname_with_index defining_proc (get_fresh_block_index ()) in
Procname.mangled_objc_block name
module NoAstDecl = struct
let c_function_of_string translation_unit_context name =
mk_c_function translation_unit_context name None
let cpp_method_of_string class_name method_name =
mk_cpp_method class_name method_name None
let objc_method_of_string_kind class_name method_name method_kind =
Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name method_kind)
end
let from_decl translation_unit_context meth_decl =
let open Clang_ast_t in
match meth_decl with
| FunctionDecl (decl_info, name_info, _, fdi) ->
let name = CAst_utils.get_qualified_name name_info in
let function_info = Some (decl_info, fdi) in
mk_c_function translation_unit_context name function_info
| CXXMethodDecl (_, name_info, _, fdi, mdi)
| CXXConstructorDecl (_, name_info, _, fdi, mdi)
| CXXConversionDecl (_, name_info, _, fdi, mdi)
| CXXDestructorDecl (_, name_info, _, fdi, mdi) ->
let mangled = get_mangled_method_name fdi mdi in
let method_name = CAst_utils.get_unqualified_name name_info in
let class_name = CAst_utils.get_class_name_from_member name_info in
mk_cpp_method class_name method_name ~meth_decl mangled
| ObjCMethodDecl (_, name_info, mdi) ->
let class_name = CAst_utils.get_class_name_from_member name_info 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
NoAstDecl.objc_method_of_string_kind class_name method_name method_kind
| BlockDecl _ ->
let name = Config.anonymous_block_prefix ^ Config.anonymous_block_num_sep ^
(string_of_int (get_fresh_block_index ())) in
Procname.mangled_objc_block name
| _ -> assert false

@ -0,0 +1,35 @@
(*
* Copyright (c) 2017 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
(** Given decl, return its procname. This function should be used for all procedures
present in original AST *)
val from_decl : CFrontend_config.translation_unit_context -> Clang_ast_t.decl -> Procname.t
(** WARNING: functions from this module should not be used if full decl is available in AST *)
module NoAstDecl : sig
val c_function_of_string : CFrontend_config.translation_unit_context -> string -> Procname.t
val cpp_method_of_string : string -> string -> Procname.t
val objc_method_of_string_kind : string -> string -> Procname.objc_cpp_method_kind -> Procname.t
end
(** Makes a fresh name for a block defined inside the defining procedure.
It updates the global block_counter *)
val mk_fresh_block_procname : Procname.t -> Procname.t
(** Returns the next fresh name for a block defined inside the defining procedure
It does not update the global block_counter *)
val get_next_block_pvar : Procname.t -> Pvar.t
val reset_block_counter : unit -> unit

@ -35,7 +35,7 @@ let compute_icfg trans_unit_ctx tenv ast =
let init_global_state_capture () = let init_global_state_capture () =
Ident.NameGenerator.reset (); Ident.NameGenerator.reset ();
CFrontend_config.global_translation_unit_decls := []; CFrontend_config.global_translation_unit_decls := [];
CGeneral_utils.reset_block_counter () CProcname.reset_block_counter ()
let do_source_file translation_unit_context ast = let do_source_file translation_unit_context ast =
let tenv = Tenv.create () in let tenv = Tenv.create () in

@ -106,7 +106,7 @@ struct
Some (ProcAttributes.Objc_getter field_name) Some (ProcAttributes.Objc_getter field_name)
else else
Some (ProcAttributes.Objc_setter field_name) in Some (ProcAttributes.Objc_setter field_name) in
let procname = CGeneral_utils.procname_of_decl trans_unit_ctx d in let procname = CProcname.from_decl trans_unit_ctx d in
let attrs = { (ProcAttributes.default procname Config.Clang) with let attrs = { (ProcAttributes.default procname Config.Clang) with
loc = loc; loc = loc;
objc_accessor = property_accessor; } in objc_accessor = property_accessor; } in

@ -175,7 +175,7 @@ let expand_checkers checkers =
let get_err_log translation_unit_context method_decl_opt = let get_err_log translation_unit_context method_decl_opt =
let procname = match method_decl_opt with let procname = match method_decl_opt with
| Some method_decl -> CGeneral_utils.procname_of_decl translation_unit_context method_decl | Some method_decl -> CProcname.from_decl translation_unit_context method_decl
| None -> Procname.Linters_dummy_method in | None -> Procname.Linters_dummy_method in
LintIssues.get_err_log procname LintIssues.get_err_log procname

@ -86,36 +86,6 @@ let is_static_var var_decl_info =
| Some sc -> String.equal sc CFrontend_config.static | Some sc -> String.equal sc CFrontend_config.static
| _ -> false | _ -> false
let block_procname_with_index defining_proc i =
Config.anonymous_block_prefix ^
(Procname.to_string defining_proc) ^
Config.anonymous_block_num_sep ^
(string_of_int i)
(* Global counter for anonymous block*)
let block_counter = ref 0
(* Returns a fresh index for a new anonymous block *)
let get_fresh_block_index () =
block_counter := !block_counter +1;
!block_counter
(* Makes a fresh name for a block defined inside the defining procedure.*)
(* It updates the global block_counter *)
let mk_fresh_block_procname defining_proc =
let name = block_procname_with_index defining_proc (get_fresh_block_index ()) in
Procname.mangled_objc_block name
(* Returns the next fresh name for a block defined inside the defining procedure *)
(* It does not update the global block_counter *)
let get_next_block_pvar defining_proc =
let name = block_procname_with_index defining_proc (!block_counter +1) in
Pvar.mk_tmp name defining_proc
(* Reset block counter *)
let reset_block_counter () =
block_counter := 0
let rec zip xs ys = let rec zip xs ys =
match xs, ys with match xs, ys with
| [], _ | [], _
@ -144,93 +114,6 @@ let is_objc_extension translation_unit_context =
CFrontend_config.equal_clang_lang lang CFrontend_config.ObjC || CFrontend_config.equal_clang_lang lang CFrontend_config.ObjC ||
CFrontend_config.equal_clang_lang lang CFrontend_config.ObjCPP CFrontend_config.equal_clang_lang lang CFrontend_config.ObjCPP
let rec get_mangled_method_name function_decl_info method_decl_info =
(* For virtual methods return mangled name of the method from most base class
Go recursively until there is no method in any parent class. All names
of the same method need to be the same, otherwise dynamic dispatch won't
work. *)
let open Clang_ast_t in
match method_decl_info.xmdi_overriden_methods with
| [] -> function_decl_info.fdi_mangled_name
| base1_dr :: _ ->
(let base1 = match CAst_utils.get_decl base1_dr.dr_decl_pointer with
| Some b -> b
| _ -> assert false in
match base1 with
| CXXMethodDecl (_, _, _, fdi, mdi)
| CXXConstructorDecl (_, _, _, fdi, mdi)
| CXXConversionDecl (_, _, _, fdi, mdi)
| CXXDestructorDecl (_, _, _, fdi, mdi) ->
get_mangled_method_name fdi mdi
| _ -> assert false)
let mk_procname_from_function translation_unit_context name function_decl_info_opt =
let file =
match function_decl_info_opt with
| Some (decl_info, function_decl_info) ->
(match function_decl_info.Clang_ast_t.fdi_storage_class with
| Some "static" ->
let file_opt = (fst decl_info.Clang_ast_t.di_source_range).Clang_ast_t.sl_file in
Option.value_map ~f:SourceFile.to_string ~default:"" file_opt
| _ -> "")
| None -> "" in
let mangled_opt = match function_decl_info_opt with
| Some (_, function_decl_info) -> function_decl_info.Clang_ast_t.fdi_mangled_name
| _ -> None in
let mangled_name =
match mangled_opt with
| Some m when is_cpp_translation translation_unit_context -> m
| _ -> "" in
let mangled = (Utils.string_crc_hex32 file) ^ mangled_name in
if String.is_empty file && String.is_empty mangled_name then
Procname.from_string_c_fun name
else
Procname.C (Procname.c name mangled)
let mk_procname_from_objc_method class_name method_name method_kind =
Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name method_kind)
let mk_procname_from_cpp_method class_name method_name ?meth_decl mangled =
let method_kind = match meth_decl with
| Some (Clang_ast_t.CXXConstructorDecl (_, _, _, _, {xmdi_is_constexpr})) ->
Procname.CPPConstructor (mangled, xmdi_is_constexpr)
| _ ->
Procname.CPPMethod mangled in
Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name method_kind)
let get_objc_method_name name_info mdi class_name =
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
mk_procname_from_objc_method class_name method_name method_kind
let procname_of_decl translation_unit_context meth_decl =
let open Clang_ast_t in
match meth_decl with
| FunctionDecl (decl_info, name_info, _, fdi) ->
let name = CAst_utils.get_qualified_name name_info in
let function_info = Some (decl_info, fdi) in
mk_procname_from_function translation_unit_context name function_info
| CXXMethodDecl (_, name_info, _, fdi, mdi)
| CXXConstructorDecl (_, name_info, _, fdi, mdi)
| CXXConversionDecl (_, name_info, _, fdi, mdi)
| CXXDestructorDecl (_, name_info, _, fdi, mdi) ->
let mangled = get_mangled_method_name fdi mdi in
let method_name = CAst_utils.get_unqualified_name name_info in
let class_name = CAst_utils.get_class_name_from_member name_info in
mk_procname_from_cpp_method class_name method_name ~meth_decl mangled
| ObjCMethodDecl (_, name_info, mdi) ->
let class_name = CAst_utils.get_class_name_from_member name_info in
get_objc_method_name name_info mdi class_name
| BlockDecl _ ->
let name = Config.anonymous_block_prefix ^ Config.anonymous_block_num_sep ^
(string_of_int (get_fresh_block_index ())) in
Procname.mangled_objc_block name
| _ -> assert false
let get_var_name_mangled name_info var_decl_info = let get_var_name_mangled name_info var_decl_info =
let clang_name = CAst_utils.get_qualified_name name_info in let clang_name = CAst_utils.get_qualified_name name_info in
let param_idx_opt = var_decl_info.Clang_ast_t.vdi_parm_index_in_function in let param_idx_opt = var_decl_info.Clang_ast_t.vdi_parm_index_in_function in

@ -37,31 +37,12 @@ val swap_elements_list : 'a list -> 'a list
val is_static_var : Clang_ast_t.var_decl_info -> bool val is_static_var : Clang_ast_t.var_decl_info -> bool
val mk_fresh_block_procname : Procname.t -> Procname.t
val get_next_block_pvar : Procname.t -> Pvar.t
val reset_block_counter : unit -> unit
val zip: 'a list -> 'b list -> ('a * 'b) list val zip: 'a list -> 'b list -> ('a * 'b) list
val list_range: int -> int -> int list val list_range: int -> int -> int list
val replicate: int -> 'a -> 'a list val replicate: int -> 'a -> 'a list
val mk_procname_from_objc_method : string -> string -> Procname.objc_cpp_method_kind -> Procname.t
val mk_procname_from_function : CFrontend_config.translation_unit_context -> string
-> (Clang_ast_t.decl_info * Clang_ast_t.function_decl_info) option -> Procname.t
val get_mangled_method_name : Clang_ast_t.function_decl_info ->
Clang_ast_t.cxx_method_decl_info -> string option
val mk_procname_from_cpp_method :
string -> string -> ?meth_decl:Clang_ast_t.decl -> string option -> Procname.t
val procname_of_decl : CFrontend_config.translation_unit_context -> Clang_ast_t.decl -> Procname.t
val mk_class_field_name : Clang_ast_t.named_decl_info -> Ident.fieldname val mk_class_field_name : Clang_ast_t.named_decl_info -> Ident.fieldname
val get_var_name_mangled : Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info -> val get_var_name_mangled : Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info ->

@ -162,7 +162,7 @@ let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt =
match meth_decl, block_data_opt with match meth_decl, block_data_opt with
| FunctionDecl (decl_info, _, qt, fdi), _ -> | FunctionDecl (decl_info, _, qt, fdi), _ ->
let func_decl = Func_decl_info (fdi, qt.Clang_ast_t.qt_type_ptr) in let func_decl = Func_decl_info (fdi, qt.Clang_ast_t.qt_type_ptr) in
let procname = CGeneral_utils.procname_of_decl trans_unit_ctx meth_decl in let procname = CProcname.from_decl trans_unit_ctx meth_decl in
let ms = build_method_signature trans_unit_ctx tenv decl_info procname func_decl None None in let ms = build_method_signature trans_unit_ctx tenv decl_info procname func_decl 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
@ -170,7 +170,7 @@ let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt =
| CXXConstructorDecl (decl_info, _, qt, fdi, mdi), _ | CXXConstructorDecl (decl_info, _, qt, fdi, mdi), _
| CXXConversionDecl (decl_info, _, qt, fdi, mdi), _ | CXXConversionDecl (decl_info, _, qt, fdi, mdi), _
| CXXDestructorDecl (decl_info, _, qt, fdi, mdi), _ -> | CXXDestructorDecl (decl_info, _, qt, fdi, mdi), _ ->
let procname = CGeneral_utils.procname_of_decl trans_unit_ctx meth_decl in let procname = CProcname.from_decl trans_unit_ctx meth_decl in
let parent_ptr = Option.value_exn decl_info.di_parent_pointer in let parent_ptr = Option.value_exn decl_info.di_parent_pointer in
let method_decl = Cpp_Meth_decl_info (fdi, mdi, parent_ptr, qt.Clang_ast_t.qt_type_ptr) in let method_decl = Cpp_Meth_decl_info (fdi, mdi, parent_ptr, qt.Clang_ast_t.qt_type_ptr) 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
@ -180,7 +180,7 @@ let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt =
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 *)
ms, fdi.Clang_ast_t.fdi_body, (init_list_instrs @ non_null_instrs) ms, fdi.Clang_ast_t.fdi_body, (init_list_instrs @ non_null_instrs)
| ObjCMethodDecl (decl_info, _, mdi), _ -> | ObjCMethodDecl (decl_info, _, mdi), _ ->
let procname = CGeneral_utils.procname_of_decl trans_unit_ctx meth_decl in let procname = CProcname.from_decl trans_unit_ctx meth_decl in
let parent_ptr = Option.value_exn decl_info.di_parent_pointer in let parent_ptr = Option.value_exn decl_info.di_parent_pointer in
let method_decl = ObjC_Meth_decl_info (mdi, parent_ptr) in let method_decl = ObjC_Meth_decl_info (mdi, parent_ptr) 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
@ -468,9 +468,9 @@ let create_procdesc_with_pointer context pointer class_name_opt name =
let callee_name = let callee_name =
match class_name_opt with match class_name_opt with
| Some class_name -> | Some class_name ->
CGeneral_utils.mk_procname_from_cpp_method class_name name None CProcname.NoAstDecl.cpp_method_of_string class_name name
| None -> | None ->
CGeneral_utils.mk_procname_from_function context.translation_unit_context name None in CProcname.NoAstDecl.c_function_of_string context.translation_unit_context name in
create_external_procdesc context.cfg callee_name false None; create_external_procdesc context.cfg callee_name false None;
callee_name callee_name

@ -43,12 +43,12 @@ struct
| None -> (* fall back to our method resolution if clang's fails *) | None -> (* fall back to our method resolution if clang's fails *)
let class_name = CMethod_trans.get_class_name_method_call_from_receiver_kind context let class_name = CMethod_trans.get_class_name_method_call_from_receiver_kind context
obj_c_message_expr_info act_params in obj_c_message_expr_info act_params in
CGeneral_utils.mk_procname_from_objc_method class_name selector method_kind in CProcname.NoAstDecl.objc_method_of_string_kind class_name selector method_kind in
let predefined_ms_opt = match proc_name with let predefined_ms_opt = match proc_name with
| Procname.ObjC_Cpp objc_cpp -> | Procname.ObjC_Cpp objc_cpp ->
let class_name = Procname.objc_cpp_get_class_name objc_cpp in let class_name = Procname.objc_cpp_get_class_name objc_cpp in
CTrans_models.get_predefined_model_method_signature class_name selector CTrans_models.get_predefined_model_method_signature class_name selector
CGeneral_utils.mk_procname_from_objc_method CFrontend_config.ObjC CProcname.NoAstDecl.objc_method_of_string_kind CFrontend_config.ObjC
| _ -> | _ ->
None in None in
match predefined_ms_opt, ms_opt with match predefined_ms_opt, ms_opt with
@ -1120,7 +1120,7 @@ struct
and block_enumeration_trans trans_state stmt_info stmt_list ei = and block_enumeration_trans trans_state stmt_info stmt_list ei =
Logging.out_debug "\n Call to a block enumeration function treated as special case...\n@."; Logging.out_debug "\n Call to a block enumeration function treated as special case...\n@.";
let procname = Procdesc.get_proc_name trans_state.context.CContext.procdesc in let procname = Procdesc.get_proc_name trans_state.context.CContext.procdesc in
let pvar = CGeneral_utils.get_next_block_pvar procname in let pvar = CProcname.get_next_block_pvar procname in
let transformed_stmt, _ = let transformed_stmt, _ =
Ast_expressions.translate_block_enumerate (Pvar.to_string pvar) stmt_info stmt_list ei in Ast_expressions.translate_block_enumerate (Pvar.to_string pvar) stmt_info stmt_list ei in
instruction trans_state transformed_stmt instruction trans_state transformed_stmt
@ -2061,7 +2061,7 @@ struct
| Clang_ast_t.BlockDecl (_, block_decl_info) -> | Clang_ast_t.BlockDecl (_, block_decl_info) ->
let open CContext in let open CContext in
let type_ptr = expr_info.Clang_ast_t.ei_type_ptr in let type_ptr = expr_info.Clang_ast_t.ei_type_ptr in
let block_pname = CGeneral_utils.mk_fresh_block_procname procname in let block_pname = CProcname.mk_fresh_block_procname procname in
let typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in let typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in
(* We need to set the explicit dependency between the newly created block and the *) (* We need to set the explicit dependency between the newly created block and the *)
(* defining procedure. We add an edge in the call graph.*) (* defining procedure. We add an edge in the call graph.*)

@ -335,7 +335,7 @@ let objc_new_trans trans_state loc stmt_info cls_name function_type =
let is_instance = true in let is_instance = true in
let call_flags = { CallFlags.default with CallFlags.cf_virtual = is_instance; } in let call_flags = { CallFlags.default with CallFlags.cf_virtual = is_instance; } in
let pname = let pname =
CGeneral_utils.mk_procname_from_objc_method CProcname.NoAstDecl.objc_method_of_string_kind
cls_name CFrontend_config.init Procname.ObjCInstanceMethod in cls_name CFrontend_config.init Procname.ObjCInstanceMethod in
CMethod_trans.create_external_procdesc trans_state.context.CContext.cfg pname is_instance None; CMethod_trans.create_external_procdesc trans_state.context.CContext.cfg pname is_instance None;
let args = [(alloc_ret_exp, alloc_ret_type)] in let args = [(alloc_ret_exp, alloc_ret_type)] in

Loading…
Cancel
Save