You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
4.1 KiB
103 lines
4.1 KiB
(*
|
|
* Copyright (c) 2015 - 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 Utils
|
|
|
|
type procedure_type =
|
|
| ALL
|
|
| DEFINED
|
|
| OBJC_GENERATED
|
|
|
|
let print_map procname_map =
|
|
Procname.Hash.iter
|
|
(fun pname redefined ->
|
|
print_endline ((Procname.to_string pname)^" "^(string_of_bool redefined)))
|
|
procname_map
|
|
|
|
let process_all_cfgs process_function default_value =
|
|
let source_dirs = DB.find_source_dirs () in
|
|
let process_dir source_dir value =
|
|
let cfg_name = DB.source_dir_get_internal_file source_dir ".cfg" in
|
|
let cfg_opt = Cfg.load_cfg_from_file cfg_name in
|
|
match cfg_opt with
|
|
| None -> value
|
|
| Some cfg -> process_function cfg source_dir in
|
|
IList.fold_right process_dir source_dirs default_value
|
|
|
|
let process_procedures process_function default_value procedure_type =
|
|
let process_cfg_procedures cfg source_dir =
|
|
let procdescs =
|
|
match procedure_type with
|
|
| DEFINED -> Cfg.get_defined_procs cfg
|
|
| ALL -> Cfg.get_all_procs cfg
|
|
| OBJC_GENERATED -> Cfg.get_objc_generated_procs cfg in
|
|
IList.fold_right (process_function cfg source_dir) procdescs default_value in
|
|
process_all_cfgs process_cfg_procedures default_value
|
|
|
|
let process_all_procedures process_function default_value =
|
|
process_procedures process_function default_value ALL
|
|
|
|
let process_defined_procedures process_function default_value =
|
|
process_procedures process_function default_value DEFINED
|
|
|
|
let process_objc_generated_procedures process_function default_value =
|
|
process_procedures process_function default_value OBJC_GENERATED
|
|
|
|
(* first run to fill the map. The bool that indicates whether the method *)
|
|
(* has a real implementation is false by default *)
|
|
let fill_generated_proc_map generated_proc_map =
|
|
let add_generated_pname_to_map cfg source_dir procdesc () =
|
|
let pname = Cfg.Procdesc.get_proc_name procdesc in
|
|
Procname.Hash.replace generated_proc_map pname false in
|
|
process_objc_generated_procedures add_generated_pname_to_map ()
|
|
|
|
(* second run to update the map. Now we check whether there is a real *)
|
|
(* implementation for the generated methods *)
|
|
let update_generate_proc_map generated_proc_map =
|
|
let update_generated_pname_to_map cfg source_dir procdesc () =
|
|
let cfg_pname = Cfg.Procdesc.get_proc_name procdesc in
|
|
if not (Cfg.Procdesc.get_attributes procdesc).ProcAttributes.is_generated then
|
|
try ignore(Procname.Hash.find generated_proc_map cfg_pname);
|
|
Procname.Hash.replace generated_proc_map cfg_pname true
|
|
with Not_found -> () in
|
|
process_defined_procedures update_generated_pname_to_map ()
|
|
|
|
(* third run to change the cfgs according to the map. The generated methods *)
|
|
(* that have implementations get deleted. *)
|
|
let update_cfgs generated_proc_map =
|
|
let update_cfg cfg source_dir =
|
|
let generated_procs = Cfg.get_objc_generated_procs cfg in
|
|
let cfg_name = DB.source_dir_get_internal_file source_dir ".cfg" in
|
|
let cg_name = DB.source_dir_get_internal_file source_dir ".cg" in
|
|
let cg_opt = Cg.load_from_file cg_name in
|
|
match cg_opt with
|
|
| None -> assert false
|
|
| Some cg ->
|
|
let update_cfg_procdesc procdesc need_updating =
|
|
let pname = Cfg.Procdesc.get_proc_name procdesc in
|
|
let is_redefined =
|
|
try Procname.Hash.find generated_proc_map pname
|
|
with Not_found -> assert false in
|
|
if is_redefined then
|
|
(Cfg.Procdesc.remove cfg pname true;
|
|
Cg.node_set_defined cg pname false;
|
|
true)
|
|
else need_updating in
|
|
let need_updating = IList.fold_right update_cfg_procdesc generated_procs false in
|
|
if need_updating then
|
|
(Cfg.store_cfg_to_file cfg_name false cfg;
|
|
Cg.store_to_file cg_name cg) in
|
|
process_all_cfgs update_cfg ()
|
|
|
|
let do_objc_preanalysis () =
|
|
let generated_proc_map = Procname.Hash.create 100 in
|
|
fill_generated_proc_map generated_proc_map;
|
|
update_generate_proc_map generated_proc_map;
|
|
update_cfgs generated_proc_map
|