From ebee6fd7bad15ec6baa7c18703c32a3c8eb85a6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezgi=20=C3=87i=C3=A7ek?= Date: Fri, 9 Oct 2020 08:40:22 -0700 Subject: [PATCH] [IR] Track objC protocols in each class Summary: This will be needed in the next diff so that we can find all classes that conform to `NSCopying` protocol. Reviewed By: skcho Differential Revision: D24216549 fbshipit-source-id: 297b527a6 --- infer/src/IR/Struct.ml | 37 +++++++++++++++++++++------ infer/src/IR/Struct.mli | 2 ++ infer/src/IR/Tenv.ml | 6 ++--- infer/src/IR/Tenv.mli | 1 + infer/src/clang/objcInterface_decl.ml | 11 ++++++-- 5 files changed, 44 insertions(+), 13 deletions(-) diff --git a/infer/src/IR/Struct.ml b/infer/src/IR/Struct.ml index a67a05d07..acce23968 100644 --- a/infer/src/IR/Struct.ml +++ b/infer/src/IR/Struct.ml @@ -43,6 +43,7 @@ type t = { fields: fields (** non-static fields *) ; statics: fields (** static fields *) ; supers: Typ.Name.t list (** superclasses *) + ; objc_protocols: Typ.Name.t list (** ObjC protocols *) ; methods: Procname.t list (** methods defined *) ; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *) ; annots: Annot.Item.t (** annotations *) @@ -57,9 +58,15 @@ let pp_field pe f (field_name, typ, ann) = let pp pe name f - ({fields; statics; supers; methods; exported_objc_methods; annots; java_class_info; dummy}[@warning - "+9"]) - = + ({ fields + ; statics + ; supers + ; objc_protocols + ; methods + ; exported_objc_methods + ; annots + ; java_class_info + ; dummy }[@warning "+9"]) = let pp_field pe f (field_name, typ, ann) = F.fprintf f "@;<0 2>%a %a %a" (Typ.pp_full pe) typ Fieldname.pp field_name Annot.Item.pp ann in @@ -75,6 +82,7 @@ let pp pe name f @[fields: {@[%a@]}@,\ statics: {@[%a@]}@,\ supers: {@[%a@]}@,\ + objc_protocols: {@[%a@]}@,\ methods: {@[%a@]}@,\ exported_obj_methods: {@[%a@]}@,\ annots: {@[%a@]}@,\ @@ -87,30 +95,43 @@ let pp pe name f statics (seq (fun f n -> F.fprintf f "@;<0 2>%a" Typ.Name.pp n)) supers + (seq (fun f n -> F.fprintf f "@;<0 2>%a" Typ.Name.pp n)) + objc_protocols (seq (fun f m -> F.fprintf f "@;<0 2>%a" Procname.pp m)) methods (seq (fun f m -> F.fprintf f "@;<0 2>%a" Procname.pp m)) exported_objc_methods Annot.Item.pp annots pp_java_class_info_opt java_class_info dummy -let internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots - ?java_class_info ?dummy () = +let internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers + ?objc_protocols ?annots ?java_class_info ?dummy () = let default_ = { fields= [] ; statics= [] ; methods= [] ; exported_objc_methods= [] ; supers= [] + ; objc_protocols= [] ; annots= Annot.Item.empty ; java_class_info= None ; 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) ?(dummy = default.dummy) () = - {fields; statics; methods; exported_objc_methods; supers; annots; java_class_info; dummy} + ?(supers = default.supers) ?(objc_protocols = default.objc_protocols) + ?(annots = default.annots) ?(dummy = default.dummy) () = + { fields + ; statics + ; methods + ; exported_objc_methods + ; supers + ; objc_protocols + ; annots + ; java_class_info + ; dummy } in - mk_struct_ ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?annots ?dummy () + mk_struct_ ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?objc_protocols + ?annots ?dummy () (** the element typ of the final extensible array in the given typ, if any *) diff --git a/infer/src/IR/Struct.mli b/infer/src/IR/Struct.mli index ed8f5fd5d..0cc963dcf 100644 --- a/infer/src/IR/Struct.mli +++ b/infer/src/IR/Struct.mli @@ -26,6 +26,7 @@ type t = { fields: fields (** non-static fields *) ; statics: fields (** static fields *) ; supers: Typ.Name.t list (** superclasses *) + ; objc_protocols: Typ.Name.t list (** ObjC protocols *) ; methods: Procname.t list (** methods defined *) ; exported_objc_methods: Procname.t list (** methods in ObjC interface, subset of [methods] *) ; annots: Annot.Item.t (** annotations *) @@ -46,6 +47,7 @@ val internal_mk_struct : -> ?methods:Procname.t list -> ?exported_objc_methods:Procname.t list -> ?supers:Typ.Name.t list + -> ?objc_protocols:Typ.Name.t list -> ?annots:Annot.Item.t -> ?java_class_info:java_class_info -> ?dummy:bool diff --git a/infer/src/IR/Tenv.ml b/infer/src/IR/Tenv.ml index 1a08de65d..1a1d6bb6e 100644 --- a/infer/src/IR/Tenv.ml +++ b/infer/src/IR/Tenv.ml @@ -25,11 +25,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 - ?java_class_info ?dummy name = +let mk_struct tenv ?default ?fields ?statics ?methods ?exported_objc_methods ?supers ?objc_protocols + ?annots ?java_class_info ?dummy name = let struct_typ = Struct.internal_mk_struct ?default ?fields ?statics ?methods ?exported_objc_methods ?supers - ?annots ?java_class_info ?dummy () + ?objc_protocols ?annots ?java_class_info ?dummy () in TypenameHash.replace tenv name struct_typ ; struct_typ diff --git a/infer/src/IR/Tenv.mli b/infer/src/IR/Tenv.mli index cf82b5f43..5911a184c 100644 --- a/infer/src/IR/Tenv.mli +++ b/infer/src/IR/Tenv.mli @@ -40,6 +40,7 @@ val mk_struct : -> ?methods:Procname.t list -> ?exported_objc_methods:Procname.t list -> ?supers:Typ.Name.t list + -> ?objc_protocols:Typ.Name.t list -> ?annots:Annot.Item.t -> ?java_class_info:Struct.java_class_info -> ?dummy:bool diff --git a/infer/src/clang/objcInterface_decl.ml b/infer/src/clang/objcInterface_decl.ml index 742538bd0..13a9c20cd 100644 --- a/infer/src/clang/objcInterface_decl.ml +++ b/infer/src/clang/objcInterface_decl.ml @@ -75,6 +75,13 @@ let add_class_to_tenv qual_type_to_sil_type procname_from_decl tenv decl_info na create_supers_fields qual_type_to_sil_type tenv interface_name decl_list ocidi.Clang_ast_t.otdi_super in + let objc_protocols = + List.filter_map + ~f:(fun dr -> + Option.map dr.Clang_ast_t.dr_name ~f:(fun x -> + CAst_utils.get_qualified_name x |> Typ.Name.Objc.from_qual_name ) ) + ocidi.Clang_ast_t.otdi_protocols + in let fields_sc = CField_decl.fields_superclass tenv ocidi in (*In case we found categories, or partial definition of this class earlier and they are already in the tenv *) let fields, (supers : Typ.Name.t list), methods = @@ -95,8 +102,8 @@ let add_class_to_tenv qual_type_to_sil_type procname_from_decl tenv decl_info na methods in ignore - (Tenv.mk_struct tenv ~fields:all_fields ~supers ~methods ~annots:Annot.Class.objc - ~exported_objc_methods:methods interface_name) ; + (Tenv.mk_struct tenv ~fields:all_fields ~supers ~objc_protocols ~methods + ~annots:Annot.Class.objc ~exported_objc_methods:methods interface_name) ; interface_desc