parent
c9f07e31e3
commit
d7655a087e
@ -0,0 +1,102 @@
|
|||||||
|
(*
|
||||||
|
* 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
|
||||||
|
list_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
|
||||||
|
list_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).Sil.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 = list_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
|
@ -0,0 +1,10 @@
|
|||||||
|
(*
|
||||||
|
* 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.
|
||||||
|
*)
|
||||||
|
|
||||||
|
val do_objc_preanalysis : unit -> unit
|
@ -1,24 +0,0 @@
|
|||||||
digraph iCFG {
|
|
||||||
6 [label="6: BinaryOperatorStmt: Assign \n n$2=*&self:class Test * [line 14]\n n$3=*&numberOfFiles:int [line 14]\n *n$2.numberOfFiles:int =n$3 [line -1]\n REMOVE_TEMPS(n$2,n$3); [line -1]\n NULLIFY(&numberOfFiles,false); [line -1]\n NULLIFY(&self,false); [line -1]\n APPLY_ABSTRACTION; [line -1]\n " shape="box"]
|
|
||||||
|
|
||||||
|
|
||||||
6 -> 5 ;
|
|
||||||
5 [label="5: Exit Test_setNumberOfFiles: \n " color=yellow style=filled]
|
|
||||||
|
|
||||||
|
|
||||||
4 [label="4: Start Test_setNumberOfFiles:\nFormals: self:class Test * numberOfFiles:int \nLocals: \n DECLARE_LOCALS(&return); [line -1]\n " color=yellow style=filled]
|
|
||||||
|
|
||||||
|
|
||||||
4 -> 6 ;
|
|
||||||
3 [label="3: Return Stmt \n n$0=*&self:class Test * [line -1]\n n$1=*n$0.numberOfFiles:int [line -1]\n *&return:int =n$1 [line -1]\n REMOVE_TEMPS(n$0,n$1); [line -1]\n NULLIFY(&self,false); [line -1]\n APPLY_ABSTRACTION; [line -1]\n " shape="box"]
|
|
||||||
|
|
||||||
|
|
||||||
3 -> 2 ;
|
|
||||||
2 [label="2: Exit Test_numberOfFiles \n " color=yellow style=filled]
|
|
||||||
|
|
||||||
|
|
||||||
1 [label="1: Start Test_numberOfFiles\nFormals: self:class Test *\nLocals: \n DECLARE_LOCALS(&return); [line -1]\n " color=yellow style=filled]
|
|
||||||
|
|
||||||
|
|
||||||
1 -> 3 ;
|
|
||||||
}
|
|
Loading…
Reference in new issue