diff --git a/infer/src/IR/Tenv.ml b/infer/src/IR/Tenv.ml index 109766225..933d60dcd 100644 --- a/infer/src/IR/Tenv.ml +++ b/infer/src/IR/Tenv.ml @@ -29,10 +29,11 @@ let pp fmt (tenv : t) = let create () = TypenameHash.create 1000 (** Construct a struct type in a type environment *) -let mk_struct tenv ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots name = +let mk_struct tenv ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots ?dummy + name = let struct_typ = Typ.Struct.internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers - ?annots () + ?annots ?dummy () in TypenameHash.replace tenv name struct_typ ; struct_typ @@ -99,7 +100,13 @@ module SQLite : SqliteUtils.Data with type t = per_file = struct FileLocal (Serializer.deserialize blob) end -let merge ~src ~dst = TypenameHash.iter (fun pname cfg -> TypenameHash.replace dst pname cfg) src +let merge ~src ~dst = + TypenameHash.iter + (fun pname cfg -> + if (not (Typ.Struct.is_dummy cfg)) || not (TypenameHash.mem dst pname) then + TypenameHash.replace dst pname cfg ) + src + let merge_per_file ~src ~dst = match (src, dst) with diff --git a/infer/src/IR/Tenv.mli b/infer/src/IR/Tenv.mli index 473f37b72..ecf7c9b16 100644 --- a/infer/src/IR/Tenv.mli +++ b/infer/src/IR/Tenv.mli @@ -41,6 +41,7 @@ val mk_struct : -> ?exported_objc_methods:Typ.Procname.t list -> ?supers:Typ.Name.t list -> ?annots:Annot.Item.t + -> ?dummy:bool -> Typ.Name.t -> Typ.Struct.t (** Construct a struct_typ, normalizing field types *) diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index 191bf591f..c69558cba 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -1518,7 +1518,8 @@ module Struct = struct ; supers: Name.t list (** superclasses *) ; methods: Procname.t list (** methods defined *) ; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *) - ; annots: Annot.Item.t (** annotations *) } + ; annots: Annot.Item.t (** annotations *) + ; dummy: bool (** dummy struct for class including static method *) } type lookup = Name.t -> t option @@ -1554,21 +1555,22 @@ module Struct = struct let internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots - () = + ?dummy () = let default_ = { fields= [] ; statics= [] ; methods= [] ; exported_objc_methods= [] ; supers= [] - ; annots= Annot.Item.empty } + ; annots= Annot.Item.empty + ; dummy= false } in let mk_struct_ ?(default = default_) ?(fields = default.fields) ?(statics = default.statics) ?(methods = default.methods) ?(exported_objc_methods = default.exported_objc_methods) - ?(supers = default.supers) ?(annots = default.annots) () = - {fields; statics; methods; exported_objc_methods; supers; annots} + ?(supers = default.supers) ?(annots = default.annots) ?(dummy = default.dummy) () = + {fields; statics; methods; exported_objc_methods; supers; annots; dummy} in - mk_struct_ ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots () + mk_struct_ ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots ?dummy () (** the element typ of the final extensible array in the given typ, if any *) @@ -1617,4 +1619,7 @@ module Struct = struct None ) | _ -> None + + + let is_dummy {dummy} = dummy end diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index 9db8ab7a0..1e635af36 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -697,7 +697,8 @@ module Struct : sig ; supers: Name.t list (** supers *) ; methods: Procname.t list (** methods defined *) ; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *) - ; annots: Annot.Item.t (** annotations *) } + ; annots: Annot.Item.t (** annotations *) + ; dummy: bool (** dummy struct for class including static method *) } type lookup = Name.t -> t option @@ -714,6 +715,7 @@ module Struct : sig -> ?exported_objc_methods:Procname.t list -> ?supers:Name.t list -> ?annots:Annot.Item.t + -> ?dummy:bool -> unit -> t (** Construct a struct_typ, normalizing field types *) @@ -728,4 +730,6 @@ module Struct : sig val get_field_type_and_annotation : lookup:lookup -> Fieldname.t -> typ -> (typ * Annot.Item.t) option (** Return the type of the field [fn] and its annotation, None if [typ] has no field named [fn] *) + + val is_dummy : t -> bool end diff --git a/infer/src/java/jTransType.ml b/infer/src/java/jTransType.ml index 9d5551370..131c6a868 100644 --- a/infer/src/java/jTransType.ml +++ b/infer/src/java/jTransType.ml @@ -339,12 +339,12 @@ and get_class_struct_typ = | Some struct_typ -> struct_typ | None when JBasics.ClassSet.mem cn !seen -> - Tenv.mk_struct tenv name + Tenv.mk_struct ~dummy:true tenv name | None -> ( seen := JBasics.ClassSet.add cn !seen ; match JClasspath.lookup_node cn program with | None -> - Tenv.mk_struct tenv name + Tenv.mk_struct ~dummy:true 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 ;