[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.
In init - mode, finds out whether this class contains initializers at all,
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) ;
if Config.dependency_mode && not (is_classname_cached cn) then cache_classname cn ;
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 ;
if JClasspath.is_model proc_name then
(* 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
(select
(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)
in
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 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 -> () ) ;
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)
&& BuiltinDecl.is_declared proc
then proc
else JTransType.get_method_procname cn' ms method_kind
else JTransType.get_method_procname program tenv cn' ms method_kind
in
JClasspath.add_missing_callee program callee_procname cn' ms ;
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
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 = JBasics.fs_name fs 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
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 {Typ.Struct.fields; statics} = get_class_struct_typ program tenv classname in
(statics, fields)
@ -346,49 +347,60 @@ let rec get_all_fields program tenv cn =
trans_fields cn
and get_class_struct_typ program tenv cn =
let name = typename_of_classname cn in
match Tenv.lookup tenv name with
| Some struct_typ ->
struct_typ
| None ->
match JClasspath.lookup_node cn program with
| None ->
and get_class_struct_typ =
let seen = ref JBasics.ClassSet.empty in
fun program tenv cn ->
let name = typename_of_classname cn in
match Tenv.lookup tenv name with
| Some struct_typ ->
struct_typ
| None when JBasics.ClassSet.mem cn !seen ->
Tenv.mk_struct tenv name
| Some node ->
let create_super_list interface_names =
List.iter ~f:(fun cn -> ignore (get_class_struct_typ program tenv cn)) interface_names ;
List.map ~f:typename_of_classname interface_names
in
let supers, fields, statics, annots =
match node with
| Javalib.JInterface jinterface ->
let statics, _ = get_all_fields program tenv cn in
let sil_interface_list = create_super_list jinterface.Javalib.i_interfaces in
let item_annotation = JAnnotation.translate_item jinterface.Javalib.i_annotations in
(sil_interface_list, [], statics, item_annotation)
| Javalib.JClass jclass ->
let statics, nonstatics =
let classpath_static, classpath_nonstatic = get_all_fields program tenv cn in
add_model_fields program (classpath_static, classpath_nonstatic) cn
in
let item_annotation = JAnnotation.translate_item jclass.Javalib.c_annotations in
let interface_list = create_super_list jclass.Javalib.c_interfaces in
let super_classname_list =
match jclass.Javalib.c_super_class with
| None ->
interface_list (* base case of the recursion *)
| Some super_cn ->
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 m :: procnames) node []
in
Tenv.mk_struct tenv ~fields ~statics ~methods ~supers ~annots name
| None ->
seen := JBasics.ClassSet.add cn !seen ;
match JClasspath.lookup_node cn program with
| None ->
Tenv.mk_struct tenv name
| Some node ->
let create_super_list interface_names =
List.iter
~f:(fun cn -> ignore (get_class_struct_typ program tenv cn))
interface_names ;
List.map ~f:typename_of_classname interface_names
in
let supers, fields, statics, annots =
match node with
| Javalib.JInterface jinterface ->
let statics, _ = get_all_fields program tenv cn in
let sil_interface_list = create_super_list jinterface.Javalib.i_interfaces in
let item_annotation =
JAnnotation.translate_item jinterface.Javalib.i_annotations
in
(sil_interface_list, [], statics, item_annotation)
| Javalib.JClass jclass ->
let statics, nonstatics =
let classpath_static, classpath_nonstatic = get_all_fields program tenv cn in
add_model_fields program (classpath_static, classpath_nonstatic) cn
in
let item_annotation = JAnnotation.translate_item jclass.Javalib.c_annotations in
let interface_list = create_super_list jclass.Javalib.c_interfaces in
let super_classname_list =
match jclass.Javalib.c_super_class with
| None ->
interface_list (* base case of the recursion *)
| Some super_cn ->
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 =

@ -13,10 +13,12 @@ open Sawja_pack
val get_method_kind : JCode.jcode Javalib.jmethod -> Typ.Procname.Java.kind
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. *)
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 *)
val get_class_struct_typ : JClasspath.program -> Tenv.t -> JBasics.class_name -> Typ.Struct.t

Loading…
Cancel
Save