diff --git a/infer/src/clang/CType_decl.ml b/infer/src/clang/CType_decl.ml index f9746d536..862818235 100644 --- a/infer/src/clang/CType_decl.ml +++ b/infer/src/clang/CType_decl.ml @@ -105,7 +105,7 @@ let rec get_struct_fields tenv decl = and get_record_declaration_type tenv decl = let definition_decl = get_record_definition decl in match get_record_custom_type tenv definition_decl with - | Some t -> t + | Some t -> t.Typ.desc | None -> get_record_struct_type tenv definition_decl and get_record_custom_type tenv definition_decl = @@ -158,16 +158,16 @@ and get_superclass_list_cpp tenv decl = let get_super_field super_decl = get_record_typename ~tenv super_decl in List.map ~f:get_super_field base_decls -and get_record_struct_type tenv definition_decl : Typ.t = +and get_record_struct_type tenv definition_decl : Typ.desc = let open Clang_ast_t in match definition_decl with | ClassTemplateSpecializationDecl (_, _, _, type_ptr, _, _, record_decl_info, _, _) | CXXRecordDecl (_, _, _, type_ptr, _, _, record_decl_info, _) | RecordDecl (_, _, _, type_ptr, _, _, record_decl_info) -> let sil_typename = get_record_typename ~tenv definition_decl in - let sil_type = Typ.mk (Tstruct sil_typename) in + let sil_desc = Typ.Tstruct sil_typename in (match Tenv.lookup tenv sil_typename with - | Some _ -> sil_type (* just reuse what is already in tenv *) + | Some _ -> sil_desc (* just reuse what is already in tenv *) | None -> let is_complete_definition = record_decl_info.Clang_ast_t.rdi_is_complete_definition in let extra_fields = @@ -178,7 +178,7 @@ and get_record_struct_type tenv definition_decl : Typ.t = if Typ.Name.Cpp.is_class sil_typename then Annot.Class.cpp else Annot.Item.empty (* No annotations for structs *) in if is_complete_definition then ( - CAst_utils.update_sil_types_map type_ptr sil_type; + CAst_utils.update_sil_types_map type_ptr sil_desc; let non_statics = get_struct_fields tenv definition_decl in let fields = CGeneral_utils.append_no_duplicates_fields non_statics extra_fields in let statics = [] in (* Note: We treat static field same as global variables *) @@ -187,14 +187,14 @@ and get_record_struct_type tenv definition_decl : Typ.t = let specialization = get_template_specialization tenv definition_decl in Tenv.mk_struct tenv ~fields ~statics ~methods ~supers ~annots ~specialization sil_typename |> ignore; - CAst_utils.update_sil_types_map type_ptr sil_type; - sil_type + CAst_utils.update_sil_types_map type_ptr sil_desc; + sil_desc ) else ( (* There is no definition for that struct in whole translation unit. Put empty struct into tenv to prevent backend problems *) ignore (Tenv.mk_struct tenv ~fields:extra_fields sil_typename); - CAst_utils.update_sil_types_map type_ptr sil_type; - sil_type)) + CAst_utils.update_sil_types_map type_ptr sil_desc; + sil_desc)) | _ -> assert false and add_types_from_decl_to_tenv tenv decl = diff --git a/infer/src/clang/CType_decl.mli b/infer/src/clang/CType_decl.mli index a594e7b9a..e375e638e 100644 --- a/infer/src/clang/CType_decl.mli +++ b/infer/src/clang/CType_decl.mli @@ -13,7 +13,7 @@ open! IStd val get_record_typename : ?tenv:Tenv.t -> Clang_ast_t.decl -> Typ.Name.t -val add_types_from_decl_to_tenv : Tenv.t -> Clang_ast_t.decl -> Typ.t +val add_types_from_decl_to_tenv : Tenv.t -> Clang_ast_t.decl -> Typ.desc (* Adds the predefined types objc_class which is a struct, *) (* and Class, which is a pointer to objc_class. *) diff --git a/infer/src/clang/cAst_utils.mli b/infer/src/clang/cAst_utils.mli index 66d4b92eb..b4cfea8f7 100644 --- a/infer/src/clang/cAst_utils.mli +++ b/infer/src/clang/cAst_utils.mli @@ -30,7 +30,7 @@ val get_decl_opt_with_decl_ref : Clang_ast_t.decl_ref option -> Clang_ast_t.decl val get_property_of_ivar : Clang_ast_t.pointer -> Clang_ast_t.decl option -val update_sil_types_map : Clang_ast_t.type_ptr -> Typ.t -> unit +val update_sil_types_map : Clang_ast_t.type_ptr -> Typ.desc -> unit val update_enum_map : Clang_ast_t.pointer -> Exp.t -> unit diff --git a/infer/src/clang/cEnum_decl.ml b/infer/src/clang/cEnum_decl.ml index 5ffe1a970..41e287539 100644 --- a/infer/src/clang/cEnum_decl.ml +++ b/infer/src/clang/cEnum_decl.ml @@ -44,8 +44,8 @@ let enum_decl decl = match decl with | EnumDecl (_, _, _, type_ptr, decl_list, _, _) -> add_enum_constants_to_map (List.rev decl_list); - let sil_type = Typ.mk (Typ.Tint Typ.IInt) in - CAst_utils.update_sil_types_map type_ptr sil_type; - sil_type + let sil_desc = Typ.Tint Typ.IInt in + CAst_utils.update_sil_types_map type_ptr sil_desc; + sil_desc | _ -> assert false diff --git a/infer/src/clang/cEnum_decl.mli b/infer/src/clang/cEnum_decl.mli index aebfd4435..0dca50a22 100644 --- a/infer/src/clang/cEnum_decl.mli +++ b/infer/src/clang/cEnum_decl.mli @@ -12,4 +12,4 @@ open! IStd (** Translate an enumeration declaration by adding it to the tenv and *) (** translating the code and adding it to a fake procdesc *) -val enum_decl : Clang_ast_t.decl -> Typ.t +val enum_decl : Clang_ast_t.decl -> Typ.desc diff --git a/infer/src/clang/cFrontend_config.mli b/infer/src/clang/cFrontend_config.mli index 225146264..80cd535d1 100644 --- a/infer/src/clang/cFrontend_config.mli +++ b/infer/src/clang/cFrontend_config.mli @@ -106,6 +106,6 @@ val pointer_type_index : Clang_ast_t.c_type Clang_ast_main.PointerMap.t ref (** Map from type pointers (clang pointers and types created later by frontend) to sil types Populated during frontend execution when new type is found *) -val sil_types_map : (Typ.t Clang_ast_extend.TypePointerMap.t) ref +val sil_types_map : (Typ.desc Clang_ast_extend.TypePointerMap.t) ref val reset_global_state : unit -> unit diff --git a/infer/src/clang/cType_to_sil_type.ml b/infer/src/clang/cType_to_sil_type.ml index d12965884..536a19516 100644 --- a/infer/src/clang/cType_to_sil_type.ml +++ b/infer/src/clang/cType_to_sil_type.ml @@ -17,40 +17,40 @@ let get_builtin_objc_typename builtin_type = let get_builtin_objc_type builtin_type = let typ = Typ.mk (Tstruct (get_builtin_objc_typename builtin_type)) in match builtin_type with - | `ObjCId -> typ - | `ObjCClass -> Typ.mk (Tptr (typ, Typ.Pk_pointer)) + | `ObjCId -> typ.Typ.desc + | `ObjCClass -> Typ.Tptr (typ, Typ.Pk_pointer) -let sil_type_of_builtin_type_kind builtin_type_kind = +let type_desc_of_builtin_type_kind builtin_type_kind = match builtin_type_kind with - | `Void -> Typ.mk Tvoid - | `Bool -> Typ.mk (Tint IBool) - | `Char_U -> Typ.mk (Tint IUChar) - | `UChar -> Typ.mk (Tint IUChar) - | `WChar_U -> Typ.mk (Tint IUChar) - | `Char_S -> Typ.mk (Tint IChar) - | `SChar -> Typ.mk (Tint ISChar) + | `Void -> Typ.Tvoid + | `Bool -> Typ.Tint IBool + | `Char_U -> Typ.Tint IUChar + | `UChar -> Typ.Tint IUChar + | `WChar_U -> Typ.Tint IUChar + | `Char_S -> Typ.Tint IChar + | `SChar -> Typ.Tint ISChar | `WChar_S | `Char16 - | `Char32 -> Typ.mk (Tint IChar) + | `Char32 -> Typ.Tint IChar | `UShort - | `Short -> Typ.mk (Tint IShort) + | `Short -> Typ.Tint IShort | `UInt - | `UInt128 -> Typ.mk (Tint IUInt) - | `ULong -> Typ.mk (Tint IULong) - | `ULongLong -> Typ.mk (Tint IULongLong) + | `UInt128 -> Typ.Tint IUInt + | `ULong -> Typ.Tint IULong + | `ULongLong -> Typ.Tint IULongLong | `Int - | `Int128 -> Typ.mk (Tint IInt) - | `Long -> Typ.mk (Tint ILong) - | `LongLong -> Typ.mk (Tint ILongLong) - | `Half -> Typ.mk (Tint IShort) (*?*) - | `Float -> Typ.mk (Tfloat FFloat) - | `Double -> Typ.mk (Tfloat FDouble) - | `LongDouble -> Typ.mk (Tfloat FLongDouble) - | `NullPtr -> Typ.mk (Tint IInt) + | `Int128 -> Typ.Tint IInt + | `Long -> Typ.Tint ILong + | `LongLong -> Typ.Tint ILongLong + | `Half -> Typ.Tint IShort (*?*) + | `Float -> Typ.Tfloat FFloat + | `Double -> Typ.Tfloat FDouble + | `LongDouble -> Typ.Tfloat FLongDouble + | `NullPtr -> Typ.Tint IInt | `ObjCId -> get_builtin_objc_type `ObjCId | `ObjCClass -> get_builtin_objc_type `ObjCClass - | _ -> Typ.mk Tvoid + | _ -> Typ.Tvoid let pointer_attribute_of_objc_attribute attr_info = match attr_info.Clang_ast_t.ati_lifetime with @@ -62,35 +62,36 @@ let pointer_attribute_of_objc_attribute attr_info = let rec build_array_type translate_decl tenv (qual_type : Clang_ast_t.qual_type) n_opt = let array_type = qual_type_to_sil_type translate_decl tenv qual_type in let len = Option.map ~f:(fun n -> IntLit.of_int64 (Int64.of_int n)) n_opt in - Typ.mk (Tarray (array_type, len)) + Typ.Tarray (array_type, len) -and sil_type_of_attr_type translate_decl tenv type_info attr_info = +and type_desc_of_attr_type translate_decl tenv type_info attr_info = match type_info.Clang_ast_t.ti_desugared_type with | Some type_ptr -> (match CAst_utils.get_type type_ptr with | Some Clang_ast_t.ObjCObjectPointerType (_, qual_type) -> let typ = qual_type_to_sil_type translate_decl tenv qual_type in - Typ.mk (Tptr (typ, pointer_attribute_of_objc_attribute attr_info)) - | _ -> type_ptr_to_sil_type translate_decl tenv type_ptr) - | None -> Typ.mk Tvoid + Typ.Tptr (typ, pointer_attribute_of_objc_attribute attr_info) + | _ -> type_ptr_to_type_desc translate_decl tenv type_ptr) + | None -> Typ.Tvoid -and sil_type_of_c_type translate_decl tenv c_type : Typ.t = +and type_desc_of_c_type translate_decl tenv c_type : Typ.desc = let open Clang_ast_t in match c_type with - | NoneType _ -> Typ.mk Tvoid + | NoneType _ -> Tvoid | BuiltinType (_, builtin_type_kind) -> - sil_type_of_builtin_type_kind builtin_type_kind + type_desc_of_builtin_type_kind builtin_type_kind | PointerType (_, qual_type) | ObjCObjectPointerType (_, qual_type) -> let typ = qual_type_to_sil_type translate_decl tenv qual_type in - if Typ.equal typ (get_builtin_objc_type `ObjCClass) then - typ - else Typ.mk (Tptr (typ, Typ.Pk_pointer)) + let desc = typ.Typ.desc in + if Typ.equal_desc desc (get_builtin_objc_type `ObjCClass) then + desc + else Typ.Tptr (typ, Typ.Pk_pointer) | ObjCObjectType (_, objc_object_type_info) -> - type_ptr_to_sil_type translate_decl tenv objc_object_type_info.Clang_ast_t.base_type + type_ptr_to_type_desc translate_decl tenv objc_object_type_info.Clang_ast_t.base_type | BlockPointerType (_, qual_type) -> let typ = qual_type_to_sil_type translate_decl tenv qual_type in - Typ.mk (Tptr (typ, Typ.Pk_pointer)) + Typ.Tptr (typ, Typ.Pk_pointer) | IncompleteArrayType (_, qual_type) | DependentSizedArrayType (_, qual_type) | VariableArrayType (_, qual_type) -> @@ -99,33 +100,33 @@ and sil_type_of_c_type translate_decl tenv c_type : Typ.t = build_array_type translate_decl tenv qual_type (Some n) | FunctionProtoType _ | FunctionNoProtoType _ -> - Typ.mk (Tfun false) + Typ.Tfun false | ParenType (_, qual_type) -> - qual_type_to_sil_type translate_decl tenv qual_type + (qual_type_to_sil_type translate_decl tenv qual_type).Typ.desc | DecayedType (_, qual_type) -> - qual_type_to_sil_type translate_decl tenv qual_type + (qual_type_to_sil_type translate_decl tenv qual_type).Typ.desc | RecordType (_, pointer) | EnumType (_, pointer) -> - decl_ptr_to_sil_type translate_decl tenv pointer + decl_ptr_to_type_desc translate_decl tenv pointer | ElaboratedType (type_info) -> (match type_info.Clang_ast_t.ti_desugared_type with (* TODO desugar to qualtype *) - Some type_ptr -> type_ptr_to_sil_type translate_decl tenv type_ptr - | None -> Typ.mk Tvoid) + Some type_ptr -> type_ptr_to_type_desc translate_decl tenv type_ptr + | None -> Typ.Tvoid) | ObjCInterfaceType (_, pointer) -> - decl_ptr_to_sil_type translate_decl tenv pointer + decl_ptr_to_type_desc translate_decl tenv pointer | RValueReferenceType (_, qual_type) | LValueReferenceType (_, qual_type) -> let typ = qual_type_to_sil_type translate_decl tenv qual_type in - Typ.mk (Tptr (typ, Typ.Pk_reference)) + Typ.Tptr (typ, Typ.Pk_reference) | AttributedType (type_info, attr_info) -> (* TODO desugar to qualtyp *) - sil_type_of_attr_type translate_decl tenv type_info attr_info + type_desc_of_attr_type translate_decl tenv type_info attr_info | _ -> (* TypedefType, etc *) let type_info = Clang_ast_proj.get_type_tuple c_type in match type_info.Clang_ast_t.ti_desugared_type with (* TODO desugar typedeftype to qualtype *) - | Some typ -> type_ptr_to_sil_type translate_decl tenv typ - | None -> Typ.mk Tvoid + | Some typ -> type_ptr_to_type_desc translate_decl tenv typ + | None -> Typ.Tvoid -and decl_ptr_to_sil_type translate_decl tenv decl_ptr = +and decl_ptr_to_type_desc translate_decl tenv decl_ptr : Typ.desc = let open Clang_ast_t in let typ = Clang_ast_extend.DeclPtr decl_ptr in try Clang_ast_extend.TypePointerMap.find typ !CFrontend_config.sil_types_map @@ -143,38 +144,40 @@ and decl_ptr_to_sil_type translate_decl tenv decl_ptr = | Some _ -> Logging.err_debug "Warning: Wrong decl found for pointer %s " (Clang_ast_j.string_of_pointer decl_ptr); - Typ.mk Tvoid + Typ.Tvoid | None -> Logging.err_debug "Warning: Decl pointer %s not found." (Clang_ast_j.string_of_pointer decl_ptr); - Typ.mk Tvoid + Typ.Tvoid -and clang_type_ptr_to_sil_type translate_decl tenv type_ptr = +and clang_type_ptr_to_type_desc translate_decl tenv type_ptr = try Clang_ast_extend.TypePointerMap.find type_ptr !CFrontend_config.sil_types_map with Not_found -> (match CAst_utils.get_type type_ptr with | Some c_type -> - let sil_type = sil_type_of_c_type translate_decl tenv c_type in - CAst_utils.update_sil_types_map type_ptr sil_type; - sil_type - | _ -> Typ.mk Tvoid) + let type_desc = type_desc_of_c_type translate_decl tenv c_type in + CAst_utils.update_sil_types_map type_ptr type_desc; + type_desc + | _ -> Typ.Tvoid) -and type_ptr_to_sil_type translate_decl tenv type_ptr = +and type_ptr_to_type_desc translate_decl tenv type_ptr : Typ.desc = match type_ptr with - | Clang_ast_types.TypePtr.Ptr _ -> clang_type_ptr_to_sil_type translate_decl tenv type_ptr - | Clang_ast_extend.Builtin kind -> sil_type_of_builtin_type_kind kind + | Clang_ast_types.TypePtr.Ptr _ -> clang_type_ptr_to_type_desc translate_decl tenv type_ptr + | Clang_ast_extend.Builtin kind -> type_desc_of_builtin_type_kind kind | Clang_ast_extend.PointerOf typ -> let sil_typ = qual_type_to_sil_type translate_decl tenv typ in - Typ.mk (Tptr (sil_typ, Pk_pointer)) + Typ.Tptr (sil_typ, Pk_pointer) | Clang_ast_extend.ReferenceOf typ -> let sil_typ = qual_type_to_sil_type translate_decl tenv typ in - Typ.mk (Tptr (sil_typ, Pk_reference)) + Typ.Tptr (sil_typ, Pk_reference) | Clang_ast_extend.ClassType typename -> - Typ.mk (Tstruct typename) - | Clang_ast_extend.DeclPtr ptr -> decl_ptr_to_sil_type translate_decl tenv ptr - | Clang_ast_extend.ErrorType -> Typ.mk Tvoid + Typ.Tstruct typename + | Clang_ast_extend.DeclPtr ptr -> decl_ptr_to_type_desc translate_decl tenv ptr + | Clang_ast_extend.ErrorType -> Typ.Tvoid | _ -> raise (invalid_arg "unknown variant for type_ptr") and qual_type_to_sil_type translate_decl tenv qual_type = - type_ptr_to_sil_type translate_decl tenv qual_type.Clang_ast_t.qt_type_ptr (* FIXME *) + let desc = type_ptr_to_type_desc translate_decl tenv qual_type.Clang_ast_t.qt_type_ptr in + let quals = Typ.mk_type_quals ~is_const:qual_type.Clang_ast_t.qt_is_const () in + Typ.mk ~quals desc diff --git a/infer/src/clang/cType_to_sil_type.mli b/infer/src/clang/cType_to_sil_type.mli index 86b01e845..d6ea8dc82 100644 --- a/infer/src/clang/cType_to_sil_type.mli +++ b/infer/src/clang/cType_to_sil_type.mli @@ -11,12 +11,5 @@ open! IStd val get_builtin_objc_typename : [< `ObjCClass | `ObjCId ] -> Typ.Name.t -val get_builtin_objc_type : [< `ObjCClass | `ObjCId ] -> Typ.t - -val sil_type_of_builtin_type_kind : Clang_ast_t.builtin_type_kind -> Typ.t - -val type_ptr_to_sil_type : (Tenv.t -> Clang_ast_t.decl -> Typ.t) -> - Tenv.t -> Clang_ast_t.type_ptr -> Typ.t - -val qual_type_to_sil_type : (Tenv.t -> Clang_ast_t.decl -> Typ.t) -> +val qual_type_to_sil_type : (Tenv.t -> Clang_ast_t.decl -> Typ.desc) -> Tenv.t -> Clang_ast_t.qual_type -> Typ.t diff --git a/infer/src/clang/objcCategory_decl.ml b/infer/src/clang/objcCategory_decl.ml index 47d97d248..a1cb385c8 100644 --- a/infer/src/clang/objcCategory_decl.ml +++ b/infer/src/clang/objcCategory_decl.ml @@ -68,9 +68,9 @@ let get_base_class_name_from_category decl = let process_category qual_type_to_sil_type tenv class_name decl_info decl_list = let decl_fields = CField_decl.get_fields qual_type_to_sil_type tenv decl_list in let class_tn_name = Typ.Name.Objc.from_qual_name class_name in - let class_tn_type = Typ.mk (Typ.Tstruct class_tn_name) in + let class_tn_desc = Typ.Tstruct class_tn_name in let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in - CAst_utils.update_sil_types_map decl_key class_tn_type; + CAst_utils.update_sil_types_map decl_key class_tn_desc; (match Tenv.lookup tenv class_tn_name with | Some ({ fields } as struct_typ) -> let new_fields = CGeneral_utils.append_no_duplicates_fields decl_fields fields in @@ -79,7 +79,7 @@ let process_category qual_type_to_sil_type tenv class_name decl_info decl_list = ~default:struct_typ ~fields:new_fields ~statics:[] ~methods:[] class_tn_name ); Logging.out_debug " Updating info for class '%a' in tenv\n" QualifiedCppName.pp class_name | _ -> ()); - class_tn_type + class_tn_desc let category_decl qual_type_to_sil_type tenv decl = let open Clang_ast_t in diff --git a/infer/src/clang/objcCategory_decl.mli b/infer/src/clang/objcCategory_decl.mli index 477a5fe06..54db1a863 100644 --- a/infer/src/clang/objcCategory_decl.mli +++ b/infer/src/clang/objcCategory_decl.mli @@ -12,9 +12,9 @@ open! IStd (** In this module an ObjC category declaration or implementation is processed. The category *) (** is saved in the tenv as a struct with the corresponding fields and methods , and the class it belongs to *) -val category_decl : CAst_utils.qual_type_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t +val category_decl : CAst_utils.qual_type_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.desc -val category_impl_decl : CAst_utils.qual_type_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t +val category_impl_decl : CAst_utils.qual_type_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.desc val noname_category : string -> string diff --git a/infer/src/clang/objcInterface_decl.ml b/infer/src/clang/objcInterface_decl.ml index 079fecb44..1896ee3ff 100644 --- a/infer/src/clang/objcInterface_decl.ml +++ b/infer/src/clang/objcInterface_decl.ml @@ -78,9 +78,9 @@ let add_class_to_tenv qual_type_to_sil_type tenv decl_info name_info decl_list o let class_name = CAst_utils.get_qualified_name name_info in Logging.out_debug "ADDING: ObjCInterfaceDecl for '%a'\n" QualifiedCppName.pp class_name; let interface_name = Typ.Name.Objc.from_qual_name class_name in - let interface_type = Typ.mk (Tstruct interface_name) in + let interface_desc = Typ.Tstruct interface_name in let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in - CAst_utils.update_sil_types_map decl_key interface_type; + CAst_utils.update_sil_types_map decl_key interface_desc; let decl_supers, decl_fields = create_supers_fields qual_type_to_sil_type tenv decl_list ocidi.Clang_ast_t.otdi_super @@ -114,7 +114,7 @@ let add_class_to_tenv qual_type_to_sil_type tenv decl_info name_info decl_list o Logging.out_debug " >>>OK. Found typ='%a'\n" (Typ.Struct.pp Pp.text interface_name) st | None -> Logging.out_debug " >>>NOT Found!!\n"); - interface_type + interface_desc (* Interface_type_info has the name of instance variables and the name of methods. *) let interface_declaration qual_type_to_sil_type tenv decl = @@ -144,7 +144,7 @@ let interface_impl_declaration qual_type_to_sil_type tenv decl = CField_decl.add_missing_fields tenv class_name fields; let class_tn_name = Typ.Name.Objc.from_qual_name class_name in let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in - let class_typ = Typ.mk (Tstruct class_tn_name) in - CAst_utils.update_sil_types_map decl_key class_typ; - class_typ + let class_desc = Typ.Tstruct class_tn_name in + CAst_utils.update_sil_types_map decl_key class_desc; + class_desc | _ -> assert false diff --git a/infer/src/clang/objcInterface_decl.mli b/infer/src/clang/objcInterface_decl.mli index 67ca8f1e9..49c4b7358 100644 --- a/infer/src/clang/objcInterface_decl.mli +++ b/infer/src/clang/objcInterface_decl.mli @@ -13,9 +13,9 @@ open! IStd struct with the corresponding fields, potential superclass and list of defined methods *) val interface_declaration : CAst_utils.qual_type_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> - Typ.t + Typ.desc val interface_impl_declaration : CAst_utils.qual_type_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> - Typ.t + Typ.desc val is_pointer_to_objc_class : Typ.t -> bool diff --git a/infer/src/clang/objcProtocol_decl.ml b/infer/src/clang/objcProtocol_decl.ml index 353c73ae4..a1d06d19e 100644 --- a/infer/src/clang/objcProtocol_decl.ml +++ b/infer/src/clang/objcProtocol_decl.ml @@ -26,12 +26,12 @@ let protocol_decl qual_type_to_sil_type tenv decl = (* It may turn out that we need a more specific treatment for protocols*) Logging.out_debug "ADDING: ObjCProtocolDecl for '%a'\n" QualifiedCppName.pp name; let protocol_name = Typ.Name.Objc.protocol_from_qual_name name in - let protocol_type = Typ.mk (Tstruct protocol_name) in + let protocol_desc = Typ.Tstruct protocol_name in let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in - CAst_utils.update_sil_types_map decl_key protocol_type; + CAst_utils.update_sil_types_map decl_key protocol_desc; ignore( Tenv.mk_struct tenv ~methods:[] protocol_name ); add_protocol_super qual_type_to_sil_type tenv obj_c_protocol_decl_info; - protocol_type + protocol_desc | _ -> assert false let is_protocol decl = diff --git a/infer/src/clang/objcProtocol_decl.mli b/infer/src/clang/objcProtocol_decl.mli index cc7308abf..e762adf12 100644 --- a/infer/src/clang/objcProtocol_decl.mli +++ b/infer/src/clang/objcProtocol_decl.mli @@ -12,6 +12,6 @@ open! IStd (** In this module an ObjC protocol declaration or implementation is processed. The protocol *) (** is saved in the tenv as a struct with the corresponding methods *) -val protocol_decl : CAst_utils.qual_type_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t +val protocol_decl : CAst_utils.qual_type_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.desc val is_protocol : Clang_ast_t.decl -> bool diff --git a/infer/tests/codetoanalyze/cpp/errors/Makefile b/infer/tests/codetoanalyze/cpp/errors/Makefile index 18c4d66ec..1ee25aa0a 100644 --- a/infer/tests/codetoanalyze/cpp/errors/Makefile +++ b/infer/tests/codetoanalyze/cpp/errors/Makefile @@ -50,6 +50,7 @@ SOURCES = \ shared/templates/function.cpp \ shared/templates/function_pack.cpp \ shared/templates/method.cpp \ + shared/types/const.cpp \ shared/types/inheritance_casts.cpp \ shared/types/inheritance_field.cpp \ shared/types/operator_overload.cpp \ diff --git a/infer/tests/codetoanalyze/cpp/errors/issues.exp b/infer/tests/codetoanalyze/cpp/errors/issues.exp index 8f1d6f958..fda9aad76 100644 --- a/infer/tests/codetoanalyze/cpp/errors/issues.exp +++ b/infer/tests/codetoanalyze/cpp/errors/issues.exp @@ -125,6 +125,8 @@ codetoanalyze/cpp/errors/subtyping/dynamic_cast.cpp, dynamic__cast::wrongPointer codetoanalyze/cpp/errors/subtyping/dynamic_cast.cpp, dynamic__cast::wrongPointerCast, 6, DIVIDE_BY_ZERO, [start of procedure dynamic__cast::wrongPointerCast(),start of procedure Base,return from a call to dynamic__cast::Base_Base,Condition is false] codetoanalyze/cpp/errors/subtyping/dynamic_cast.cpp, dynamic__cast::wrongReferenceCast, 3, CLASS_CAST_EXCEPTION, [start of procedure dynamic__cast::wrongReferenceCast(),start of procedure Base,return from a call to dynamic__cast::Base_Base] codetoanalyze/cpp/errors/subtyping/dynamic_cast.cpp, dynamic__cast::wrongReferenceCastNotAssigned, 3, CLASS_CAST_EXCEPTION, [start of procedure dynamic__cast::wrongReferenceCastNotAssigned(),start of procedure Base,return from a call to dynamic__cast::Base_Base] +codetoanalyze/cpp/errors/subtyping/implicit_cast_with_const.cpp, implicit_cast_with_const::BaseDerefNPE, 2, NULL_DEREFERENCE, [start of procedure implicit_cast_with_const::BaseDerefNPE(),start of procedure Base,return from a call to implicit_cast_with_const::Base_Base,start of procedure implicit_cast_with_const::deref()] +codetoanalyze/cpp/errors/subtyping/implicit_cast_with_const.cpp, implicit_cast_with_const::DerivedDerefNPE, 2, NULL_DEREFERENCE, [start of procedure implicit_cast_with_const::DerivedDerefNPE(),start of procedure Derived,start of procedure Base,return from a call to implicit_cast_with_const::Base_Base,return from a call to implicit_cast_with_const::Derived_Derived,start of procedure implicit_cast_with_const::deref()] codetoanalyze/cpp/errors/subtyping/subtyping_check.cpp, B_setFG, 4, DIVIDE_BY_ZERO, [start of procedure setFG,start of procedure setF,return from a call to A_setF,Condition is true] codetoanalyze/cpp/errors/vector/access_field_later.cpp, getIntPtr, 1, RETURN_VALUE_IGNORED, [start of procedure getIntPtr()] codetoanalyze/cpp/errors/vector/access_field_later.cpp, getIntPtr, 2, EMPTY_VECTOR_ACCESS, [start of procedure getIntPtr()] @@ -277,6 +279,9 @@ codetoanalyze/cpp/shared/templates/function_pack.cpp, div0_3args4, 0, DIVIDE_BY_ codetoanalyze/cpp/shared/templates/method.cpp, method::div0_getter, 3, DIVIDE_BY_ZERO, [start of procedure method::div0_getter(),start of procedure X2,return from a call to method::X2_X2,start of procedure Getter,return from a call to method::Getter_Getter,start of procedure get,start of procedure get,return from a call to method::X2_get,return from a call to method::Getter_get] codetoanalyze/cpp/shared/templates/method.cpp, method::div0_getter_templ, 4, DIVIDE_BY_ZERO, [start of procedure method::div0_getter_templ(),start of procedure X2,return from a call to method::X2_X2,start of procedure X3,return from a call to method::X3_X3,start of procedure GetterTempl,return from a call to method::GetterTempl_GetterTempl,start of procedure get,start of procedure get,return from a call to method::X3_get,start of procedure get,return from a call to method::X2_get,return from a call to method::GetterTempl_get] codetoanalyze/cpp/shared/templates/method.cpp, method::div0_getter_templ2, 4, DIVIDE_BY_ZERO, [start of procedure method::div0_getter_templ2(),start of procedure X2,return from a call to method::X2_X2,start of procedure X2,return from a call to method::X2_X2,start of procedure GetterTempl,return from a call to method::GetterTempl_GetterTempl,start of procedure get,start of procedure get,return from a call to method::X2_get,start of procedure get,return from a call to method::X2_get,return from a call to method::GetterTempl_get] +codetoanalyze/cpp/shared/types/const.cpp, call_const_params_with_pointer1, 2, NULL_DEREFERENCE, [start of procedure call_const_params_with_pointer1(),start of procedure const_in_param1()] +codetoanalyze/cpp/shared/types/const.cpp, call_const_params_with_pointer2, 2, NULL_DEREFERENCE, [start of procedure call_const_params_with_pointer2(),start of procedure const_in_param2()] +codetoanalyze/cpp/shared/types/const.cpp, call_const_params_with_pointer3, 2, NULL_DEREFERENCE, [start of procedure call_const_params_with_pointer3(),start of procedure const_in_param2()] codetoanalyze/cpp/shared/types/inheritance_casts.cpp, inheritance_casts::div0_A, 0, DIVIDE_BY_ZERO, [start of procedure inheritance_casts::div0_A(),start of procedure inheritance_casts::getA(),start of procedure A,return from a call to inheritance_casts::A_A,start of procedure A,return from a call to inheritance_casts::A_A,return from a call to inheritance_casts::getA,start of procedure inheritance_casts::div()] codetoanalyze/cpp/shared/types/inheritance_casts.cpp, inheritance_casts::div0_B, 0, DIVIDE_BY_ZERO, [start of procedure inheritance_casts::div0_B(),start of procedure inheritance_casts::getB(),start of procedure B,start of procedure A,return from a call to inheritance_casts::A_A,return from a call to inheritance_casts::B_B,start of procedure B,start of procedure A,return from a call to inheritance_casts::A_A,return from a call to inheritance_casts::B_B,return from a call to inheritance_casts::getB,start of procedure inheritance_casts::div()] codetoanalyze/cpp/shared/types/inheritance_field.cpp, div0_b1, 2, DIVIDE_BY_ZERO, [start of procedure div0_b1()] diff --git a/infer/tests/codetoanalyze/cpp/errors/subtyping/implicit_cast_with_const.cpp b/infer/tests/codetoanalyze/cpp/errors/subtyping/implicit_cast_with_const.cpp new file mode 100644 index 000000000..1edba1113 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/errors/subtyping/implicit_cast_with_const.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +namespace implicit_cast_with_const { + +struct Base { + int* f{nullptr}; +}; + +struct Derived : public Base {}; + +int deref(const Base& b) { return *b.f; } + +int BaseDerefNPE() { + Base b; + return deref(b); +} + +int DerivedDerefNPE() { + Derived d; + return deref(d); +} + +int DerivedDerefNoNpe() { + Derived d; + int x; + d.f = &x; + return deref(d); +} +} diff --git a/infer/tests/codetoanalyze/cpp/shared/types/const.cpp b/infer/tests/codetoanalyze/cpp/shared/types/const.cpp new file mode 100644 index 000000000..e6fdbce33 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/shared/types/const.cpp @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +int const_in_param1(int const* p) { return *p; } + +int const_in_param2(int const* const p) { return *p; } + +int call_const_params_with_address() { + int x = 1; + const_in_param1(&x); + const_in_param2(&x); + + const int cx = 0; + + const_in_param1(&cx); + const_in_param2(&cx); +} + +int call_const_params_with_pointer1() { + int* p = nullptr; + const_in_param1(p); +} +int call_const_params_with_pointer2() { + int* p = nullptr; + const_in_param2(p); +} + +int call_const_params_with_pointer3() { + int* const cp = nullptr; + const_in_param2(cp); +} diff --git a/infer/tests/codetoanalyze/cpp/shared/types/const.cpp.dot b/infer/tests/codetoanalyze/cpp/shared/types/const.cpp.dot new file mode 100644 index 000000000..02710630a --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/shared/types/const.cpp.dot @@ -0,0 +1,101 @@ +/* @generated */ +digraph iCFG { +"call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_1" [label="1: Start call_const_params_with_address\nFormals: \nLocals: cx:int x:int \n DECLARE_LOCALS(&return,&cx,&x); [line 13]\n " color=yellow style=filled] + + + "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_1" -> "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_8" ; +"call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_2" [label="2: Exit call_const_params_with_address \n " color=yellow style=filled] + + +"call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_3" [label="3: Call _fun_const_in_param2 \n n$0=_fun_const_in_param2(&cx:int*) [line 21]\n " shape="box"] + + + "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_3" -> "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_2" ; +"call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_4" [label="4: Call _fun_const_in_param1 \n n$1=_fun_const_in_param1(&cx:int*) [line 20]\n " shape="box"] + + + "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_4" -> "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_3" ; +"call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_5" [label="5: DeclStmt \n *&cx:int=0 [line 18]\n " shape="box"] + + + "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_5" -> "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_4" ; +"call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_6" [label="6: Call _fun_const_in_param2 \n n$2=_fun_const_in_param2(&x:int*) [line 16]\n " shape="box"] + + + "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_6" -> "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_5" ; +"call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_7" [label="7: Call _fun_const_in_param1 \n n$3=_fun_const_in_param1(&x:int*) [line 15]\n " shape="box"] + + + "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_7" -> "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_6" ; +"call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_8" [label="8: DeclStmt \n *&x:int=1 [line 14]\n " shape="box"] + + + "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_8" -> "call_const_params_with_address#_Z30call_const_params_with_addressv.e754c92d7d89808473eac017465662b5_7" ; +"call_const_params_with_pointer1#_Z31call_const_params_with_pointer1v.95229883c9127e312980c9ae25c8da43_1" [label="1: Start call_const_params_with_pointer1\nFormals: \nLocals: p:int* \n DECLARE_LOCALS(&return,&p); [line 24]\n " color=yellow style=filled] + + + "call_const_params_with_pointer1#_Z31call_const_params_with_pointer1v.95229883c9127e312980c9ae25c8da43_1" -> "call_const_params_with_pointer1#_Z31call_const_params_with_pointer1v.95229883c9127e312980c9ae25c8da43_4" ; +"call_const_params_with_pointer1#_Z31call_const_params_with_pointer1v.95229883c9127e312980c9ae25c8da43_2" [label="2: Exit call_const_params_with_pointer1 \n " color=yellow style=filled] + + +"call_const_params_with_pointer1#_Z31call_const_params_with_pointer1v.95229883c9127e312980c9ae25c8da43_3" [label="3: Call _fun_const_in_param1 \n n$0=*&p:int* [line 26]\n n$1=_fun_const_in_param1(n$0:int*) [line 26]\n " shape="box"] + + + "call_const_params_with_pointer1#_Z31call_const_params_with_pointer1v.95229883c9127e312980c9ae25c8da43_3" -> "call_const_params_with_pointer1#_Z31call_const_params_with_pointer1v.95229883c9127e312980c9ae25c8da43_2" ; +"call_const_params_with_pointer1#_Z31call_const_params_with_pointer1v.95229883c9127e312980c9ae25c8da43_4" [label="4: DeclStmt \n *&p:int*=null [line 25]\n " shape="box"] + + + "call_const_params_with_pointer1#_Z31call_const_params_with_pointer1v.95229883c9127e312980c9ae25c8da43_4" -> "call_const_params_with_pointer1#_Z31call_const_params_with_pointer1v.95229883c9127e312980c9ae25c8da43_3" ; +"call_const_params_with_pointer2#_Z31call_const_params_with_pointer2v.d36c25662191fdac9d4028112e2d7d51_1" [label="1: Start call_const_params_with_pointer2\nFormals: \nLocals: p:int* \n DECLARE_LOCALS(&return,&p); [line 28]\n " color=yellow style=filled] + + + "call_const_params_with_pointer2#_Z31call_const_params_with_pointer2v.d36c25662191fdac9d4028112e2d7d51_1" -> "call_const_params_with_pointer2#_Z31call_const_params_with_pointer2v.d36c25662191fdac9d4028112e2d7d51_4" ; +"call_const_params_with_pointer2#_Z31call_const_params_with_pointer2v.d36c25662191fdac9d4028112e2d7d51_2" [label="2: Exit call_const_params_with_pointer2 \n " color=yellow style=filled] + + +"call_const_params_with_pointer2#_Z31call_const_params_with_pointer2v.d36c25662191fdac9d4028112e2d7d51_3" [label="3: Call _fun_const_in_param2 \n n$0=*&p:int* [line 30]\n n$1=_fun_const_in_param2(n$0:int*) [line 30]\n " shape="box"] + + + "call_const_params_with_pointer2#_Z31call_const_params_with_pointer2v.d36c25662191fdac9d4028112e2d7d51_3" -> "call_const_params_with_pointer2#_Z31call_const_params_with_pointer2v.d36c25662191fdac9d4028112e2d7d51_2" ; +"call_const_params_with_pointer2#_Z31call_const_params_with_pointer2v.d36c25662191fdac9d4028112e2d7d51_4" [label="4: DeclStmt \n *&p:int*=null [line 29]\n " shape="box"] + + + "call_const_params_with_pointer2#_Z31call_const_params_with_pointer2v.d36c25662191fdac9d4028112e2d7d51_4" -> "call_const_params_with_pointer2#_Z31call_const_params_with_pointer2v.d36c25662191fdac9d4028112e2d7d51_3" ; +"call_const_params_with_pointer3#_Z31call_const_params_with_pointer3v.3e5ec1065082911e42d0566ebc0bf6ed_1" [label="1: Start call_const_params_with_pointer3\nFormals: \nLocals: cp:int* \n DECLARE_LOCALS(&return,&cp); [line 33]\n " color=yellow style=filled] + + + "call_const_params_with_pointer3#_Z31call_const_params_with_pointer3v.3e5ec1065082911e42d0566ebc0bf6ed_1" -> "call_const_params_with_pointer3#_Z31call_const_params_with_pointer3v.3e5ec1065082911e42d0566ebc0bf6ed_4" ; +"call_const_params_with_pointer3#_Z31call_const_params_with_pointer3v.3e5ec1065082911e42d0566ebc0bf6ed_2" [label="2: Exit call_const_params_with_pointer3 \n " color=yellow style=filled] + + +"call_const_params_with_pointer3#_Z31call_const_params_with_pointer3v.3e5ec1065082911e42d0566ebc0bf6ed_3" [label="3: Call _fun_const_in_param2 \n n$0=*&cp:int* [line 35]\n n$1=_fun_const_in_param2(n$0:int*) [line 35]\n " shape="box"] + + + "call_const_params_with_pointer3#_Z31call_const_params_with_pointer3v.3e5ec1065082911e42d0566ebc0bf6ed_3" -> "call_const_params_with_pointer3#_Z31call_const_params_with_pointer3v.3e5ec1065082911e42d0566ebc0bf6ed_2" ; +"call_const_params_with_pointer3#_Z31call_const_params_with_pointer3v.3e5ec1065082911e42d0566ebc0bf6ed_4" [label="4: DeclStmt \n *&cp:int*=null [line 34]\n " shape="box"] + + + "call_const_params_with_pointer3#_Z31call_const_params_with_pointer3v.3e5ec1065082911e42d0566ebc0bf6ed_4" -> "call_const_params_with_pointer3#_Z31call_const_params_with_pointer3v.3e5ec1065082911e42d0566ebc0bf6ed_3" ; +"const_in_param1#_Z15const_in_param1PKi.1071f2f253e69ef9bc570605af35bf83_1" [label="1: Start const_in_param1\nFormals: p:int*\nLocals: \n DECLARE_LOCALS(&return); [line 9]\n " color=yellow style=filled] + + + "const_in_param1#_Z15const_in_param1PKi.1071f2f253e69ef9bc570605af35bf83_1" -> "const_in_param1#_Z15const_in_param1PKi.1071f2f253e69ef9bc570605af35bf83_3" ; +"const_in_param1#_Z15const_in_param1PKi.1071f2f253e69ef9bc570605af35bf83_2" [label="2: Exit const_in_param1 \n " color=yellow style=filled] + + +"const_in_param1#_Z15const_in_param1PKi.1071f2f253e69ef9bc570605af35bf83_3" [label="3: Return Stmt \n n$0=*&p:int* [line 9]\n n$1=*n$0:int [line 9]\n *&return:int=n$1 [line 9]\n " shape="box"] + + + "const_in_param1#_Z15const_in_param1PKi.1071f2f253e69ef9bc570605af35bf83_3" -> "const_in_param1#_Z15const_in_param1PKi.1071f2f253e69ef9bc570605af35bf83_2" ; +"const_in_param2#_Z15const_in_param2PKi.659d05c79678837da803a1f8b1bc46c1_1" [label="1: Start const_in_param2\nFormals: p:int*\nLocals: \n DECLARE_LOCALS(&return); [line 11]\n " color=yellow style=filled] + + + "const_in_param2#_Z15const_in_param2PKi.659d05c79678837da803a1f8b1bc46c1_1" -> "const_in_param2#_Z15const_in_param2PKi.659d05c79678837da803a1f8b1bc46c1_3" ; +"const_in_param2#_Z15const_in_param2PKi.659d05c79678837da803a1f8b1bc46c1_2" [label="2: Exit const_in_param2 \n " color=yellow style=filled] + + +"const_in_param2#_Z15const_in_param2PKi.659d05c79678837da803a1f8b1bc46c1_3" [label="3: Return Stmt \n n$0=*&p:int* [line 11]\n n$1=*n$0:int [line 11]\n *&return:int=n$1 [line 11]\n " shape="box"] + + + "const_in_param2#_Z15const_in_param2PKi.659d05c79678837da803a1f8b1bc46c1_3" -> "const_in_param2#_Z15const_in_param2PKi.659d05c79678837da803a1f8b1bc46c1_2" ; +}