diff --git a/infer/src/IR/Cfg.ml b/infer/src/IR/Cfg.ml index a12782fac..4dd7e9de6 100644 --- a/infer/src/IR/Cfg.ml +++ b/infer/src/IR/Cfg.ml @@ -418,7 +418,10 @@ let specialize_types callee_pdesc resolved_pname args = in let resolved_attributes = { callee_attributes with - formals= List.rev resolved_params; proc_name= resolved_pname; err_log= Errlog.empty () } + formals= List.rev resolved_params + ; proc_name= resolved_pname + ; is_specialized= true + ; err_log= Errlog.empty () } in Attributes.store resolved_attributes ; let resolved_pdesc = diff --git a/infer/src/IR/ProcAttributes.ml b/infer/src/IR/ProcAttributes.ml index ee7a5ae08..9dfa5da4d 100644 --- a/infer/src/IR/ProcAttributes.ml +++ b/infer/src/IR/ProcAttributes.ml @@ -54,6 +54,7 @@ type t = ; is_cpp_noexcept_method: bool (** the procedure is an C++ method annotated with "noexcept" *) ; is_java_synchronized_method: bool (** the procedure is a Java synchronized method *) ; is_model: bool (** the procedure is a model *) + ; is_specialized: bool (** the procedure is a clone specialized for dynamic dispatch handling *) ; is_synthetic_method: bool (** the procedure is a synthetic method *) ; language: Config.language (** language of the procedure *) ; loc: Location.t (** location of this procedure in the source code *) @@ -86,6 +87,7 @@ let default proc_name language = ; is_defined= false ; is_objc_instance_method= false ; is_model= false + ; is_specialized= false ; is_synthetic_method= false ; language ; loc= Location.dummy diff --git a/infer/src/IR/ProcAttributes.mli b/infer/src/IR/ProcAttributes.mli index ca8745d90..cdf8c0445 100644 --- a/infer/src/IR/ProcAttributes.mli +++ b/infer/src/IR/ProcAttributes.mli @@ -52,6 +52,7 @@ type t = ; is_cpp_noexcept_method: bool (** the procedure is an C++ method annotated with "noexcept" *) ; is_java_synchronized_method: bool (** the procedure is a Java synchronized method *) ; is_model: bool (** the procedure is a model *) + ; is_specialized: bool (** the procedure is a clone specialized for dynamic dispatch handling *) ; is_synthetic_method: bool (** the procedure is a synthetic method *) ; language: Config.language (** language of the procedure *) ; loc: Location.t (** location of this procedure in the source code *) diff --git a/infer/src/IR/Procdesc.ml b/infer/src/IR/Procdesc.ml index 2bccd5010..783e02e91 100644 --- a/infer/src/IR/Procdesc.ml +++ b/infer/src/IR/Procdesc.ml @@ -510,3 +510,7 @@ let pp_signature fmt pdesc = if not (Annot.Method.is_empty method_annotation) then Format.fprintf fmt ", Annotation: %a" (Annot.Method.pp pname_string) method_annotation ; Format.fprintf fmt "]@\n" + +let is_specialized pdesc = + let attributes = get_attributes pdesc in + attributes.ProcAttributes.is_specialized diff --git a/infer/src/IR/Procdesc.mli b/infer/src/IR/Procdesc.mli index b445c3ad9..21a38db6b 100644 --- a/infer/src/IR/Procdesc.mli +++ b/infer/src/IR/Procdesc.mli @@ -247,3 +247,5 @@ val signal_did_preanalysis : t -> unit val is_loop_head : t -> Node.t -> bool val pp_signature : Format.formatter -> t -> unit + +val is_specialized : t -> bool diff --git a/infer/src/backend/callbacks.ml b/infer/src/backend/callbacks.ml index 9c8987651..d6ba51275 100644 --- a/infer/src/backend/callbacks.ml +++ b/infer/src/backend/callbacks.ml @@ -31,8 +31,8 @@ let procedure_callbacks = ref [] let cluster_callbacks = ref [] -let register_procedure_callback language (callback: proc_callback_t) = - procedure_callbacks := (language, callback) :: !procedure_callbacks +let register_procedure_callback ?(dynamic_dispath= false) language (callback: proc_callback_t) = + procedure_callbacks := (language, dynamic_dispath, callback) :: !procedure_callbacks let register_cluster_callback language (callback: cluster_callback_t) = cluster_callbacks := (language, callback) :: !cluster_callbacks @@ -57,9 +57,10 @@ let iterate_procedure_callbacks get_proc_desc exe_env summary proc_desc = -> [] in let tenv = Exe_env.get_tenv exe_env proc_name in + let is_specialized = Procdesc.is_specialized proc_desc in List.fold ~init:summary - ~f:(fun summary (language, proc_callback) -> - if Config.equal_language language procedure_language then + ~f:(fun summary (language, resolved, proc_callback) -> + if Config.equal_language language procedure_language && (resolved || not is_specialized) then proc_callback {get_proc_desc; get_procs_in_file; tenv; summary; proc_desc} else summary) !procedure_callbacks diff --git a/infer/src/backend/callbacks.mli b/infer/src/backend/callbacks.mli index 18f390e74..dcec36ef1 100644 --- a/infer/src/backend/callbacks.mli +++ b/infer/src/backend/callbacks.mli @@ -30,7 +30,7 @@ type cluster_callback_args = type cluster_callback_t = cluster_callback_args -> unit -val register_procedure_callback : Config.language -> proc_callback_t -> unit +val register_procedure_callback : ?dynamic_dispath:bool -> Config.language -> proc_callback_t -> unit (** register a procedure callback *) val register_cluster_callback : Config.language -> cluster_callback_t -> unit diff --git a/infer/src/checkers/registerCheckers.ml b/infer/src/checkers/registerCheckers.ml index 68ea3031d..9bf81db7d 100644 --- a/infer/src/checkers/registerCheckers.ml +++ b/infer/src/checkers/registerCheckers.ml @@ -17,7 +17,10 @@ module F = Format (* make sure SimpleChecker.ml is not dead code *) let () = if false then let module SC = SimpleChecker.Make in () -type callback = Procedure of Callbacks.proc_callback_t | Cluster of Callbacks.cluster_callback_t +type callback = + | Procedure of Callbacks.proc_callback_t + | DynamicDispatch of Callbacks.proc_callback_t + | Cluster of Callbacks.cluster_callback_t let checkers = [ ( "annotation reachability" @@ -26,7 +29,7 @@ let checkers = ; ( "biabduction" , Config.biabduction , [ (Procedure Interproc.analyze_procedure, Config.Clang) - ; (Procedure Interproc.analyze_procedure, Config.Java) ] ) + ; (DynamicDispatch Interproc.analyze_procedure, Config.Java) ] ) ; ( "buffer overrun" , Config.bufferoverrun , [ (Procedure BufferOverrunChecker.checker, Config.Clang) @@ -68,6 +71,8 @@ let register () = match callback with | Procedure procedure_cb -> Callbacks.register_procedure_callback language procedure_cb + | DynamicDispatch procedure_cb + -> Callbacks.register_procedure_callback ~dynamic_dispath:true language procedure_cb | Cluster cluster_cb -> Callbacks.register_cluster_callback language cluster_cb in