From 9111526a5ed474c4ab5fafaeb357eb5874a6a1f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ezgi=20=C3=87i=C3=A7ek?= Date: Wed, 4 Nov 2020 10:14:15 -0800 Subject: [PATCH] [frontend] Track protocols in A Reviewed By: skcho Differential Revision: D24566435 fbshipit-source-id: 62d41c8c6 --- infer/models/objc/src/NSMutableDictionary.m | 4 +- infer/src/IR/QualifiedCppName.ml | 8 ++ infer/src/IR/QualifiedCppName.mli | 3 + infer/src/IR/Typ.ml | 83 +++++++++++-------- infer/src/IR/Typ.mli | 11 ++- infer/src/absint/PatternMatch.ml | 14 +++- infer/src/absint/ProcnameDispatcher.ml | 5 +- infer/src/clang/CType.ml | 12 +-- infer/src/clang/CType.mli | 2 + infer/src/clang/cMethod_trans.ml | 2 +- infer/src/clang/cType_to_sil_type.ml | 31 ++++++- .../objc/frontend/boxing/dict_literal.c.dot | 2 +- .../property/PropertyCustomAccessor.m.dot | 4 +- .../frontend/property/Property_getter.m.dot | 4 +- .../objc/performance/NSEnumeration.m | 15 +++- .../objc/performance/cost-issues.exp | 4 +- .../codetoanalyze/objc/performance/issues.exp | 1 - .../annotations/nullable_annotations.m.dot | 2 +- .../objc/shared/block/dispatch_examples.m.dot | 10 +-- .../memory_leaks_benchmark/ArcExample.m.dot | 4 +- .../npe/Nonnull_attribute_example.m.dot | 4 +- .../shared/property/PropertyAttributes.m.dot | 12 +-- 22 files changed, 164 insertions(+), 73 deletions(-) diff --git a/infer/models/objc/src/NSMutableDictionary.m b/infer/models/objc/src/NSMutableDictionary.m index f6d87b1ad..f0f325381 100644 --- a/infer/models/objc/src/NSMutableDictionary.m +++ b/infer/models/objc/src/NSMutableDictionary.m @@ -17,11 +17,11 @@ id a = ((NSObject*)aKey)->isa; } -- (void)setObject:(id)object forKeyedSubscript:(id)aKey { +- (void)setObject:(id)object forKeyedSubscript:(id)aKey { id a = ((NSObject*)aKey)->isa; } -- (void)setObject:(id)anObject forKey:(id)aKey { +- (void)setObject:(id)anObject forKey:(id)aKey { id a = ((NSObject*)anObject)->isa; id b = ((NSObject*)aKey)->isa; } diff --git a/infer/src/IR/QualifiedCppName.ml b/infer/src/IR/QualifiedCppName.ml index 355bc7cee..6f3ac4588 100644 --- a/infer/src/IR/QualifiedCppName.ml +++ b/infer/src/IR/QualifiedCppName.ml @@ -38,6 +38,14 @@ let append_template_args_to_last quals ~args = raise (ParseError "expected non-empty qualified name") +let append_protocols quals ~protocols = + match quals with + | last :: rest -> + (last ^ protocols) :: rest + | [] -> + raise (ParseError "expected non-empty qualified name") + + let to_list = List.rev let to_rev_list = ident diff --git a/infer/src/IR/QualifiedCppName.mli b/infer/src/IR/QualifiedCppName.mli index 629d6169d..eccbe187e 100644 --- a/infer/src/IR/QualifiedCppName.mli +++ b/infer/src/IR/QualifiedCppName.mli @@ -36,6 +36,9 @@ val append_template_args_to_last : t -> args:string -> t (** append template arguments to the last qualifier. Fails if qualified name is empty or it already has template args *) +val append_protocols : t -> protocols:string -> t +(** append protocols to the qualified name *) + val to_list : t -> string list (** returns list of qualifiers *) diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index 582825744..6b03dcbaa 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -184,7 +184,7 @@ module T = struct | CUnion of QualifiedCppName.t | CppClass of QualifiedCppName.t * template_spec_info | JavaClass of JavaClassName.t - | ObjcClass of QualifiedCppName.t + | ObjcClass of QualifiedCppName.t * name list | ObjcProtocol of QualifiedCppName.t and template_arg = TType of t | TInt of int64 | TNull | TNullPtr | TOpaque @@ -275,39 +275,37 @@ let rec pp_full pe f typ = if is_restrict quals then F.pp_print_string f " __restrict " ; if is_volatile quals then F.pp_print_string f " volatile " in - let pp_desc f {desc} = - match desc with - | Tstruct tname -> - (pp_name_c_syntax pe) f tname - | TVar name -> - F.pp_print_string f name - | Tint ik -> - F.pp_print_string f (ikind_to_string ik) - | Tfloat fk -> - F.pp_print_string f (fkind_to_string fk) - | Tvoid -> - F.pp_print_string f "void" - | Tfun -> - F.pp_print_string f "_fn_" - | Tptr (({desc= Tarray _ | Tfun} as typ), pk) -> - F.fprintf f "%a(%s)" (pp_full pe) typ (ptr_kind_string pk |> escape pe) - | Tptr (typ, pk) -> - F.fprintf f "%a%s" (pp_full pe) typ (ptr_kind_string pk |> escape pe) - | Tarray {elt; length; stride} -> - let pp_int_opt fmt = function - | Some x -> - IntLit.pp fmt x - | None -> - F.pp_print_char fmt '_' - in - F.fprintf f "%a[%a*%a]" (pp_full pe) elt pp_int_opt length pp_int_opt stride - in - F.fprintf f "%a%a" pp_desc typ pp_quals typ + F.fprintf f "%a%a" (pp_desc pe) typ.desc pp_quals typ + + +and pp_desc pe f desc = + match desc with + | Tstruct tname -> + (pp_name_c_syntax pe) f tname + | TVar name -> + F.pp_print_string f name + | Tint ik -> + F.pp_print_string f (ikind_to_string ik) + | Tfloat fk -> + F.pp_print_string f (fkind_to_string fk) + | Tvoid -> + F.pp_print_string f "void" + | Tfun -> + F.pp_print_string f "_fn_" + | Tptr (({desc= Tarray _ | Tfun} as typ), pk) -> + F.fprintf f "%a(%s)" (pp_full pe) typ (ptr_kind_string pk |> escape pe) + | Tptr (typ, pk) -> + F.fprintf f "%a%s" (pp_full pe) typ (ptr_kind_string pk |> escape pe) + | Tarray {elt; length; stride} -> + let pp_int_opt fmt = function Some x -> IntLit.pp fmt x | None -> F.pp_print_char fmt '_' in + F.fprintf f "%a[%a*%a]" (pp_full pe) elt pp_int_opt length pp_int_opt stride and pp_name_c_syntax pe f = function - | CStruct name | CUnion name | ObjcClass name | ObjcProtocol name -> + | CStruct name | CUnion name | ObjcProtocol name -> QualifiedCppName.pp f name + | ObjcClass (name, protocol_names) -> + F.fprintf f "%a%a" QualifiedCppName.pp name (pp_protocols pe) protocol_names | CppClass (name, template_spec) -> F.fprintf f "%a%a" QualifiedCppName.pp name (pp_template_spec_info pe) template_spec | JavaClass name -> @@ -333,6 +331,14 @@ and pp_template_spec_info pe f = function F.fprintf f "%s%a%s" (escape pe "<") (Pp.comma_seq pp_arg_opt) args (escape pe ">") +and pp_protocols pe f protocols = + if List.is_empty protocols then () + else + F.fprintf f "%s%a%s" (escape pe "<") + (Pp.comma_seq (pp_name_c_syntax pe)) + protocols (escape pe ">") + + (** Pretty print a type. Do nothing by default. *) let pp pe f te = if Config.print_types then pp_full pe f te else () @@ -341,14 +347,22 @@ let to_string typ = F.asprintf "%t" pp +let desc_to_string desc = + let pp fmt = pp_desc Pp.text fmt desc in + F.asprintf "%t" pp + + module Name = struct type t = name [@@deriving compare, equal, yojson_of] let hash = Hashtbl.hash let qual_name = function - | CStruct name | CUnion name | ObjcClass name | ObjcProtocol name -> + | CStruct name | CUnion name | ObjcProtocol name -> name + | ObjcClass (name, protocol_names) -> + let protocols = F.asprintf "%a" (pp_protocols Pp.text) protocol_names in + QualifiedCppName.append_protocols name ~protocols | CppClass (name, templ_args) -> let template_suffix = F.asprintf "%a" (pp_template_spec_info Pp.text) templ_args in QualifiedCppName.append_template_args_to_last name ~args:template_suffix @@ -357,7 +371,7 @@ module Name = struct let unqualified_name = function - | CStruct name | CUnion name | ObjcClass name | ObjcProtocol name -> + | CStruct name | CUnion name | ObjcProtocol name | ObjcClass (name, _) -> name | CppClass (name, _) -> name @@ -457,7 +471,7 @@ module Name = struct end module Objc = struct - let from_qual_name qual_name = ObjcClass qual_name + let from_qual_name qual_name = ObjcClass (qual_name, []) let from_string name_str = QualifiedCppName.of_qual_string name_str |> from_qual_name @@ -483,7 +497,8 @@ module Name = struct |> List.map ~f:QualifiedCppName.of_qual_string |> QualifiedCppName.Set.of_list in - function ObjcClass name -> not (QualifiedCppName.Set.mem name tagged_classes) | _ -> false + function + | ObjcClass (name, _) -> not (QualifiedCppName.Set.mem name tagged_classes) | _ -> false end module Set = PrettyPrintable.MakePPSet (struct diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index 18f992fcb..d640a3b15 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -107,7 +107,9 @@ and name = "MyClass", "InnerClass" *) | CppClass of QualifiedCppName.t * template_spec_info | JavaClass of JavaClassName.t - | ObjcClass of QualifiedCppName.t + | ObjcClass of QualifiedCppName.t * name list + (* ObjC class that conforms to a list of protocols, + e.g. id *) | ObjcProtocol of QualifiedCppName.t and template_arg = TType of t | TInt of Int64.t | TNull | TNullPtr | TOpaque @@ -251,11 +253,18 @@ val pp_full : Pp.env -> F.formatter -> t -> unit val pp : Pp.env -> F.formatter -> t -> unit (** Pretty print a type. *) +val pp_desc : Pp.env -> F.formatter -> desc -> unit +(** Pretty print a type desc. *) + val pp_java : verbose:bool -> F.formatter -> t -> unit (** Pretty print a Java type. Raises if type isn't produced by the Java frontend *) +val pp_protocols : Pp.env -> F.formatter -> name list -> unit + val to_string : t -> string +val desc_to_string : desc -> string + val d_full : t -> unit (** Dump a type with all the details. *) diff --git a/infer/src/absint/PatternMatch.ml b/infer/src/absint/PatternMatch.ml index 411dc6ec9..3e32bdb20 100644 --- a/infer/src/absint/PatternMatch.ml +++ b/infer/src/absint/PatternMatch.ml @@ -301,9 +301,17 @@ module ObjectiveC = struct supertype_exists tenv is_interface (Typ.Name.Objc.from_string typename) - let conforms_to ~protocol tenv typename = - let is_protocol s = String.equal protocol (Typ.Name.name s) in - protocol_exists tenv is_protocol (Typ.Name.Objc.from_string typename) + let conforms_to = + let protocol_reg = Str.regexp ".+<\\(.+\\)>" in + fun ~protocol tenv typename -> + let is_protocol s = String.equal protocol (Typ.Name.name s) in + protocol_exists tenv is_protocol (Typ.Name.Objc.from_string typename) + || (* Corresponds to the case where we look inside protocols in + ObjCClass *) + Str.string_match protocol_reg typename 0 + && + let conformed_protocols = Str.matched_group 1 typename |> String.split ~on:',' in + List.exists conformed_protocols ~f:(String.equal protocol) let implements_collection = diff --git a/infer/src/absint/ProcnameDispatcher.ml b/infer/src/absint/ProcnameDispatcher.ml index aeca09b3e..0a6ee95bb 100644 --- a/infer/src/absint/ProcnameDispatcher.ml +++ b/infer/src/absint/ProcnameDispatcher.ml @@ -43,8 +43,11 @@ let template_args_of_template_spec_info = function let templated_name_of_class_name class_name = let open Typ in match class_name with - | CStruct qual_name | CUnion qual_name | ObjcClass qual_name | ObjcProtocol qual_name -> + | CStruct qual_name | CUnion qual_name | ObjcProtocol qual_name -> (qual_name, []) + | ObjcClass (qual_name, protocol_names) -> + let protocols = F.asprintf "%a" (Typ.pp_protocols Pp.text) protocol_names in + (QualifiedCppName.append_protocols qual_name ~protocols, []) | CppClass (qual_name, template_spec_info) -> (qual_name, template_args_of_template_spec_info template_spec_info) | JavaClass mangled_name -> diff --git a/infer/src/clang/CType.ml b/infer/src/clang/CType.ml index 518d03065..5b45f9aed 100644 --- a/infer/src/clang/CType.ml +++ b/infer/src/clang/CType.ml @@ -13,18 +13,20 @@ module L = Logging let add_pointer_to_typ typ = Typ.mk (Tptr (typ, Typ.Pk_pointer)) -let objc_classname_of_type typ = - match typ.Typ.desc with - | Typ.Tstruct name -> +let objc_classname_of_desc desc = + match (desc : Typ.desc) with + | Tstruct name -> name - | Typ.Tfun -> + | Tfun -> Typ.Name.Objc.from_string CFrontend_config.objc_object | _ -> L.(debug Capture Verbose) - "Classname of type cannot be extracted in type %s" (Typ.to_string typ) ; + "Classname of type cannot be extracted in %s" (Typ.desc_to_string desc) ; Typ.Name.Objc.from_string "undefined" +let objc_classname_of_type Typ.{desc} = objc_classname_of_desc desc + let is_class typ = match typ.Typ.desc with | Typ.Tptr ({desc= Tstruct name}, _) -> diff --git a/infer/src/clang/CType.mli b/infer/src/clang/CType.mli index 7fbd955ed..c431635e7 100644 --- a/infer/src/clang/CType.mli +++ b/infer/src/clang/CType.mli @@ -13,6 +13,8 @@ val add_pointer_to_typ : Typ.t -> Typ.t val objc_classname_of_type : Typ.t -> Typ.Name.t +val objc_classname_of_desc : Typ.desc -> Typ.Name.t + val is_class : Typ.t -> bool val return_type_of_function_type : Clang_ast_t.qual_type -> Clang_ast_t.qual_type diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 906a04cbf..d931810e4 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -92,7 +92,7 @@ let get_class_name_method_call_from_clang tenv obj_c_message_expr_info = None -(* Get class name from a method call accorsing to the info given by the receiver kind *) +(* Get class name from a method call according to the info given by the receiver kind *) let get_class_name_method_call_from_receiver_kind context obj_c_message_expr_info act_params = match obj_c_message_expr_info.Clang_ast_t.omei_receiver_kind with | `Class qt -> diff --git a/infer/src/clang/cType_to_sil_type.ml b/infer/src/clang/cType_to_sil_type.ml index c5f18907c..106cf0ea1 100644 --- a/infer/src/clang/cType_to_sil_type.ml +++ b/infer/src/clang/cType_to_sil_type.ml @@ -91,6 +91,28 @@ let pointer_attribute_of_objc_attribute attr_info = Typ.Pk_objc_autoreleasing +let add_protocols_to_desc tenv desc protocol_desc_list = + let rec add_nonempty_protocol desc = + match (desc : Typ.desc) with + | Tstruct (CStruct nm | ObjcClass (nm, _)) -> + let objc_protocols = List.map ~f:CType.objc_classname_of_desc protocol_desc_list in + let name = Typ.ObjcClass (nm, objc_protocols) in + ignore (Tenv.mk_struct tenv name ~objc_protocols) ; + let desc = Typ.Tstruct name in + Logging.(debug Analysis Verbose) + "@.Found class with protocols, replacing the existing desc with %a.. \n" + (Typ.pp_desc Pp.text) desc ; + desc + | Tptr (Typ.{desc; quals}, pkind) -> + Typ.Tptr ({desc= add_nonempty_protocol desc; quals}, pkind) + | Tarray Typ.{elt= {desc; quals}; length; stride} -> + Typ.Tarray {elt= {desc= add_nonempty_protocol desc; quals}; length; stride} + | _ -> + desc + in + if List.is_empty protocol_desc_list then desc else add_nonempty_protocol desc + + let rec build_array_type translate_decl tenv (qual_type : Clang_ast_t.qual_type) length_opt stride_opt = let array_type = qual_type_to_sil_type translate_decl tenv qual_type in @@ -126,7 +148,14 @@ and type_desc_of_c_type translate_decl tenv c_type : Typ.desc = if Typ.equal_desc desc (get_builtin_objc_type `ObjCClass) then desc else Typ.Tptr (typ, Typ.Pk_pointer) | ObjCObjectType (_, objc_object_type_info) -> - type_ptr_to_type_desc translate_decl tenv objc_object_type_info.Clang_ast_t.ooti_base_type + let protocol_decls_ptr = objc_object_type_info.Clang_ast_t.ooti_protocol_decls_ptr in + let protocol_desc_list = + List.map protocol_decls_ptr ~f:(fun pointer -> + decl_ptr_to_type_desc translate_decl tenv pointer ) + in + let type_ptr = objc_object_type_info.Clang_ast_t.ooti_base_type in + let desc = type_ptr_to_type_desc translate_decl tenv type_ptr in + add_protocols_to_desc tenv desc protocol_desc_list | BlockPointerType (_, qual_type) -> let typ = qual_type_to_sil_type translate_decl tenv qual_type in Typ.Tptr (typ, Typ.Pk_pointer) diff --git a/infer/tests/codetoanalyze/objc/frontend/boxing/dict_literal.c.dot b/infer/tests/codetoanalyze/objc/frontend/boxing/dict_literal.c.dot index c9738c6ea..cf774c6e3 100644 --- a/infer/tests/codetoanalyze/objc/frontend/boxing/dict_literal.c.dot +++ b/infer/tests/codetoanalyze/objc/frontend/boxing/dict_literal.c.dot @@ -18,7 +18,7 @@ digraph cfg { "get_array2.84aa3c70cb20e7edbe4f0b8d0bd6aa3d_2" [label="2: Exit get_array2 \n " color=yellow style=filled] -"get_array2.84aa3c70cb20e7edbe4f0b8d0bd6aa3d_3" [label="3: Return Stmt \n n$2=_fun_NSString.stringWithUTF8String:(\"firstName\":char* const ) [line 23, column 12]\n n$3=_fun_NSString.stringWithUTF8String:(\"Matt\":char* const ) [line 23, column 27]\n n$4=_fun_NSString.stringWithUTF8String:(\"lastName\":char* const ) [line 23, column 36]\n n$5=_fun_NSString.stringWithUTF8String:(\"Galloway\":char* const ) [line 23, column 50]\n n$6=_fun_NSString.stringWithUTF8String:(\"age\":char* const ) [line 23, column 63]\n n$7=_fun_NSNumber.numberWithInt:(28:int) [line 23, column 72]\n _=*n$3:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0[0]:objc_object*=n$3 [line 23, column 10]\n _=*n$5:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0[1]:objc_object*=n$5 [line 23, column 10]\n _=*n$7:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0[2]:objc_object*=n$7 [line 23, column 10]\n _=*n$2:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1[0]:objc_object*=n$2 [line 23, column 10]\n _=*n$4:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1[1]:objc_object*=n$4 [line 23, column 10]\n _=*n$6:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1[2]:objc_object*=n$6 [line 23, column 10]\n n$9=_fun_NSDictionary.dictionaryWithObjects:forKeys:count:(&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0:objc_object* const [6*8],&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1:objc_object* const [6*8],3:int) [line 23, column 10]\n *&return:NSDictionary*=n$9 [line 23, column 3]\n " shape="box"] +"get_array2.84aa3c70cb20e7edbe4f0b8d0bd6aa3d_3" [label="3: Return Stmt \n n$2=_fun_NSString.stringWithUTF8String:(\"firstName\":char* const ) [line 23, column 12]\n n$3=_fun_NSString.stringWithUTF8String:(\"Matt\":char* const ) [line 23, column 27]\n n$4=_fun_NSString.stringWithUTF8String:(\"lastName\":char* const ) [line 23, column 36]\n n$5=_fun_NSString.stringWithUTF8String:(\"Galloway\":char* const ) [line 23, column 50]\n n$6=_fun_NSString.stringWithUTF8String:(\"age\":char* const ) [line 23, column 63]\n n$7=_fun_NSNumber.numberWithInt:(28:int) [line 23, column 72]\n _=*n$3:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0[0]:objc_object*=n$3 [line 23, column 10]\n _=*n$5:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0[1]:objc_object*=n$5 [line 23, column 10]\n _=*n$7:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0[2]:objc_object*=n$7 [line 23, column 10]\n _=*n$2:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1[0]:objc_object*=n$2 [line 23, column 10]\n _=*n$4:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1[1]:objc_object*=n$4 [line 23, column 10]\n _=*n$6:objc_object* [line 23, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1[2]:objc_object*=n$6 [line 23, column 10]\n n$9=_fun_NSDictionary.dictionaryWithObjects:forKeys:count:(&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0:objc_object* const [6*8],&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1:objc_object* const [6*8],3:int) [line 23, column 10]\n *&return:NSDictionary*=n$9 [line 23, column 3]\n " shape="box"] "get_array2.84aa3c70cb20e7edbe4f0b8d0bd6aa3d_3" -> "get_array2.84aa3c70cb20e7edbe4f0b8d0bd6aa3d_2" ; diff --git a/infer/tests/codetoanalyze/objc/frontend/property/PropertyCustomAccessor.m.dot b/infer/tests/codetoanalyze/objc/frontend/property/PropertyCustomAccessor.m.dot index 6863c4628..1307b5b1e 100644 --- a/infer/tests/codetoanalyze/objc/frontend/property/PropertyCustomAccessor.m.dot +++ b/infer/tests/codetoanalyze/objc/frontend/property/PropertyCustomAccessor.m.dot @@ -18,7 +18,7 @@ digraph cfg { "isOpaque#ASDisplayNode#instance.efbf8192c0bb59de353a9d71765d463c_2" [label="2: Exit ASDisplayNode.isOpaque \n " color=yellow style=filled] -"isOpaque#ASDisplayNode#instance.efbf8192c0bb59de353a9d71765d463c_3" [label="3: BinaryOperatorStmt: Node \n n$2=*&self:ASDisplayNode* [line 12, column 41]\n n$3=*n$2._opaque:_Bool [line 12, column 41]\n *&return:_Bool=n$3 [line 12, column 41]\n " shape="box"] +"isOpaque#ASDisplayNode#instance.efbf8192c0bb59de353a9d71765d463c_3" [label="3: BinaryOperatorStmt: Node \n n$0=*&self:ASDisplayNode* [line 12, column 41]\n n$1=*n$0._opaque:_Bool [line 12, column 41]\n *&return:_Bool=n$1 [line 12, column 41]\n " shape="box"] "isOpaque#ASDisplayNode#instance.efbf8192c0bb59de353a9d71765d463c_3" -> "isOpaque#ASDisplayNode#instance.efbf8192c0bb59de353a9d71765d463c_2" ; @@ -29,7 +29,7 @@ digraph cfg { "setOpaque:#ASDisplayNode#instance.f5e64d1703bd4ab716e8ec5de489150d_2" [label="2: Exit ASDisplayNode.setOpaque: \n " color=yellow style=filled] -"setOpaque:#ASDisplayNode#instance.f5e64d1703bd4ab716e8ec5de489150d_3" [label="3: BinaryOperatorStmt: Node \n n$0=*&self:ASDisplayNode* [line 12, column 41]\n n$1=*&opaque:_Bool [line 12, column 41]\n *n$0._opaque:_Bool=n$1 [line 12, column 41]\n " shape="box"] +"setOpaque:#ASDisplayNode#instance.f5e64d1703bd4ab716e8ec5de489150d_3" [label="3: BinaryOperatorStmt: Node \n n$2=*&self:ASDisplayNode* [line 12, column 41]\n n$3=*&opaque:_Bool [line 12, column 41]\n *n$2._opaque:_Bool=n$3 [line 12, column 41]\n " shape="box"] "setOpaque:#ASDisplayNode#instance.f5e64d1703bd4ab716e8ec5de489150d_3" -> "setOpaque:#ASDisplayNode#instance.f5e64d1703bd4ab716e8ec5de489150d_2" ; diff --git a/infer/tests/codetoanalyze/objc/frontend/property/Property_getter.m.dot b/infer/tests/codetoanalyze/objc/frontend/property/Property_getter.m.dot index 9deac3f18..0234cf2cb 100644 --- a/infer/tests/codetoanalyze/objc/frontend/property/Property_getter.m.dot +++ b/infer/tests/codetoanalyze/objc/frontend/property/Property_getter.m.dot @@ -29,7 +29,7 @@ digraph cfg { "setX:#A#instance.00c5402542b9aade8ca8191be56dcd87_2" [label="2: Exit A.setX: \n " color=yellow style=filled] -"setX:#A#instance.00c5402542b9aade8ca8191be56dcd87_3" [label="3: BinaryOperatorStmt: Node \n n$2=*&self:A* [line 11, column 15]\n n$3=*&x:int [line 11, column 15]\n *n$2._x:int=n$3 [line 11, column 15]\n " shape="box"] +"setX:#A#instance.00c5402542b9aade8ca8191be56dcd87_3" [label="3: BinaryOperatorStmt: Node \n n$0=*&self:A* [line 11, column 15]\n n$1=*&x:int [line 11, column 15]\n *n$0._x:int=n$1 [line 11, column 15]\n " shape="box"] "setX:#A#instance.00c5402542b9aade8ca8191be56dcd87_3" -> "setX:#A#instance.00c5402542b9aade8ca8191be56dcd87_2" ; @@ -40,7 +40,7 @@ digraph cfg { "x#A#instance.37ea1b3cd5342ae67c7383da2227f91f_2" [label="2: Exit A.x \n " color=yellow style=filled] -"x#A#instance.37ea1b3cd5342ae67c7383da2227f91f_3" [label="3: BinaryOperatorStmt: Node \n n$0=*&self:A* [line 11, column 15]\n n$1=*n$0._x:int [line 11, column 15]\n *&return:int=n$1 [line 11, column 15]\n " shape="box"] +"x#A#instance.37ea1b3cd5342ae67c7383da2227f91f_3" [label="3: BinaryOperatorStmt: Node \n n$2=*&self:A* [line 11, column 15]\n n$3=*n$2._x:int [line 11, column 15]\n *&return:int=n$3 [line 11, column 15]\n " shape="box"] "x#A#instance.37ea1b3cd5342ae67c7383da2227f91f_3" -> "x#A#instance.37ea1b3cd5342ae67c7383da2227f91f_2" ; diff --git a/infer/tests/codetoanalyze/objc/performance/NSEnumeration.m b/infer/tests/codetoanalyze/objc/performance/NSEnumeration.m index 1bfc53074..31e7cbfcb 100644 --- a/infer/tests/codetoanalyze/objc/performance/NSEnumeration.m +++ b/infer/tests/codetoanalyze/objc/performance/NSEnumeration.m @@ -18,8 +18,19 @@ void call_loop_enumerator_constant() { loop_enumerator_linear(arr); } -// We get Top because front-end can't recognize NSFastEnumeration -void loop_id_enumerator_linear_FP(id enumeration) { +void loop_id_enumerator_linear(id enumeration) { for (id obj in enumeration) { } } + +void call_loop_id_enumerator_linear(NSArray* arr) { + loop_id_enumerator_linear(arr); +} + +@interface A : NSObject +@end + +void loop_enumerator_over_class_linear(A* a) { + for (id obj in a) { + } +} diff --git a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp index 1fe01977d..c9ba8331a 100644 --- a/infer/tests/codetoanalyze/objc/performance/cost-issues.exp +++ b/infer/tests/codetoanalyze/objc/performance/cost-issues.exp @@ -56,8 +56,10 @@ codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_init_dictionary_cons codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_init_literal_constant, 45, OnUIThread:false, [] codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_init_with_dictionary_linear, 7 + 3 ⋅ dict->elements.length.ub + 4 ⋅ (dict->elements.length.ub + 1), OnUIThread:false, [{dict->elements.length.ub + 1},Loop,{dict->elements.length.ub},Loop] codetoanalyze/objc/performance/NSEnumeration.m, call_loop_enumerator_constant, 35, OnUIThread:false, [] +codetoanalyze/objc/performance/NSEnumeration.m, call_loop_id_enumerator_linear, 7 + 5 ⋅ (arr->elements.length.ub + 1), OnUIThread:false, [{arr->elements.length.ub + 1},Call to loop_id_enumerator_linear,Loop] codetoanalyze/objc/performance/NSEnumeration.m, loop_enumerator_linear, 5 + 5 ⋅ (enumeration->elements.length.ub + 1), OnUIThread:false, [{enumeration->elements.length.ub + 1},Loop] -codetoanalyze/objc/performance/NSEnumeration.m, loop_id_enumerator_linear_FP, ⊤, OnUIThread:false, [Unbounded loop,Loop] +codetoanalyze/objc/performance/NSEnumeration.m, loop_enumerator_over_class_linear, 5 + 5 ⋅ (a->elements.length.ub + 1), OnUIThread:false, [{a->elements.length.ub + 1},Loop] +codetoanalyze/objc/performance/NSEnumeration.m, loop_id_enumerator_linear, 5 + 5 ⋅ (enumeration->elements.length.ub + 1), OnUIThread:false, [{enumeration->elements.length.ub + 1},Loop] codetoanalyze/objc/performance/NSFileManager.m, contents_of_directory_at_url_constant, 11, OnUIThread:false, [] codetoanalyze/objc/performance/NSInteger.m, nsinteger_value_linear, 3 + 3 ⋅ integer + 2 ⋅ (1+max(0, integer)), OnUIThread:false, [{1+max(0, integer)},Loop,{integer},Loop] codetoanalyze/objc/performance/NSInteger.m, nsnumber_number_with_int_integer_value_constant, 34, OnUIThread:false, [] diff --git a/infer/tests/codetoanalyze/objc/performance/issues.exp b/infer/tests/codetoanalyze/objc/performance/issues.exp index bbe760e79..7f07153e3 100644 --- a/infer/tests/codetoanalyze/objc/performance/issues.exp +++ b/infer/tests/codetoanalyze/objc/performance/issues.exp @@ -3,7 +3,6 @@ codetoanalyze/objc/performance/NSArray.m, nsarray_enumerator_linear, 7, INTEGER_ codetoanalyze/objc/performance/NSArray.m, nsarray_init_constant, 3, CONDITION_ALWAYS_FALSE, no_bucket, WARNING, [Here] codetoanalyze/objc/performance/NSArray.m, nsarray_iterate_linear, 3, INTEGER_OVERFLOW_L5, no_bucket, ERROR, [,Assignment,,Assignment,Binary operation: ([0, +oo] + [1, array->elements.length.ub + 1]):signed64] codetoanalyze/objc/performance/NSDictionary.m, nsdictionary_enumerate_constant, 6, BUFFER_OVERRUN_L2, no_bucket, ERROR, [,Assignment,,Array declaration,Array access: Offset: [1, 3] Size: 2] -codetoanalyze/objc/performance/NSEnumeration.m, loop_id_enumerator_linear_FP, 0, INFINITE_EXECUTION_TIME, no_bucket, ERROR, [Unbounded loop,Loop] codetoanalyze/objc/performance/NSFileManager.m, contents_of_directory_at_url_constant, 7, CONDITION_ALWAYS_FALSE, no_bucket, WARNING, [Here] codetoanalyze/objc/performance/NSMutableArray.m, nsarray_new_constant, 2, CONDITION_ALWAYS_FALSE, no_bucket, WARNING, [Here] codetoanalyze/objc/performance/NSMutableArray.m, nsmarray_remove_constant, 6, BUFFER_OVERRUN_L1, no_bucket, ERROR, [,Array declaration,Through,Through,Through,Through,Array access: Offset: 0 Size: 0] diff --git a/infer/tests/codetoanalyze/objc/shared/annotations/nullable_annotations.m.dot b/infer/tests/codetoanalyze/objc/shared/annotations/nullable_annotations.m.dot index c9b7bce09..1b3325fd7 100644 --- a/infer/tests/codetoanalyze/objc/shared/annotations/nullable_annotations.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/annotations/nullable_annotations.m.dot @@ -7,7 +7,7 @@ digraph cfg { "npe_property_nullable.ba4461b16b55481ab8de5124734d2bf3_2" [label="2: Exit npe_property_nullable \n " color=yellow style=filled] -"npe_property_nullable.ba4461b16b55481ab8de5124734d2bf3_3" [label="3: Return Stmt \n n$2=_fun_NSString.stringWithUTF8String:(\"key\":char* const ) [line 56, column 12]\n n$3=*&child:Person* [line 56, column 21]\n _=*n$3:objc_object* [line 56, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0[0]:objc_object*=n$3 [line 56, column 10]\n _=*n$2:objc_object* [line 56, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1[0]:objc_object*=n$2 [line 56, column 10]\n n$5=_fun_NSDictionary.dictionaryWithObjects:forKeys:count:(&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0:objc_object* const [2*8],&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1:objc_object* const [2*8],1:int) [line 56, column 10]\n *&return:NSDictionary*=n$5 [line 56, column 3]\n " shape="box"] +"npe_property_nullable.ba4461b16b55481ab8de5124734d2bf3_3" [label="3: Return Stmt \n n$2=_fun_NSString.stringWithUTF8String:(\"key\":char* const ) [line 56, column 12]\n n$3=*&child:Person* [line 56, column 21]\n _=*n$3:objc_object* [line 56, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0[0]:objc_object*=n$3 [line 56, column 10]\n _=*n$2:objc_object* [line 56, column 10]\n *&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1[0]:objc_object*=n$2 [line 56, column 10]\n n$5=_fun_NSDictionary.dictionaryWithObjects:forKeys:count:(&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count1___n$0:objc_object* const [2*8],&0$?%__sil_tmpSIL_dictionaryWithObjects_forKeys_count2___n$1:objc_object* const [2*8],1:int) [line 56, column 10]\n *&return:NSDictionary*=n$5 [line 56, column 3]\n " shape="box"] "npe_property_nullable.ba4461b16b55481ab8de5124734d2bf3_3" -> "npe_property_nullable.ba4461b16b55481ab8de5124734d2bf3_2" ; diff --git a/infer/tests/codetoanalyze/objc/shared/block/dispatch_examples.m.dot b/infer/tests/codetoanalyze/objc/shared/block/dispatch_examples.m.dot index 30e3c5ac3..3e92be28c 100644 --- a/infer/tests/codetoanalyze/objc/shared/block/dispatch_examples.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/block/dispatch_examples.m.dot @@ -101,7 +101,7 @@ digraph cfg { "dispatch_after_example#DispatchEx#class.1d25856bd99eb1ef683c8f65ff46d05d_3" -> "dispatch_after_example#DispatchEx#class.1d25856bd99eb1ef683c8f65ff46d05d_2" ; -"dispatch_after_example#DispatchEx#class.1d25856bd99eb1ef683c8f65ff46d05d_4" [label="4: Call _fun_dispatch_after \n n$16=_fun_dispatch_time(0:unsigned long long,((unsigned long long)2 * 1000000000):long long) [line 46, column 18]\n n$17=_fun_dispatch_get_main_queue() [line 47, column 18]\n n$21=_fun_dispatch_after(n$16:unsigned long long,n$17:NSObject*,(_fun_objc_blockDispatchEx.dispatch_after_example_3):_fn_(*)) [line 46, column 3]\n " shape="box"] +"dispatch_after_example#DispatchEx#class.1d25856bd99eb1ef683c8f65ff46d05d_4" [label="4: Call _fun_dispatch_after \n n$16=_fun_dispatch_time(0:unsigned long long,((unsigned long long)2 * 1000000000):long long) [line 46, column 18]\n n$17=_fun_dispatch_get_main_queue() [line 47, column 18]\n n$21=_fun_dispatch_after(n$16:unsigned long long,n$17:NSObject*,(_fun_objc_blockDispatchEx.dispatch_after_example_3):_fn_(*)) [line 46, column 3]\n " shape="box"] "dispatch_after_example#DispatchEx#class.1d25856bd99eb1ef683c8f65ff46d05d_4" -> "dispatch_after_example#DispatchEx#class.1d25856bd99eb1ef683c8f65ff46d05d_3" ; @@ -120,7 +120,7 @@ digraph cfg { "dispatch_async_example#DispatchEx#class.5c5d7347be2a9654ad7e32514189fe54_3" -> "dispatch_async_example#DispatchEx#class.5c5d7347be2a9654ad7e32514189fe54_2" ; -"dispatch_async_example#DispatchEx#class.5c5d7347be2a9654ad7e32514189fe54_4" [label="4: Call _fun_dispatch_async \n n$9=_fun_dispatch_get_global_queue(0:long,(unsigned long)0:unsigned long) [line 36, column 18]\n n$13=_fun_dispatch_async(n$9:NSObject*,(_fun_objc_blockDispatchEx.dispatch_async_example_2):_fn_(*)) [line 36, column 3]\n " shape="box"] +"dispatch_async_example#DispatchEx#class.5c5d7347be2a9654ad7e32514189fe54_4" [label="4: Call _fun_dispatch_async \n n$9=_fun_dispatch_get_global_queue(0:long,(unsigned long)0:unsigned long) [line 36, column 18]\n n$13=_fun_dispatch_async(n$9:NSObject*,(_fun_objc_blockDispatchEx.dispatch_async_example_2):_fn_(*)) [line 36, column 3]\n " shape="box"] "dispatch_async_example#DispatchEx#class.5c5d7347be2a9654ad7e32514189fe54_4" -> "dispatch_async_example#DispatchEx#class.5c5d7347be2a9654ad7e32514189fe54_3" ; @@ -139,7 +139,7 @@ digraph cfg { "dispatch_barrier_example#DispatchEx#class.a541a40f2f04e29019c58e563f7544d8_3" -> "dispatch_barrier_example#DispatchEx#class.a541a40f2f04e29019c58e563f7544d8_2" ; -"dispatch_barrier_example#DispatchEx#class.a541a40f2f04e29019c58e563f7544d8_4" [label="4: Call _fun_dispatch_barrier_async \n n$38=_fun_dispatch_get_main_queue() [line 75, column 26]\n n$42=_fun_dispatch_barrier_async(n$38:NSObject*,(_fun_objc_blockDispatchEx.dispatch_barrier_example_6):_fn_(*)) [line 75, column 3]\n " shape="box"] +"dispatch_barrier_example#DispatchEx#class.a541a40f2f04e29019c58e563f7544d8_4" [label="4: Call _fun_dispatch_barrier_async \n n$38=_fun_dispatch_get_main_queue() [line 75, column 26]\n n$42=_fun_dispatch_barrier_async(n$38:NSObject*,(_fun_objc_blockDispatchEx.dispatch_barrier_example_6):_fn_(*)) [line 75, column 3]\n " shape="box"] "dispatch_barrier_example#DispatchEx#class.a541a40f2f04e29019c58e563f7544d8_4" -> "dispatch_barrier_example#DispatchEx#class.a541a40f2f04e29019c58e563f7544d8_3" ; @@ -158,7 +158,7 @@ digraph cfg { "dispatch_group_example#DispatchEx#class.f420a75c58eda6d3f0e5e05fadabfc18_3" -> "dispatch_group_example#DispatchEx#class.f420a75c58eda6d3f0e5e05fadabfc18_2" ; -"dispatch_group_example#DispatchEx#class.f420a75c58eda6d3f0e5e05fadabfc18_4" [label="4: Call _fun_dispatch_group_async \n n$24=_fun_dispatch_get_main_queue() [line 57, column 30]\n n$28=_fun_dispatch_group_async(null:NSObject*,n$24:NSObject*,(_fun_objc_blockDispatchEx.dispatch_group_example_4):_fn_(*)) [line 57, column 3]\n " shape="box"] +"dispatch_group_example#DispatchEx#class.f420a75c58eda6d3f0e5e05fadabfc18_4" [label="4: Call _fun_dispatch_group_async \n n$24=_fun_dispatch_get_main_queue() [line 57, column 30]\n n$28=_fun_dispatch_group_async(null:NSObject*,n$24:NSObject*,(_fun_objc_blockDispatchEx.dispatch_group_example_4):_fn_(*)) [line 57, column 3]\n " shape="box"] "dispatch_group_example#DispatchEx#class.f420a75c58eda6d3f0e5e05fadabfc18_4" -> "dispatch_group_example#DispatchEx#class.f420a75c58eda6d3f0e5e05fadabfc18_3" ; @@ -177,7 +177,7 @@ digraph cfg { "dispatch_group_notify_example#DispatchEx#class.f5cf54b07621c319cf7ead3b217760ed_3" -> "dispatch_group_notify_example#DispatchEx#class.f5cf54b07621c319cf7ead3b217760ed_2" ; -"dispatch_group_notify_example#DispatchEx#class.f5cf54b07621c319cf7ead3b217760ed_4" [label="4: Call _fun_dispatch_group_async \n n$31=_fun_dispatch_get_main_queue() [line 66, column 30]\n n$35=_fun_dispatch_group_async(null:NSObject*,n$31:NSObject*,(_fun_objc_blockDispatchEx.dispatch_group_notify_example_5):_fn_(*)) [line 66, column 3]\n " shape="box"] +"dispatch_group_notify_example#DispatchEx#class.f5cf54b07621c319cf7ead3b217760ed_4" [label="4: Call _fun_dispatch_group_async \n n$31=_fun_dispatch_get_main_queue() [line 66, column 30]\n n$35=_fun_dispatch_group_async(null:NSObject*,n$31:NSObject*,(_fun_objc_blockDispatchEx.dispatch_group_notify_example_5):_fn_(*)) [line 66, column 3]\n " shape="box"] "dispatch_group_notify_example#DispatchEx#class.f5cf54b07621c319cf7ead3b217760ed_4" -> "dispatch_group_notify_example#DispatchEx#class.f5cf54b07621c319cf7ead3b217760ed_3" ; diff --git a/infer/tests/codetoanalyze/objc/shared/memory_leaks_benchmark/ArcExample.m.dot b/infer/tests/codetoanalyze/objc/shared/memory_leaks_benchmark/ArcExample.m.dot index 20dfcc612..2c8eb3c1a 100644 --- a/infer/tests/codetoanalyze/objc/shared/memory_leaks_benchmark/ArcExample.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/memory_leaks_benchmark/ArcExample.m.dot @@ -48,7 +48,7 @@ digraph cfg { "setSon:#ArcA(class ArcA)#instance.baae73471012ee089a7558f57ddd56fe_2" [label="2: Exit ArcA.setSon: \n " color=yellow style=filled] -"setSon:#ArcA(class ArcA)#instance.baae73471012ee089a7558f57ddd56fe_3" [label="3: BinaryOperatorStmt: Node \n n$3=*&self:ArcA* [line 14, column 17]\n n$4=*&son:ArcA* [line 14, column 17]\n *n$3._son:ArcA*=n$4 [line 14, column 17]\n " shape="box"] +"setSon:#ArcA(class ArcA)#instance.baae73471012ee089a7558f57ddd56fe_3" [label="3: BinaryOperatorStmt: Node \n n$5=*&self:ArcA* [line 14, column 17]\n n$6=*&son:ArcA* [line 14, column 17]\n *n$5._son:ArcA*=n$6 [line 14, column 17]\n " shape="box"] "setSon:#ArcA(class ArcA)#instance.baae73471012ee089a7558f57ddd56fe_3" -> "setSon:#ArcA(class ArcA)#instance.baae73471012ee089a7558f57ddd56fe_2" ; @@ -59,7 +59,7 @@ digraph cfg { "son#ArcA#instance.eb40da6c5ac3fdfdee0ebe6b666b1ea5_2" [label="2: Exit ArcA.son \n " color=yellow style=filled] -"son#ArcA#instance.eb40da6c5ac3fdfdee0ebe6b666b1ea5_3" [label="3: BinaryOperatorStmt: Node \n n$5=*&self:ArcA* [line 14, column 17]\n n$6=*n$5._son:ArcA* [line 14, column 17]\n *&return:ArcA*=n$6 [line 14, column 17]\n " shape="box"] +"son#ArcA#instance.eb40da6c5ac3fdfdee0ebe6b666b1ea5_3" [label="3: BinaryOperatorStmt: Node \n n$3=*&self:ArcA* [line 14, column 17]\n n$4=*n$3._son:ArcA* [line 14, column 17]\n *&return:ArcA*=n$4 [line 14, column 17]\n " shape="box"] "son#ArcA#instance.eb40da6c5ac3fdfdee0ebe6b666b1ea5_3" -> "son#ArcA#instance.eb40da6c5ac3fdfdee0ebe6b666b1ea5_2" ; diff --git a/infer/tests/codetoanalyze/objc/shared/npe/Nonnull_attribute_example.m.dot b/infer/tests/codetoanalyze/objc/shared/npe/Nonnull_attribute_example.m.dot index 7dae9e937..fc89fe5a7 100644 --- a/infer/tests/codetoanalyze/objc/shared/npe/Nonnull_attribute_example.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/npe/Nonnull_attribute_example.m.dot @@ -70,7 +70,7 @@ digraph cfg { "name#NonnullC#instance.9c59c8694c0f7942ace24d4346f9a7cd_2" [label="2: Exit NonnullC.name \n " color=yellow style=filled] -"name#NonnullC#instance.9c59c8694c0f7942ace24d4346f9a7cd_3" [label="3: BinaryOperatorStmt: Node \n n$5=*&self:NonnullC* [line 30, column 36]\n n$6=*n$5._name:NSString* [line 30, column 36]\n *&return:NSString*=n$6 [line 30, column 36]\n " shape="box"] +"name#NonnullC#instance.9c59c8694c0f7942ace24d4346f9a7cd_3" [label="3: BinaryOperatorStmt: Node \n n$3=*&self:NonnullC* [line 30, column 36]\n n$4=*n$3._name:NSString* [line 30, column 36]\n *&return:NSString*=n$4 [line 30, column 36]\n " shape="box"] "name#NonnullC#instance.9c59c8694c0f7942ace24d4346f9a7cd_3" -> "name#NonnullC#instance.9c59c8694c0f7942ace24d4346f9a7cd_2" ; @@ -81,7 +81,7 @@ digraph cfg { "setName:#NonnullC(class NSString)#instance.06c11492d4403b7a142558aeec6ac42a_2" [label="2: Exit NonnullC.setName: \n " color=yellow style=filled] -"setName:#NonnullC(class NSString)#instance.06c11492d4403b7a142558aeec6ac42a_3" [label="3: BinaryOperatorStmt: Node \n n$3=*&self:NonnullC* [line 30, column 36]\n n$4=*&name:NSString* [line 30, column 36]\n *n$3._name:NSString*=n$4 [line 30, column 36]\n " shape="box"] +"setName:#NonnullC(class NSString)#instance.06c11492d4403b7a142558aeec6ac42a_3" [label="3: BinaryOperatorStmt: Node \n n$5=*&self:NonnullC* [line 30, column 36]\n n$6=*&name:NSString* [line 30, column 36]\n *n$5._name:NSString*=n$6 [line 30, column 36]\n " shape="box"] "setName:#NonnullC(class NSString)#instance.06c11492d4403b7a142558aeec6ac42a_3" -> "setName:#NonnullC(class NSString)#instance.06c11492d4403b7a142558aeec6ac42a_2" ; diff --git a/infer/tests/codetoanalyze/objc/shared/property/PropertyAttributes.m.dot b/infer/tests/codetoanalyze/objc/shared/property/PropertyAttributes.m.dot index a48a548da..ec0e66b94 100644 --- a/infer/tests/codetoanalyze/objc/shared/property/PropertyAttributes.m.dot +++ b/infer/tests/codetoanalyze/objc/shared/property/PropertyAttributes.m.dot @@ -30,7 +30,7 @@ digraph cfg { "child#PropertyA#instance.6f8ba5a5a49be48cc5dabe234a5b1918_2" [label="2: Exit PropertyA.child \n " color=yellow style=filled] -"child#PropertyA#instance.6f8ba5a5a49be48cc5dabe234a5b1918_3" [label="3: BinaryOperatorStmt: Node \n n$15=*&self:PropertyA* [line 12, column 39]\n n$16=*n$15._child:PropertyA* [line 12, column 39]\n *&return:PropertyA*=n$16 [line 12, column 39]\n " shape="box"] +"child#PropertyA#instance.6f8ba5a5a49be48cc5dabe234a5b1918_3" [label="3: BinaryOperatorStmt: Node \n n$13=*&self:PropertyA* [line 12, column 39]\n n$14=*n$13._child:PropertyA* [line 12, column 39]\n *&return:PropertyA*=n$14 [line 12, column 39]\n " shape="box"] "child#PropertyA#instance.6f8ba5a5a49be48cc5dabe234a5b1918_3" -> "child#PropertyA#instance.6f8ba5a5a49be48cc5dabe234a5b1918_2" ; @@ -103,7 +103,7 @@ digraph cfg { "last_name#PropertyA#instance.1ce5ad70e2d4c718c3a98ccc959a3bc9_2" [label="2: Exit PropertyA.last_name \n " color=yellow style=filled] -"last_name#PropertyA#instance.1ce5ad70e2d4c718c3a98ccc959a3bc9_3" [label="3: BinaryOperatorStmt: Node \n n$13=*&self:PropertyA* [line 16, column 52]\n n$14=*n$13._last_name:PropertyA* [line 16, column 52]\n *&return:PropertyA*=n$14 [line 16, column 52]\n " shape="box"] +"last_name#PropertyA#instance.1ce5ad70e2d4c718c3a98ccc959a3bc9_3" [label="3: BinaryOperatorStmt: Node \n n$19=*&self:PropertyA* [line 16, column 52]\n n$20=*n$19._last_name:PropertyA* [line 16, column 52]\n *&return:PropertyA*=n$20 [line 16, column 52]\n " shape="box"] "last_name#PropertyA#instance.1ce5ad70e2d4c718c3a98ccc959a3bc9_3" -> "last_name#PropertyA#instance.1ce5ad70e2d4c718c3a98ccc959a3bc9_2" ; @@ -114,7 +114,7 @@ digraph cfg { "name#PropertyA#instance.c1cdbf324fa14cda26c4633e95fc7667_2" [label="2: Exit PropertyA.name \n " color=yellow style=filled] -"name#PropertyA#instance.c1cdbf324fa14cda26c4633e95fc7667_3" [label="3: BinaryOperatorStmt: Node \n n$19=*&self:PropertyA* [line 14, column 41]\n n$20=*n$19._name:PropertyA* [line 14, column 41]\n *&return:PropertyA*=n$20 [line 14, column 41]\n " shape="box"] +"name#PropertyA#instance.c1cdbf324fa14cda26c4633e95fc7667_3" [label="3: BinaryOperatorStmt: Node \n n$11=*&self:PropertyA* [line 14, column 41]\n n$12=*n$11._name:PropertyA* [line 14, column 41]\n *&return:PropertyA*=n$12 [line 14, column 41]\n " shape="box"] "name#PropertyA#instance.c1cdbf324fa14cda26c4633e95fc7667_3" -> "name#PropertyA#instance.c1cdbf324fa14cda26c4633e95fc7667_2" ; @@ -125,7 +125,7 @@ digraph cfg { "setChild:#PropertyA(class PropertyA)#instance.2830b91fc93649a2fb3b313489bf5461_2" [label="2: Exit PropertyA.setChild: \n " color=yellow style=filled] -"setChild:#PropertyA(class PropertyA)#instance.2830b91fc93649a2fb3b313489bf5461_3" [label="3: BinaryOperatorStmt: Node \n n$9=*&self:PropertyA* [line 12, column 39]\n n$10=*&child:PropertyA* [line 12, column 39]\n *n$9._child:PropertyA*=n$10 [line 12, column 39]\n " shape="box"] +"setChild:#PropertyA(class PropertyA)#instance.2830b91fc93649a2fb3b313489bf5461_3" [label="3: BinaryOperatorStmt: Node \n n$17=*&self:PropertyA* [line 12, column 39]\n n$18=*&child:PropertyA* [line 12, column 39]\n *n$17._child:PropertyA*=n$18 [line 12, column 39]\n " shape="box"] "setChild:#PropertyA(class PropertyA)#instance.2830b91fc93649a2fb3b313489bf5461_3" -> "setChild:#PropertyA(class PropertyA)#instance.2830b91fc93649a2fb3b313489bf5461_2" ; @@ -136,7 +136,7 @@ digraph cfg { "setLast_name:#PropertyA(class PropertyA)#instance.47d6f73ea37f95beeca8ce7a0352c15f_2" [label="2: Exit PropertyA.setLast_name: \n " color=yellow style=filled] -"setLast_name:#PropertyA(class PropertyA)#instance.47d6f73ea37f95beeca8ce7a0352c15f_3" [label="3: BinaryOperatorStmt: Node \n n$11=*&self:PropertyA* [line 16, column 52]\n n$12=*&last_name:PropertyA* [line 16, column 52]\n *n$11._last_name:PropertyA*=n$12 [line 16, column 52]\n " shape="box"] +"setLast_name:#PropertyA(class PropertyA)#instance.47d6f73ea37f95beeca8ce7a0352c15f_3" [label="3: BinaryOperatorStmt: Node \n n$15=*&self:PropertyA* [line 16, column 52]\n n$16=*&last_name:PropertyA* [line 16, column 52]\n *n$15._last_name:PropertyA*=n$16 [line 16, column 52]\n " shape="box"] "setLast_name:#PropertyA(class PropertyA)#instance.47d6f73ea37f95beeca8ce7a0352c15f_3" -> "setLast_name:#PropertyA(class PropertyA)#instance.47d6f73ea37f95beeca8ce7a0352c15f_2" ; @@ -147,7 +147,7 @@ digraph cfg { "setName:#PropertyA(class PropertyA)#instance.530a6c9eaa83786feeaf3a50fc2cd0e6_2" [label="2: Exit PropertyA.setName: \n " color=yellow style=filled] -"setName:#PropertyA(class PropertyA)#instance.530a6c9eaa83786feeaf3a50fc2cd0e6_3" [label="3: BinaryOperatorStmt: Node \n n$17=*&self:PropertyA* [line 14, column 41]\n n$18=*&name:PropertyA* [line 14, column 41]\n *n$17._name:PropertyA*=n$18 [line 14, column 41]\n " shape="box"] +"setName:#PropertyA(class PropertyA)#instance.530a6c9eaa83786feeaf3a50fc2cd0e6_3" [label="3: BinaryOperatorStmt: Node \n n$9=*&self:PropertyA* [line 14, column 41]\n n$10=*&name:PropertyA* [line 14, column 41]\n *n$9._name:PropertyA*=n$10 [line 14, column 41]\n " shape="box"] "setName:#PropertyA(class PropertyA)#instance.530a6c9eaa83786feeaf3a50fc2cd0e6_3" -> "setName:#PropertyA(class PropertyA)#instance.530a6c9eaa83786feeaf3a50fc2cd0e6_2" ;