From 65f4280d6ef4d2366b6bac0f3c5798c98c9ca40f Mon Sep 17 00:00:00 2001 From: Dulma Rodriguez Date: Tue, 15 Sep 2015 09:45:06 -0100 Subject: [PATCH] [clang] [3 of 3] Changes to the translation of record, classes and enums Summary: This is the second of 3 stack diffs to deal with replacing the parser of types. This diff is about changes to translate record types, as well as class types and enum types. For class types and enum types we store the declaration pointer in the map of types to find the type easier later. For record declarations, we change the way we build record names. Moreover, we don't translate typedefs anymore, because when we have a pointer to a typedef, we can find the actual type it points to. --- infer/src/clang/cEnum_decl.ml | 5 +- infer/src/clang/cEnum_decl.mli | 2 +- infer/src/clang/cFrontend.ml | 16 +- infer/src/clang/cFrontend_config.ml | 1 + infer/src/clang/cFrontend_config.mli | 1 + infer/src/clang/cFrontend_utils.ml | 6 + infer/src/clang/cFrontend_utils.mli | 3 + infer/src/clang/cTypes.ml | 13 +- infer/src/clang/cTypes.mli | 4 - infer/src/clang/cTypes_decl.ml | 307 ++++-------------- infer/src/clang/cTypes_decl.mli | 11 +- infer/src/clang/cVar_decl.ml | 3 +- infer/src/clang/objcInterface_decl.ml | 12 +- infer/src/clang/objcInterface_decl.mli | 2 +- .../initialization/struct_initlistexpr.dot | 2 +- .../cpp/frontend/types/methods.dot | 8 +- .../MemoryLeakExample.dot | 4 +- .../TollBridgeExample.dot | 2 +- .../errors/npe/Nonnull_attribute_example.dot | 12 +- .../objc/frontend/block/block-it.dot | 78 ++--- .../objc/frontend/block/block_release.dot | 2 +- .../objc/frontend/block/dispatch.dot | 16 +- .../objc/frontend/block/dispatch_examples.dot | 58 ++-- .../objc/frontend/vardecl/initlist.dot | 4 +- 24 files changed, 197 insertions(+), 375 deletions(-) diff --git a/infer/src/clang/cEnum_decl.ml b/infer/src/clang/cEnum_decl.ml index 3dec73c5e..42d134cb9 100644 --- a/infer/src/clang/cEnum_decl.ml +++ b/infer/src/clang/cEnum_decl.ml @@ -47,7 +47,7 @@ let rec get_enum_constants context decl_list v = (Mangled.from_string name, const) :: get_enum_constants context decl_list' v) | _ -> assert false -let enum_decl name tenv cfg cg namespace decl_list opt_type = +let enum_decl name tenv cfg cg namespace pointer decl_list opt_type = Printing.log_out "ADDING: EnumDecl '%s'\n" name; let context' = CContext.create_context tenv cg cfg !global_procdesc namespace CContext.ContextNoCls @@ -57,7 +57,8 @@ let enum_decl name tenv cfg cg namespace decl_list opt_type = | `Type s -> s | `NoType -> assert false) in (* Here we could give "enum "^name but I want to check that this the type is always defined *) - let typename = Sil.TN_enum (Mangled.from_string name) in + let typename = CTypes.mk_enumname name in let typ = Sil.Tenum enum_constants in + Ast_utils.update_sil_types_map pointer typ; Printing.log_out " TN_typename('%s')\n" (Sil.typename_to_string typename); Sil.tenv_add tenv typename typ diff --git a/infer/src/clang/cEnum_decl.mli b/infer/src/clang/cEnum_decl.mli index fe8a24795..f744fe347 100644 --- a/infer/src/clang/cEnum_decl.mli +++ b/infer/src/clang/cEnum_decl.mli @@ -10,5 +10,5 @@ (** Translate an enumeration declaration by adding it to the tenv and *) (** translating the code and adding it to a fake procdesc *) -val enum_decl : string -> Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> +val enum_decl : string -> Sil.tenv -> Cfg.cfg -> Cg.t -> string option -> Clang_ast_t.pointer -> Clang_ast_t.decl list -> Clang_ast_t.opt_type -> unit diff --git a/infer/src/clang/cFrontend.ml b/infer/src/clang/cFrontend.ml index 1972dec31..ec69644d6 100644 --- a/infer/src/clang/cFrontend.ml +++ b/infer/src/clang/cFrontend.ml @@ -34,9 +34,7 @@ let rec translate_one_declaration tenv cg cfg namespace parent_dec dec = | FunctionDecl(di, name_info, qt, fdecl_info) -> CMethod_declImpl.function_decl tenv cfg cg namespace dec None | TypedefDecl (decl_info, name_info, opt_type, _, typedef_decl_info) -> - let name = name_info.Clang_ast_t.ni_name in - CTypes_decl.do_typedef_declaration tenv namespace - decl_info name opt_type typedef_decl_info + Printing.log_out "%s" "Skipping typedef declaration. Will expand the type in its occurrences." (* Currently C/C++ record decl treated in the same way *) | CXXRecordDecl (_, _, _, _, decl_list, _, _, _) | RecordDecl (_, _, _, _, decl_list, _, _) -> @@ -50,10 +48,10 @@ let rec translate_one_declaration tenv cg cfg namespace parent_dec dec = let name = name_info.Clang_ast_t.ni_name in CVar_decl.global_var_decl tenv namespace decl_info name t - | ObjCInterfaceDecl(decl_info, name_info, decl_list, decl_context_info, obj_c_interface_decl_info) -> + | ObjCInterfaceDecl(decl_info, name_info, decl_list, decl_context_info, oi_decl_info) -> let name = name_info.Clang_ast_t.ni_name in let curr_class = - ObjcInterface_decl.interface_declaration tenv name decl_list obj_c_interface_decl_info in + ObjcInterface_decl.interface_declaration tenv decl_info name decl_list oi_decl_info in CMethod_declImpl.process_methods tenv cg cfg curr_class namespace decl_list | ObjCProtocolDecl(decl_info, name_info, decl_list, decl_context_info, obj_c_protocol_decl_info) -> @@ -85,18 +83,18 @@ let rec translate_one_declaration tenv cg cfg namespace parent_dec dec = | Some ptr -> Ast_utils.get_decl ptr | None -> Some parent_dec in (match class_decl with - | Some CXXRecordDecl(_, _, opt_type, _, _, _, _, _) -> - let class_name = CTypes_decl.get_record_name opt_type in + | Some CXXRecordDecl(_, name_info, opt_type, _, _, _, _, _) -> + let class_name = CTypes_decl.get_record_name opt_type name_info in let curr_class = CContext.ContextCls(class_name, None, []) in if !CFrontend_config.testing_mode then CMethod_declImpl.process_methods tenv cg cfg curr_class namespace [dec] | Some dec -> Printing.log_stats "Methods of %s skipped\n" (Ast_utils.string_of_decl dec) | None -> ()) - | EnumDecl(decl_info, name_info, opt_type, _, decl_list, decl_context_info, enum_decl_info) + | EnumDecl(decl_info, name_info, opt_type, pointer, decl_list, decl_context_info, enum_decl_info) when should_translate_enum -> let name = name_info.Clang_ast_t.ni_name in - CEnum_decl.enum_decl name tenv cfg cg namespace decl_list opt_type + CEnum_decl.enum_decl name tenv cfg cg namespace pointer decl_list opt_type | LinkageSpecDecl(decl_info, decl_list, decl_context_info) -> Printing.log_out "ADDING: LinkageSpecDecl decl list\n"; diff --git a/infer/src/clang/cFrontend_config.ml b/infer/src/clang/cFrontend_config.ml index ce7345db1..6a257237e 100644 --- a/infer/src/clang/cFrontend_config.ml +++ b/infer/src/clang/cFrontend_config.ml @@ -152,6 +152,7 @@ let generated_suffix = "*generated" let pointer_type_index = ref Clang_ast_main.PointerMap.empty +(* Map from type pointers or declaration pointers to sil types *) let sil_types_map = ref Clang_ast_main.PointerMap.empty let weak_attribute = "__weak" diff --git a/infer/src/clang/cFrontend_config.mli b/infer/src/clang/cFrontend_config.mli index 301694fd3..33c718d64 100644 --- a/infer/src/clang/cFrontend_config.mli +++ b/infer/src/clang/cFrontend_config.mli @@ -149,6 +149,7 @@ val generated_suffix : string val pointer_type_index : Clang_ast_t.c_type Clang_ast_main.PointerMap.t ref +(* Map from type pointers or declaration pointers to sil types *) val sil_types_map : (Sil.typ Clang_ast_main.PointerMap.t) ref val weak_attribute : string diff --git a/infer/src/clang/cFrontend_utils.ml b/infer/src/clang/cFrontend_utils.ml index 0638cdd63..c17cf9a28 100644 --- a/infer/src/clang/cFrontend_utils.ml +++ b/infer/src/clang/cFrontend_utils.ml @@ -147,6 +147,12 @@ struct | Some ns when ns ="" -> "" | Some ns -> ns^"::" + let get_qualifier_string name_info = + match name_info.Clang_ast_t.ni_qual_name with + | [] -> "" + | name :: qualifiers -> + list_fold_right (fun el res -> res ^ el ^ "::") qualifiers "" + let property_name property_impl_decl_info = let no_property_name = "WARNING_NO_PROPERTY_NAME" in match property_impl_decl_info.Clang_ast_t.opidi_property_decl with diff --git a/infer/src/clang/cFrontend_utils.mli b/infer/src/clang/cFrontend_utils.mli index dd42c5368..317efcbd2 100644 --- a/infer/src/clang/cFrontend_utils.mli +++ b/infer/src/clang/cFrontend_utils.mli @@ -79,6 +79,9 @@ sig val update_sil_types_map : Clang_ast_t.pointer -> Sil.typ -> unit + (** creates a string to append to a name from a list of qualifiers to a name *) + val get_qualifier_string : Clang_ast_t.named_decl_info -> string + end module General_utils : diff --git a/infer/src/clang/cTypes.ml b/infer/src/clang/cTypes.ml index a134cb044..dd211e8a1 100644 --- a/infer/src/clang/cTypes.ml +++ b/infer/src/clang/cTypes.ml @@ -113,17 +113,6 @@ let get_desugared_type t = | Some t' -> t' | _ -> assert false -(* Remove the work 'struct' from a type name. Used to avoid repetition when typename are constructed*) -(* E.g. 'struct struct s' *) -let cut_struct_union s = - Printing.log_out "Cutting '%s'@." s; - let buf = Str.split (Str.regexp "[ \t]+") s in - match buf with - | "struct":: l (*-> Printing.string_from_list l *) - | "class":: l - | "union":: l -> General_utils.string_from_list l - | _ -> s - let get_name_from_struct s = match s with | Sil.Tstruct(_, _, _, Some n, _, _, _) -> n @@ -155,7 +144,7 @@ let classname_of_type typ = | _ -> Printing.log_out "Classname of type cannot be extracted in type %s" (Sil.typ_to_string typ); - assert false + "undefined" let get_raw_qual_type_decl_ref_exp_info decl_ref_expr_info = match decl_ref_expr_info.Clang_ast_t.drti_decl_ref with diff --git a/infer/src/clang/cTypes.mli b/infer/src/clang/cTypes.mli index e42544e3b..08cd0cc68 100644 --- a/infer/src/clang/cTypes.mli +++ b/infer/src/clang/cTypes.mli @@ -31,10 +31,6 @@ val mk_enumname : string -> Sil.typename val get_name_from_struct: Sil.typ -> Mangled.t -(* Remove the work 'struct' from a type name. Used to avoid repetition when typename are constructed*) -(* E.g. 'struct struct s' *) -val cut_struct_union : string -> string - val remove_pointer_to_typ : Sil.typ -> Sil.typ val is_class : Sil.typ -> bool diff --git a/infer/src/clang/cTypes_decl.ml b/infer/src/clang/cTypes_decl.ml index 2aa73e6e4..64bc15b32 100644 --- a/infer/src/clang/cTypes_decl.ml +++ b/infer/src/clang/cTypes_decl.ml @@ -66,44 +66,29 @@ let add_predefined_types tenv = add_predefined_objc_types tenv; add_predefined_basic_types tenv -let rec search_for_named_type tenv typ = - let search typename = - match typename with - | Sil.TN_typedef name -> - (match Sil.tenv_lookup tenv typename with - | Some _ -> typename - | None -> - let pot_class_type = Sil.TN_csu (Sil.Class, name) in - match Sil.tenv_lookup tenv pot_class_type with - | Some _ -> pot_class_type - | None -> - let pot_protocol_type = Sil.TN_csu (Sil.Protocol, name) in - match Sil.tenv_lookup tenv pot_protocol_type with - | Some _ -> pot_protocol_type - | None -> - let pot_struct_type = Sil.TN_csu (Sil.Struct, name) in - match Sil.tenv_lookup tenv pot_struct_type with - | Some _ -> pot_struct_type - | None -> - let pot_union_type = Sil.TN_csu (Sil.Union, name) in - match Sil.tenv_lookup tenv pot_union_type with - | Some _ -> pot_union_type - | None -> raise Typename_not_found) - | _ -> typename in - match typ with - | Sil.Tvar typename -> Sil.Tvar (search typename) - | Sil.Tptr (typ, p) -> - Sil.Tptr (search_for_named_type tenv typ, p) - | _ -> typ - -let parse_func_type name func_type = None - +let create_csu opt_type = + match opt_type with + | `Type s -> + (let buf = Str.split (Str.regexp "[ \t]+") s in + match buf with + | "struct":: l ->Sil.Struct, General_utils.string_from_list l + | "class":: l -> Sil.Class, General_utils.string_from_list l + | "union":: l -> Sil.Union, General_utils.string_from_list l + | _ -> Sil.Struct, s) + | _ -> assert false (* We need to take the name out of the type as the struct can be anonymous*) -let get_record_name opt_type = match opt_type with - | `Type n' -> CTypes.cut_struct_union n' - | `NoType -> assert false +let get_record_name_csu opt_type name_info = + let name_str = name_info.Clang_ast_t.ni_name in + let csu, type_name = create_csu opt_type in + let prefix = Ast_utils.get_qualifier_string name_info in + let name = + if (String.length name_str = 0) then prefix ^ type_name else prefix ^ name_str in + csu, name + +let get_record_name opt_type name_info = + snd (get_record_name_csu opt_type name_info) let get_method_decls parent decl_list = let open Clang_ast_t in @@ -115,64 +100,31 @@ let get_method_decls parent decl_list = and traverse_decl_list parent decl_list = list_flatten (list_map (traverse_decl parent) decl_list) in traverse_decl_list parent decl_list -(*In case of typedef like *) -(* typedef struct { f1; f2; ... } s; *) -(* the AST-dump splits the typedef definition from the struct definition. *) -(* The type in the typedef "s" will be "s" and this become detached from the struct definition.*) -(* To avoid circular entry in tenv, we disambiguate this case.*) -(* We check if in tenv there is a "strucs s" defined and we make the type def "s" *) -(* point directly to "struct s" *) -let rec disambiguate_typedef tenv namespace t mn = - match t with - | Sil.Tvar(Sil.TN_typedef mn') -> - if (Mangled.equal mn mn') then - (* This will give a circularity in the definition of typedef in the tenv. *) - (* Eg. TN_typdef(mn) --> TN_typedef(mn). We need to break it*) - let tn = Sil.TN_csu(Sil.Struct, mn) in - (match Sil.tenv_lookup tenv tn with - | Some _ -> - (* There is a struct in tenv, so we make the typedef mn pointing to the struct*) - Printing.log_out " ...Found type TN_typdef('%s') " (Mangled.to_string mn); - Printing.log_out "in typedef of '%s'@." (Mangled.to_string mn); - Printing.log_out - "Avoid circular definition in tenv by pointing the typedef to struc TN_csu('%s')@." - (Mangled.to_string mn); - Sil.Tvar(tn) - | None -> - if add_late_defined_record tenv namespace tn then - disambiguate_typedef tenv namespace t mn - else t) - else t - | _ -> t - -and opt_type_to_sil_type tenv opt_type = - match opt_type with - | `Type(s) -> qual_type_to_sil_type tenv (Ast_expressions.create_qual_type s) - | `NoType -> Sil.Tvoid +let get_class_methods tenv class_name namespace decl_list = + let process_method_decl = function + | Clang_ast_t.CXXMethodDecl (decl_info, name_info, qual_type, function_decl_info) -> + let method_name = name_info.Clang_ast_t.ni_name in + Printing.log_out " ...Declaring method '%s'.\n" method_name; + let typ = CTypes.get_type qual_type in + let method_proc = General_utils.mk_procname_from_cpp_method class_name method_name typ in + Some method_proc + | _ -> None in + (* poor mans list_filter_map *) + list_flatten_options (list_map process_method_decl decl_list) -and do_typedef_declaration tenv namespace decl_info name opt_type typedef_decl_info = - if name = CFrontend_config.class_type || name = CFrontend_config.id_cl then () - else - let ns_suffix = Ast_utils.namespace_to_string namespace in - let name = ns_suffix^name in - let mn = Mangled.from_string name in - let typename = Sil.TN_typedef(mn) in - let t = opt_type_to_sil_type tenv opt_type in - (* check for ambiguities in typedef that may create circularities in tenv*) - let typ = disambiguate_typedef tenv namespace t mn in - Printing.log_out "ADDING: TypedefDecl for '%s'" name; - Printing.log_out " with type '%s'\n" (Sil.typ_to_string typ); - Printing.log_out " ...Adding entry to tenv with Typename TN_typedef = '%s'\n" - (Sil.typename_to_string typename); - Sil.tenv_add tenv typename typ +let add_struct_to_tenv tenv typ = + let csu = match typ with + | Sil.Tstruct(_, _, csu, _, _, _, _) -> csu + | _ -> assert false in + let mangled = CTypes.get_name_from_struct typ in + let typename = Sil.TN_csu(csu, mangled) in + Sil.tenv_add tenv typename typ -and get_struct_fields tenv record_name namespace decl_list = +let rec get_struct_fields tenv record_name namespace decl_list = let open Clang_ast_t in let do_one_decl decl = match decl with | FieldDecl (_, name_info, qual_type, _) -> - let field_name = name_info.Clang_ast_t.ni_name in - Printing.log_out " ...Defining field '%s'.\n" field_name; - let id = General_utils.mk_class_field_name record_name field_name in + let id = General_utils.mk_class_field_name record_name name_info.Clang_ast_t.ni_name in let typ = qual_type_to_sil_type tenv qual_type in let annotation_items = [] in (* For the moment we don't use them*) [(id, typ, annotation_items)] @@ -182,163 +134,46 @@ and get_struct_fields tenv record_name namespace decl_list = | _ -> [] in list_flatten (list_map do_one_decl decl_list) -and get_class_methods tenv class_name namespace decl_list = - let process_method_decl = function - | Clang_ast_t.CXXMethodDecl (decl_info, name_info, qual_type, function_decl_info) -> - let method_name = name_info.Clang_ast_t.ni_name in - Printing.log_out " ...Declaring method '%s'.\n" method_name; - let method_proc = General_utils.mk_procname_from_cpp_method class_name method_name (CTypes.get_type qual_type) in - Some method_proc - | _ -> None in - (* poor mans list_filter_map *) - list_flatten_options (list_map process_method_decl decl_list) +(* For a record declaration it returns/constructs the type *) +and get_declaration_type tenv namespace decl = + let open Clang_ast_t in + match decl with + | CXXRecordDecl (decl_info, name_info, opt_type, type_ptr, decl_list, _, record_decl_info, _) + | RecordDecl (decl_info, name_info, opt_type, type_ptr, decl_list, _, record_decl_info) -> + let csu, name = get_record_name_csu opt_type name_info in + let mangled_name = Mangled.from_string name in + let sil_typename = Sil.Tvar (Sil.TN_csu (csu, mangled_name)) in + (* temporarily saves the type name to avoid infinite loops in recursive types *) + Ast_utils.update_sil_types_map type_ptr sil_typename; + if not record_decl_info.Clang_ast_t.rdi_is_complete_definition then + Printing.log_err + " ...Warning, definition incomplete. The full definition will probably be later \n@."; + let non_static_fields = get_struct_fields tenv name namespace decl_list in + let non_static_fields' = if CTrans_models.is_objc_memory_model_controlled name then + General_utils.append_no_duplicates_fields [Sil.objc_ref_counter_field] non_static_fields + else non_static_fields in + let sorted_non_static_fields = CFrontend_utils.General_utils.sort_fields non_static_fields' in + let static_fields = [] in (* Warning for the moment we do not treat static field. *) + let methods = get_class_methods tenv name namespace decl_list in (* C++ methods only *) + let superclasses = [] in + let item_annotation = Sil.item_annotation_empty in (* No annotations for struts *) + let sil_type = Sil.Tstruct (sorted_non_static_fields, static_fields, csu, Some mangled_name, + superclasses, methods, item_annotation) in + Ast_utils.update_sil_types_map type_ptr sil_type; + sil_type + | _ -> assert false and add_types_from_decl_to_tenv tenv namespace decl = let typ = get_declaration_type tenv namespace decl in - let typ = expand_structured_type tenv typ in add_struct_to_tenv tenv typ; typ -(* For a record declaration it returns/constructs the type *) -and get_declaration_type tenv namespace decl = - let open Clang_ast_t in - let n, opt_type, decl_list = match decl with - | CXXRecordDecl (decl_info, name_info, opt_type, _, decl_list, _, record_decl_info, _) - | RecordDecl (decl_info, name_info, opt_type, _, decl_list, _, record_decl_info) -> - let ptr = decl_info.Clang_ast_t.di_pointer in - let name = name_info.Clang_ast_t.ni_name in - Printing.log_out "ADDING: RecordDecl for '%s'" name; - Printing.log_out " pointer= '%s'\n" ptr; - if not record_decl_info.Clang_ast_t.rdi_is_complete_definition then - Printing.log_err " ...Warning, definition incomplete. The full definition will probably be later \n@."; - name, opt_type, decl_list - | _ -> assert false in - - let ns_suffix = Ast_utils.namespace_to_string namespace in - let n = ns_suffix^n in - let name_str = get_record_name opt_type in - Printing.log_out "Record Declaration '%s' defined as struct\n" n; - let non_static_fields = get_struct_fields tenv name_str namespace decl_list in - let non_static_fields = if CTrans_models.is_objc_memory_model_controlled n then - General_utils.append_no_duplicates_fields [Sil.objc_ref_counter_field] non_static_fields - else non_static_fields in - let non_static_fields = CFrontend_utils.General_utils.sort_fields non_static_fields in - let static_fields = [] in (* Warning for the moment we do not treat static field. *) - let typ = (match opt_type with - | `Type s -> qual_type_to_sil_type tenv (Ast_expressions.create_qual_type s) - | _ -> assert false) in - let csu = (match typ with - | Sil.Tvar (Sil.TN_csu (csu, _)) -> csu - | _ -> Sil.Struct) in - let name = Some (Mangled.from_string name_str) in - let methods_list = get_class_methods tenv name_str namespace decl_list in (* C++ methods only *) - let superclass_list = [] in - let item_annotation = Sil.item_annotation_empty in (* No annotations for struts *) - Sil.Tstruct - (non_static_fields, static_fields, csu, name, superclass_list, methods_list, item_annotation) - -(* Look for a record definition that is defined after it is dereferenced. *) -(* It returns true if a new record definition has been added to tenv.*) -and add_late_defined_record tenv namespace typename = - Printing.log_out "!!!! Calling late-defined record '%s'\n" (Sil.typename_to_string typename) ; - match typename with - | Sil.TN_csu(Sil.Struct, name) | Sil.TN_csu(Sil.Union, name) -> - let open Clang_ast_t in - let rec scan decls = - match decls with - | [] -> false - | (CXXRecordDecl (_, _, opt_type, _, _, _, record_decl_info, _) as d) :: decls' - | (RecordDecl (_, _, opt_type, _, _, _, record_decl_info) as d) :: decls' -> - (match opt_type with - | `Type t -> - (* the string t contains the name of the type preceded by the word struct. *) - let t_no_struct = CTypes.cut_struct_union t in - let pot_struct_type = Sil.TN_csu (Sil.Struct, (Mangled.from_string t_no_struct)) in - let pot_union_type = Sil.TN_csu (Sil.Union, (Mangled.from_string t_no_struct)) in - if (Sil.typename_equal typename pot_struct_type || - Sil.typename_equal typename pot_union_type) && - record_decl_info.Clang_ast_t.rdi_is_complete_definition then ( - Printing.log_out "!!!! Adding late-defined record '%s'\n" t; - ignore (add_types_from_decl_to_tenv tenv namespace d); - true) - else scan decls' - | _ -> scan decls') - | LinkageSpecDecl(_, decl_list', _):: decls' -> scan (decl_list'@decls') - | _:: decls' -> scan decls' in - scan !CFrontend_config.global_translation_unit_decls - | _ -> false - -(* Look for a typedef definition that is defined after it is used. *) -(* It returns true if a new typedef definition has been added to tenv.*) -and add_late_defined_typedef tenv namespace typename = - Printing.log_out "Calling late-defined typedef '%s'\n" (Sil.typename_to_string typename); - match typename with - | Sil.TN_typedef name -> - let rec scan decls = - let open Clang_ast_t in - match decls with - | [] -> false - | TypedefDecl (decl_info, name_info, opt_type, _, tdi) :: decls' -> - let name' = name_info.Clang_ast_t.ni_name in - (match opt_type with - | `Type t -> - if (Mangled.to_string name) = name' then ( - Printing.log_out "!!!! Adding late-defined typedef '%s'\n" t; - do_typedef_declaration tenv namespace decl_info name' opt_type tdi; - true) - else scan decls' - | _ -> scan decls') - | LinkageSpecDecl(_, decl_list', _):: decls' -> scan (decl_list'@decls') - | _:: decls' -> scan decls' in - scan !CFrontend_config.global_translation_unit_decls - | _ -> false - -(* Expand a named type Tvar if it has a definition in tenv. This is used for Tenum, Tstruct, etc. *) -and expand_structured_type tenv typ = - match typ with - | Sil.Tvar tn -> - (match Sil.tenv_lookup tenv tn with - | Some t -> - Printing.log_out - " Type expanded with type '%s' found in tenv@." (Sil.typ_to_string t); - if Sil.typ_equal t typ then - typ - else expand_structured_type tenv t - | None -> if (add_late_defined_record tenv None tn || - add_late_defined_typedef tenv None tn) then - expand_structured_type tenv typ - else typ) - | Sil.Tptr(t, _) -> typ (*do not expand types under pointers *) - | _ -> typ - -and add_struct_to_tenv tenv typ = - let typ = expand_structured_type tenv typ in - let csu = match typ with - | Sil.Tstruct(_, _, csu, _, _, _, _) -> csu - | _ -> assert false in - let mangled = CTypes.get_name_from_struct typ in - let typename = Sil.TN_csu(csu, mangled) in - Printing.log_out " >>>Adding struct to tenv mangled='%s'\n" (Mangled.to_string mangled); - Printing.log_out " >>>Adding struct to tenv typ='%s'\n" (Sil.typ_to_string typ); - Printing.log_out " >>>with Key Typename TN_csu('%s')\n" (Sil.typename_to_string typename); - Printing.log_out " >>>Adding entry to tenv ('%s'," (Sil.typename_to_string typename); - Printing.log_out "'%s')\n" (Sil.typ_to_string typ); - Sil.tenv_add tenv typename typ; - Printing.log_out " >>>Verifying that Typename TN_csu('%s') is in tenv\n" - (Sil.typename_to_string typename); - (match Sil.tenv_lookup tenv typename with - | Some t -> Printing.log_out " >>>OK. Found typ='%s'\n" (Sil.typ_to_string t) - | None -> Printing.log_out " >>>NOT Found!!\n") - -(* Translate a qual_type from clang to sil type. *) and qual_type_to_sil_type tenv qt = CType_to_sil_type.qual_type_to_sil_type add_types_from_decl_to_tenv tenv qt -and qual_type_to_sil_type_np tenv qt = - qual_type_to_sil_type tenv qt -and type_name_to_sil_type tenv name = - qual_type_to_sil_type tenv (Ast_expressions.create_qual_type name) +let type_name_to_sil_type tenv name = + qual_type_to_sil_type tenv (Ast_expressions.create_class_type name) let get_type_from_expr_info ei tenv = let qt = ei.Clang_ast_t.ei_qual_type in @@ -364,4 +199,4 @@ let extract_sil_type_from_stmt tenv s = let get_type_curr_class tenv curr_class_opt = let name = CContext.get_curr_class_name curr_class_opt in let typ = Sil.Tvar (Sil.TN_csu (Sil.Class, (Mangled.from_string name))) in - expand_structured_type tenv typ + CTypes.expand_structured_type tenv typ diff --git a/infer/src/clang/cTypes_decl.mli b/infer/src/clang/cTypes_decl.mli index 47b2c1ef6..6741b8857 100644 --- a/infer/src/clang/cTypes_decl.mli +++ b/infer/src/clang/cTypes_decl.mli @@ -13,25 +13,18 @@ val get_declaration_type : Sil.tenv -> string option -> Clang_ast_t.decl -> Sil. val add_struct_to_tenv : Sil.tenv -> Sil.typ -> unit -val get_record_name : Clang_ast_t.opt_type -> string +val get_record_name : Clang_ast_t.opt_type -> Clang_ast_t.named_decl_info -> string val get_method_decls : Clang_ast_t.decl -> Clang_ast_t.decl list -> (Clang_ast_t.decl * Clang_ast_t.decl) list -val do_typedef_declaration : Sil.tenv -> string option -> Clang_ast_t.decl_info -> string -> - Clang_ast_t.opt_type -> Clang_ast_t.typedef_decl_info -> unit - val add_types_from_decl_to_tenv : Sil.tenv -> string option -> Clang_ast_t.decl -> Sil.typ -val parse_func_type : string -> string -> (Sil.typ * Sil.typ list) option - (* Adds the predefined types objc_class which is a struct, *) (* and Class, which is a pointer to objc_class. *) val add_predefined_types : Sil.tenv -> unit val qual_type_to_sil_type : Sil.tenv -> Clang_ast_t.qual_type -> Sil.typ -val qual_type_to_sil_type_np : Sil.tenv -> Clang_ast_t.qual_type -> Sil.typ - val class_from_pointer_type : Sil.tenv -> Clang_ast_t.qual_type -> string val get_class_type_np : Sil.tenv -> Clang_ast_t.expr_info -> @@ -41,8 +34,6 @@ val extract_sil_type_from_stmt : Sil.tenv -> Clang_ast_t.stmt -> Sil.typ val get_type_curr_class : Sil.tenv -> CContext.curr_class -> Sil.typ -val expand_structured_type : Sil.tenv -> Sil.typ -> Sil.typ - val get_type_from_expr_info : Clang_ast_t.expr_info -> Sil.tenv -> Sil.typ val type_name_to_sil_type : Sil.tenv -> string -> Sil.typ diff --git a/infer/src/clang/cVar_decl.ml b/infer/src/clang/cVar_decl.ml index cfa4fa10e..1def94643 100644 --- a/infer/src/clang/cVar_decl.ml +++ b/infer/src/clang/cVar_decl.ml @@ -162,8 +162,7 @@ and get_variables_decls context (decl_list : Clang_ast_t.decl list) : unit = let typ = CTypes_decl.get_declaration_type context.CContext.tenv context.CContext.namespace decl in CTypes_decl.add_struct_to_tenv context.CContext.tenv typ | TypedefDecl (decl_info, name_info, opt_type, _, typedef_decl_info) -> - CTypes_decl.do_typedef_declaration context.CContext.tenv context.CContext.namespace - decl_info name_info.Clang_ast_t.ni_name opt_type typedef_decl_info + Printing.log_out "%s" "Skipping typedef. Will expand the type in its occurrences." | StaticAssertDecl decl_info -> (* We do not treat Assertions. *) Printing.log_out "WARNING: When collecting variables, passing from StaticAssertDecl '%s'. Skipped.\n" diff --git a/infer/src/clang/objcInterface_decl.ml b/infer/src/clang/objcInterface_decl.ml index 80e15ed08..912da5ac0 100644 --- a/infer/src/clang/objcInterface_decl.ml +++ b/infer/src/clang/objcInterface_decl.ml @@ -90,7 +90,7 @@ let update_curr_class curr_class superclasses = | _ -> assert false (* Adds pairs (interface name, interface_type_info) to the global environment. *) -let add_class_to_tenv tenv class_name decl_list obj_c_interface_decl_info = +let add_class_to_tenv tenv decl_info class_name decl_list obj_c_interface_decl_info = Printing.log_out "ADDING: ObjCInterfaceDecl for '%s'\n" class_name; let interface_name = CTypes.mk_classname class_name in let curr_class, superclasses, fields = @@ -121,6 +121,7 @@ let add_class_to_tenv tenv class_name decl_list obj_c_interface_decl_info = Sil.Tstruct(fields, [], Sil.Class, Some (Mangled.from_string class_name), superclasses, methods, objc_class_annotation) in Sil.tenv_add tenv interface_name interface_type_info; + Ast_utils.update_sil_types_map decl_info.Clang_ast_t.di_pointer (Sil.Tvar interface_name); Printing.log_out " >>>Verifying that Typename '%s' is in tenv\n" (Sil.typename_to_string interface_name); (match Sil.tenv_lookup tenv interface_name with @@ -139,8 +140,8 @@ let add_missing_methods tenv class_name decl_list curr_class = | _ -> () (* Interface_type_info has the name of instance variables and the name of methods. *) -let interface_declaration tenv class_name decl_list obj_c_interface_decl_info = - add_class_to_tenv tenv class_name decl_list obj_c_interface_decl_info +let interface_declaration tenv decl_info class_name decl_list obj_c_interface_decl_info = + add_class_to_tenv tenv decl_info class_name decl_list obj_c_interface_decl_info (* Translate the methods defined in the implementation.*) let interface_impl_declaration tenv class_name decl_list idi = @@ -167,12 +168,13 @@ let lookup_late_defined_interface tenv cname = :: decls' when (Mangled.from_string name_info.Clang_ast_t.ni_name) = cname -> scan decls' - | ObjCInterfaceDecl (decl_info, name_info, decl_list, decl_context_info, obj_c_interface_decl_info) + | ObjCInterfaceDecl (decl_info, name_info, decl_list, decl_context_info, oi_decl_info) :: decls' when (Mangled.from_string name_info.Clang_ast_t.ni_name) = cname -> (* Assumption: here we assume that the first interface declaration with non empty set of fields is the *) (* correct one. So we stop. *) - ignore (interface_declaration tenv name_info.Clang_ast_t.ni_name decl_list obj_c_interface_decl_info) + let name = name_info.Clang_ast_t.ni_name in + ignore (interface_declaration tenv decl_info name decl_list oi_decl_info) | _:: decls' -> scan decls' in scan !CFrontend_config.global_translation_unit_decls diff --git a/infer/src/clang/objcInterface_decl.mli b/infer/src/clang/objcInterface_decl.mli index 6dde20ed6..a9f3e9017 100644 --- a/infer/src/clang/objcInterface_decl.mli +++ b/infer/src/clang/objcInterface_decl.mli @@ -11,7 +11,7 @@ (** is saved in the tenv as a struct with the corresponding fields, potential superclass and *) (** list of defined methods *) -val interface_declaration : Sil.tenv -> string -> Clang_ast_t.decl list -> +val interface_declaration : Sil.tenv -> Clang_ast_t.decl_info -> string -> Clang_ast_t.decl list -> Clang_ast_t.obj_c_interface_decl_info -> CContext.curr_class val find_field : Sil.tenv -> string -> Sil.typ option -> bool -> diff --git a/infer/tests/codetoanalyze/c/frontend/initialization/struct_initlistexpr.dot b/infer/tests/codetoanalyze/c/frontend/initialization/struct_initlistexpr.dot index c0394cd3a..5869ccb12 100644 --- a/infer/tests/codetoanalyze/c/frontend/initialization/struct_initlistexpr.dot +++ b/infer/tests/codetoanalyze/c/frontend/initialization/struct_initlistexpr.dot @@ -25,7 +25,7 @@ digraph iCFG { 8 [label="8: Exit test \n " color=yellow style=filled] -7 [label="7: Start test\nFormals: p:Point *\nLocals: \n DECLARE_LOCALS(&return); [line 23]\n NULLIFY(&p,false); [line 23]\n " color=yellow style=filled] +7 [label="7: Start test\nFormals: p:struct Point *\nLocals: \n DECLARE_LOCALS(&return); [line 23]\n NULLIFY(&p,false); [line 23]\n " color=yellow style=filled] 7 -> 10 ; diff --git a/infer/tests/codetoanalyze/cpp/frontend/types/methods.dot b/infer/tests/codetoanalyze/cpp/frontend/types/methods.dot index 907c36aef..9ee1390ec 100644 --- a/infer/tests/codetoanalyze/cpp/frontend/types/methods.dot +++ b/infer/tests/codetoanalyze/cpp/frontend/types/methods.dot @@ -32,7 +32,7 @@ digraph iCFG { 21 [label="21: Exit A_add \n " color=yellow style=filled] -20 [label="20: Start A_add\nFormals: this:struct A other:struct A &\nLocals: \n DECLARE_LOCALS(&return); [line 41]\n NULLIFY(&this,false); [line 41]\n NULLIFY(&other,false); [line 41]\n " color=yellow style=filled] +20 [label="20: Start A_add\nFormals: this:struct A other:struct A &\nLocals: \n DECLARE_LOCALS(&return); [line 41]\n NULLIFY(&other,false); [line 41]\n NULLIFY(&this,false); [line 41]\n " color=yellow style=filled] 20 -> 21 ; @@ -58,14 +58,14 @@ digraph iCFG { 14 [label="14: Exit A_fun \n " color=yellow style=filled] -13 [label="13: Start A_fun\nFormals: this:struct A a:int b:int \nLocals: c:int \n DECLARE_LOCALS(&return,&c); [line 30]\n NULLIFY(&this,false); [line 30]\n NULLIFY(&c,false); [line 30]\n " color=yellow style=filled] +13 [label="13: Start A_fun\nFormals: this:struct A a:int b:int \nLocals: c:int \n DECLARE_LOCALS(&return,&c); [line 30]\n NULLIFY(&c,false); [line 30]\n NULLIFY(&this,false); [line 30]\n " color=yellow style=filled] 13 -> 16 ; 12 [label="12: Exit A_fun \n " color=yellow style=filled] -11 [label="11: Start A_fun\nFormals: this:struct A a:int b:int c:int \nLocals: \n DECLARE_LOCALS(&return); [line 25]\n NULLIFY(&this,false); [line 25]\n NULLIFY(&a,false); [line 25]\n NULLIFY(&b,false); [line 25]\n NULLIFY(&c,false); [line 25]\n " color=yellow style=filled] +11 [label="11: Start A_fun\nFormals: this:struct A a:int b:int c:int \nLocals: \n DECLARE_LOCALS(&return); [line 25]\n NULLIFY(&a,false); [line 25]\n NULLIFY(&b,false); [line 25]\n NULLIFY(&c,false); [line 25]\n NULLIFY(&this,false); [line 25]\n " color=yellow style=filled] 11 -> 12 ; @@ -91,7 +91,7 @@ digraph iCFG { 5 [label="5: Exit A_def_in \n " color=yellow style=filled] -4 [label="4: Start A_def_in\nFormals: this:struct A \nLocals: c:int \n DECLARE_LOCALS(&return,&c); [line 17]\n NULLIFY(&this,false); [line 17]\n NULLIFY(&c,false); [line 17]\n " color=yellow style=filled] +4 [label="4: Start A_def_in\nFormals: this:struct A \nLocals: c:int \n DECLARE_LOCALS(&return,&c); [line 17]\n NULLIFY(&c,false); [line 17]\n NULLIFY(&this,false); [line 17]\n " color=yellow style=filled] 4 -> 7 ; diff --git a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/MemoryLeakExample.dot b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/MemoryLeakExample.dot index ca4ff413b..e0a01004f 100644 --- a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/MemoryLeakExample.dot +++ b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/MemoryLeakExample.dot @@ -141,7 +141,7 @@ digraph iCFG { 11 -> 13 ; -10 [label="10: DeclStmt \n n$13=*&self:class MemoryLeakExample * [line 31]\n n$12=_fun_MemoryLeakExample_backgroundCoveringView(n$13:class MemoryLeakExample *) virtual [line 31]\n n$11=_fun_UIView_bounds(n$12:class UIView *) virtual [line 31]\n n$14=_fun_CGPathCreateWithRect(n$11:struct CGRect ,0:CGAffineTransform *) [line 31]\n *&shadowPath:struct CGPath *=n$14 [line 31]\n REMOVE_TEMPS(n$11,n$12,n$13,n$14); [line 31]\n " shape="box"] +10 [label="10: DeclStmt \n n$13=*&self:class MemoryLeakExample * [line 31]\n n$12=_fun_MemoryLeakExample_backgroundCoveringView(n$13:class MemoryLeakExample *) virtual [line 31]\n n$11=_fun_UIView_bounds(n$12:class UIView *) virtual [line 31]\n n$14=_fun_CGPathCreateWithRect(n$11:struct CGRect ,0:struct CGAffineTransform *) [line 31]\n *&shadowPath:struct CGPath *=n$14 [line 31]\n REMOVE_TEMPS(n$11,n$12,n$13,n$14); [line 31]\n " shape="box"] 10 -> 9 ; @@ -160,7 +160,7 @@ digraph iCFG { 6 -> 5 ; -5 [label="5: DeclStmt \n n$3=*&attachmentContainerView:class UIView * [line 22]\n n$2=_fun_UIView_bounds(n$3:class UIView *) virtual [line 22]\n n$4=_fun_CGPathCreateWithRect(n$2:struct CGRect ,0:CGAffineTransform *) [line 22]\n *&shadowPath:struct CGPath *=n$4 [line 22]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 22]\n " shape="box"] +5 [label="5: DeclStmt \n n$3=*&attachmentContainerView:class UIView * [line 22]\n n$2=_fun_UIView_bounds(n$3:class UIView *) virtual [line 22]\n n$4=_fun_CGPathCreateWithRect(n$2:struct CGRect ,0:struct CGAffineTransform *) [line 22]\n *&shadowPath:struct CGPath *=n$4 [line 22]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 22]\n " shape="box"] 5 -> 4 ; diff --git a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/TollBridgeExample.dot b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/TollBridgeExample.dot index 4438f5365..ac027c260 100644 --- a/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/TollBridgeExample.dot +++ b/infer/tests/codetoanalyze/objc/errors/memory_leaks_benchmark/TollBridgeExample.dot @@ -1,5 +1,5 @@ digraph iCFG { -19 [label="19: Return Stmt \n n$0=_fun___builtin___CFStringMakeConstantString(\"Icon\":char *) [line 43]\n n$1=_fun_CTFontCreateWithName(n$0:struct __CFString *,17.000000:double ,0:CGAffineTransform *) [line 43]\n n$2=_fun___objc_cast(n$1:void *,sizeof(void ):unsigned long ) [line 43]\n *&return:struct __CTFont *=n$2 [line 43]\n REMOVE_TEMPS(n$0,n$1,n$2); [line 43]\n APPLY_ABSTRACTION; [line 43]\n " shape="box"] +19 [label="19: Return Stmt \n n$0=_fun___builtin___CFStringMakeConstantString(\"Icon\":char *) [line 43]\n n$1=_fun_CTFontCreateWithName(n$0:struct __CFString *,17.000000:double ,0:struct CGAffineTransform *) [line 43]\n n$2=_fun___objc_cast(n$1:void *,sizeof(void ):unsigned long ) [line 43]\n *&return:struct __CTFont *=n$2 [line 43]\n REMOVE_TEMPS(n$0,n$1,n$2); [line 43]\n APPLY_ABSTRACTION; [line 43]\n " shape="box"] 19 -> 18 ; diff --git a/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot b/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot index ba08e3d0e..bf94345f4 100644 --- a/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot +++ b/infer/tests/codetoanalyze/objc/errors/npe/Nonnull_attribute_example.dot @@ -1,9 +1,9 @@ digraph iCFG { -20 [label="20: Call _fun___infer_assume \n n$1=*&callback:_fn_ (*) [line 46]\n n$2=_fun___infer_assume((n$1 != 0):_fn_ (*)) [line 46]\n REMOVE_TEMPS(n$1,n$2); [line 46]\n " shape="box"] +20 [label="20: Call _fun___infer_assume \n n$1=*&callback:_fn_ (*) [line 46]\n _fun___infer_assume((n$1 != 0):_fn_ (*)) [line 46]\n REMOVE_TEMPS(n$1); [line 46]\n " shape="box"] 20 -> 19 ; -19 [label="19: Call n$0 \n n$0=*&callback:_fn_ (*) [line 47]\n n$0(0:class NSError *,0:id *) [line 47]\n REMOVE_TEMPS(n$0); [line 47]\n NULLIFY(&callback,false); [line 47]\n APPLY_ABSTRACTION; [line 47]\n " shape="box"] +19 [label="19: Call n$0 \n n$0=*&callback:_fn_ (*) [line 47]\n n$0(0:class NSError *,0:struct objc_object *) [line 47]\n REMOVE_TEMPS(n$0); [line 47]\n NULLIFY(&callback,false); [line 47]\n APPLY_ABSTRACTION; [line 47]\n " shape="box"] 19 -> 18 ; @@ -14,11 +14,11 @@ digraph iCFG { 17 -> 20 ; -16 [label="16: Call _fun___infer_assume \n n$13=*&name:class NSString * [line -1]\n n$14=_fun___infer_assume((n$13 != 0):class NSString *) [line -1]\n REMOVE_TEMPS(n$13,n$14); [line -1]\n " shape="box"] +16 [label="16: Call _fun___infer_assume \n n$12=*&name:class NSString * [line -1]\n _fun___infer_assume((n$12 != 0):class NSString *) [line -1]\n REMOVE_TEMPS(n$12); [line -1]\n " shape="box"] 16 -> 15 ; -15 [label="15: BinaryOperatorStmt: Assign \n n$10=*&self:class C * [line 31]\n n$12=*&name:class NSString * [line 31]\n n$11=_fun_NSString_copy(n$12:class NSString *) virtual [line 31]\n *n$10._name:class NSString *=n$11 [line 31]\n REMOVE_TEMPS(n$10,n$11,n$12); [line 31]\n NULLIFY(&name,false); [line 31]\n NULLIFY(&self,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"] +15 [label="15: BinaryOperatorStmt: Assign \n n$9=*&self:class C * [line 31]\n n$11=*&name:class NSString * [line 31]\n n$10=_fun_NSString_copy(n$11:class NSString *) virtual [line 31]\n *n$9._name:class NSString *=n$10 [line 31]\n REMOVE_TEMPS(n$9,n$10,n$11); [line 31]\n NULLIFY(&name,false); [line 31]\n NULLIFY(&self,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"] 15 -> 14 ; @@ -29,7 +29,7 @@ digraph iCFG { 13 -> 16 ; -12 [label="12: Return Stmt \n n$7=*&self:class C * [line 31]\n n$8=*n$7._name:class NSString * [line 31]\n *&return:class NSString *=n$8 [line 31]\n n$9=_fun___set_autorelease_attribute(n$8:class NSString *) [line 31]\n REMOVE_TEMPS(n$7,n$8,n$9); [line 31]\n NULLIFY(&self,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"] +12 [label="12: Return Stmt \n n$6=*&self:class C * [line 31]\n n$7=*n$6._name:class NSString * [line 31]\n *&return:class NSString *=n$7 [line 31]\n n$8=_fun___set_autorelease_attribute(n$7:class NSString *) [line 31]\n REMOVE_TEMPS(n$6,n$7,n$8); [line 31]\n NULLIFY(&self,false); [line 31]\n APPLY_ABSTRACTION; [line 31]\n " shape="box"] 12 -> 11 ; @@ -40,7 +40,7 @@ digraph iCFG { 10 -> 12 ; -9 [label="9: Call _fun___infer_assume \n n$5=*&a:class A * [line -1]\n n$6=_fun___infer_assume((n$5 != 0):class A *) [line -1]\n REMOVE_TEMPS(n$5,n$6); [line -1]\n " shape="box"] +9 [label="9: Call _fun___infer_assume \n n$5=*&a:class A * [line -1]\n _fun___infer_assume((n$5 != 0):class A *) [line -1]\n REMOVE_TEMPS(n$5); [line -1]\n " shape="box"] 9 -> 8 ; diff --git a/infer/tests/codetoanalyze/objc/frontend/block/block-it.dot b/infer/tests/codetoanalyze/objc/frontend/block/block-it.dot index 112040be3..93477ed93 100644 --- a/infer/tests/codetoanalyze/objc/frontend/block/block-it.dot +++ b/infer/tests/codetoanalyze/objc/frontend/block/block-it.dot @@ -1,21 +1,21 @@ digraph iCFG { -52 [label="52: DeclStmt \n n$47=_fun___objc_alloc_no_fail(sizeof(class NSArray ):unsigned long ) [line 30]\n n$45=_fun_NSArray_init(n$47:class NSArray *) virtual [line 30]\n *&a:class NSArray *=n$45 [line 30]\n REMOVE_TEMPS(n$45,n$47); [line 30]\n " shape="box"] +52 [label="52: DeclStmt \n n$44=_fun___objc_alloc_no_fail(sizeof(class NSArray ):unsigned long ) [line 30]\n n$42=_fun_NSArray_init(n$44:class NSArray *) virtual [line 30]\n *&a:class NSArray *=n$42 [line 30]\n REMOVE_TEMPS(n$42,n$44); [line 30]\n " shape="box"] 52 -> 51 ; -51 [label="51: DeclStmt \n n$44=*&a:class NSArray * [line 32]\n *&objects:class NSArray *=n$44 [line 32]\n REMOVE_TEMPS(n$44); [line 32]\n NULLIFY(&a,false); [line 32]\n " shape="box"] +51 [label="51: DeclStmt \n n$41=*&a:class NSArray * [line 32]\n *&objects:class NSArray *=n$41 [line 32]\n REMOVE_TEMPS(n$41); [line 32]\n NULLIFY(&a,false); [line 32]\n " shape="box"] 51 -> 44 ; -50 [label="50: BinaryOperatorStmt: Assign \n NULLIFY(&ShouldStop,false); [line 40]\n n$42=*&stop:BOOL * [line 40]\n *n$42:_Bool =1 [line 40]\n REMOVE_TEMPS(n$42); [line 40]\n NULLIFY(&stop,false); [line 40]\n APPLY_ABSTRACTION; [line 40]\n " shape="box"] +50 [label="50: BinaryOperatorStmt: Assign \n NULLIFY(&ShouldStop,false); [line 40]\n n$39=*&stop:_Bool * [line 40]\n *n$39:_Bool =1 [line 40]\n REMOVE_TEMPS(n$39); [line 40]\n NULLIFY(&stop,false); [line 40]\n APPLY_ABSTRACTION; [line 40]\n " shape="box"] 50 -> 47 ; -49 [label="49: Prune (false branch) \n n$41=*&ShouldStop:int [line 39]\n PRUNE((n$41 == 0), false); [line 39]\n REMOVE_TEMPS(n$41); [line 39]\n APPLY_ABSTRACTION; [line 39]\n " shape="invhouse"] +49 [label="49: Prune (false branch) \n n$38=*&ShouldStop:int [line 39]\n PRUNE((n$38 == 0), false); [line 39]\n REMOVE_TEMPS(n$38); [line 39]\n APPLY_ABSTRACTION; [line 39]\n " shape="invhouse"] 49 -> 47 ; -48 [label="48: Prune (true branch) \n n$41=*&ShouldStop:int [line 39]\n PRUNE((n$41 != 0), true); [line 39]\n REMOVE_TEMPS(n$41); [line 39]\n " shape="invhouse"] +48 [label="48: Prune (true branch) \n n$38=*&ShouldStop:int [line 39]\n PRUNE((n$38 != 0), true); [line 39]\n REMOVE_TEMPS(n$38); [line 39]\n " shape="invhouse"] 48 -> 50 ; @@ -26,40 +26,40 @@ digraph iCFG { 46 [label="46: Exit __objc_anonymous_block_MyBlock_array_trans______2 \n " color=yellow style=filled] -45 [label="45: Start __objc_anonymous_block_MyBlock_array_trans______2\nFormals: object:struct objc_object * idx:unsigned long stop:BOOL *\nLocals: ShouldStop:int \n DECLARE_LOCALS(&return,&ShouldStop); [line 35]\n NULLIFY(&idx,false); [line 35]\n NULLIFY(&object,false); [line 35]\n " color=yellow style=filled] +45 [label="45: Start __objc_anonymous_block_MyBlock_array_trans______2\nFormals: object:struct objc_object * idx:unsigned long stop:_Bool *\nLocals: ShouldStop:int \n DECLARE_LOCALS(&return,&ShouldStop); [line 35]\n NULLIFY(&idx,false); [line 35]\n NULLIFY(&object,false); [line 35]\n " color=yellow style=filled] 45 -> 48 ; 45 -> 49 ; -44 [label="44: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_MyBlock_array_trans______2); [line 35]\n n$43=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_MyBlock_array_trans______2 ):unsigned long ) [line 35]\n *&__objc_anonymous_block_MyBlock_array_trans______2:class __objc_anonymous_block_MyBlock_array_trans______2 =n$43 [line 35]\n *&enumerateObjectsUsingBlock:_fn_ (*)=(_fun___objc_anonymous_block_MyBlock_array_trans______2) [line 35]\n REMOVE_TEMPS(n$43); [line 35]\n " shape="box"] +44 [label="44: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_MyBlock_array_trans______2); [line 35]\n n$40=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_MyBlock_array_trans______2 ):unsigned long ) [line 35]\n *&__objc_anonymous_block_MyBlock_array_trans______2:class __objc_anonymous_block_MyBlock_array_trans______2 =n$40 [line 35]\n *&enumerateObjectsUsingBlock:_fn_ (*)=(_fun___objc_anonymous_block_MyBlock_array_trans______2) [line 35]\n REMOVE_TEMPS(n$40); [line 35]\n " shape="box"] 44 -> 43 ; -43 [label="43: DeclStmt \n n$40=_fun_malloc_no_fail(sizeof(_Bool ):_Bool ) [line 43]\n *&stop:BOOL *=n$40 [line 43]\n REMOVE_TEMPS(n$40); [line 43]\n " shape="box"] +43 [label="43: DeclStmt \n n$37=_fun_malloc_no_fail(sizeof(_Bool ):_Bool ) [line 43]\n *&stop:_Bool *=n$37 [line 43]\n REMOVE_TEMPS(n$37); [line 43]\n " shape="box"] 43 -> 42 ; -42 [label="42: BinaryOperatorStmt: Assign \n n$39=*&stop:BOOL * [line 44]\n *n$39:_Bool =0 [line 44]\n REMOVE_TEMPS(n$39); [line 44]\n " shape="box"] +42 [label="42: BinaryOperatorStmt: Assign \n n$36=*&stop:_Bool * [line 44]\n *n$36:_Bool =0 [line 44]\n REMOVE_TEMPS(n$36); [line 44]\n " shape="box"] 42 -> 31 ; -41 [label="41: DeclStmt \n n$37=*&objects:class NSArray * [line 49]\n n$38=*&idx:unsigned long [line 49]\n n$36=_fun_NSArray_objectAtIndexedSubscript:(n$37:class NSArray *,n$38:unsigned long ) virtual [line 49]\n *&object:struct objc_object *=n$36 [line 49]\n REMOVE_TEMPS(n$36,n$37,n$38); [line 49]\n " shape="box"] +41 [label="41: DeclStmt \n n$34=*&objects:class NSArray * [line 49]\n n$35=*&idx:unsigned long [line 49]\n n$33=_fun_NSArray_objectAtIndexedSubscript:(n$34:class NSArray *,n$35:unsigned long ) virtual [line 49]\n *&object:struct objc_object *=n$33 [line 49]\n REMOVE_TEMPS(n$33,n$34,n$35); [line 49]\n " shape="box"] 41 -> 40 ; -40 [label="40: Call n$32 \n n$32=*&enumerateObjectsUsingBlock:_fn_ (*) [line 50]\n n$33=*&object:struct objc_object * [line 50]\n n$34=*&idx:unsigned long [line 50]\n n$35=*&stop:BOOL * [line 50]\n n$32(n$33:struct objc_object *,n$34:unsigned long ,n$35:BOOL *) [line 50]\n REMOVE_TEMPS(n$32,n$33,n$34,n$35); [line 50]\n NULLIFY(&object,false); [line 50]\n " shape="box"] +40 [label="40: Call n$29 \n n$29=*&enumerateObjectsUsingBlock:_fn_ (*) [line 50]\n n$30=*&object:struct objc_object * [line 50]\n n$31=*&idx:unsigned long [line 50]\n n$32=*&stop:_Bool * [line 50]\n n$29(n$30:struct objc_object *,n$31:unsigned long ,n$32:_Bool *) [line 50]\n REMOVE_TEMPS(n$29,n$30,n$31,n$32); [line 50]\n NULLIFY(&object,false); [line 50]\n " shape="box"] 40 -> 37 ; -39 [label="39: Prune (false branch) \n PRUNE(((n$31 == 1) == 0), false); [line 51]\n REMOVE_TEMPS(n$30,n$31); [line 51]\n " shape="invhouse"] +39 [label="39: Prune (false branch) \n PRUNE(((n$28 == 1) == 0), false); [line 51]\n REMOVE_TEMPS(n$27,n$28); [line 51]\n " shape="invhouse"] 39 -> 36 ; -38 [label="38: Prune (true branch) \n PRUNE(((n$31 == 1) != 0), true); [line 51]\n REMOVE_TEMPS(n$30,n$31); [line 51]\n APPLY_ABSTRACTION; [line 51]\n " shape="invhouse"] +38 [label="38: Prune (true branch) \n PRUNE(((n$28 == 1) != 0), true); [line 51]\n REMOVE_TEMPS(n$27,n$28); [line 51]\n APPLY_ABSTRACTION; [line 51]\n " shape="invhouse"] 38 -> 29 ; -37 [label="37: BinaryOperatorStmt: EQ \n n$30=*&stop:BOOL * [line 51]\n n$31=*n$30:_Bool [line 51]\n " shape="box"] +37 [label="37: BinaryOperatorStmt: EQ \n n$27=*&stop:_Bool * [line 51]\n n$28=*n$27:_Bool [line 51]\n " shape="box"] 37 -> 38 ; @@ -68,20 +68,20 @@ digraph iCFG { 36 -> 32 ; -35 [label="35: Prune (false branch) \n PRUNE(((n$27 < n$28) == 0), false); [line 46]\n REMOVE_TEMPS(n$27,n$28,n$29); [line 46]\n APPLY_ABSTRACTION; [line 46]\n " shape="invhouse"] +35 [label="35: Prune (false branch) \n PRUNE(((n$24 < n$25) == 0), false); [line 46]\n REMOVE_TEMPS(n$24,n$25,n$26); [line 46]\n APPLY_ABSTRACTION; [line 46]\n " shape="invhouse"] 35 -> 29 ; -34 [label="34: Prune (true branch) \n PRUNE(((n$27 < n$28) != 0), true); [line 46]\n REMOVE_TEMPS(n$27,n$28,n$29); [line 46]\n " shape="invhouse"] +34 [label="34: Prune (true branch) \n PRUNE(((n$24 < n$25) != 0), true); [line 46]\n REMOVE_TEMPS(n$24,n$25,n$26); [line 46]\n " shape="invhouse"] 34 -> 41 ; -33 [label="33: BinaryOperatorStmt: LT \n n$27=*&idx:unsigned long [line 46]\n n$29=*&objects:class NSArray * [line 46]\n n$28=_fun_NSArray_count(n$29:class NSArray *) virtual [line 46]\n " shape="box"] +33 [label="33: BinaryOperatorStmt: LT \n n$24=*&idx:unsigned long [line 46]\n n$26=*&objects:class NSArray * [line 46]\n n$25=_fun_NSArray_count(n$26:class NSArray *) virtual [line 46]\n " shape="box"] 33 -> 34 ; 33 -> 35 ; -32 [label="32: UnaryOperator \n n$26=*&idx:unsigned long [line 46]\n *&idx:unsigned long =(n$26 + 1) [line 46]\n REMOVE_TEMPS(n$26); [line 46]\n APPLY_ABSTRACTION; [line 46]\n " shape="box"] +32 [label="32: UnaryOperator \n n$23=*&idx:unsigned long [line 46]\n *&idx:unsigned long =(n$23 + 1) [line 46]\n REMOVE_TEMPS(n$23); [line 46]\n APPLY_ABSTRACTION; [line 46]\n " shape="box"] 32 -> 30 ; @@ -93,34 +93,34 @@ digraph iCFG { 30 -> 33 ; -29 [label="29: Call _fun_free \n NULLIFY(&enumerateObjectsUsingBlock,false); [line 53]\n NULLIFY(&idx,false); [line 53]\n NULLIFY(&objects,false); [line 53]\n n$25=*&stop:BOOL * [line 53]\n _fun_free(n$25:void *) [line 53]\n REMOVE_TEMPS(n$25); [line 53]\n NULLIFY(&__objc_anonymous_block_MyBlock_array_trans______2,true); [line 53]\n NULLIFY(&stop,false); [line 53]\n APPLY_ABSTRACTION; [line 53]\n " shape="box"] +29 [label="29: Call _fun_free \n NULLIFY(&enumerateObjectsUsingBlock,false); [line 53]\n NULLIFY(&idx,false); [line 53]\n NULLIFY(&objects,false); [line 53]\n n$22=*&stop:_Bool * [line 53]\n _fun_free(n$22:void *) [line 53]\n REMOVE_TEMPS(n$22); [line 53]\n NULLIFY(&__objc_anonymous_block_MyBlock_array_trans______2,true); [line 53]\n NULLIFY(&stop,false); [line 53]\n APPLY_ABSTRACTION; [line 53]\n " shape="box"] 29 -> 28 ; 28 [label="28: Exit MyBlock_array_trans \n " color=yellow style=filled] -27 [label="27: Start MyBlock_array_trans\nFormals: self:class MyBlock *\nLocals: a:class NSArray * objects:class NSArray * enumerateObjectsUsingBlock:_fn_ (*) stop:BOOL * idx:unsigned long object:struct objc_object * \n DECLARE_LOCALS(&return,&a,&objects,&enumerateObjectsUsingBlock,&stop,&idx,&object); [line 28]\n NULLIFY(&a,false); [line 28]\n NULLIFY(&enumerateObjectsUsingBlock,false); [line 28]\n NULLIFY(&idx,false); [line 28]\n NULLIFY(&object,false); [line 28]\n NULLIFY(&objects,false); [line 28]\n NULLIFY(&self,false); [line 28]\n NULLIFY(&stop,false); [line 28]\n " color=yellow style=filled] +27 [label="27: Start MyBlock_array_trans\nFormals: self:class MyBlock *\nLocals: a:class NSArray * objects:class NSArray * enumerateObjectsUsingBlock:_fn_ (*) stop:_Bool * idx:unsigned long object:struct objc_object * \n DECLARE_LOCALS(&return,&a,&objects,&enumerateObjectsUsingBlock,&stop,&idx,&object); [line 28]\n NULLIFY(&a,false); [line 28]\n NULLIFY(&enumerateObjectsUsingBlock,false); [line 28]\n NULLIFY(&idx,false); [line 28]\n NULLIFY(&object,false); [line 28]\n NULLIFY(&objects,false); [line 28]\n NULLIFY(&self,false); [line 28]\n NULLIFY(&stop,false); [line 28]\n " color=yellow style=filled] 27 -> 52 ; -26 [label="26: DeclStmt \n n$24=_fun___objc_alloc_no_fail(sizeof(class NSArray ):unsigned long ) [line 14]\n n$22=_fun_NSArray_init(n$24:class NSArray *) virtual [line 14]\n *&a:class NSArray *=n$22 [line 14]\n REMOVE_TEMPS(n$22,n$24); [line 14]\n " shape="box"] +26 [label="26: DeclStmt \n n$21=_fun___objc_alloc_no_fail(sizeof(class NSArray ):unsigned long ) [line 14]\n n$19=_fun_NSArray_init(n$21:class NSArray *) virtual [line 14]\n *&a:class NSArray *=n$19 [line 14]\n REMOVE_TEMPS(n$19,n$21); [line 14]\n " shape="box"] 26 -> 25 ; -25 [label="25: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_MyBlock_array______1); [line 15]\n DECLARE_LOCALS(&objects); [line 15]\n DECLARE_LOCALS(&stop); [line 15]\n DECLARE_LOCALS(&idx); [line 15]\n DECLARE_LOCALS(&object); [line 15]\n n$21=*&a:class NSArray * [line 15]\n *&objects:class NSArray *=n$21 [line 15]\n REMOVE_TEMPS(n$21); [line 15]\n NULLIFY(&a,false); [line 15]\n " shape="box"] +25 [label="25: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_MyBlock_array______1); [line 15]\n DECLARE_LOCALS(&objects); [line 15]\n DECLARE_LOCALS(&stop); [line 15]\n DECLARE_LOCALS(&idx); [line 15]\n DECLARE_LOCALS(&object); [line 15]\n n$18=*&a:class NSArray * [line 15]\n *&objects:class NSArray *=n$18 [line 15]\n REMOVE_TEMPS(n$18); [line 15]\n NULLIFY(&a,false); [line 15]\n " shape="box"] 25 -> 18 ; -24 [label="24: BinaryOperatorStmt: Assign \n NULLIFY(&ShouldStop,false); [line 22]\n n$19=*&stop:BOOL * [line 22]\n *n$19:_Bool =1 [line 22]\n REMOVE_TEMPS(n$19); [line 22]\n NULLIFY(&stop,false); [line 22]\n APPLY_ABSTRACTION; [line 22]\n " shape="box"] +24 [label="24: BinaryOperatorStmt: Assign \n NULLIFY(&ShouldStop,false); [line 22]\n n$16=*&stop:_Bool * [line 22]\n *n$16:_Bool =1 [line 22]\n REMOVE_TEMPS(n$16); [line 22]\n NULLIFY(&stop,false); [line 22]\n APPLY_ABSTRACTION; [line 22]\n " shape="box"] 24 -> 21 ; -23 [label="23: Prune (false branch) \n n$18=*&ShouldStop:int [line 20]\n PRUNE((n$18 == 0), false); [line 20]\n REMOVE_TEMPS(n$18); [line 20]\n APPLY_ABSTRACTION; [line 20]\n " shape="invhouse"] +23 [label="23: Prune (false branch) \n n$15=*&ShouldStop:int [line 20]\n PRUNE((n$15 == 0), false); [line 20]\n REMOVE_TEMPS(n$15); [line 20]\n APPLY_ABSTRACTION; [line 20]\n " shape="invhouse"] 23 -> 21 ; -22 [label="22: Prune (true branch) \n n$18=*&ShouldStop:int [line 20]\n PRUNE((n$18 != 0), true); [line 20]\n REMOVE_TEMPS(n$18); [line 20]\n " shape="invhouse"] +22 [label="22: Prune (true branch) \n n$15=*&ShouldStop:int [line 20]\n PRUNE((n$15 != 0), true); [line 20]\n REMOVE_TEMPS(n$15); [line 20]\n " shape="invhouse"] 22 -> 24 ; @@ -131,40 +131,40 @@ digraph iCFG { 20 [label="20: Exit __objc_anonymous_block_MyBlock_array______1 \n " color=yellow style=filled] -19 [label="19: Start __objc_anonymous_block_MyBlock_array______1\nFormals: object:struct objc_object * idx:unsigned long stop:BOOL *\nLocals: ShouldStop:int \n DECLARE_LOCALS(&return,&ShouldStop); [line 15]\n NULLIFY(&idx,false); [line 15]\n NULLIFY(&object,false); [line 15]\n " color=yellow style=filled] +19 [label="19: Start __objc_anonymous_block_MyBlock_array______1\nFormals: object:struct objc_object * idx:unsigned long stop:_Bool *\nLocals: ShouldStop:int \n DECLARE_LOCALS(&return,&ShouldStop); [line 15]\n NULLIFY(&idx,false); [line 15]\n NULLIFY(&object,false); [line 15]\n " color=yellow style=filled] 19 -> 22 ; 19 -> 23 ; -18 [label="18: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_MyBlock_array______1); [line 15]\n n$20=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_MyBlock_array______1 ):unsigned long ) [line 15]\n *&__objc_anonymous_block_MyBlock_array______1:class __objc_anonymous_block_MyBlock_array______1 =n$20 [line 15]\n *&infer___objc_anonymous_block_MyBlock_array______1:_fn_ (*)=(_fun___objc_anonymous_block_MyBlock_array______1) [line 15]\n REMOVE_TEMPS(n$20); [line 15]\n " shape="box"] +18 [label="18: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_MyBlock_array______1); [line 15]\n n$17=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_MyBlock_array______1 ):unsigned long ) [line 15]\n *&__objc_anonymous_block_MyBlock_array______1:class __objc_anonymous_block_MyBlock_array______1 =n$17 [line 15]\n *&infer___objc_anonymous_block_MyBlock_array______1:_fn_ (*)=(_fun___objc_anonymous_block_MyBlock_array______1) [line 15]\n REMOVE_TEMPS(n$17); [line 15]\n " shape="box"] 18 -> 17 ; -17 [label="17: DeclStmt \n n$17=_fun_malloc_no_fail(sizeof(signed char ):signed char ) [line 15]\n *&stop:BOOL *=n$17 [line 15]\n REMOVE_TEMPS(n$17); [line 15]\n " shape="box"] +17 [label="17: DeclStmt \n _fun_malloc_no_fail(sizeof(signed char ):signed char ) [line 15]\n *&stop:_Bool *=-1 [line 15]\n " shape="box"] 17 -> 16 ; -16 [label="16: BinaryOperatorStmt: Assign \n n$16=*&stop:BOOL * [line 15]\n *n$16:void =0 [line 15]\n REMOVE_TEMPS(n$16); [line 15]\n " shape="box"] +16 [label="16: BinaryOperatorStmt: Assign \n n$14=*&stop:_Bool * [line 15]\n *n$14:void =0 [line 15]\n REMOVE_TEMPS(n$14); [line 15]\n " shape="box"] 16 -> 5 ; -15 [label="15: DeclStmt \n n$14=*&objects:class NSArray * [line 15]\n n$15=*&idx:unsigned long [line 15]\n n$13=_fun_NSArray_objectAtIndexedSubscript:(n$14:class NSArray *,n$15:unsigned long ) virtual [line 15]\n *&object:struct objc_object *=n$13 [line 15]\n REMOVE_TEMPS(n$13,n$14,n$15); [line 15]\n " shape="box"] +15 [label="15: DeclStmt \n n$12=*&objects:class NSArray * [line 15]\n n$13=*&idx:unsigned long [line 15]\n n$11=_fun_NSArray_objectAtIndexedSubscript:(n$12:class NSArray *,n$13:unsigned long ) virtual [line 15]\n *&object:struct objc_object *=n$11 [line 15]\n REMOVE_TEMPS(n$11,n$12,n$13); [line 15]\n " shape="box"] 15 -> 14 ; -14 [label="14: Call n$8 \n n$8=*&infer___objc_anonymous_block_MyBlock_array______1:_fn_ (*) [line 15]\n n$9=*&object:struct objc_object * [line 15]\n n$10=*&idx:unsigned long [line 15]\n n$11=*&stop:BOOL * [line 15]\n n$12=n$8(n$9:struct objc_object *,n$10:unsigned long ,n$11:BOOL *) [line 15]\n REMOVE_TEMPS(n$8,n$9,n$10,n$11,n$12); [line 15]\n " shape="box"] +14 [label="14: Call n$7 \n n$7=*&infer___objc_anonymous_block_MyBlock_array______1:_fn_ (*) [line 15]\n n$8=*&object:struct objc_object * [line 15]\n n$9=*&idx:unsigned long [line 15]\n n$10=*&stop:_Bool * [line 15]\n n$7(n$8:struct objc_object *,n$9:unsigned long ,n$10:_Bool *) [line 15]\n REMOVE_TEMPS(n$7,n$8,n$9,n$10); [line 15]\n " shape="box"] 14 -> 11 ; -13 [label="13: Prune (false branch) \n n$7=*n$6:signed char [line 15]\n PRUNE((n$7 == 0), false); [line 15]\n REMOVE_TEMPS(n$6,n$7); [line 15]\n " shape="invhouse"] +13 [label="13: Prune (false branch) \n n$6=*n$5:signed char [line 15]\n PRUNE((n$6 == 0), false); [line 15]\n REMOVE_TEMPS(n$5,n$6); [line 15]\n " shape="invhouse"] 13 -> 10 ; -12 [label="12: Prune (true branch) \n n$7=*n$6:signed char [line 15]\n PRUNE((n$7 != 0), true); [line 15]\n REMOVE_TEMPS(n$6,n$7); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="invhouse"] +12 [label="12: Prune (true branch) \n n$6=*n$5:signed char [line 15]\n PRUNE((n$6 != 0), true); [line 15]\n REMOVE_TEMPS(n$5,n$6); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="invhouse"] 12 -> 3 ; -11 [label="11: UnaryOperator \n n$6=*&stop:BOOL * [line 15]\n " shape="box"] +11 [label="11: UnaryOperator \n n$5=*&stop:_Bool * [line 15]\n " shape="box"] 11 -> 12 ; @@ -173,20 +173,20 @@ digraph iCFG { 10 -> 6 ; -9 [label="9: Prune (false branch) \n PRUNE(((n$3 < n$4) == 0), false); [line 15]\n REMOVE_TEMPS(n$3,n$4,n$5); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="invhouse"] +9 [label="9: Prune (false branch) \n PRUNE(((n$2 < n$3) == 0), false); [line 15]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="invhouse"] 9 -> 3 ; -8 [label="8: Prune (true branch) \n PRUNE(((n$3 < n$4) != 0), true); [line 15]\n REMOVE_TEMPS(n$3,n$4,n$5); [line 15]\n " shape="invhouse"] +8 [label="8: Prune (true branch) \n PRUNE(((n$2 < n$3) != 0), true); [line 15]\n REMOVE_TEMPS(n$2,n$3,n$4); [line 15]\n " shape="invhouse"] 8 -> 15 ; -7 [label="7: BinaryOperatorStmt: LT \n n$3=*&idx:unsigned long [line 15]\n n$5=*&objects:class NSArray * [line 15]\n n$4=_fun_NSArray_count(n$5:class NSArray *) virtual [line 15]\n " shape="box"] +7 [label="7: BinaryOperatorStmt: LT \n n$2=*&idx:unsigned long [line 15]\n n$4=*&objects:class NSArray * [line 15]\n n$3=_fun_NSArray_count(n$4:class NSArray *) virtual [line 15]\n " shape="box"] 7 -> 8 ; 7 -> 9 ; -6 [label="6: UnaryOperator \n n$2=*&idx:unsigned long [line 15]\n *&idx:unsigned long =(n$2 + 1) [line 15]\n REMOVE_TEMPS(n$2); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"] +6 [label="6: UnaryOperator \n n$1=*&idx:unsigned long [line 15]\n *&idx:unsigned long =(n$1 + 1) [line 15]\n REMOVE_TEMPS(n$1); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"] 6 -> 4 ; @@ -198,7 +198,7 @@ digraph iCFG { 4 -> 7 ; -3 [label="3: Call _fun_free \n n$0=*&stop:BOOL * [line 15]\n n$1=_fun_free(n$0:void *) [line 15]\n NULLIFY(&object,true); [line 15]\n NULLIFY(&idx,true); [line 15]\n NULLIFY(&stop,true); [line 15]\n NULLIFY(&objects,true); [line 15]\n REMOVE_TEMPS(n$0,n$1); [line 15]\n NULLIFY(&__objc_anonymous_block_MyBlock_array______1,true); [line 15]\n NULLIFY(&infer___objc_anonymous_block_MyBlock_array______1,true); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"] +3 [label="3: Call _fun_free \n n$0=*&stop:_Bool * [line 15]\n _fun_free(n$0:void ) [line 15]\n NULLIFY(&object,true); [line 15]\n NULLIFY(&idx,true); [line 15]\n NULLIFY(&stop,true); [line 15]\n NULLIFY(&objects,true); [line 15]\n REMOVE_TEMPS(n$0); [line 15]\n NULLIFY(&__objc_anonymous_block_MyBlock_array______1,true); [line 15]\n NULLIFY(&infer___objc_anonymous_block_MyBlock_array______1,true); [line 15]\n APPLY_ABSTRACTION; [line 15]\n " shape="box"] 3 -> 2 ; diff --git a/infer/tests/codetoanalyze/objc/frontend/block/block_release.dot b/infer/tests/codetoanalyze/objc/frontend/block/block_release.dot index 0783b6dd7..03650a6af 100644 --- a/infer/tests/codetoanalyze/objc/frontend/block/block_release.dot +++ b/infer/tests/codetoanalyze/objc/frontend/block/block_release.dot @@ -7,7 +7,7 @@ digraph iCFG { 18 -> 17 ; -17 [label="17: DeclStmt \n n$12=_fun_CGBitmapContextCreate(0:void *,0:unsigned long ,0:unsigned long ,8:unsigned long ,0:unsigned long ,0:struct CGColorSpace *,0:enum CGBitmapInfo ) [line 27]\n *&context:struct CGContext *=n$12 [line 27]\n REMOVE_TEMPS(n$12); [line 27]\n " shape="box"] +17 [label="17: DeclStmt \n n$12=_fun_CGBitmapContextCreate(0:void *,0:unsigned long ,0:unsigned long ,8:unsigned long ,0:unsigned long ,0:struct CGColorSpace *,0:CGBitmapInfo ) [line 27]\n *&context:struct CGContext *=n$12 [line 27]\n REMOVE_TEMPS(n$12); [line 27]\n " shape="box"] 17 -> 16 ; diff --git a/infer/tests/codetoanalyze/objc/frontend/block/dispatch.dot b/infer/tests/codetoanalyze/objc/frontend/block/dispatch.dot index d81e73299..dd60e561d 100644 --- a/infer/tests/codetoanalyze/objc/frontend/block/dispatch.dot +++ b/infer/tests/codetoanalyze/objc/frontend/block/dispatch.dot @@ -29,7 +29,7 @@ digraph iCFG { 23 -> 30 ; -19 [label="19: Return Stmt \n n$13=*&self:class A * [line 14]\n n$14=*n$13._x:int [line 14]\n *&return:int =n$14 [line 14]\n REMOVE_TEMPS(n$13,n$14); [line 14]\n NULLIFY(&self,false); [line 14]\n APPLY_ABSTRACTION; [line 14]\n " shape="box"] +19 [label="19: Return Stmt \n n$12=*&self:class A * [line 14]\n n$13=*n$12._x:int [line 14]\n *&return:int =n$13 [line 14]\n REMOVE_TEMPS(n$12,n$13); [line 14]\n NULLIFY(&self,false); [line 14]\n APPLY_ABSTRACTION; [line 14]\n " shape="box"] 19 -> 18 ; @@ -40,7 +40,7 @@ digraph iCFG { 17 -> 19 ; -16 [label="16: BinaryOperatorStmt: Assign \n n$11=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 41]\n n$9=_fun_A_init(n$11:class A *) virtual [line 41]\n *&#GB$A_trans_SI_sharedInstance:struct objc_object *=n$9 [line 41]\n REMOVE_TEMPS(n$9,n$11); [line 41]\n APPLY_ABSTRACTION; [line 41]\n " shape="box"] +16 [label="16: BinaryOperatorStmt: Assign \n n$10=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 41]\n n$8=_fun_A_init(n$10:class A *) virtual [line 41]\n *&#GB$A_trans_SI_sharedInstance:struct objc_object *=n$8 [line 41]\n REMOVE_TEMPS(n$8,n$10); [line 41]\n APPLY_ABSTRACTION; [line 41]\n " shape="box"] 16 -> 15 ; @@ -51,15 +51,15 @@ digraph iCFG { 14 -> 16 ; -13 [label="13: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_A_trans_SI______2); [line 40]\n n$12=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_trans_SI______2 ):unsigned long ) [line 40]\n *&__objc_anonymous_block_A_trans_SI______2:class __objc_anonymous_block_A_trans_SI______2 =n$12 [line 40]\n *&dummy_block:_fn_ (*)=(_fun___objc_anonymous_block_A_trans_SI______2) [line 40]\n REMOVE_TEMPS(n$12); [line 40]\n " shape="box"] +13 [label="13: DeclStmt \n DECLARE_LOCALS(&__objc_anonymous_block_A_trans_SI______2); [line 40]\n n$11=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_trans_SI______2 ):unsigned long ) [line 40]\n *&__objc_anonymous_block_A_trans_SI______2:class __objc_anonymous_block_A_trans_SI______2 =n$11 [line 40]\n *&dummy_block:_fn_ (*)=(_fun___objc_anonymous_block_A_trans_SI______2) [line 40]\n REMOVE_TEMPS(n$11); [line 40]\n " shape="box"] 13 -> 12 ; -12 [label="12: Call n$8 \n n$8=*&dummy_block:_fn_ (*) [line 43]\n n$8() [line 43]\n REMOVE_TEMPS(n$8); [line 43]\n NULLIFY(&dummy_block,false); [line 43]\n " shape="box"] +12 [label="12: Call n$7 \n n$7=*&dummy_block:_fn_ (*) [line 43]\n n$7() [line 43]\n REMOVE_TEMPS(n$7); [line 43]\n NULLIFY(&dummy_block,false); [line 43]\n " shape="box"] 12 -> 11 ; -11 [label="11: Return Stmt \n n$7=*&#GB$A_trans_SI_sharedInstance:struct objc_object * [line 44]\n *&return:struct objc_object *=n$7 [line 44]\n REMOVE_TEMPS(n$7); [line 44]\n NULLIFY(&__objc_anonymous_block_A_trans_SI______2,true); [line 44]\n APPLY_ABSTRACTION; [line 44]\n " shape="box"] +11 [label="11: Return Stmt \n n$6=*&#GB$A_trans_SI_sharedInstance:struct objc_object * [line 44]\n *&return:struct objc_object *=n$6 [line 44]\n REMOVE_TEMPS(n$6); [line 44]\n NULLIFY(&__objc_anonymous_block_A_trans_SI______2,true); [line 44]\n APPLY_ABSTRACTION; [line 44]\n " shape="box"] 11 -> 10 ; @@ -70,7 +70,7 @@ digraph iCFG { 9 -> 13 ; -8 [label="8: BinaryOperatorStmt: Assign \n n$5=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 29]\n n$3=_fun_A_init(n$5:class A *) virtual [line 29]\n *&#GB$A_sharedInstance_sharedInstance:struct objc_object *=n$3 [line 29]\n REMOVE_TEMPS(n$3,n$5); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"] +8 [label="8: BinaryOperatorStmt: Assign \n n$4=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 29]\n n$2=_fun_A_init(n$4:class A *) virtual [line 29]\n *&#GB$A_sharedInstance_sharedInstance:struct objc_object *=n$2 [line 29]\n REMOVE_TEMPS(n$2,n$4); [line 29]\n APPLY_ABSTRACTION; [line 29]\n " shape="box"] 8 -> 7 ; @@ -81,11 +81,11 @@ digraph iCFG { 6 -> 8 ; -5 [label="5: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_sharedInstance______1); [line 30]\n DECLARE_LOCALS(&__objc_anonymous_block_A_sharedInstance______1); [line 28]\n n$6=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_sharedInstance______1 ):unsigned long ) [line 28]\n *&__objc_anonymous_block_A_sharedInstance______1:class __objc_anonymous_block_A_sharedInstance______1 =n$6 [line 28]\n *&infer___objc_anonymous_block_A_sharedInstance______1:_fn_ (*)=(_fun___objc_anonymous_block_A_sharedInstance______1) [line 30]\n REMOVE_TEMPS(n$6); [line 30]\n " shape="box"] +5 [label="5: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_sharedInstance______1); [line 30]\n DECLARE_LOCALS(&__objc_anonymous_block_A_sharedInstance______1); [line 28]\n n$5=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_sharedInstance______1 ):unsigned long ) [line 28]\n *&__objc_anonymous_block_A_sharedInstance______1:class __objc_anonymous_block_A_sharedInstance______1 =n$5 [line 28]\n *&infer___objc_anonymous_block_A_sharedInstance______1:_fn_ (*)=(_fun___objc_anonymous_block_A_sharedInstance______1) [line 30]\n REMOVE_TEMPS(n$5); [line 30]\n " shape="box"] 5 -> 4 ; -4 [label="4: Call n$1 \n n$1=*&infer___objc_anonymous_block_A_sharedInstance______1:_fn_ (*) [line 30]\n n$2=n$1() [line 30]\n REMOVE_TEMPS(n$1,n$2); [line 30]\n NULLIFY(&infer___objc_anonymous_block_A_sharedInstance______1,true); [line 30]\n " shape="box"] +4 [label="4: Call n$1 \n n$1=*&infer___objc_anonymous_block_A_sharedInstance______1:_fn_ (*) [line 30]\n n$1() [line 30]\n REMOVE_TEMPS(n$1); [line 30]\n NULLIFY(&infer___objc_anonymous_block_A_sharedInstance______1,true); [line 30]\n " shape="box"] 4 -> 3 ; diff --git a/infer/tests/codetoanalyze/objc/frontend/block/dispatch_examples.dot b/infer/tests/codetoanalyze/objc/frontend/block/dispatch_examples.dot index 7a5934295..f767b0252 100644 --- a/infer/tests/codetoanalyze/objc/frontend/block/dispatch_examples.dot +++ b/infer/tests/codetoanalyze/objc/frontend/block/dispatch_examples.dot @@ -3,11 +3,11 @@ digraph iCFG { 60 -> 55 ; -59 [label="59: BinaryOperatorStmt: Assign \n n$52=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 71]\n n$50=_fun_A_init(n$52:class A *) virtual [line 71]\n *&#GB$A_dispatch_barrier_example_a:class A *=n$50 [line 71]\n REMOVE_TEMPS(n$50,n$52); [line 71]\n " shape="box"] +59 [label="59: BinaryOperatorStmt: Assign \n n$46=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 71]\n n$44=_fun_A_init(n$46:class A *) virtual [line 71]\n *&#GB$A_dispatch_barrier_example_a:class A *=n$44 [line 71]\n REMOVE_TEMPS(n$44,n$46); [line 71]\n " shape="box"] 59 -> 58 ; -58 [label="58: BinaryOperatorStmt: Assign \n n$49=*&#GB$A_dispatch_barrier_example_a:class A * [line 72]\n *n$49.x:int =10 [line 72]\n REMOVE_TEMPS(n$49); [line 72]\n APPLY_ABSTRACTION; [line 72]\n " shape="box"] +58 [label="58: BinaryOperatorStmt: Assign \n n$43=*&#GB$A_dispatch_barrier_example_a:class A * [line 72]\n *n$43.x:int =10 [line 72]\n REMOVE_TEMPS(n$43); [line 72]\n APPLY_ABSTRACTION; [line 72]\n " shape="box"] 58 -> 57 ; @@ -18,15 +18,15 @@ digraph iCFG { 56 -> 59 ; -55 [label="55: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_barrier_example______6); [line 70]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_barrier_example______6); [line 70]\n n$53=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_barrier_example______6 ):unsigned long ) [line 70]\n *&__objc_anonymous_block_A_dispatch_barrier_example______6:class __objc_anonymous_block_A_dispatch_barrier_example______6 =n$53 [line 70]\n *&infer___objc_anonymous_block_A_dispatch_barrier_example______6:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_barrier_example______6) [line 70]\n REMOVE_TEMPS(n$53); [line 70]\n " shape="box"] +55 [label="55: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_barrier_example______6); [line 70]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_barrier_example______6); [line 70]\n n$47=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_barrier_example______6 ):unsigned long ) [line 70]\n *&__objc_anonymous_block_A_dispatch_barrier_example______6:class __objc_anonymous_block_A_dispatch_barrier_example______6 =n$47 [line 70]\n *&infer___objc_anonymous_block_A_dispatch_barrier_example______6:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_barrier_example______6) [line 70]\n REMOVE_TEMPS(n$47); [line 70]\n " shape="box"] 55 -> 54 ; -54 [label="54: Call n$47 \n n$47=*&infer___objc_anonymous_block_A_dispatch_barrier_example______6:_fn_ (*) [line 70]\n n$48=n$47() [line 70]\n REMOVE_TEMPS(n$47,n$48); [line 70]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_barrier_example______6,true); [line 70]\n " shape="box"] +54 [label="54: Call n$42 \n n$42=*&infer___objc_anonymous_block_A_dispatch_barrier_example______6:_fn_ (*) [line 70]\n n$42() [line 70]\n REMOVE_TEMPS(n$42); [line 70]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_barrier_example______6,true); [line 70]\n " shape="box"] 54 -> 53 ; -53 [label="53: Return Stmt \n n$45=*&#GB$A_dispatch_barrier_example_a:class A * [line 74]\n n$46=*n$45.x:int [line 74]\n *&return:int =n$46 [line 74]\n REMOVE_TEMPS(n$45,n$46); [line 74]\n NULLIFY(&__objc_anonymous_block_A_dispatch_barrier_example______6,true); [line 74]\n APPLY_ABSTRACTION; [line 74]\n " shape="box"] +53 [label="53: Return Stmt \n n$40=*&#GB$A_dispatch_barrier_example_a:class A * [line 74]\n n$41=*n$40.x:int [line 74]\n *&return:int =n$41 [line 74]\n REMOVE_TEMPS(n$40,n$41); [line 74]\n NULLIFY(&__objc_anonymous_block_A_dispatch_barrier_example______6,true); [line 74]\n APPLY_ABSTRACTION; [line 74]\n " shape="box"] 53 -> 52 ; @@ -41,11 +41,11 @@ digraph iCFG { 50 -> 45 ; -49 [label="49: BinaryOperatorStmt: Assign \n n$43=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 62]\n n$41=_fun_A_init(n$43:class A *) virtual [line 62]\n *&#GB$A_dispatch_group_notify_example_a:class A *=n$41 [line 62]\n REMOVE_TEMPS(n$41,n$43); [line 62]\n " shape="box"] +49 [label="49: BinaryOperatorStmt: Assign \n n$38=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 62]\n n$36=_fun_A_init(n$38:class A *) virtual [line 62]\n *&#GB$A_dispatch_group_notify_example_a:class A *=n$36 [line 62]\n REMOVE_TEMPS(n$36,n$38); [line 62]\n " shape="box"] 49 -> 48 ; -48 [label="48: BinaryOperatorStmt: Assign \n n$40=*&#GB$A_dispatch_group_notify_example_a:class A * [line 63]\n *n$40.x:int =10 [line 63]\n REMOVE_TEMPS(n$40); [line 63]\n APPLY_ABSTRACTION; [line 63]\n " shape="box"] +48 [label="48: BinaryOperatorStmt: Assign \n n$35=*&#GB$A_dispatch_group_notify_example_a:class A * [line 63]\n *n$35.x:int =10 [line 63]\n REMOVE_TEMPS(n$35); [line 63]\n APPLY_ABSTRACTION; [line 63]\n " shape="box"] 48 -> 47 ; @@ -56,15 +56,15 @@ digraph iCFG { 46 -> 49 ; -45 [label="45: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_group_notify_example______5); [line 61]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_group_notify_example______5); [line 61]\n n$44=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_group_notify_example______5 ):unsigned long ) [line 61]\n *&__objc_anonymous_block_A_dispatch_group_notify_example______5:class __objc_anonymous_block_A_dispatch_group_notify_example______5 =n$44 [line 61]\n *&infer___objc_anonymous_block_A_dispatch_group_notify_example______5:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_group_notify_example______5) [line 61]\n REMOVE_TEMPS(n$44); [line 61]\n " shape="box"] +45 [label="45: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_group_notify_example______5); [line 61]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_group_notify_example______5); [line 61]\n n$39=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_group_notify_example______5 ):unsigned long ) [line 61]\n *&__objc_anonymous_block_A_dispatch_group_notify_example______5:class __objc_anonymous_block_A_dispatch_group_notify_example______5 =n$39 [line 61]\n *&infer___objc_anonymous_block_A_dispatch_group_notify_example______5:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_group_notify_example______5) [line 61]\n REMOVE_TEMPS(n$39); [line 61]\n " shape="box"] 45 -> 44 ; -44 [label="44: Call n$38 \n n$38=*&infer___objc_anonymous_block_A_dispatch_group_notify_example______5:_fn_ (*) [line 61]\n n$39=n$38() [line 61]\n REMOVE_TEMPS(n$38,n$39); [line 61]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_group_notify_example______5,true); [line 61]\n " shape="box"] +44 [label="44: Call n$34 \n n$34=*&infer___objc_anonymous_block_A_dispatch_group_notify_example______5:_fn_ (*) [line 61]\n n$34() [line 61]\n REMOVE_TEMPS(n$34); [line 61]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_group_notify_example______5,true); [line 61]\n " shape="box"] 44 -> 43 ; -43 [label="43: Return Stmt \n n$36=*&#GB$A_dispatch_group_notify_example_a:class A * [line 65]\n n$37=*n$36.x:int [line 65]\n *&return:int =n$37 [line 65]\n REMOVE_TEMPS(n$36,n$37); [line 65]\n NULLIFY(&__objc_anonymous_block_A_dispatch_group_notify_example______5,true); [line 65]\n APPLY_ABSTRACTION; [line 65]\n " shape="box"] +43 [label="43: Return Stmt \n n$32=*&#GB$A_dispatch_group_notify_example_a:class A * [line 65]\n n$33=*n$32.x:int [line 65]\n *&return:int =n$33 [line 65]\n REMOVE_TEMPS(n$32,n$33); [line 65]\n NULLIFY(&__objc_anonymous_block_A_dispatch_group_notify_example______5,true); [line 65]\n APPLY_ABSTRACTION; [line 65]\n " shape="box"] 43 -> 42 ; @@ -79,11 +79,11 @@ digraph iCFG { 40 -> 35 ; -39 [label="39: BinaryOperatorStmt: Assign \n n$34=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 53]\n n$32=_fun_A_init(n$34:class A *) virtual [line 53]\n *&#GB$A_dispatch_group_example_a:class A *=n$32 [line 53]\n REMOVE_TEMPS(n$32,n$34); [line 53]\n " shape="box"] +39 [label="39: BinaryOperatorStmt: Assign \n n$30=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 53]\n n$28=_fun_A_init(n$30:class A *) virtual [line 53]\n *&#GB$A_dispatch_group_example_a:class A *=n$28 [line 53]\n REMOVE_TEMPS(n$28,n$30); [line 53]\n " shape="box"] 39 -> 38 ; -38 [label="38: BinaryOperatorStmt: Assign \n n$31=*&#GB$A_dispatch_group_example_a:class A * [line 54]\n *n$31.x:int =10 [line 54]\n REMOVE_TEMPS(n$31); [line 54]\n APPLY_ABSTRACTION; [line 54]\n " shape="box"] +38 [label="38: BinaryOperatorStmt: Assign \n n$27=*&#GB$A_dispatch_group_example_a:class A * [line 54]\n *n$27.x:int =10 [line 54]\n REMOVE_TEMPS(n$27); [line 54]\n APPLY_ABSTRACTION; [line 54]\n " shape="box"] 38 -> 37 ; @@ -94,15 +94,15 @@ digraph iCFG { 36 -> 39 ; -35 [label="35: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_group_example______4); [line 52]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_group_example______4); [line 52]\n n$35=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_group_example______4 ):unsigned long ) [line 52]\n *&__objc_anonymous_block_A_dispatch_group_example______4:class __objc_anonymous_block_A_dispatch_group_example______4 =n$35 [line 52]\n *&infer___objc_anonymous_block_A_dispatch_group_example______4:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_group_example______4) [line 52]\n REMOVE_TEMPS(n$35); [line 52]\n " shape="box"] +35 [label="35: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_group_example______4); [line 52]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_group_example______4); [line 52]\n n$31=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_group_example______4 ):unsigned long ) [line 52]\n *&__objc_anonymous_block_A_dispatch_group_example______4:class __objc_anonymous_block_A_dispatch_group_example______4 =n$31 [line 52]\n *&infer___objc_anonymous_block_A_dispatch_group_example______4:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_group_example______4) [line 52]\n REMOVE_TEMPS(n$31); [line 52]\n " shape="box"] 35 -> 34 ; -34 [label="34: Call n$29 \n n$29=*&infer___objc_anonymous_block_A_dispatch_group_example______4:_fn_ (*) [line 52]\n n$30=n$29() [line 52]\n REMOVE_TEMPS(n$29,n$30); [line 52]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_group_example______4,true); [line 52]\n " shape="box"] +34 [label="34: Call n$26 \n n$26=*&infer___objc_anonymous_block_A_dispatch_group_example______4:_fn_ (*) [line 52]\n n$26() [line 52]\n REMOVE_TEMPS(n$26); [line 52]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_group_example______4,true); [line 52]\n " shape="box"] 34 -> 33 ; -33 [label="33: Return Stmt \n n$27=*&#GB$A_dispatch_group_example_a:class A * [line 56]\n n$28=*n$27.x:int [line 56]\n *&return:int =n$28 [line 56]\n REMOVE_TEMPS(n$27,n$28); [line 56]\n NULLIFY(&__objc_anonymous_block_A_dispatch_group_example______4,true); [line 56]\n APPLY_ABSTRACTION; [line 56]\n " shape="box"] +33 [label="33: Return Stmt \n n$24=*&#GB$A_dispatch_group_example_a:class A * [line 56]\n n$25=*n$24.x:int [line 56]\n *&return:int =n$25 [line 56]\n REMOVE_TEMPS(n$24,n$25); [line 56]\n NULLIFY(&__objc_anonymous_block_A_dispatch_group_example______4,true); [line 56]\n APPLY_ABSTRACTION; [line 56]\n " shape="box"] 33 -> 32 ; @@ -117,11 +117,11 @@ digraph iCFG { 30 -> 25 ; -29 [label="29: BinaryOperatorStmt: Assign \n n$25=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 44]\n n$23=_fun_A_init(n$25:class A *) virtual [line 44]\n *&#GB$A_dispatch_after_example_a:class A *=n$23 [line 44]\n REMOVE_TEMPS(n$23,n$25); [line 44]\n " shape="box"] +29 [label="29: BinaryOperatorStmt: Assign \n n$22=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 44]\n n$20=_fun_A_init(n$22:class A *) virtual [line 44]\n *&#GB$A_dispatch_after_example_a:class A *=n$20 [line 44]\n REMOVE_TEMPS(n$20,n$22); [line 44]\n " shape="box"] 29 -> 28 ; -28 [label="28: BinaryOperatorStmt: Assign \n n$22=*&#GB$A_dispatch_after_example_a:class A * [line 45]\n *n$22.x:int =10 [line 45]\n REMOVE_TEMPS(n$22); [line 45]\n APPLY_ABSTRACTION; [line 45]\n " shape="box"] +28 [label="28: BinaryOperatorStmt: Assign \n n$19=*&#GB$A_dispatch_after_example_a:class A * [line 45]\n *n$19.x:int =10 [line 45]\n REMOVE_TEMPS(n$19); [line 45]\n APPLY_ABSTRACTION; [line 45]\n " shape="box"] 28 -> 27 ; @@ -132,15 +132,15 @@ digraph iCFG { 26 -> 29 ; -25 [label="25: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_after_example______3); [line 42]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_after_example______3); [line 43]\n n$26=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_after_example______3 ):unsigned long ) [line 43]\n *&__objc_anonymous_block_A_dispatch_after_example______3:class __objc_anonymous_block_A_dispatch_after_example______3 =n$26 [line 43]\n *&infer___objc_anonymous_block_A_dispatch_after_example______3:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_after_example______3) [line 42]\n REMOVE_TEMPS(n$26); [line 42]\n " shape="box"] +25 [label="25: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_after_example______3); [line 42]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_after_example______3); [line 43]\n n$23=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_after_example______3 ):unsigned long ) [line 43]\n *&__objc_anonymous_block_A_dispatch_after_example______3:class __objc_anonymous_block_A_dispatch_after_example______3 =n$23 [line 43]\n *&infer___objc_anonymous_block_A_dispatch_after_example______3:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_after_example______3) [line 42]\n REMOVE_TEMPS(n$23); [line 42]\n " shape="box"] 25 -> 24 ; -24 [label="24: Call n$20 \n n$20=*&infer___objc_anonymous_block_A_dispatch_after_example______3:_fn_ (*) [line 42]\n n$21=n$20() [line 42]\n REMOVE_TEMPS(n$20,n$21); [line 42]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_after_example______3,true); [line 42]\n " shape="box"] +24 [label="24: Call n$18 \n n$18=*&infer___objc_anonymous_block_A_dispatch_after_example______3:_fn_ (*) [line 42]\n n$18() [line 42]\n REMOVE_TEMPS(n$18); [line 42]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_after_example______3,true); [line 42]\n " shape="box"] 24 -> 23 ; -23 [label="23: Return Stmt \n n$18=*&#GB$A_dispatch_after_example_a:class A * [line 47]\n n$19=*n$18.x:int [line 47]\n *&return:int =n$19 [line 47]\n REMOVE_TEMPS(n$18,n$19); [line 47]\n NULLIFY(&__objc_anonymous_block_A_dispatch_after_example______3,true); [line 47]\n APPLY_ABSTRACTION; [line 47]\n " shape="box"] +23 [label="23: Return Stmt \n n$16=*&#GB$A_dispatch_after_example_a:class A * [line 47]\n n$17=*n$16.x:int [line 47]\n *&return:int =n$17 [line 47]\n REMOVE_TEMPS(n$16,n$17); [line 47]\n NULLIFY(&__objc_anonymous_block_A_dispatch_after_example______3,true); [line 47]\n APPLY_ABSTRACTION; [line 47]\n " shape="box"] 23 -> 22 ; @@ -155,11 +155,11 @@ digraph iCFG { 20 -> 15 ; -19 [label="19: BinaryOperatorStmt: Assign \n n$16=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 34]\n n$14=_fun_A_init(n$16:class A *) virtual [line 34]\n *&#GB$A_dispatch_async_example_a:class A *=n$14 [line 34]\n REMOVE_TEMPS(n$14,n$16); [line 34]\n " shape="box"] +19 [label="19: BinaryOperatorStmt: Assign \n n$14=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 34]\n n$12=_fun_A_init(n$14:class A *) virtual [line 34]\n *&#GB$A_dispatch_async_example_a:class A *=n$12 [line 34]\n REMOVE_TEMPS(n$12,n$14); [line 34]\n " shape="box"] 19 -> 18 ; -18 [label="18: BinaryOperatorStmt: Assign \n n$13=*&#GB$A_dispatch_async_example_a:class A * [line 35]\n *n$13.x:int =10 [line 35]\n REMOVE_TEMPS(n$13); [line 35]\n APPLY_ABSTRACTION; [line 35]\n " shape="box"] +18 [label="18: BinaryOperatorStmt: Assign \n n$11=*&#GB$A_dispatch_async_example_a:class A * [line 35]\n *n$11.x:int =10 [line 35]\n REMOVE_TEMPS(n$11); [line 35]\n APPLY_ABSTRACTION; [line 35]\n " shape="box"] 18 -> 17 ; @@ -170,15 +170,15 @@ digraph iCFG { 16 -> 19 ; -15 [label="15: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_async_example______2); [line 33]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_async_example______2); [line 33]\n n$17=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_async_example______2 ):unsigned long ) [line 33]\n *&__objc_anonymous_block_A_dispatch_async_example______2:class __objc_anonymous_block_A_dispatch_async_example______2 =n$17 [line 33]\n *&infer___objc_anonymous_block_A_dispatch_async_example______2:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_async_example______2) [line 33]\n REMOVE_TEMPS(n$17); [line 33]\n " shape="box"] +15 [label="15: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_async_example______2); [line 33]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_async_example______2); [line 33]\n n$15=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_async_example______2 ):unsigned long ) [line 33]\n *&__objc_anonymous_block_A_dispatch_async_example______2:class __objc_anonymous_block_A_dispatch_async_example______2 =n$15 [line 33]\n *&infer___objc_anonymous_block_A_dispatch_async_example______2:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_async_example______2) [line 33]\n REMOVE_TEMPS(n$15); [line 33]\n " shape="box"] 15 -> 14 ; -14 [label="14: Call n$11 \n n$11=*&infer___objc_anonymous_block_A_dispatch_async_example______2:_fn_ (*) [line 33]\n n$12=n$11() [line 33]\n REMOVE_TEMPS(n$11,n$12); [line 33]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_async_example______2,true); [line 33]\n " shape="box"] +14 [label="14: Call n$10 \n n$10=*&infer___objc_anonymous_block_A_dispatch_async_example______2:_fn_ (*) [line 33]\n n$10() [line 33]\n REMOVE_TEMPS(n$10); [line 33]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_async_example______2,true); [line 33]\n " shape="box"] 14 -> 13 ; -13 [label="13: Return Stmt \n n$9=*&#GB$A_dispatch_async_example_a:class A * [line 37]\n n$10=*n$9.x:int [line 37]\n *&return:int =n$10 [line 37]\n REMOVE_TEMPS(n$9,n$10); [line 37]\n NULLIFY(&__objc_anonymous_block_A_dispatch_async_example______2,true); [line 37]\n APPLY_ABSTRACTION; [line 37]\n " shape="box"] +13 [label="13: Return Stmt \n n$8=*&#GB$A_dispatch_async_example_a:class A * [line 37]\n n$9=*n$8.x:int [line 37]\n *&return:int =n$9 [line 37]\n REMOVE_TEMPS(n$8,n$9); [line 37]\n NULLIFY(&__objc_anonymous_block_A_dispatch_async_example______2,true); [line 37]\n APPLY_ABSTRACTION; [line 37]\n " shape="box"] 13 -> 12 ; @@ -193,11 +193,11 @@ digraph iCFG { 10 -> 5 ; -9 [label="9: BinaryOperatorStmt: Assign \n n$7=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 25]\n n$5=_fun_A_init(n$7:class A *) virtual [line 25]\n *&#GB$A_dispatch_once_example_a:class A *=n$5 [line 25]\n REMOVE_TEMPS(n$5,n$7); [line 25]\n " shape="box"] +9 [label="9: BinaryOperatorStmt: Assign \n n$6=_fun___objc_alloc_no_fail(sizeof(class A ):unsigned long ) [line 25]\n n$4=_fun_A_init(n$6:class A *) virtual [line 25]\n *&#GB$A_dispatch_once_example_a:class A *=n$4 [line 25]\n REMOVE_TEMPS(n$4,n$6); [line 25]\n " shape="box"] 9 -> 8 ; -8 [label="8: BinaryOperatorStmt: Assign \n n$4=*&#GB$A_dispatch_once_example_a:class A * [line 26]\n *n$4.x:int =10 [line 26]\n REMOVE_TEMPS(n$4); [line 26]\n APPLY_ABSTRACTION; [line 26]\n " shape="box"] +8 [label="8: BinaryOperatorStmt: Assign \n n$3=*&#GB$A_dispatch_once_example_a:class A * [line 26]\n *n$3.x:int =10 [line 26]\n REMOVE_TEMPS(n$3); [line 26]\n APPLY_ABSTRACTION; [line 26]\n " shape="box"] 8 -> 7 ; @@ -208,11 +208,11 @@ digraph iCFG { 6 -> 9 ; -5 [label="5: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_once_example______1); [line 23]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_once_example______1); [line 24]\n n$8=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_once_example______1 ):unsigned long ) [line 24]\n *&__objc_anonymous_block_A_dispatch_once_example______1:class __objc_anonymous_block_A_dispatch_once_example______1 =n$8 [line 24]\n *&infer___objc_anonymous_block_A_dispatch_once_example______1:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_once_example______1) [line 23]\n REMOVE_TEMPS(n$8); [line 23]\n " shape="box"] +5 [label="5: DeclStmt \n DECLARE_LOCALS(&infer___objc_anonymous_block_A_dispatch_once_example______1); [line 23]\n DECLARE_LOCALS(&__objc_anonymous_block_A_dispatch_once_example______1); [line 24]\n n$7=_fun___objc_alloc_no_fail(sizeof(class __objc_anonymous_block_A_dispatch_once_example______1 ):unsigned long ) [line 24]\n *&__objc_anonymous_block_A_dispatch_once_example______1:class __objc_anonymous_block_A_dispatch_once_example______1 =n$7 [line 24]\n *&infer___objc_anonymous_block_A_dispatch_once_example______1:_fn_ (*)=(_fun___objc_anonymous_block_A_dispatch_once_example______1) [line 23]\n REMOVE_TEMPS(n$7); [line 23]\n " shape="box"] 5 -> 4 ; -4 [label="4: Call n$2 \n n$2=*&infer___objc_anonymous_block_A_dispatch_once_example______1:_fn_ (*) [line 23]\n n$3=n$2() [line 23]\n REMOVE_TEMPS(n$2,n$3); [line 23]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_once_example______1,true); [line 23]\n " shape="box"] +4 [label="4: Call n$2 \n n$2=*&infer___objc_anonymous_block_A_dispatch_once_example______1:_fn_ (*) [line 23]\n n$2() [line 23]\n REMOVE_TEMPS(n$2); [line 23]\n NULLIFY(&infer___objc_anonymous_block_A_dispatch_once_example______1,true); [line 23]\n " shape="box"] 4 -> 3 ; diff --git a/infer/tests/codetoanalyze/objc/frontend/vardecl/initlist.dot b/infer/tests/codetoanalyze/objc/frontend/vardecl/initlist.dot index ca12d728a..bd61e5b86 100644 --- a/infer/tests/codetoanalyze/objc/frontend/vardecl/initlist.dot +++ b/infer/tests/codetoanalyze/objc/frontend/vardecl/initlist.dot @@ -7,14 +7,14 @@ digraph iCFG { 7 -> 6 ; -6 [label="6: InitListExp \n n$1=*&c1:class C * [line 24]\n n$0=_fun_C_init(n$1:class C *) virtual [line 24]\n n$2=*&c1:class C * [line 24]\n n$3=*&c2:class C * [line 24]\n *&a[0]:C *=n$0 [line 24]\n _fun___objc_retain(n$2:C *) [line 24]\n *&a[1]:C *=n$2 [line 24]\n _fun___objc_retain(n$3:C *) [line 24]\n *&a[2]:C *=n$3 [line 24]\n REMOVE_TEMPS(n$0,n$1,n$2,n$3); [line 24]\n NULLIFY(&c1,false); [line 24]\n NULLIFY(&c2,false); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"] +6 [label="6: InitListExp \n n$1=*&c1:class C * [line 24]\n n$0=_fun_C_init(n$1:class C *) virtual [line 24]\n n$2=*&c1:class C * [line 24]\n n$3=*&c2:class C * [line 24]\n *&a[0]:class C *=n$0 [line 24]\n _fun___objc_retain(n$2:class C *) [line 24]\n *&a[1]:class C *=n$2 [line 24]\n _fun___objc_retain(n$3:class C *) [line 24]\n *&a[2]:class C *=n$3 [line 24]\n REMOVE_TEMPS(n$0,n$1,n$2,n$3); [line 24]\n NULLIFY(&c1,false); [line 24]\n NULLIFY(&c2,false); [line 24]\n APPLY_ABSTRACTION; [line 24]\n " shape="box"] 6 -> 5 ; 5 [label="5: Exit test \n " color=yellow style=filled] -4 [label="4: Start test\nFormals: \nLocals: c1:class C * c2:class C * a:C *[3] \n DECLARE_LOCALS(&return,&c1,&c2,&a); [line 21]\n NULLIFY(&a,false); [line 21]\n NULLIFY(&c1,false); [line 21]\n NULLIFY(&c2,false); [line 21]\n " color=yellow style=filled] +4 [label="4: Start test\nFormals: \nLocals: c1:class C * c2:class C * a:class C *[3] \n DECLARE_LOCALS(&return,&c1,&c2,&a); [line 21]\n NULLIFY(&a,false); [line 21]\n NULLIFY(&c1,false); [line 21]\n NULLIFY(&c2,false); [line 21]\n " color=yellow style=filled] 4 -> 8 ;