[infer][java] make sure the type definition of the class always exists in the type environment when translating one of its method

Summary: This avoid cases where the type definition is not found when trying to lookup the type definition for the class starting from the method name.

Reviewed By: ngorogiannis

Differential Revision: D9027983

fbshipit-source-id: 1add7692f
master
Jeremy Dubreil 6 years ago committed by Facebook Github Bot
parent 396caca5d6
commit ad8c5d68a2

@ -134,11 +134,11 @@ let is_classname_cached cn = Sys.file_exists (path_of_cached_classname cn) = `Ye
(* Given a source file and a class, translates the code of this class. (* Given a source file and a class, translates the code of this class.
In init - mode, finds out whether this class contains initializers at all, In init - mode, finds out whether this class contains initializers at all,
in this case translates it. In standard mode, all methods are translated *) in this case translates it. In standard mode, all methods are translated *)
let create_icfg source_file linereader program icfg cn node = let create_icfg source_file linereader program tenv icfg cn node =
L.(debug Capture Verbose) "\tclassname: %s@." (JBasics.cn_name cn) ; L.(debug Capture Verbose) "\tclassname: %s@." (JBasics.cn_name cn) ;
if Config.dependency_mode && not (is_classname_cached cn) then cache_classname cn ; if Config.dependency_mode && not (is_classname_cached cn) then cache_classname cn ;
let translate m = let translate m =
let proc_name = JTransType.translate_method_name m in let proc_name = JTransType.translate_method_name program tenv m in
JClasspath.set_callee_translated program proc_name ; JClasspath.set_callee_translated program proc_name ;
if JClasspath.is_model proc_name then if JClasspath.is_model proc_name then
(* do not translate the method if there is a model for it *) (* do not translate the method if there is a model for it *)
@ -198,7 +198,7 @@ let compute_source_icfg linereader classes program tenv source_basename package_
JBasics.ClassMap.iter JBasics.ClassMap.iter
(select (select
(should_capture classes package_opt source_basename) (should_capture classes package_opt source_basename)
(create_icfg source_file linereader program icfg)) (create_icfg source_file linereader program tenv icfg))
(JClasspath.get_classmap program) (JClasspath.get_classmap program)
in in
icfg.JContext.cfg icfg.JContext.cfg
@ -206,6 +206,6 @@ let compute_source_icfg linereader classes program tenv source_basename package_
let compute_class_icfg source_file linereader program tenv node = let compute_class_icfg source_file linereader program tenv node =
let icfg = {JContext.cfg= Cfg.create (); tenv} in let icfg = {JContext.cfg= Cfg.create (); tenv} in
( try create_icfg source_file linereader program icfg (Javalib.get_name node) node ( try create_icfg source_file linereader program tenv icfg (Javalib.get_name node) node
with Bir.Subroutine -> () ) ; with Bir.Subroutine -> () ) ;
icfg.JContext.cfg icfg.JContext.cfg

@ -651,7 +651,7 @@ let method_invocation (context: JContext.t) loc pc var_opt cn ms sil_obj_opt exp
JBasics.cn_equal cn' (JBasics.make_cn JConfig.infer_builtins_cl) JBasics.cn_equal cn' (JBasics.make_cn JConfig.infer_builtins_cl)
&& BuiltinDecl.is_declared proc && BuiltinDecl.is_declared proc
then proc then proc
else JTransType.get_method_procname cn' ms method_kind else JTransType.get_method_procname program tenv cn' ms method_kind
in in
JClasspath.add_missing_callee program callee_procname cn' ms ; JClasspath.add_missing_callee program callee_procname cn' ms ;
let call_instrs = let call_instrs =

@ -216,21 +216,6 @@ let get_method_kind m =
if Javalib.is_static_method m then Typ.Procname.Java.Static else Typ.Procname.Java.Non_Static if Javalib.is_static_method m then Typ.Procname.Java.Static else Typ.Procname.Java.Non_Static
let get_method_procname cn ms method_kind =
let return_type_name, method_name, args_type_name = method_signature_names ms in
let class_name = Typ.Name.Java.from_string (JBasics.cn_name cn) in
let proc_name_java =
Typ.Procname.Java.make class_name return_type_name method_name args_type_name method_kind
in
Typ.Procname.Java proc_name_java
(* create a mangled procname from an abstract or concrete method *)
let translate_method_name m =
let cn, ms = JBasics.cms_split (Javalib.get_class_method_signature m) in
get_method_procname cn ms (get_method_kind m)
let fieldname_create cn fs = let fieldname_create cn fs =
let fieldname = JBasics.fs_name fs in let fieldname = JBasics.fs_name fs in
let classname = JBasics.cn_name cn in let classname = JBasics.cn_name cn in
@ -310,7 +295,23 @@ let add_model_fields program classpath_fields cn =
with Caml.Not_found -> classpath_fields with Caml.Not_found -> classpath_fields
let rec get_all_fields program tenv cn = let rec get_method_procname program tenv cn ms method_kind =
let _ : Typ.Struct.t = get_class_struct_typ program tenv cn in
let return_type_name, method_name, args_type_name = method_signature_names ms in
let class_name = Typ.Name.Java.from_string (JBasics.cn_name cn) in
let proc_name_java =
Typ.Procname.Java.make class_name return_type_name method_name args_type_name method_kind
in
Typ.Procname.Java proc_name_java
(* create a mangled procname from an abstract or concrete method *)
and translate_method_name program tenv m =
let cn, ms = JBasics.cms_split (Javalib.get_class_method_signature m) in
get_method_procname program tenv cn ms (get_method_kind m)
and get_all_fields program tenv cn =
let extract_class_fields classname = let extract_class_fields classname =
let {Typ.Struct.fields; statics} = get_class_struct_typ program tenv classname in let {Typ.Struct.fields; statics} = get_class_struct_typ program tenv classname in
(statics, fields) (statics, fields)
@ -346,49 +347,60 @@ let rec get_all_fields program tenv cn =
trans_fields cn trans_fields cn
and get_class_struct_typ program tenv cn = and get_class_struct_typ =
let name = typename_of_classname cn in let seen = ref JBasics.ClassSet.empty in
match Tenv.lookup tenv name with fun program tenv cn ->
| Some struct_typ -> let name = typename_of_classname cn in
struct_typ match Tenv.lookup tenv name with
| None -> | Some struct_typ ->
match JClasspath.lookup_node cn program with struct_typ
| None -> | None when JBasics.ClassSet.mem cn !seen ->
Tenv.mk_struct tenv name Tenv.mk_struct tenv name
| Some node -> | None ->
let create_super_list interface_names = seen := JBasics.ClassSet.add cn !seen ;
List.iter ~f:(fun cn -> ignore (get_class_struct_typ program tenv cn)) interface_names ; match JClasspath.lookup_node cn program with
List.map ~f:typename_of_classname interface_names | None ->
in Tenv.mk_struct tenv name
let supers, fields, statics, annots = | Some node ->
match node with let create_super_list interface_names =
| Javalib.JInterface jinterface -> List.iter
let statics, _ = get_all_fields program tenv cn in ~f:(fun cn -> ignore (get_class_struct_typ program tenv cn))
let sil_interface_list = create_super_list jinterface.Javalib.i_interfaces in interface_names ;
let item_annotation = JAnnotation.translate_item jinterface.Javalib.i_annotations in List.map ~f:typename_of_classname interface_names
(sil_interface_list, [], statics, item_annotation) in
| Javalib.JClass jclass -> let supers, fields, statics, annots =
let statics, nonstatics = match node with
let classpath_static, classpath_nonstatic = get_all_fields program tenv cn in | Javalib.JInterface jinterface ->
add_model_fields program (classpath_static, classpath_nonstatic) cn let statics, _ = get_all_fields program tenv cn in
in let sil_interface_list = create_super_list jinterface.Javalib.i_interfaces in
let item_annotation = JAnnotation.translate_item jclass.Javalib.c_annotations in let item_annotation =
let interface_list = create_super_list jclass.Javalib.c_interfaces in JAnnotation.translate_item jinterface.Javalib.i_annotations
let super_classname_list = in
match jclass.Javalib.c_super_class with (sil_interface_list, [], statics, item_annotation)
| None -> | Javalib.JClass jclass ->
interface_list (* base case of the recursion *) let statics, nonstatics =
| Some super_cn -> let classpath_static, classpath_nonstatic = get_all_fields program tenv cn in
ignore (get_class_struct_typ program tenv super_cn) ; add_model_fields program (classpath_static, classpath_nonstatic) cn
let super_classname = typename_of_classname super_cn in in
super_classname :: interface_list let item_annotation = JAnnotation.translate_item jclass.Javalib.c_annotations in
in let interface_list = create_super_list jclass.Javalib.c_interfaces in
(super_classname_list, nonstatics, statics, item_annotation) let super_classname_list =
in match jclass.Javalib.c_super_class with
let methods = | None ->
Javalib.m_fold (fun m procnames -> translate_method_name m :: procnames) node [] interface_list (* base case of the recursion *)
in | Some super_cn ->
Tenv.mk_struct tenv ~fields ~statics ~methods ~supers ~annots name ignore (get_class_struct_typ program tenv super_cn) ;
let super_classname = typename_of_classname super_cn in
super_classname :: interface_list
in
(super_classname_list, nonstatics, statics, item_annotation)
in
let methods =
Javalib.m_fold
(fun m procnames -> translate_method_name program tenv m :: procnames)
node []
in
Tenv.mk_struct tenv ~fields ~statics ~methods ~supers ~annots name
let get_class_type_no_pointer program tenv cn = let get_class_type_no_pointer program tenv cn =

@ -13,10 +13,12 @@ open Sawja_pack
val get_method_kind : JCode.jcode Javalib.jmethod -> Typ.Procname.Java.kind val get_method_kind : JCode.jcode Javalib.jmethod -> Typ.Procname.Java.kind
val get_method_procname : val get_method_procname :
JBasics.class_name -> JBasics.method_signature -> Typ.Procname.Java.kind -> Typ.Procname.t JClasspath.program -> Tenv.t -> JBasics.class_name -> JBasics.method_signature
-> Typ.Procname.Java.kind -> Typ.Procname.t
(** returns a procedure name based on the class name and the method's signature. *) (** returns a procedure name based on the class name and the method's signature. *)
val translate_method_name : JCode.jcode Javalib.jmethod -> Typ.Procname.t val translate_method_name :
JClasspath.program -> Tenv.t -> JCode.jcode Javalib.jmethod -> Typ.Procname.t
(** translate the SIL procedure name of the Java method *) (** translate the SIL procedure name of the Java method *)
val get_class_struct_typ : JClasspath.program -> Tenv.t -> JBasics.class_name -> Typ.Struct.t val get_class_struct_typ : JClasspath.program -> Tenv.t -> JBasics.class_name -> Typ.Struct.t

Loading…
Cancel
Save