diff --git a/infer/src/clang/CType.ml b/infer/src/clang/CType.ml index 558af3d07..ac85da433 100644 --- a/infer/src/clang/CType.ml +++ b/infer/src/clang/CType.ml @@ -11,7 +11,6 @@ open! IStd (** Utility module for retrieving types *) -open CFrontend_utils module L = Logging let add_pointer_to_typ typ = @@ -43,7 +42,7 @@ let is_class typ = let rec return_type_of_function_type_ptr type_ptr = let open Clang_ast_t in - match Ast_utils.get_type type_ptr with + match CAst_utils.get_type type_ptr with | Some FunctionProtoType (_, function_type_info, _) | Some FunctionNoProtoType (_, function_type_info) -> function_type_info.Clang_ast_t.fti_return_type @@ -63,12 +62,12 @@ let return_type_of_function_type tp = let is_block_type tp = let open Clang_ast_t in - match Ast_utils.get_desugared_type tp with + match CAst_utils.get_desugared_type tp with | Some BlockPointerType _ -> true | _ -> false let is_reference_type tp = - match Ast_utils.get_desugared_type tp with + match CAst_utils.get_desugared_type tp with | Some Clang_ast_t.LValueReferenceType _ -> true | Some Clang_ast_t.RValueReferenceType _ -> true | _ -> false diff --git a/infer/src/clang/CType_decl.ml b/infer/src/clang/CType_decl.ml index 1b6892c27..2875f50b6 100644 --- a/infer/src/clang/CType_decl.ml +++ b/infer/src/clang/CType_decl.ml @@ -11,8 +11,6 @@ open! IStd (** Processes types and record declarations by adding them to the tenv *) -open CFrontend_utils - module L = Logging let add_predefined_objc_types tenv = @@ -25,13 +23,13 @@ let add_predefined_basic_types () = let open Ast_expressions in let add_basic_type tp basic_type_kind = let sil_type = CType_to_sil_type.sil_type_of_builtin_type_kind basic_type_kind in - Ast_utils.update_sil_types_map tp sil_type in + CAst_utils.update_sil_types_map tp sil_type in let add_pointer_type tp sil_type = let pointer_type = CType.add_pointer_to_typ sil_type in - Ast_utils.update_sil_types_map tp pointer_type in + CAst_utils.update_sil_types_map tp pointer_type in let add_function_type tp return_type = (* We translate function types as the return type of the function *) - Ast_utils.update_sil_types_map tp return_type in + CAst_utils.update_sil_types_map tp return_type in let sil_void_type = CType_to_sil_type.sil_type_of_builtin_type_kind `Void in let sil_char_type = CType_to_sil_type.sil_type_of_builtin_type_kind `Char_S in let sil_nsarray_type = Typ.Tstruct (CType.mk_classname CFrontend_config.nsarray_cl Csu.Objc) in @@ -75,7 +73,7 @@ let get_record_name_csu decl = (* types that have methods. And in C++ struct/class/union can have methods *) name_info, Csu.Class Csu.CPP | _-> assert false in - let name = Ast_utils.get_qualified_name name_info in + let name = CAst_utils.get_qualified_name name_info in csu, name let get_record_name decl = snd (get_record_name_csu decl) @@ -88,9 +86,9 @@ let get_class_methods class_name decl_list = | Clang_ast_t.CXXDestructorDecl (_, name_info, _, fdi, mdi) -> let method_name = name_info.Clang_ast_t.ni_name in Logging.out_debug " ...Declaring method '%s'.\n" method_name; - let mangled = General_utils.get_mangled_method_name fdi mdi in + let mangled = CGeneral_utils.get_mangled_method_name fdi mdi in let procname = - General_utils.mk_procname_from_cpp_method class_name method_name ~meth_decl mangled in + CGeneral_utils.mk_procname_from_cpp_method class_name method_name ~meth_decl mangled in Some procname | _ -> None in (* poor mans list_filter_map *) @@ -103,7 +101,7 @@ let get_superclass_decls decl = | ClassTemplateSpecializationDecl (_, _, _, _, _, _, _, cxx_rec_info, _) -> (* there is no concept of virtual inheritance in the backend right now *) let base_ptr = cxx_rec_info.Clang_ast_t.xrdi_bases @ cxx_rec_info.Clang_ast_t.xrdi_vbases in - let get_decl_or_fail typ_ptr = match Ast_utils.get_decl_from_typ_ptr typ_ptr with + let get_decl_or_fail typ_ptr = match CAst_utils.get_decl_from_typ_ptr typ_ptr with | Some decl -> decl | None -> assert false in IList.map get_decl_or_fail base_ptr @@ -120,9 +118,9 @@ let get_superclass_list_cpp decl = let get_translate_as_friend_decl decl_list = let is_translate_as_friend_name (_, name_info) = let translate_as_str = "infer_traits::TranslateAsType" in - String.is_substring ~substring:translate_as_str (Ast_utils.get_qualified_name name_info) in + String.is_substring ~substring:translate_as_str (CAst_utils.get_qualified_name name_info) in let get_friend_decl_opt (decl : Clang_ast_t.decl) = match decl with - | FriendDecl (_, `Type type_ptr) -> Ast_utils.get_decl_from_typ_ptr type_ptr + | FriendDecl (_, `Type type_ptr) -> CAst_utils.get_decl_from_typ_ptr type_ptr | _ -> None in let is_translate_as_friend_decl decl = match get_friend_decl_opt decl with @@ -145,7 +143,7 @@ let rec get_struct_fields tenv decl = | _ -> [] in let do_one_decl decl = match decl with | FieldDecl (_, name_info, qt, _) -> - let id = General_utils.mk_class_field_name name_info in + let id = CGeneral_utils.mk_class_field_name name_info in let typ = type_ptr_to_sil_type tenv qt.Clang_ast_t.qt_type_ptr in let annotation_items = [] in (* For the moment we don't use them*) [(id, typ, annotation_items)] @@ -185,15 +183,15 @@ and get_record_declaration_struct_type tenv decl = if csu = Csu.Class Csu.CPP then Annot.Class.cpp else Annot.Item.empty (* No annotations for structs *) in if is_complete_definition then ( - Ast_utils.update_sil_types_map type_ptr (Typ.Tstruct sil_typename); + CAst_utils.update_sil_types_map type_ptr (Typ.Tstruct sil_typename); let non_statics = get_struct_fields tenv decl in - let fields = General_utils.append_no_duplicates_fields non_statics extra_fields 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 *) let methods = get_class_methods name decl_list in (* C++ methods only *) let supers = get_superclass_list_cpp decl in ignore (Tenv.mk_struct tenv ~fields ~statics ~methods ~supers ~annots sil_typename); let sil_type = Typ.Tstruct sil_typename in - Ast_utils.update_sil_types_map type_ptr sil_type; + CAst_utils.update_sil_types_map type_ptr sil_type; sil_type ) else ( match Tenv.lookup tenv sil_typename with @@ -204,7 +202,7 @@ and get_record_declaration_struct_type tenv decl = updated with a new struct including the other fields. *) ignore (Tenv.mk_struct tenv ~fields:extra_fields sil_typename); let tvar_type = Typ.Tstruct sil_typename in - Ast_utils.update_sil_types_map type_ptr tvar_type; + CAst_utils.update_sil_types_map type_ptr tvar_type; tvar_type) | _ -> assert false diff --git a/infer/src/clang/ComponentKit.ml b/infer/src/clang/ComponentKit.ml index 8ef7b3dfe..92a0dd928 100644 --- a/infer/src/clang/ComponentKit.ml +++ b/infer/src/clang/ComponentKit.ml @@ -7,7 +7,6 @@ * of patent rights can be found in the PATENTS file in the same directory. *) -open CFrontend_utils open! IStd let get_source_range an = @@ -30,21 +29,21 @@ let is_in_main_file translation_unit_context an = let is_ck_context (context: CLintersContext.context) an = context.is_ck_translation_unit && is_in_main_file context.translation_unit_context an - && General_utils.is_objc_extension context.translation_unit_context + && CGeneral_utils.is_objc_extension context.translation_unit_context (** Recursively go up the inheritance hierarchy of a given ObjCInterfaceDecl. (Returns false on decls other than that one.) *) let is_component_or_controller_if decl = let open CFrontend_config in - Ast_utils.is_objc_if_descendant decl [ckcomponent_cl; ckcomponentcontroller_cl] + CAst_utils.is_objc_if_descendant decl [ckcomponent_cl; ckcomponentcontroller_cl] (** True if it's an objc class impl that extends from CKComponent or CKComponentController, false otherwise *) let rec is_component_or_controller_descendant_impl decl = match decl with | Clang_ast_t.ObjCImplementationDecl _ -> - is_component_or_controller_if (Ast_utils.get_super_if (Some decl)) + is_component_or_controller_if (CAst_utils.get_super_if (Some decl)) | Clang_ast_t.LinkageSpecDecl (_, decl_list, _) -> contains_ck_impl decl_list | _ -> false @@ -83,10 +82,10 @@ and contains_ck_impl decl_list = ``` *) let mutable_local_vars_advice context an = let rec get_referenced_type (qual_type: Clang_ast_t.qual_type) : Clang_ast_t.decl option = - let typ_opt = Ast_utils.get_desugared_type qual_type.qt_type_ptr in + let typ_opt = CAst_utils.get_desugared_type qual_type.qt_type_ptr in match (typ_opt : Clang_ast_t.c_type option) with | Some ObjCInterfaceType (_, decl_ptr) - | Some RecordType (_, decl_ptr) -> Ast_utils.get_decl decl_ptr + | Some RecordType (_, decl_ptr) -> CAst_utils.get_decl decl_ptr | Some PointerType (_, inner_qual_type) | Some ObjCObjectPointerType (_, inner_qual_type) | Some LValueReferenceType (_, inner_qual_type) -> get_referenced_type inner_qual_type @@ -104,13 +103,13 @@ let mutable_local_vars_advice context an = match an with | CTL.Decl (Clang_ast_t.VarDecl(decl_info, named_decl_info, qual_type, _) as decl)-> - let is_const_ref = match Ast_utils.get_type qual_type.qt_type_ptr with + let is_const_ref = match CAst_utils.get_type qual_type.qt_type_ptr with | Some LValueReferenceType (_, {Clang_ast_t.qt_is_const}) -> qt_is_const | _ -> false in let is_const = qual_type.qt_is_const || is_const_ref in let condition = is_ck_context context an - && (not (Ast_utils.is_syntactically_global_var decl)) + && (not (CAst_utils.is_syntactically_global_var decl)) && (not is_const) && not (is_of_whitelisted_type qual_type) && not decl_info.di_is_implicit in @@ -134,12 +133,12 @@ let mutable_local_vars_advice context an = Any static function that returns a subclass of CKComponent will be flagged. *) let component_factory_function_advice context an = let is_component_if decl = - Ast_utils.is_objc_if_descendant decl [CFrontend_config.ckcomponent_cl] in + CAst_utils.is_objc_if_descendant decl [CFrontend_config.ckcomponent_cl] in match an with | CTL.Decl (Clang_ast_t.FunctionDecl (decl_info, _, (qual_type: Clang_ast_t.qual_type), _)) -> let objc_interface = - Ast_utils.type_ptr_to_objc_interface qual_type.qt_type_ptr in + CAst_utils.type_ptr_to_objc_interface qual_type.qt_type_ptr in let condition = is_ck_context context an && is_component_if objc_interface in if condition then @@ -165,7 +164,7 @@ let component_with_unconventional_superclass_advice context an = match if_decl with | Clang_ast_t.ObjCInterfaceDecl (_, _, _, _, _) -> if is_component_or_controller_if (Some if_decl) then - let superclass_name = match Ast_utils.get_super_if (Some if_decl) with + let superclass_name = match CAst_utils.get_super_if (Some if_decl) with | Some Clang_ast_t.ObjCInterfaceDecl (_, named_decl_info, _, _, _) -> Some named_decl_info.ni_name | _ -> None in @@ -203,7 +202,7 @@ let component_with_unconventional_superclass_advice context an = match an with | CTL.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info)) -> let if_decl_opt = - Ast_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in + CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in if Option.is_some if_decl_opt && is_ck_context context an then check_interface (Option.value_exn if_decl_opt) else @@ -233,7 +232,7 @@ let component_with_multiple_factory_methods_advice context an = | _ -> assert false in let unavailable_attrs = (IList.filter is_unavailable_attr attrs) in let is_available = IList.length unavailable_attrs = 0 in - (Ast_utils.is_objc_factory_method if_decl decl) && is_available in + (CAst_utils.is_objc_factory_method if_decl decl) && is_available in let check_interface if_decl = match if_decl with @@ -253,7 +252,7 @@ let component_with_multiple_factory_methods_advice context an = match an with | CTL.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info)) -> let if_decl_opt = - Ast_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in + CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in (match if_decl_opt with | Some d when is_ck_context context an -> check_interface d | _ -> CTL.False, []) @@ -262,7 +261,7 @@ let component_with_multiple_factory_methods_advice context an = let in_ck_class (context: CLintersContext.context) = Option.value_map ~f:is_component_or_controller_descendant_impl ~default:false context.current_objc_impl - && General_utils.is_objc_extension context.translation_unit_context + && CGeneral_utils.is_objc_extension context.translation_unit_context (** Components shouldn't have side-effects in its initializer. @@ -288,7 +287,7 @@ let rec _component_initializer_with_side_effects_advice | Clang_ast_t.DeclRefExpr (_, _, _, decl_ref_expr_info) -> let refs = [decl_ref_expr_info.drti_decl_ref; decl_ref_expr_info.drti_found_decl_ref] in - (match IList.find_map_opt Ast_utils.name_of_decl_ref_opt refs with + (match IList.find_map_opt CAst_utils.name_of_decl_ref_opt refs with | Some "dispatch_after" | Some "dispatch_async" | Some "dispatch_sync" -> diff --git a/infer/src/clang/ast_expressions.ml b/infer/src/clang/ast_expressions.ml index b03c7787c..f3bd564b7 100644 --- a/infer/src/clang/ast_expressions.ml +++ b/infer/src/clang/ast_expressions.ml @@ -9,8 +9,6 @@ open! IStd -open CFrontend_utils - (** This module creates extra ast constructs that are needed for the translation *) let dummy_source_range () = @@ -22,19 +20,19 @@ let dummy_source_range () = (dummy_source_loc, dummy_source_loc) let dummy_stmt_info () = { - Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer (); + Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer (); si_source_range = dummy_source_range (); } (* given a stmt_info return the same stmt_info with a fresh pointer *) let fresh_stmt_info stmt_info = - { stmt_info with Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer () } + { stmt_info with Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer () } let fresh_decl_info decl_info = - { decl_info with Clang_ast_t.di_pointer = Ast_utils.get_fresh_pointer () } + { decl_info with Clang_ast_t.di_pointer = CAst_utils.get_fresh_pointer () } let empty_decl_info = { - Clang_ast_t.di_pointer = Ast_utils.get_invalid_pointer (); + Clang_ast_t.di_pointer = CAst_utils.get_invalid_pointer (); di_parent_pointer = None; di_previous_decl = `None; di_source_range = dummy_source_range (); @@ -61,7 +59,7 @@ let empty_var_decl_info = { } let stmt_info_with_fresh_pointer stmt_info = { - Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer (); + Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer (); si_source_range = stmt_info.Clang_ast_t.si_source_range; } @@ -69,7 +67,7 @@ let create_qual_type ?(is_const=false) qt_type_ptr = { Clang_ast_t.qt_type_ptr; qt_is_const=is_const } let new_constant_type_ptr () = - let pointer = Ast_utils.get_fresh_pointer () in + let pointer = CAst_utils.get_fresh_pointer () in `Prebuilt pointer (* Whenever new type are added manually to the translation here, *) @@ -172,7 +170,7 @@ let create_nil stmt_info = create_implicit_cast_expr stmt_info [paren_expr] create_id_type `NullToPointer let dummy_stmt () = - let pointer = Ast_utils.get_fresh_pointer () in + let pointer = CAst_utils.get_fresh_pointer () in let source_range = dummy_source_range () in Clang_ast_t.NullStmt({ Clang_ast_t.si_pointer = pointer; si_source_range = source_range } ,[]) @@ -192,7 +190,7 @@ let make_expr_info_with_objc_kind tp objc_kind = let make_decl_ref_exp stmt_info expr_info drei = let stmt_info = { - Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer (); + Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer (); si_source_range = stmt_info.Clang_ast_t.si_source_range } in Clang_ast_t.DeclRefExpr(stmt_info, [], expr_info, drei) @@ -226,7 +224,7 @@ let make_decl_ref_no_tp k decl_ptr name is_hidden = make_decl_ref k decl_ptr name is_hidden None let make_decl_ref_invalid k name is_hidden tp = - make_decl_ref k (Ast_utils.get_invalid_pointer ()) name is_hidden (Some tp) + make_decl_ref k (CAst_utils.get_invalid_pointer ()) name is_hidden (Some tp) let make_decl_ref_expr_info decl_ref = { Clang_ast_t.drti_decl_ref = Some decl_ref; @@ -341,7 +339,7 @@ let build_PseudoObjectExpr tp_m o_cast_decl_ref_exp mname = | Clang_ast_t.ImplicitCastExpr (si, _, ei, _) -> let ove = build_OpaqueValueExpr si o_cast_decl_ref_exp ei in let ei_opre = make_expr_info (pseudo_object_tp ()) in - let count_name = Ast_utils.make_name_decl CFrontend_config.count in + let count_name = CAst_utils.make_name_decl CFrontend_config.count in let pointer = si.Clang_ast_t.si_pointer in let obj_c_property_ref_expr_info = { Clang_ast_t.oprei_kind = @@ -437,7 +435,7 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = { Clang_ast_t.uttei_kind = `SizeOf; Clang_ast_t.uttei_type_ptr = type_opt}) in let pointer = di.Clang_ast_t.di_pointer in let stmt_info = fresh_stmt_info stmt_info in - let malloc_name = Ast_utils.make_name_decl CFrontend_config.malloc in + let malloc_name = CAst_utils.make_name_decl CFrontend_config.malloc in let malloc = create_call stmt_info pointer malloc_name tp_fun [parameter] in let tp = qt.Clang_ast_t.qt_type_ptr in let init_exp = create_implicit_cast_expr (fresh_stmt_info stmt_info) [malloc] tp `BitCast in @@ -466,7 +464,7 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = let tp_fun = create_void_void_type in let decl_ref = make_decl_ref_tp `Var di.Clang_ast_t.di_pointer name false tp in let cast = cast_expr decl_ref tp in - let free_name = Ast_utils.make_name_decl CFrontend_config.free in + let free_name = CAst_utils.make_name_decl CFrontend_config.free in let parameter = create_implicit_cast_expr (fresh_stmt_info stmt_info) [cast] create_void_star_type `BitCast in let pointer = di.Clang_ast_t.di_pointer in @@ -516,12 +514,12 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = (* NSArray *objects = a *) let objects_array_DeclStmt init = - let di = { empty_decl_info with Clang_ast_t.di_pointer = Ast_utils.get_fresh_pointer () } in + let di = { empty_decl_info with Clang_ast_t.di_pointer = CAst_utils.get_fresh_pointer () } in let tp = create_qual_type @@ create_pointer_type @@ create_class_type (CFrontend_config.nsarray_cl, `OBJC) in (* init should be ImplicitCastExpr of array a *) let vdi = { empty_var_decl_info with Clang_ast_t.vdi_init_expr = Some (init) } in - let objects_name = Ast_utils.make_name_decl CFrontend_config.objects in + let objects_name = CAst_utils.make_name_decl CFrontend_config.objects in let var_decl = Clang_ast_t.VarDecl (di, objects_name, tp, vdi) in Clang_ast_t.DeclStmt (fresh_stmt_info stmt_info, [init], [var_decl]), [(CFrontend_config.objects, di.Clang_ast_t.di_pointer, tp)] in @@ -541,12 +539,12 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = cast_expr decl_ref tp | _ -> assert false in - let qual_block_name = Ast_utils.make_name_decl block_name in + let qual_block_name = CAst_utils.make_name_decl block_name in let make_block_decl be = match be with | Clang_ast_t.BlockExpr (bsi, _, bei, _) -> - let di = { empty_decl_info with Clang_ast_t.di_pointer = Ast_utils.get_fresh_pointer () } in + let di = { empty_decl_info with di_pointer = CAst_utils.get_fresh_pointer () } in let vdi = { empty_var_decl_info with Clang_ast_t.vdi_init_expr = Some (be) } in let qt = create_qual_type bei.Clang_ast_t.ei_type_ptr in let var_decl = Clang_ast_t.VarDecl (di, qual_block_name, qt, vdi) in @@ -615,7 +613,7 @@ let create_assume_not_null_call decl_info var_name var_type = let stmt_info_var = dummy_stmt_info () in let decl_ref_info = make_decl_ref_expr_info decl_ref in let var_decl_ref = Clang_ast_t.DeclRefExpr (stmt_info_var, [], (make_expr_info var_type), decl_ref_info) in - let var_decl_ptr = Ast_utils.get_invalid_pointer () in + let var_decl_ptr = CAst_utils.get_invalid_pointer () in let expr_info = { Clang_ast_t.ei_type_ptr = var_type; ei_value_kind = `RValue; @@ -628,5 +626,5 @@ let create_assume_not_null_call decl_info var_name var_type = let bin_op = make_binary_stmt decl_ref_exp_cast null_expr stmt_info bin_op_expr_info boi in let parameters = [bin_op] in let procname = Procname.to_string BuiltinDecl.__infer_assume in - let qual_procname = Ast_utils.make_name_decl procname in + let qual_procname = CAst_utils.make_name_decl procname in create_call stmt_info var_decl_ptr qual_procname create_void_star_type parameters diff --git a/infer/src/clang/cArithmetic_trans.ml b/infer/src/clang/cArithmetic_trans.ml index 9cfc399c0..7dfa97c12 100644 --- a/infer/src/clang/cArithmetic_trans.ml +++ b/infer/src/clang/cArithmetic_trans.ml @@ -11,8 +11,6 @@ open! IStd (** Utility module for translating unary and binary operations and compound assignments *) -open CFrontend_utils - (* Returns the translation of assignment when ARC mode is enabled in Obj-C *) (* For __weak and __unsafe_unretained the translation is the same as non-ARC *) (* (this is because, in these cases, there is no change in the reference counter *) @@ -150,7 +148,7 @@ let unary_operation_instruction translation_unit_context uoi e typ loc = let id = Ident.create_fresh Ident.knormal in let instr1 = Sil.Load (id, e, typ, loc) in let e_plus_1 = Exp.BinOp(Binop.PlusA, Exp.Var id, Exp.Const(Const.Cint (IntLit.one))) in - let exp = if General_utils.is_cpp_translation translation_unit_context then + let exp = if CGeneral_utils.is_cpp_translation translation_unit_context then e else e_plus_1 in @@ -164,7 +162,7 @@ let unary_operation_instruction translation_unit_context uoi e typ loc = let id = Ident.create_fresh Ident.knormal in let instr1 = Sil.Load (id, e, typ, loc) in let e_minus_1 = Exp.BinOp(Binop.MinusA, Exp.Var id, Exp.Const(Const.Cint (IntLit.one))) in - let exp = if General_utils.is_cpp_translation translation_unit_context then + let exp = if CGeneral_utils.is_cpp_translation translation_unit_context then e else e_minus_1 in diff --git a/infer/src/clang/cAst_utils.ml b/infer/src/clang/cAst_utils.ml new file mode 100644 index 000000000..a9fa769ae --- /dev/null +++ b/infer/src/clang/cAst_utils.ml @@ -0,0 +1,471 @@ +(* + * Copyright (c) 2013 - 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. + *) + +open! IStd + +(** Functions for transformations of ast nodes *) + +module L = Logging +module F = Format + +type type_ptr_to_sil_type = Tenv.t -> Clang_ast_t.type_ptr -> Typ.t + +let string_of_decl decl = + let name = Clang_ast_proj.get_decl_kind_string decl in + let info = Clang_ast_proj.get_decl_tuple decl in + Printf.sprintf "<\"%s\"> '%d'" name info.Clang_ast_t.di_pointer + +let string_of_unary_operator_kind = function + | `PostInc -> "PostInc" + | `PostDec -> "PostDec" + | `PreInc -> "PreInc" + | `PreDec -> "PreDec" + | `AddrOf -> "AddrOf" + | `Deref -> "Deref" + | `Plus -> "Plus" + | `Minus -> "Minus" + | `Not -> "Not" + | `LNot -> "LNot" + | `Real -> "Real" + | `Imag -> "Imag" + | `Extension -> "Extension" + | `Coawait -> "Coawait" + +let string_of_stmt stmt = + let name = Clang_ast_proj.get_stmt_kind_string stmt in + let info, _ = Clang_ast_proj.get_stmt_tuple stmt in + Printf.sprintf "<\"%s\"> '%d'" name info.Clang_ast_t.si_pointer + +let get_stmts_from_stmt stmt = + let open Clang_ast_t in + match stmt with + | OpaqueValueExpr (_, lstmt, _, opaque_value_expr_info) -> + (match opaque_value_expr_info.Clang_ast_t.ovei_source_expr with + | Some stmt -> lstmt @ [stmt] + | _ -> lstmt) + (* given that this has not been translated, looking up for variables *) + (* inside leads to inconsistencies *) + | ObjCAtCatchStmt _ -> + [] + | _ -> snd (Clang_ast_proj.get_stmt_tuple stmt) + +let fold_qual_name qual_name_list = + match qual_name_list with + | [] -> "" + | name :: quals -> + let s = (IList.fold_right (fun el res -> res ^ el ^ "::") quals "") ^ name in + let no_slash_space = Str.global_replace (Str.regexp "[/ ]") "_" s in + no_slash_space + +let get_qualified_name name_info = + fold_qual_name name_info.Clang_ast_t.ni_qual_name + +let get_unqualified_name name_info = + let name = match name_info.Clang_ast_t.ni_qual_name with + | name :: _ -> name + | [] -> name_info.Clang_ast_t.ni_name in + fold_qual_name [name] + +let get_class_name_from_member member_name_info = + match member_name_info.Clang_ast_t.ni_qual_name with + | _ :: class_qual_list -> fold_qual_name class_qual_list + | [] -> assert false + +let make_name_decl name = { + Clang_ast_t.ni_name = name; + ni_qual_name = [name]; +} + +let make_qual_name_decl class_name_quals name = { + Clang_ast_t.ni_name = name; + ni_qual_name = name :: class_name_quals; +} + +let property_name property_impl_decl_info = + let no_property_name = make_name_decl "WARNING_NO_PROPERTY_NAME" in + match property_impl_decl_info.Clang_ast_t.opidi_property_decl with + | Some decl_ref -> + (match decl_ref.Clang_ast_t.dr_name with + | Some n -> n + | _ -> no_property_name) + | None -> no_property_name + +let generated_ivar_name property_name = + match property_name.Clang_ast_t.ni_qual_name with + | [name; class_name] -> + let ivar_name = "_" ^ name in + { Clang_ast_t.ni_name = ivar_name; + ni_qual_name = [ivar_name; class_name] + } + | _ -> make_name_decl property_name.Clang_ast_t.ni_name + +let compare_property_attribute = + [%compare: [ + `Readonly | `Assign | `Readwrite | `Retain | `Copy | `Nonatomic | `Atomic + | `Weak | `Strong | `Unsafe_unretained | `ExplicitGetter | `ExplicitSetter + ]] + +let equal_property_attribute att1 att2 = + compare_property_attribute att1 att2 = 0 + +let get_memory_management_attributes () = + [`Assign; `Retain; `Copy; `Weak; `Strong; `Unsafe_unretained] + +let is_retain attribute_opt = + match attribute_opt with + | Some attribute -> + attribute = `Retain || attribute = `Strong + | _ -> false + +let is_copy attribute_opt = + match attribute_opt with + | Some attribute -> + attribute = `Copy + | _ -> false + +let name_opt_of_name_info_opt name_info_opt = + match name_info_opt with + | Some name_info -> Some (get_qualified_name name_info) + | None -> None + +let pointer_counter = ref 0 + +let get_fresh_pointer () = + pointer_counter := !pointer_counter + 1; + let internal_pointer = -(!pointer_counter) in + internal_pointer + +let get_invalid_pointer () = + CFrontend_config.invalid_pointer + +let type_from_unary_expr_or_type_trait_expr_info info = + match info.Clang_ast_t.uttei_type_ptr with + | Some tp -> Some tp + | None -> None + +let get_decl decl_ptr = + try + Some (Clang_ast_main.PointerMap.find decl_ptr !CFrontend_config.pointer_decl_index) + with Not_found -> Logging.out "decl with pointer %d not found\n" decl_ptr; None + +let get_decl_opt decl_ptr_opt = + match decl_ptr_opt with + | Some decl_ptr -> get_decl decl_ptr + | None -> None + +let get_stmt stmt_ptr = + try + Some (Clang_ast_main.PointerMap.find stmt_ptr !CFrontend_config.pointer_stmt_index) + with Not_found -> Logging.out "stmt with pointer %d not found\n" stmt_ptr; None + +let get_stmt_opt stmt_ptr_opt = + match stmt_ptr_opt with + | Some stmt_ptr -> get_stmt stmt_ptr + | None -> None + +let get_decl_opt_with_decl_ref decl_ref_opt = + match decl_ref_opt with + | Some decl_ref -> get_decl decl_ref.Clang_ast_t.dr_decl_pointer + | None -> None + +let get_property_of_ivar decl_ptr = + try + Some (Clang_ast_main.PointerMap.find decl_ptr !CFrontend_config.ivar_to_property_index) + with Not_found -> Logging.out "property with pointer %d not found\n" decl_ptr; None + +let update_sil_types_map type_ptr sil_type = + CFrontend_config.sil_types_map := + Clang_ast_types.TypePointerMap.add type_ptr sil_type !CFrontend_config.sil_types_map + +let update_enum_map enum_constant_pointer sil_exp = + let open Clang_ast_main in + let (predecessor_pointer_opt, _) = + try PointerMap.find enum_constant_pointer !CFrontend_config.enum_map + with Not_found -> assert false in + let enum_map_value = (predecessor_pointer_opt, Some sil_exp) in + CFrontend_config.enum_map := + PointerMap.add enum_constant_pointer enum_map_value !CFrontend_config.enum_map + +let add_enum_constant enum_constant_pointer predecessor_pointer_opt = + let enum_map_value = (predecessor_pointer_opt, None) in + CFrontend_config.enum_map := + Clang_ast_main.PointerMap.add enum_constant_pointer enum_map_value !CFrontend_config.enum_map + +let get_enum_constant_exp enum_constant_pointer = + Clang_ast_main.PointerMap.find enum_constant_pointer !CFrontend_config.enum_map + +let get_type type_ptr = + try + (* There is chance for success only if type_ptr is in fact clang pointer *) + (let raw_ptr = Clang_ast_types.type_ptr_to_clang_pointer type_ptr in + try + Some (Clang_ast_main.PointerMap.find raw_ptr !CFrontend_config.pointer_type_index) + with Not_found -> Logging.out "type with pointer %d not found\n" raw_ptr; None) + with Clang_ast_types.Not_Clang_Pointer -> + (* otherwise, function fails *) + let type_str = Clang_ast_types.type_ptr_to_string type_ptr in + Logging.out "type %s is not clang pointer\n" type_str; + None + +let get_desugared_type type_ptr = + let typ_opt = get_type type_ptr in + match typ_opt with + | Some typ -> + let type_info = Clang_ast_proj.get_type_tuple typ in + (match type_info.Clang_ast_t.ti_desugared_type with + | Some ptr -> get_type ptr + | _ -> typ_opt) + | _ -> typ_opt + +let get_decl_from_typ_ptr typ_ptr = + let typ_opt = get_desugared_type typ_ptr in + let typ = match typ_opt with Some t -> t | _ -> assert false in + match typ with + | Clang_ast_t.RecordType (_, decl_ptr) + | Clang_ast_t.ObjCInterfaceType (_, decl_ptr) -> get_decl decl_ptr + | _ -> None + +(* TODO take the attributes into account too. To be done after we get the attribute's arguments. *) +let is_type_nonnull type_ptr = + let open Clang_ast_t in + match get_type type_ptr with + | Some AttributedType (_, attr_info) -> attr_info.ati_attr_kind = `Nonnull + | _ -> false + +let is_type_nullable type_ptr = + let open Clang_ast_t in + match get_type type_ptr with + | Some AttributedType (_, attr_info) -> attr_info.ati_attr_kind = `Nullable + | _ -> false + +let string_of_type_ptr type_ptr = Clang_ast_j.string_of_type_ptr type_ptr + +let name_of_typedef_type_info {Clang_ast_t.tti_decl_ptr} = + match get_decl tti_decl_ptr with + | Some TypedefDecl (_, name_decl_info, _, _, _) -> + get_qualified_name name_decl_info + | _ -> "" + +let name_opt_of_typedef_type_ptr type_ptr = + match get_type type_ptr with + | Some Clang_ast_t.TypedefType (_, typedef_type_info) -> + Some (name_of_typedef_type_info typedef_type_info) + | _ -> None + +let string_of_qual_type {Clang_ast_t.qt_type_ptr; qt_is_const} = + Printf.sprintf "%s%s" (if qt_is_const then "is_const " else "") (string_of_type_ptr qt_type_ptr) + +let add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt fail_if_not_found = + match decl_ref_opt with (* translate interface first if found *) + | Some dr -> + ignore (type_ptr_to_sil_type tenv (`DeclPtr dr.Clang_ast_t.dr_decl_pointer)); + | _ -> if fail_if_not_found then assert false else () + +let add_type_from_decl_ref_list type_ptr_to_sil_type tenv decl_ref_list = + let add_elem dr = + ignore (type_ptr_to_sil_type tenv (`DeclPtr dr.Clang_ast_t.dr_decl_pointer)) in + IList.iter add_elem decl_ref_list + +let get_function_decl_with_body decl_ptr = + let open Clang_ast_t in + let decl_opt = get_decl decl_ptr in + let decl_ptr' = match decl_opt with + | Some (FunctionDecl (_, _, _, fdecl_info)) + | Some (CXXMethodDecl (_, _, _, fdecl_info, _)) + | Some (CXXConstructorDecl (_, _, _, fdecl_info, _)) + | Some (CXXConversionDecl (_, _, _, fdecl_info, _)) + | Some (CXXDestructorDecl (_, _, _, fdecl_info, _)) -> + fdecl_info.Clang_ast_t.fdi_decl_ptr_with_body + | _ -> Some decl_ptr in + if decl_ptr' = (Some decl_ptr) then decl_opt + else get_decl_opt decl_ptr' + +let get_info_from_decl_ref decl_ref = + let name_info = match decl_ref.Clang_ast_t.dr_name with Some ni -> ni | _ -> assert false in + let decl_ptr = decl_ref.Clang_ast_t.dr_decl_pointer in + let type_ptr = match decl_ref.Clang_ast_t.dr_type_ptr with Some tp -> tp | _ -> assert false in + name_info, decl_ptr, type_ptr + +(* st |= EF (atomic_pred param) *) +let rec exists_eventually_st atomic_pred param st = + if atomic_pred param st then true + else + let _, st_list = Clang_ast_proj.get_stmt_tuple st in + IList.exists (exists_eventually_st atomic_pred param) st_list + +let is_syntactically_global_var decl = + match decl with + | Clang_ast_t.VarDecl (_, _ ,_, vdi) -> + vdi.vdi_is_global && not vdi.vdi_is_static_local + | _ -> false + +let is_const_expr_var decl = + match decl with + | Clang_ast_t.VarDecl (_, _ ,_, vdi) -> vdi.vdi_is_const_expr + | _ -> false + +let is_ptr_to_objc_class typ class_name = + match typ with + | Some Clang_ast_t.ObjCObjectPointerType (_, {Clang_ast_t.qt_type_ptr}) -> + (match get_desugared_type qt_type_ptr with + | Some ObjCInterfaceType (_, ptr) -> + (match get_decl ptr with + | Some ObjCInterfaceDecl (_, ndi, _, _, _) -> + String.compare ndi.ni_name class_name = 0 + | _ -> false) + | _ -> false) + | _ -> false + +let full_name_of_decl_opt decl_opt = + match decl_opt with + | Some decl -> + (match Clang_ast_proj.get_named_decl_tuple decl with + | Some (_, name_info) -> get_qualified_name name_info + | None -> "") + | None -> "" + +(* Generates a unique number for each variant of a type. *) +let get_tag ast_item = + let item_rep = Obj.repr ast_item in + if Obj.is_block item_rep then + Obj.tag item_rep + else -(Obj.obj item_rep) + +(* Generates a key for a statement based on its sub-statements and the statement tag. *) +let rec generate_key_stmt stmt = + let tag_str = string_of_int (get_tag stmt) in + let _, stmts = Clang_ast_proj.get_stmt_tuple stmt in + let tags = IList.map generate_key_stmt stmts in + let buffer = Buffer.create 16 in + let tags = tag_str :: tags in + IList.iter (fun tag -> Buffer.add_string buffer tag) tags; + Buffer.contents buffer + +(* Generates a key for a declaration based on its name and the declaration tag. *) +let generate_key_decl decl = + let buffer = Buffer.create 16 in + let name = full_name_of_decl_opt (Some decl) in + Buffer.add_string buffer (string_of_int (get_tag decl)); + Buffer.add_string buffer name; + Buffer.contents buffer + +let rec get_super_if decl = + match decl with + | Some Clang_ast_t.ObjCImplementationDecl(_, _, _, _, impl_decl_info) -> + (* Try getting the super ref through the impl info, and fall back to + getting the if decl first and getting the super ref through it. *) + let super_ref = get_decl_opt_with_decl_ref impl_decl_info.oidi_super in + if Option.is_some super_ref then + super_ref + else + get_super_if (get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface) + | Some Clang_ast_t.ObjCInterfaceDecl(_, _, _, _, interface_decl_info) -> + get_decl_opt_with_decl_ref interface_decl_info.otdi_super + | _ -> None + +let get_super_impl impl_decl_info = + let objc_interface_decl_current = + get_decl_opt_with_decl_ref + impl_decl_info.Clang_ast_t.oidi_class_interface in + let objc_interface_decl_super = get_super_if objc_interface_decl_current in + let objc_implementation_decl_super = + match objc_interface_decl_super with + | Some ObjCInterfaceDecl(_, _, _, _, interface_decl_info) -> + get_decl_opt_with_decl_ref + interface_decl_info.otdi_implementation + | _ -> None in + match objc_implementation_decl_super with + | Some ObjCImplementationDecl(_, _, decl_list, _, impl_decl_info) -> + Some (decl_list, impl_decl_info) + | _ -> None + +let get_super_ObjCImplementationDecl impl_decl_info = + let objc_interface_decl_current = + get_decl_opt_with_decl_ref + impl_decl_info.Clang_ast_t.oidi_class_interface in + let objc_interface_decl_super = get_super_if objc_interface_decl_current in + let objc_implementation_decl_super = + match objc_interface_decl_super with + | Some ObjCInterfaceDecl(_, _, _, _, interface_decl_info) -> + get_decl_opt_with_decl_ref + interface_decl_info.otdi_implementation + | _ -> None in + objc_implementation_decl_super + +let get_impl_decl_info dec = + match dec with + | Clang_ast_t.ObjCImplementationDecl (_, _, _, _, idi) -> Some idi + | _ -> None + +let default_blacklist = + let open CFrontend_config in + [nsobject_cl; nsproxy_cl] + +let rec is_objc_if_descendant ?(blacklist = default_blacklist) if_decl ancestors = + (* List of ancestors to check for and list of classes to short-circuit to + false can't intersect *) + if not String.Set.(is_empty (inter (of_list blacklist) (of_list ancestors))) then + failwith "Blacklist and ancestors must be mutually exclusive." + else + match if_decl with + | Some Clang_ast_t.ObjCInterfaceDecl (_, ndi, _, _, _) -> + let in_list some_list = + IList.mem String.equal ndi.Clang_ast_t.ni_name some_list in + not (in_list blacklist) + && (in_list ancestors + || is_objc_if_descendant ~blacklist:blacklist (get_super_if if_decl) ancestors) + | _ -> false + +let rec type_ptr_to_objc_interface type_ptr = + let typ_opt = get_desugared_type type_ptr in + match (typ_opt : Clang_ast_t.c_type option) with + | Some ObjCInterfaceType (_, decl_ptr) -> get_decl decl_ptr + | Some ObjCObjectPointerType (_, (inner_qual_type: Clang_ast_t.qual_type)) -> + type_ptr_to_objc_interface inner_qual_type.qt_type_ptr + | Some FunctionProtoType (_, function_type_info, _) + | Some FunctionNoProtoType (_, function_type_info) -> + type_ptr_to_objc_interface function_type_info.Clang_ast_t.fti_return_type + | _ -> None + + +let if_decl_to_di_pointer_opt if_decl = + match if_decl with + | Clang_ast_t.ObjCInterfaceDecl (if_decl_info, _, _, _, _) -> + Some if_decl_info.di_pointer + | _ -> None + +let is_instance_type type_ptr = + match name_opt_of_typedef_type_ptr type_ptr with + | Some name -> name = "instancetype" + | None -> false + +let return_type_matches_class_type rtp type_decl_pointer = + if is_instance_type rtp then + true + else + let return_type_decl_opt = type_ptr_to_objc_interface rtp in + let return_type_decl_pointer_opt = + Option.map ~f:if_decl_to_di_pointer_opt return_type_decl_opt in + (Some type_decl_pointer) = return_type_decl_pointer_opt + +let is_objc_factory_method if_decl meth_decl = + let if_type_decl_pointer = if_decl_to_di_pointer_opt if_decl in + match meth_decl with + | Clang_ast_t.ObjCMethodDecl (_, _, omdi) -> + (not omdi.omdi_is_instance_method) && + (return_type_matches_class_type omdi.omdi_result_type if_type_decl_pointer) + | _ -> false + +let name_of_decl_ref_opt (decl_ref_opt: Clang_ast_t.decl_ref option) = + match decl_ref_opt with + | Some decl_ref -> + (match decl_ref.dr_name with + | Some named_decl_info -> Some named_decl_info.ni_name + | _ -> None) + | _ -> None diff --git a/infer/src/clang/cAst_utils.mli b/infer/src/clang/cAst_utils.mli new file mode 100644 index 000000000..9a96b69a8 --- /dev/null +++ b/infer/src/clang/cAst_utils.mli @@ -0,0 +1,172 @@ +(* + * Copyright (c) 2013 - 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. + *) + +open! IStd + +(** Functions for transformations of ast nodes *) + +val string_of_stmt : Clang_ast_t.stmt -> string + +val get_stmts_from_stmt : Clang_ast_t.stmt -> Clang_ast_t.stmt list + +val string_of_decl : Clang_ast_t.decl -> string + +val string_of_unary_operator_kind : Clang_ast_t.unary_operator_kind -> string + +val name_opt_of_name_info_opt : Clang_ast_t.named_decl_info option -> string option + +val property_name : Clang_ast_t.obj_c_property_impl_decl_info -> Clang_ast_t.named_decl_info + +val compare_property_attribute : + Clang_ast_t.property_attribute -> Clang_ast_t.property_attribute -> int + +val generated_ivar_name : + Clang_ast_t.named_decl_info -> Clang_ast_t.named_decl_info + +val equal_property_attribute : + Clang_ast_t.property_attribute -> Clang_ast_t.property_attribute -> bool + +val get_memory_management_attributes : unit -> Clang_ast_t.property_attribute list + +val is_retain : Clang_ast_t.property_attribute option -> bool + +val is_copy : Clang_ast_t.property_attribute option -> bool + +val is_type_nonnull : Clang_ast_t.type_ptr -> bool + +val is_type_nullable : Clang_ast_t.type_ptr -> bool + +val get_fresh_pointer : unit -> Clang_ast_t.pointer + +val get_invalid_pointer : unit -> Clang_ast_t.pointer + +val type_from_unary_expr_or_type_trait_expr_info : + Clang_ast_t.unary_expr_or_type_trait_expr_info -> Clang_ast_t.type_ptr option + +val get_decl : Clang_ast_t.pointer -> Clang_ast_t.decl option + +val get_decl_opt : Clang_ast_t.pointer option -> Clang_ast_t.decl option + +val get_stmt : Clang_ast_t.pointer -> Clang_ast_t.stmt option + +val get_stmt_opt : Clang_ast_t.pointer option -> Clang_ast_t.stmt option + +val get_decl_opt_with_decl_ref : Clang_ast_t.decl_ref option -> Clang_ast_t.decl option + +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_enum_map : Clang_ast_t.pointer -> Exp.t -> unit + +val add_enum_constant : Clang_ast_t.pointer -> Clang_ast_t.pointer option -> unit + +val get_enum_constant_exp : Clang_ast_t.pointer -> Clang_ast_t.pointer option * Exp.t option + +(** returns sanitized, fully qualified name given name info *) +val get_qualified_name : Clang_ast_t.named_decl_info -> string + +(** returns sanitized unqualified name given name info *) +val get_unqualified_name : Clang_ast_t.named_decl_info -> string + +(** returns qualified class name given member name info *) +val get_class_name_from_member : Clang_ast_t.named_decl_info -> string + +(** looks up clang pointer to type and returns c_type. It requires type_ptr to be `TPtr. *) +val get_type : Clang_ast_t.type_ptr -> Clang_ast_t.c_type option + +(** looks up clang pointer to type and resolves any sugar around it. + See get_type for more info and restrictions *) +val get_desugared_type : Clang_ast_t.type_ptr -> Clang_ast_t.c_type option + +(** returns declaration of the type for certain types + (RecordType, ObjCInterfaceType and None for others *) +val get_decl_from_typ_ptr : Clang_ast_t.type_ptr -> Clang_ast_t.decl option + +(** returns string representation of type_ptr + NOTE: this doesn't expand type, it only converts type_ptr to string *) +val string_of_type_ptr : Clang_ast_t.type_ptr -> string + +val name_of_typedef_type_info : Clang_ast_t.typedef_type_info -> string + +(** returns name of typedef if type_ptr points to Typedef, None otherwise *) +val name_opt_of_typedef_type_ptr : Clang_ast_t.type_ptr -> string option + +val string_of_qual_type : Clang_ast_t.qual_type -> string + +val make_name_decl : string -> Clang_ast_t.named_decl_info + +val make_qual_name_decl : string list -> string -> Clang_ast_t.named_decl_info + +type type_ptr_to_sil_type = Tenv.t -> Clang_ast_t.type_ptr -> Typ.t + +val add_type_from_decl_ref : type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl_ref option -> + bool -> unit + +val add_type_from_decl_ref_list : type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl_ref list -> + unit + +val get_function_decl_with_body : Clang_ast_t.pointer -> Clang_ast_t.decl option + +val get_info_from_decl_ref : Clang_ast_t.decl_ref -> + Clang_ast_t.named_decl_info * Clang_ast_t.pointer * Clang_ast_t.type_ptr + +val exists_eventually_st : ('a -> Clang_ast_t.stmt -> bool) -> 'a -> Clang_ast_t.stmt -> bool + +(** true if a declaration is a global variable *) +val is_syntactically_global_var : Clang_ast_t.decl -> bool + +(** true if a declaration is a constexpr variable *) +val is_const_expr_var : Clang_ast_t.decl -> bool + +val is_ptr_to_objc_class : Clang_ast_t.c_type option -> string -> bool + +val full_name_of_decl_opt : Clang_ast_t.decl option -> string + +(** Generates a key for a statement based on its sub-statements and the statement tag. *) +val generate_key_stmt : Clang_ast_t.stmt -> string + +(** Generates a key for a declaration based on its name and the declaration tag. *) +val generate_key_decl : Clang_ast_t.decl -> string + +(** Given an objc impl or interface decl, returns the objc interface decl of + the superclass, if any. *) +val get_super_if : Clang_ast_t.decl option -> Clang_ast_t.decl option + +val get_impl_decl_info : Clang_ast_t.decl -> Clang_ast_t.obj_c_implementation_decl_info option + +(** Given an objc impl decl info, return the super class's list of decls and + its objc impl decl info. *) +val get_super_impl : + Clang_ast_t.obj_c_implementation_decl_info -> + (Clang_ast_t.decl list * + Clang_ast_t.obj_c_implementation_decl_info) + option + +(** Given an objc impl decl info, return its super class implementation decl *) +val get_super_ObjCImplementationDecl : + Clang_ast_t.obj_c_implementation_decl_info -> Clang_ast_t.decl option + +(** Recursively go up the inheritance hierarchy of a given ObjCInterfaceDecl. + Returns true if the passed in decl is an objc interface decl that's an + eventual descendant of one of the classes passed in. + Ancestors param is a list of strings that represent the class names. + Will short-circuit on NSObject and NSProxy since those are known to be + common base classes. + The list of classes to short-circuit on can be overridden via specifying + the named `blacklist` argument. *) +val is_objc_if_descendant : + ?blacklist:string list -> Clang_ast_t.decl option -> string list -> bool + +val type_ptr_to_objc_interface : Clang_ast_types.t_ptr -> Clang_ast_t.decl option + +(** A class method that returns an instance of the class is a factory method. *) +val is_objc_factory_method : Clang_ast_t.decl -> Clang_ast_t.decl -> bool + +val name_of_decl_ref_opt : Clang_ast_t.decl_ref option -> string option diff --git a/infer/src/clang/cEnum_decl.ml b/infer/src/clang/cEnum_decl.ml index b1eb58e03..fc81e2a89 100644 --- a/infer/src/clang/cEnum_decl.ml +++ b/infer/src/clang/cEnum_decl.ml @@ -12,17 +12,15 @@ open! IStd (** Translate an enumeration declaration by adding it to the tenv and *) (** translating the code and adding it to a fake procdesc *) -open CFrontend_utils - (*Check if the constant is in the map, in which case that means that all the *) (* contants of this enum are in the map, by invariant. Otherwise, add the constant *) (* to the map. *) let add_enum_constant_to_map_if_needed decl_pointer pred_decl_opt = try - ignore (Ast_utils.get_enum_constant_exp decl_pointer); + ignore (CAst_utils.get_enum_constant_exp decl_pointer); true with Not_found -> - Ast_utils.add_enum_constant decl_pointer pred_decl_opt; + CAst_utils.add_enum_constant decl_pointer pred_decl_opt; false (* Add the constants of this enum to the map if they are not in the map yet *) @@ -47,7 +45,7 @@ let enum_decl decl = | EnumDecl (_, _, _, type_ptr, decl_list, _, _) -> add_enum_constants_to_map (IList.rev decl_list); let sil_type = Typ.Tint Typ.IInt in - Ast_utils.update_sil_types_map type_ptr sil_type; + CAst_utils.update_sil_types_map type_ptr sil_type; sil_type | _ -> assert false diff --git a/infer/src/clang/cField_decl.ml b/infer/src/clang/cField_decl.ml index 7aac306b7..49eb0e827 100644 --- a/infer/src/clang/cField_decl.ml +++ b/infer/src/clang/cField_decl.ml @@ -11,8 +11,6 @@ open! IStd (** Utility module to retrieve fields of structs of classes *) -open CFrontend_utils - module L = Logging type field_type = Ident.fieldname * Typ.t * (Annot.t * bool) list @@ -23,7 +21,7 @@ let rec get_fields_super_classes tenv super_class = | None -> [] | Some { fields; supers = super_class :: _ } -> let sc_fields = get_fields_super_classes tenv super_class in - General_utils.append_no_duplicates_fields fields sc_fields + CGeneral_utils.append_no_duplicates_fields fields sc_fields | Some { fields } -> fields let fields_superclass tenv interface_decl_info ck = @@ -31,7 +29,7 @@ let fields_superclass tenv interface_decl_info ck = | Some dr -> (match dr.Clang_ast_t.dr_name with | Some sc -> - let classname = CType.mk_classname (Ast_utils.get_qualified_name sc) ck in + let classname = CType.mk_classname (CAst_utils.get_qualified_name sc) ck in get_fields_super_classes tenv classname | _ -> []) | _ -> [] @@ -43,7 +41,7 @@ let build_sil_field type_ptr_to_sil_type tenv field_name type_ptr prop_attribute | Typ.Tptr (_, Typ.Pk_objc_weak) -> [Config.weak] | Typ.Tptr (_, Typ.Pk_objc_unsafe_unretained) -> [Config.unsafe_unret] | _ -> [] in - let fname = General_utils.mk_class_field_name field_name in + let fname = CGeneral_utils.mk_class_field_name field_name in let typ = type_ptr_to_sil_type tenv type_ptr in let item_annotations = match prop_atts with | [] -> @@ -61,12 +59,12 @@ let rec get_fields type_ptr_to_sil_type tenv curr_class decl_list = let fields = get_fields type_ptr_to_sil_type tenv curr_class decl_list' in let field_tuple = build_sil_field type_ptr_to_sil_type tenv name_info qt.Clang_ast_t.qt_type_ptr attributes in - General_utils.append_no_duplicates_fields [field_tuple] fields in + CGeneral_utils.append_no_duplicates_fields [field_tuple] fields in match decl_list with | [] -> [] | ObjCPropertyDecl (_, _, obj_c_property_decl_info) :: decl_list' -> (let ivar_decl_ref = obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl in - match Ast_utils.get_decl_opt_with_decl_ref ivar_decl_ref with + match CAst_utils.get_decl_opt_with_decl_ref ivar_decl_ref with | Some (ObjCIvarDecl (_, name_info, type_ptr, _, _)) -> let attributes = obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes in add_field name_info type_ptr attributes decl_list' @@ -83,7 +81,7 @@ let add_missing_fields tenv class_name ck missing_fields = let class_tn_name = Typename.TN_csu (Csu.Class ck, mang_name) in match Tenv.lookup tenv class_tn_name with | Some ({ fields } as struct_typ) -> - let new_fields = General_utils.append_no_duplicates_fields fields missing_fields in + let new_fields = CGeneral_utils.append_no_duplicates_fields fields missing_fields in ignore (Tenv.mk_struct tenv ~default:struct_typ ~fields:new_fields ~statics:[] class_tn_name); Logging.out_debug " Updating info for class '%s' in tenv\n" class_name | _ -> () @@ -96,8 +94,8 @@ let modelled_field class_name_info = let modelled_field_in_class res (class_name, field_name, typ) = if class_name = class_name_info.Clang_ast_t.ni_name then let class_name_qualified = class_name_info.Clang_ast_t.ni_qual_name in - let field_name_qualified = Ast_utils.make_qual_name_decl class_name_qualified field_name in - let name = General_utils.mk_class_field_name field_name_qualified in + let field_name_qualified = CAst_utils.make_qual_name_decl class_name_qualified field_name in + let name = CGeneral_utils.mk_class_field_name field_name_qualified in (name, typ, Annot.Item.empty) :: res else res in IList.fold_left modelled_field_in_class [] modelled_fields_in_classes diff --git a/infer/src/clang/cField_decl.mli b/infer/src/clang/cField_decl.mli index 94425e348..366215f15 100644 --- a/infer/src/clang/cField_decl.mli +++ b/infer/src/clang/cField_decl.mli @@ -10,17 +10,16 @@ open! IStd (** Utility module to retrieve fields of structs of classes *) -open CFrontend_utils type field_type = Ident.fieldname * Typ.t * (Annot.t * bool) list -val get_fields : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> CContext.curr_class -> +val get_fields : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> CContext.curr_class -> Clang_ast_t.decl list -> field_type list val fields_superclass : Tenv.t -> Clang_ast_t.obj_c_interface_decl_info -> Csu.class_kind -> field_type list -val build_sil_field : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.named_decl_info -> +val build_sil_field : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.named_decl_info -> Clang_ast_t.type_ptr -> Clang_ast_t.property_attribute list -> field_type val add_missing_fields : Tenv.t -> string -> Csu.class_kind -> field_type list -> unit diff --git a/infer/src/clang/cFrontend.ml b/infer/src/clang/cFrontend.ml index 2467edd82..fd9148cfc 100644 --- a/infer/src/clang/cFrontend.ml +++ b/infer/src/clang/cFrontend.ml @@ -12,8 +12,6 @@ open! IStd module L = Logging -open CFrontend_utils - module rec CTransImpl : CModule_type.CTranslation = CTrans.CTrans_funct(CFrontend_declImpl) and CFrontend_declImpl : CModule_type.CFrontend = @@ -37,7 +35,7 @@ let compute_icfg trans_unit_ctx tenv ast = let init_global_state_capture () = Ident.NameGenerator.reset (); CFrontend_config.global_translation_unit_decls := []; - CFrontend_utils.General_utils.reset_block_counter () + CGeneral_utils.reset_block_counter () let do_source_file translation_unit_context ast = let tenv = Tenv.create () in @@ -62,7 +60,7 @@ let do_source_file translation_unit_context ast = (*Logging.out "Tenv %a@." Sil.pp_tenv tenv;*) (* Printing.print_tenv tenv; *) (*Printing.print_procedures cfg; *) - General_utils.sort_fields_tenv tenv; + CGeneral_utils.sort_fields_tenv tenv; Tenv.store_to_file tenv_file tenv; if Config.stats_mode then Cfg.check_cfg_connectedness cfg; if Config.stats_mode diff --git a/infer/src/clang/cFrontend_checkers.ml b/infer/src/clang/cFrontend_checkers.ml index 0b5299f25..ad2c4bd78 100644 --- a/infer/src/clang/cFrontend_checkers.ml +++ b/infer/src/clang/cFrontend_checkers.ml @@ -9,7 +9,6 @@ open! IStd -open CFrontend_utils (* To create a new checker you should: *) (* 1. Define a checker function, say my_checker, in this module. *) (* my_checker should define: *) @@ -83,7 +82,7 @@ let ivar_name an = | CTL.Stmt (ObjCIvarRefExpr (_, _, _, rei)) -> let dr_ref = rei.ovrei_decl_ref in let ivar_pointer = dr_ref.dr_decl_pointer in - (match Ast_utils.get_decl ivar_pointer with + (match CAst_utils.get_decl ivar_pointer with | Some (ObjCIvarDecl (_, named_decl_info, _, _, _)) -> named_decl_info.Clang_ast_t.ni_name | _ -> "") diff --git a/infer/src/clang/cFrontend_checkers_main.ml b/infer/src/clang/cFrontend_checkers_main.ml index 3ac253988..7e649cb81 100644 --- a/infer/src/clang/cFrontend_checkers_main.ml +++ b/infer/src/clang/cFrontend_checkers_main.ml @@ -8,7 +8,6 @@ *) open! IStd -open CFrontend_utils open Lexing open Ctl_lexer @@ -54,7 +53,7 @@ let rec do_frontend_checks_stmt (context:CLintersContext.context) stmt = IList.iter (do_frontend_checks_decl context') [decl] | _ -> ()); do_frontend_checks_stmt context' stmt in - let stmts = Ast_utils.get_stmts_from_stmt stmt in + let stmts = CAst_utils.get_stmts_from_stmt stmt in IList.iter (do_all_checks_on_stmts) stmts and do_frontend_checks_decl (context: CLintersContext.context) decl = @@ -76,11 +75,11 @@ and do_frontend_checks_decl (context: CLintersContext.context) decl = let if_decl_opt = (match context.current_objc_impl with | Some ObjCImplementationDecl (_, _, _, _, impl_decl_info) -> - Ast_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface + CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface | _ -> None) in let is_factory_method = (match if_decl_opt with - | Some if_decl -> Ast_utils.is_objc_factory_method if_decl decl + | Some if_decl -> CAst_utils.is_objc_factory_method if_decl decl | _ -> false) in let context' = {context with CLintersContext.current_method = Some decl; diff --git a/infer/src/clang/cFrontend_decl.ml b/infer/src/clang/cFrontend_decl.ml index 7adb26172..3f866919c 100644 --- a/infer/src/clang/cFrontend_decl.ml +++ b/infer/src/clang/cFrontend_decl.ml @@ -13,8 +13,6 @@ open! IStd module L = Logging -open CFrontend_utils - module CFrontend_decl_funct(T: CModule_type.CTranslation) : CModule_type.CFrontend = struct let model_exists procname = @@ -91,14 +89,14 @@ struct let process_property_implementation cfg trans_unit_ctx obj_c_property_impl_decl_info = let property_decl_opt = obj_c_property_impl_decl_info.Clang_ast_t.opidi_property_decl in - match Ast_utils.get_decl_opt_with_decl_ref property_decl_opt with + match CAst_utils.get_decl_opt_with_decl_ref property_decl_opt with | Some ObjCPropertyDecl (_, _, obj_c_property_decl_info) -> let ivar_decl_ref = obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl in - (match Ast_utils.get_decl_opt_with_decl_ref ivar_decl_ref with + (match CAst_utils.get_decl_opt_with_decl_ref ivar_decl_ref with | Some ObjCIvarDecl (_, named_decl_info, _, _, _) -> - let field_name = General_utils.mk_class_field_name named_decl_info in + let field_name = CGeneral_utils.mk_class_field_name named_decl_info in let process_accessor pointer ~getter = - (match Ast_utils.get_decl_opt_with_decl_ref pointer with + (match CAst_utils.get_decl_opt_with_decl_ref pointer with | Some (ObjCMethodDecl (decl_info, _, _) as d) -> let source_range = decl_info.Clang_ast_t.di_source_range in let loc = @@ -108,7 +106,7 @@ struct Some (ProcAttributes.Objc_getter field_name) else Some (ProcAttributes.Objc_setter field_name) in - let procname = General_utils.procname_of_decl trans_unit_ctx d in + let procname = CGeneral_utils.procname_of_decl trans_unit_ctx d in let attrs = { (ProcAttributes.default procname Config.Clang) with loc = loc; objc_accessor = property_accessor; } in @@ -132,7 +130,8 @@ struct | ObjCIvarDecl _ | ObjCPropertyDecl _ -> () | _ -> Logging.out - "\nWARNING: found Method Declaration '%s' skipped. NEED TO BE FIXED\n\n" (Ast_utils.string_of_decl dec); + "\nWARNING: found Method Declaration '%s' skipped. NEED TO BE FIXED\n\n" + (CAst_utils.string_of_decl dec); () let process_methods trans_unit_ctx tenv cg cfg curr_class decl_list = @@ -221,26 +220,26 @@ struct function_decl trans_unit_ctx tenv cfg cg dec None | ObjCInterfaceDecl(_, name_info, decl_list, _, oi_decl_info) -> - let name = Ast_utils.get_qualified_name name_info in + let name = CAst_utils.get_qualified_name name_info in let curr_class = ObjcInterface_decl.get_curr_class name oi_decl_info in ignore (ObjcInterface_decl.interface_declaration CType_decl.type_ptr_to_sil_type tenv dec); process_methods trans_unit_ctx tenv cg cfg curr_class decl_list | ObjCProtocolDecl(_, name_info, decl_list, _, _) -> - let name = Ast_utils.get_qualified_name name_info in + let name = CAst_utils.get_qualified_name name_info in let curr_class = CContext.ContextProtocol name in ignore (ObjcProtocol_decl.protocol_decl CType_decl.type_ptr_to_sil_type tenv dec); process_methods trans_unit_ctx tenv cg cfg curr_class decl_list | ObjCCategoryDecl(_, name_info, decl_list, _, ocdi) -> - let name = Ast_utils.get_qualified_name name_info in + let name = CAst_utils.get_qualified_name name_info in let curr_class = ObjcCategory_decl.get_curr_class_from_category_decl name ocdi in ignore (ObjcCategory_decl.category_decl CType_decl.type_ptr_to_sil_type tenv dec); process_methods trans_unit_ctx tenv cg cfg curr_class decl_list | ObjCCategoryImplDecl(_, name_info, decl_list, _, ocidi) -> - let name = Ast_utils.get_qualified_name name_info in + let name = CAst_utils.get_qualified_name name_info in let curr_class = ObjcCategory_decl.get_curr_class_from_category_impl name ocidi in ignore (ObjcCategory_decl.category_impl_decl CType_decl.type_ptr_to_sil_type tenv dec); process_methods trans_unit_ctx tenv cg cfg curr_class decl_list; @@ -259,14 +258,14 @@ struct | CXXDestructorDecl (decl_info, _, _, _, _) -> (* di_parent_pointer has pointer to lexical context such as class.*) let parent_ptr = Option.value_exn decl_info.Clang_ast_t.di_parent_pointer in - let class_decl = Ast_utils.get_decl parent_ptr in + let class_decl = CAst_utils.get_decl parent_ptr in (match class_decl with | Some (CXXRecordDecl _) | Some (ClassTemplateSpecializationDecl _) when Config.cxx -> let curr_class = CContext.ContextClsDeclPtr parent_ptr in process_methods trans_unit_ctx tenv cg cfg curr_class [dec] | Some dec -> - Logging.out "Methods of %s skipped\n" (Ast_utils.string_of_decl dec) + Logging.out "Methods of %s skipped\n" (CAst_utils.string_of_decl dec) | None -> ()) | VarDecl (decl_info, named_decl_info, qt, ({ vdi_is_global; vdi_init_expr } as vdi)) when vdi_is_global && Option.is_some vdi_init_expr -> @@ -275,13 +274,13 @@ struct let procname = (* create the corresponding global variable to get the right pname for its initializer *) - let global = General_utils.mk_sil_global_var trans_unit_ctx named_decl_info vdi qt in + let global = CGeneral_utils.mk_sil_global_var trans_unit_ctx named_decl_info vdi qt in (* safe to Option.get because it's a global *) Option.value_exn (Pvar.get_initializer_pname global) in let ms = CMethod_signature.make_ms procname [] Ast_expressions.create_void_type [] decl_info.Clang_ast_t.di_source_range false trans_unit_ctx.CFrontend_config.lang None None None in - let stmt_info = { si_pointer = Ast_utils.get_fresh_pointer (); + let stmt_info = { si_pointer = CAst_utils.get_fresh_pointer (); si_source_range = decl_info.di_source_range } in let body = Clang_ast_t.DeclStmt (stmt_info, [], [dec]) in ignore (CMethod_trans.create_local_procdesc trans_unit_ctx cfg tenv ms [body] [] false); diff --git a/infer/src/clang/cFrontend_errors.ml b/infer/src/clang/cFrontend_errors.ml index f15704a2e..a17ef2917 100644 --- a/infer/src/clang/cFrontend_errors.ml +++ b/infer/src/clang/cFrontend_errors.ml @@ -9,8 +9,6 @@ open! IStd -open CFrontend_utils - let single_to_multi checker = fun ctx an -> let condition, issue_desc_opt = checker ctx an in @@ -178,7 +176,7 @@ let expand_checkers checkers = let get_err_log translation_unit_context method_decl_opt = let procname = match method_decl_opt with - | Some method_decl -> General_utils.procname_of_decl translation_unit_context method_decl + | Some method_decl -> CGeneral_utils.procname_of_decl translation_unit_context method_decl | None -> Procname.Linters_dummy_method in LintIssues.get_err_log procname @@ -192,7 +190,7 @@ let log_frontend_issue translation_unit_context method_decl_opt key issue_desc = let exn = Exceptions.Frontend_warning (name, err_desc, __POS__) in let trace = [ Errlog.make_trace_element 0 issue_desc.CIssue.loc "" [] ] in let err_kind = issue_desc.CIssue.severity in - let method_name = Ast_utils.full_name_of_decl_opt method_decl_opt in + let method_name = CAst_utils.full_name_of_decl_opt method_decl_opt in let key = Hashtbl.hash (key ^ method_name) in Reporting.log_issue_from_errlog err_kind errlog exn ~loc ~ltr:trace ~node_id:(0, key) @@ -207,8 +205,8 @@ let fill_issue_desc_info_and_log context an key issue_desc loc = (* Calls the set of hard coded checkers (if any) *) let invoke_set_of_hard_coded_checkers_an an context = let checkers, key = match an with - | CTL.Decl dec -> decl_checkers_list, Ast_utils.generate_key_decl dec - | CTL.Stmt st -> stmt_checkers_list, Ast_utils.generate_key_stmt st in + | CTL.Decl dec -> decl_checkers_list, CAst_utils.generate_key_decl dec + | CTL.Stmt st -> stmt_checkers_list, CAst_utils.generate_key_stmt st in IList.iter (fun checker -> let condition, issue_desc_list = checker context an in if CTL.eval_formula condition an context then @@ -222,8 +220,8 @@ let invoke_set_of_hard_coded_checkers_an an context = (* Calls the set of checkers parsed from files (if any) *) let invoke_set_of_parsed_checkers_an an context = let key = match an with - | CTL.Decl dec -> Ast_utils.generate_key_decl dec - | CTL.Stmt st -> Ast_utils.generate_key_stmt st in + | CTL.Decl dec -> CAst_utils.generate_key_decl dec + | CTL.Stmt st -> CAst_utils.generate_key_stmt st in IList.iter (fun (condition, issue_desc) -> if CIssue.should_run_check issue_desc.CIssue.mode && CTL.eval_formula condition an context then @@ -253,7 +251,7 @@ let run_translation_unit_checker (context: CLintersContext.context) dec = let issue_desc_list = checker context dec in IList.iter (fun issue_desc -> if (CIssue.should_run_check issue_desc.CIssue.mode) then - let key = Ast_utils.generate_key_decl dec in + let key = CAst_utils.generate_key_decl dec in log_frontend_issue context.CLintersContext.translation_unit_context context.CLintersContext.current_method key issue_desc ) issue_desc_list) translation_unit_checkers_list diff --git a/infer/src/clang/cFrontend_utils.ml b/infer/src/clang/cFrontend_utils.ml deleted file mode 100644 index abeba5c23..000000000 --- a/infer/src/clang/cFrontend_utils.ml +++ /dev/null @@ -1,781 +0,0 @@ -(* - * Copyright (c) 2013 - 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. - *) - -open! IStd - -(** Module for utility functions for the whole frontend. Includes functions for transformations of - ast nodes and general utility functions such as functions on lists *) - -module L = Logging -module F = Format - -module Ast_utils = -struct - type type_ptr_to_sil_type = Tenv.t -> Clang_ast_t.type_ptr -> Typ.t - - let string_of_decl decl = - let name = Clang_ast_proj.get_decl_kind_string decl in - let info = Clang_ast_proj.get_decl_tuple decl in - Printf.sprintf "<\"%s\"> '%d'" name info.Clang_ast_t.di_pointer - - let string_of_unary_operator_kind = function - | `PostInc -> "PostInc" - | `PostDec -> "PostDec" - | `PreInc -> "PreInc" - | `PreDec -> "PreDec" - | `AddrOf -> "AddrOf" - | `Deref -> "Deref" - | `Plus -> "Plus" - | `Minus -> "Minus" - | `Not -> "Not" - | `LNot -> "LNot" - | `Real -> "Real" - | `Imag -> "Imag" - | `Extension -> "Extension" - | `Coawait -> "Coawait" - - let string_of_stmt stmt = - let name = Clang_ast_proj.get_stmt_kind_string stmt in - let info, _ = Clang_ast_proj.get_stmt_tuple stmt in - Printf.sprintf "<\"%s\"> '%d'" name info.Clang_ast_t.si_pointer - - let get_stmts_from_stmt stmt = - let open Clang_ast_t in - match stmt with - | OpaqueValueExpr (_, lstmt, _, opaque_value_expr_info) -> - (match opaque_value_expr_info.Clang_ast_t.ovei_source_expr with - | Some stmt -> lstmt @ [stmt] - | _ -> lstmt) - (* given that this has not been translated, looking up for variables *) - (* inside leads to inconsistencies *) - | ObjCAtCatchStmt _ -> - [] - | _ -> snd (Clang_ast_proj.get_stmt_tuple stmt) - - let fold_qual_name qual_name_list = - match qual_name_list with - | [] -> "" - | name :: quals -> - let s = (IList.fold_right (fun el res -> res ^ el ^ "::") quals "") ^ name in - let no_slash_space = Str.global_replace (Str.regexp "[/ ]") "_" s in - no_slash_space - - let get_qualified_name name_info = - fold_qual_name name_info.Clang_ast_t.ni_qual_name - - let get_unqualified_name name_info = - let name = match name_info.Clang_ast_t.ni_qual_name with - | name :: _ -> name - | [] -> name_info.Clang_ast_t.ni_name in - fold_qual_name [name] - - let get_class_name_from_member member_name_info = - match member_name_info.Clang_ast_t.ni_qual_name with - | _ :: class_qual_list -> fold_qual_name class_qual_list - | [] -> assert false - - let make_name_decl name = { - Clang_ast_t.ni_name = name; - ni_qual_name = [name]; - } - - let make_qual_name_decl class_name_quals name = { - Clang_ast_t.ni_name = name; - ni_qual_name = name :: class_name_quals; - } - - let property_name property_impl_decl_info = - let no_property_name = make_name_decl "WARNING_NO_PROPERTY_NAME" in - match property_impl_decl_info.Clang_ast_t.opidi_property_decl with - | Some decl_ref -> - (match decl_ref.Clang_ast_t.dr_name with - | Some n -> n - | _ -> no_property_name) - | None -> no_property_name - - let generated_ivar_name property_name = - match property_name.Clang_ast_t.ni_qual_name with - | [name; class_name] -> - let ivar_name = "_" ^ name in - { Clang_ast_t.ni_name = ivar_name; - ni_qual_name = [ivar_name; class_name] - } - | _ -> make_name_decl property_name.Clang_ast_t.ni_name - - let compare_property_attribute = - [%compare: [ - `Readonly | `Assign | `Readwrite | `Retain | `Copy | `Nonatomic | `Atomic - | `Weak | `Strong | `Unsafe_unretained | `ExplicitGetter | `ExplicitSetter - ]] - - let equal_property_attribute att1 att2 = - compare_property_attribute att1 att2 = 0 - - let get_memory_management_attributes () = - [`Assign; `Retain; `Copy; `Weak; `Strong; `Unsafe_unretained] - - let is_retain attribute_opt = - match attribute_opt with - | Some attribute -> - attribute = `Retain || attribute = `Strong - | _ -> false - - let is_copy attribute_opt = - match attribute_opt with - | Some attribute -> - attribute = `Copy - | _ -> false - - let name_opt_of_name_info_opt name_info_opt = - match name_info_opt with - | Some name_info -> Some (get_qualified_name name_info) - | None -> None - - let pointer_counter = ref 0 - - let get_fresh_pointer () = - pointer_counter := !pointer_counter + 1; - let internal_pointer = -(!pointer_counter) in - internal_pointer - - let get_invalid_pointer () = - CFrontend_config.invalid_pointer - - let type_from_unary_expr_or_type_trait_expr_info info = - match info.Clang_ast_t.uttei_type_ptr with - | Some tp -> Some tp - | None -> None - - let get_decl decl_ptr = - try - Some (Clang_ast_main.PointerMap.find decl_ptr !CFrontend_config.pointer_decl_index) - with Not_found -> Logging.out "decl with pointer %d not found\n" decl_ptr; None - - let get_decl_opt decl_ptr_opt = - match decl_ptr_opt with - | Some decl_ptr -> get_decl decl_ptr - | None -> None - - let get_stmt stmt_ptr = - try - Some (Clang_ast_main.PointerMap.find stmt_ptr !CFrontend_config.pointer_stmt_index) - with Not_found -> Logging.out "stmt with pointer %d not found\n" stmt_ptr; None - - let get_stmt_opt stmt_ptr_opt = - match stmt_ptr_opt with - | Some stmt_ptr -> get_stmt stmt_ptr - | None -> None - - let get_decl_opt_with_decl_ref decl_ref_opt = - match decl_ref_opt with - | Some decl_ref -> get_decl decl_ref.Clang_ast_t.dr_decl_pointer - | None -> None - - let get_property_of_ivar decl_ptr = - try - Some (Clang_ast_main.PointerMap.find decl_ptr !CFrontend_config.ivar_to_property_index) - with Not_found -> Logging.out "property with pointer %d not found\n" decl_ptr; None - - let update_sil_types_map type_ptr sil_type = - CFrontend_config.sil_types_map := - Clang_ast_types.TypePointerMap.add type_ptr sil_type !CFrontend_config.sil_types_map - - let update_enum_map enum_constant_pointer sil_exp = - let open Clang_ast_main in - let (predecessor_pointer_opt, _) = - try PointerMap.find enum_constant_pointer !CFrontend_config.enum_map - with Not_found -> assert false in - let enum_map_value = (predecessor_pointer_opt, Some sil_exp) in - CFrontend_config.enum_map := - PointerMap.add enum_constant_pointer enum_map_value !CFrontend_config.enum_map - - let add_enum_constant enum_constant_pointer predecessor_pointer_opt = - let enum_map_value = (predecessor_pointer_opt, None) in - CFrontend_config.enum_map := - Clang_ast_main.PointerMap.add enum_constant_pointer enum_map_value !CFrontend_config.enum_map - - let get_enum_constant_exp enum_constant_pointer = - Clang_ast_main.PointerMap.find enum_constant_pointer !CFrontend_config.enum_map - - let get_type type_ptr = - try - (* There is chance for success only if type_ptr is in fact clang pointer *) - (let raw_ptr = Clang_ast_types.type_ptr_to_clang_pointer type_ptr in - try - Some (Clang_ast_main.PointerMap.find raw_ptr !CFrontend_config.pointer_type_index) - with Not_found -> Logging.out "type with pointer %d not found\n" raw_ptr; None) - with Clang_ast_types.Not_Clang_Pointer -> - (* otherwise, function fails *) - let type_str = Clang_ast_types.type_ptr_to_string type_ptr in - Logging.out "type %s is not clang pointer\n" type_str; - None - - let get_desugared_type type_ptr = - let typ_opt = get_type type_ptr in - match typ_opt with - | Some typ -> - let type_info = Clang_ast_proj.get_type_tuple typ in - (match type_info.Clang_ast_t.ti_desugared_type with - | Some ptr -> get_type ptr - | _ -> typ_opt) - | _ -> typ_opt - - let get_decl_from_typ_ptr typ_ptr = - let typ_opt = get_desugared_type typ_ptr in - let typ = match typ_opt with Some t -> t | _ -> assert false in - match typ with - | Clang_ast_t.RecordType (_, decl_ptr) - | Clang_ast_t.ObjCInterfaceType (_, decl_ptr) -> get_decl decl_ptr - | _ -> None - - (*TODO take the attributes into account too. To be done after we get the attribute's arguments. *) - let is_type_nonnull type_ptr = - let open Clang_ast_t in - match get_type type_ptr with - | Some AttributedType (_, attr_info) -> attr_info.ati_attr_kind = `Nonnull - | _ -> false - - let is_type_nullable type_ptr = - let open Clang_ast_t in - match get_type type_ptr with - | Some AttributedType (_, attr_info) -> attr_info.ati_attr_kind = `Nullable - | _ -> false - - let string_of_type_ptr type_ptr = Clang_ast_j.string_of_type_ptr type_ptr - - let name_of_typedef_type_info {Clang_ast_t.tti_decl_ptr} = - match get_decl tti_decl_ptr with - | Some TypedefDecl (_, name_decl_info, _, _, _) -> - get_qualified_name name_decl_info - | _ -> "" - - let name_opt_of_typedef_type_ptr type_ptr = - match get_type type_ptr with - | Some Clang_ast_t.TypedefType (_, typedef_type_info) -> - Some (name_of_typedef_type_info typedef_type_info) - | _ -> None - - let string_of_qual_type {Clang_ast_t.qt_type_ptr; qt_is_const} = - Printf.sprintf "%s%s" (if qt_is_const then "is_const " else "") (string_of_type_ptr qt_type_ptr) - - let add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt fail_if_not_found = - match decl_ref_opt with (* translate interface first if found *) - | Some dr -> - ignore (type_ptr_to_sil_type tenv (`DeclPtr dr.Clang_ast_t.dr_decl_pointer)); - | _ -> if fail_if_not_found then assert false else () - - let add_type_from_decl_ref_list type_ptr_to_sil_type tenv decl_ref_list = - let add_elem dr = - ignore (type_ptr_to_sil_type tenv (`DeclPtr dr.Clang_ast_t.dr_decl_pointer)) in - IList.iter add_elem decl_ref_list - - let get_function_decl_with_body decl_ptr = - let open Clang_ast_t in - let decl_opt = get_decl decl_ptr in - let decl_ptr' = match decl_opt with - | Some (FunctionDecl (_, _, _, fdecl_info)) - | Some (CXXMethodDecl (_, _, _, fdecl_info, _)) - | Some (CXXConstructorDecl (_, _, _, fdecl_info, _)) - | Some (CXXConversionDecl (_, _, _, fdecl_info, _)) - | Some (CXXDestructorDecl (_, _, _, fdecl_info, _)) -> - fdecl_info.Clang_ast_t.fdi_decl_ptr_with_body - | _ -> Some decl_ptr in - if decl_ptr' = (Some decl_ptr) then decl_opt - else get_decl_opt decl_ptr' - - let get_info_from_decl_ref decl_ref = - let name_info = match decl_ref.Clang_ast_t.dr_name with Some ni -> ni | _ -> assert false in - let decl_ptr = decl_ref.Clang_ast_t.dr_decl_pointer in - let type_ptr = match decl_ref.Clang_ast_t.dr_type_ptr with Some tp -> tp | _ -> assert false in - name_info, decl_ptr, type_ptr - - (* st |= EF (atomic_pred param) *) - let rec exists_eventually_st atomic_pred param st = - if atomic_pred param st then true - else - let _, st_list = Clang_ast_proj.get_stmt_tuple st in - IList.exists (exists_eventually_st atomic_pred param) st_list - - let is_syntactically_global_var decl = - match decl with - | Clang_ast_t.VarDecl (_, _ ,_, vdi) -> - vdi.vdi_is_global && not vdi.vdi_is_static_local - | _ -> false - - let is_const_expr_var decl = - match decl with - | Clang_ast_t.VarDecl (_, _ ,_, vdi) -> vdi.vdi_is_const_expr - | _ -> false - - let is_ptr_to_objc_class typ class_name = - match typ with - | Some Clang_ast_t.ObjCObjectPointerType (_, {Clang_ast_t.qt_type_ptr}) -> - (match get_desugared_type qt_type_ptr with - | Some ObjCInterfaceType (_, ptr) -> - (match get_decl ptr with - | Some ObjCInterfaceDecl (_, ndi, _, _, _) -> - String.compare ndi.ni_name class_name = 0 - | _ -> false) - | _ -> false) - | _ -> false - - let full_name_of_decl_opt decl_opt = - match decl_opt with - | Some decl -> - (match Clang_ast_proj.get_named_decl_tuple decl with - | Some (_, name_info) -> get_qualified_name name_info - | None -> "") - | None -> "" - - (* Generates a unique number for each variant of a type. *) - let get_tag ast_item = - let item_rep = Obj.repr ast_item in - if Obj.is_block item_rep then - Obj.tag item_rep - else -(Obj.obj item_rep) - - (* Generates a key for a statement based on its sub-statements and the statement tag. *) - let rec generate_key_stmt stmt = - let tag_str = string_of_int (get_tag stmt) in - let _, stmts = Clang_ast_proj.get_stmt_tuple stmt in - let tags = IList.map generate_key_stmt stmts in - let buffer = Buffer.create 16 in - let tags = tag_str :: tags in - IList.iter (fun tag -> Buffer.add_string buffer tag) tags; - Buffer.contents buffer - - (* Generates a key for a declaration based on its name and the declaration tag. *) - let generate_key_decl decl = - let buffer = Buffer.create 16 in - let name = full_name_of_decl_opt (Some decl) in - Buffer.add_string buffer (string_of_int (get_tag decl)); - Buffer.add_string buffer name; - Buffer.contents buffer - - let rec get_super_if decl = - match decl with - | Some Clang_ast_t.ObjCImplementationDecl(_, _, _, _, impl_decl_info) -> - (* Try getting the super ref through the impl info, and fall back to - getting the if decl first and getting the super ref through it. *) - let super_ref = get_decl_opt_with_decl_ref impl_decl_info.oidi_super in - if Option.is_some super_ref then - super_ref - else - get_super_if (get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface) - | Some Clang_ast_t.ObjCInterfaceDecl(_, _, _, _, interface_decl_info) -> - get_decl_opt_with_decl_ref interface_decl_info.otdi_super - | _ -> None - - let get_super_impl impl_decl_info = - let objc_interface_decl_current = - get_decl_opt_with_decl_ref - impl_decl_info.Clang_ast_t.oidi_class_interface in - let objc_interface_decl_super = get_super_if objc_interface_decl_current in - let objc_implementation_decl_super = - match objc_interface_decl_super with - | Some ObjCInterfaceDecl(_, _, _, _, interface_decl_info) -> - get_decl_opt_with_decl_ref - interface_decl_info.otdi_implementation - | _ -> None in - match objc_implementation_decl_super with - | Some ObjCImplementationDecl(_, _, decl_list, _, impl_decl_info) -> - Some (decl_list, impl_decl_info) - | _ -> None - - let get_super_ObjCImplementationDecl impl_decl_info = - let objc_interface_decl_current = - get_decl_opt_with_decl_ref - impl_decl_info.Clang_ast_t.oidi_class_interface in - let objc_interface_decl_super = get_super_if objc_interface_decl_current in - let objc_implementation_decl_super = - match objc_interface_decl_super with - | Some ObjCInterfaceDecl(_, _, _, _, interface_decl_info) -> - get_decl_opt_with_decl_ref - interface_decl_info.otdi_implementation - | _ -> None in - objc_implementation_decl_super - - let get_impl_decl_info dec = - match dec with - | Clang_ast_t.ObjCImplementationDecl (_, _, _, _, idi) -> Some idi - | _ -> None - - let default_blacklist = - let open CFrontend_config in - [nsobject_cl; nsproxy_cl] - - let rec is_objc_if_descendant ?(blacklist = default_blacklist) if_decl ancestors = - (* List of ancestors to check for and list of classes to short-circuit to - false can't intersect *) - if not String.Set.(is_empty (inter (of_list blacklist) (of_list ancestors))) then - failwith "Blacklist and ancestors must be mutually exclusive." - else - match if_decl with - | Some Clang_ast_t.ObjCInterfaceDecl (_, ndi, _, _, _) -> - let in_list some_list = - IList.mem String.equal ndi.Clang_ast_t.ni_name some_list in - not (in_list blacklist) - && (in_list ancestors - || is_objc_if_descendant ~blacklist:blacklist (get_super_if if_decl) ancestors) - | _ -> false - - let rec type_ptr_to_objc_interface type_ptr = - let typ_opt = get_desugared_type type_ptr in - match (typ_opt : Clang_ast_t.c_type option) with - | Some ObjCInterfaceType (_, decl_ptr) -> get_decl decl_ptr - | Some ObjCObjectPointerType (_, (inner_qual_type: Clang_ast_t.qual_type)) -> - type_ptr_to_objc_interface inner_qual_type.qt_type_ptr - | Some FunctionProtoType (_, function_type_info, _) - | Some FunctionNoProtoType (_, function_type_info) -> - type_ptr_to_objc_interface function_type_info.Clang_ast_t.fti_return_type - | _ -> None - - - let if_decl_to_di_pointer_opt if_decl = - match if_decl with - | Clang_ast_t.ObjCInterfaceDecl (if_decl_info, _, _, _, _) -> - Some if_decl_info.di_pointer - | _ -> None - - let is_instance_type type_ptr = - match name_opt_of_typedef_type_ptr type_ptr with - | Some name -> name = "instancetype" - | None -> false - - let return_type_matches_class_type rtp type_decl_pointer = - if is_instance_type rtp then - true - else - let return_type_decl_opt = type_ptr_to_objc_interface rtp in - let return_type_decl_pointer_opt = - Option.map ~f:if_decl_to_di_pointer_opt return_type_decl_opt in - (Some type_decl_pointer) = return_type_decl_pointer_opt - - let is_objc_factory_method if_decl meth_decl = - let if_type_decl_pointer = if_decl_to_di_pointer_opt if_decl in - match meth_decl with - | Clang_ast_t.ObjCMethodDecl (_, _, omdi) -> - (not omdi.omdi_is_instance_method) && - (return_type_matches_class_type omdi.omdi_result_type if_type_decl_pointer) - | _ -> false - - let name_of_decl_ref_opt (decl_ref_opt: Clang_ast_t.decl_ref option) = - match decl_ref_opt with - | Some decl_ref -> - (match decl_ref.dr_name with - | Some named_decl_info -> Some named_decl_info.ni_name - | _ -> None) - | _ -> None - -(* - let rec getter_attribute_opt attributes = - match attributes with - | [] -> None - | attr:: rest -> - match attr with - | `Getter getter -> getter.Clang_ast_t.dr_name - | _ -> (getter_attribute_opt rest) - - let rec setter_attribute_opt attributes = - match attributes with - | [] -> None - | attr:: rest -> - match attr with - | `Setter setter -> setter.Clang_ast_t.dr_name - | _ -> (setter_attribute_opt rest) -*) - -end - -(* Global counter for anonymous block*) -let block_counter = ref 0 - -(* Returns a fresh index for a new anonymous block *) -let get_fresh_block_index () = - block_counter := !block_counter +1; - !block_counter - -module General_utils = -struct - - type var_info = Clang_ast_t.decl_info * Clang_ast_t.qual_type * Clang_ast_t.var_decl_info * bool - - let rec swap_elements_list l = - match l with - | el1:: el2:: rest -> - el2:: el1:: (swap_elements_list rest) - | [] -> [] - | _ -> assert false - - let rec string_from_list l = - match l with - | [] -> "" - | [item] -> item - | item:: l' -> item^" "^(string_from_list l') - - let rec append_no_duplicates eq list1 list2 = - match list2 with - | el:: rest2 -> - if (IList.mem eq el list1) then - (append_no_duplicates eq list1 rest2) - else (append_no_duplicates eq list1 rest2)@[el] - | [] -> list1 - - let append_no_duplicates_csu list1 list2 = - append_no_duplicates Typename.equal list1 list2 - - let append_no_duplicates_methods list1 list2 = - append_no_duplicates Procname.equal list1 list2 - - let append_no_duplicated_vars list1 list2 = - let eq (m1, t1) (m2, t2) = (Mangled.equal m1 m2) && (Typ.equal t1 t2) in - append_no_duplicates eq list1 list2 - - let append_no_duplicates_annotations list1 list2 = - let eq (annot1, _) (annot2, _) = annot1.Annot.class_name = annot2.Annot.class_name in - append_no_duplicates eq list1 list2 - - let add_no_duplicates_fields field_tuple l = - let rec replace_field field_tuple l found = - match field_tuple, l with - | (field, typ, annot), ((old_field, old_typ, old_annot) as old_field_tuple :: rest) -> - let ret_list, ret_found = replace_field field_tuple rest found in - if Ident.equal_fieldname field old_field && Typ.equal typ old_typ then - let annotations = append_no_duplicates_annotations annot old_annot in - (field, typ, annotations) :: ret_list, true - else old_field_tuple :: ret_list, ret_found - | _, [] -> [], found in - let new_list, found = replace_field field_tuple l false in - if found then new_list - else field_tuple :: l - - let rec append_no_duplicates_fields list1 list2 = - match list1 with - | field_tuple :: rest -> - let updated_list2 = append_no_duplicates_fields rest list2 in - add_no_duplicates_fields field_tuple updated_list2 - | [] -> list2 - - let sort_fields fields = - let compare (name1, _, _) (name2, _, _) = - Ident.compare_fieldname name1 name2 in - IList.sort compare fields - - - let sort_fields_tenv tenv = - let sort_fields_struct name ({StructTyp.fields} as st) = - ignore (Tenv.mk_struct tenv ~default:st ~fields:(sort_fields fields) name) in - Tenv.iter sort_fields_struct tenv - - let rec collect_list_tuples l (a, a1, b, c, d) = - match l with - | [] -> (a, a1, b, c, d) - | (a', a1', b', c', d'):: l' -> collect_list_tuples l' (a@a', a1@a1', b@b', c@c', d@d') - - let is_static_var var_decl_info = - match var_decl_info.Clang_ast_t.vdi_storage_class with - | Some sc -> sc = CFrontend_config.static - | _ -> false - - let block_procname_with_index defining_proc i = - Config.anonymous_block_prefix^(Procname.to_string defining_proc)^Config.anonymous_block_num_sep^(string_of_int i) - - (* Makes a fresh name for a block defined inside the defining procedure.*) - (* It updates the global block_counter *) - let mk_fresh_block_procname defining_proc = - let name = block_procname_with_index defining_proc (get_fresh_block_index ()) in - Procname.mangled_objc_block name - - (* Returns the next fresh name for a block defined inside the defining procedure *) - (* It does not update the global block_counter *) - let get_next_block_pvar defining_proc = - let name = block_procname_with_index defining_proc (!block_counter +1) in - Pvar.mk_tmp name defining_proc - - (* Reset block counter *) - let reset_block_counter () = - block_counter := 0 - - let rec zip xs ys = - match xs, ys with - | [], _ - | _, [] -> [] - | x :: xs, y :: ys -> (x, y) :: zip xs ys - - let list_range i j = - let rec aux n acc = - if n < i then acc else aux (n -1) (n :: acc) - in aux j [] ;; - - let replicate n el = IList.map (fun _ -> el) (list_range 0 (n -1)) - - let mk_class_field_name field_qual_name = - let field_name = field_qual_name.Clang_ast_t.ni_name in - let class_name = Ast_utils.get_class_name_from_member field_qual_name in - Ident.create_fieldname (Mangled.mangled field_name class_name) 0 - - let is_cpp_translation translation_unit_context = - let lang = translation_unit_context.CFrontend_config.lang in - lang = CFrontend_config.CPP || lang = CFrontend_config.ObjCPP - - let is_objc_extension translation_unit_context = - let lang = translation_unit_context.CFrontend_config.lang in - lang = CFrontend_config.ObjC || lang = CFrontend_config.ObjCPP - - let rec get_mangled_method_name function_decl_info method_decl_info = - (* For virtual methods return mangled name of the method from most base class - Go recursively until there is no method in any parent class. All names - of the same method need to be the same, otherwise dynamic dispatch won't - work. *) - let open Clang_ast_t in - match method_decl_info.xmdi_overriden_methods with - | [] -> function_decl_info.fdi_mangled_name - | base1_dr :: _ -> - (let base1 = match Ast_utils.get_decl base1_dr.dr_decl_pointer with - | Some b -> b - | _ -> assert false in - match base1 with - | CXXMethodDecl (_, _, _, fdi, mdi) - | CXXConstructorDecl (_, _, _, fdi, mdi) - | CXXConversionDecl (_, _, _, fdi, mdi) - | CXXDestructorDecl (_, _, _, fdi, mdi) -> - get_mangled_method_name fdi mdi - | _ -> assert false) - - let mk_procname_from_function translation_unit_context name function_decl_info_opt = - let file = - match function_decl_info_opt with - | Some (decl_info, function_decl_info) -> - (match function_decl_info.Clang_ast_t.fdi_storage_class with - | Some "static" -> - let file_opt = (fst decl_info.Clang_ast_t.di_source_range).Clang_ast_t.sl_file in - Option.value_map ~f:SourceFile.to_string ~default:"" file_opt - | _ -> "") - | None -> "" in - let mangled_opt = match function_decl_info_opt with - | Some (_, function_decl_info) -> function_decl_info.Clang_ast_t.fdi_mangled_name - | _ -> None in - let mangled_name = - match mangled_opt with - | Some m when is_cpp_translation translation_unit_context -> m - | _ -> "" in - let mangled = (Utils.string_crc_hex32 file) ^ mangled_name in - if String.length file = 0 && String.length mangled_name = 0 then - Procname.from_string_c_fun name - else - Procname.C (Procname.c name mangled) - - let mk_procname_from_objc_method class_name method_name method_kind = - Procname.ObjC_Cpp - (Procname.objc_cpp class_name method_name method_kind) - - let mk_procname_from_cpp_method class_name method_name ?meth_decl mangled = - let method_kind = match meth_decl with - | Some (Clang_ast_t.CXXConstructorDecl (_, _, _, _, {xmdi_is_constexpr})) -> - Procname.CPPConstructor (mangled, xmdi_is_constexpr) - | _ -> - Procname.CPPMethod mangled in - Procname.ObjC_Cpp - (Procname.objc_cpp class_name method_name method_kind) - - let get_objc_method_name name_info mdi class_name = - let method_name = name_info.Clang_ast_t.ni_name in - let is_instance = mdi.Clang_ast_t.omdi_is_instance_method in - let method_kind = Procname.objc_method_kind_of_bool is_instance in - mk_procname_from_objc_method class_name method_name method_kind - - let procname_of_decl translation_unit_context meth_decl = - let open Clang_ast_t in - match meth_decl with - | FunctionDecl (decl_info, name_info, _, fdi) -> - let name = Ast_utils.get_qualified_name name_info in - let function_info = Some (decl_info, fdi) in - mk_procname_from_function translation_unit_context name function_info - | CXXMethodDecl (_, name_info, _, fdi, mdi) - | CXXConstructorDecl (_, name_info, _, fdi, mdi) - | CXXConversionDecl (_, name_info, _, fdi, mdi) - | CXXDestructorDecl (_, name_info, _, fdi, mdi) -> - let mangled = get_mangled_method_name fdi mdi in - let method_name = Ast_utils.get_unqualified_name name_info in - let class_name = Ast_utils.get_class_name_from_member name_info in - mk_procname_from_cpp_method class_name method_name ~meth_decl mangled - | ObjCMethodDecl (_, name_info, mdi) -> - let class_name = Ast_utils.get_class_name_from_member name_info in - get_objc_method_name name_info mdi class_name - | BlockDecl _ -> - let name = Config.anonymous_block_prefix ^ Config.anonymous_block_num_sep ^ - (string_of_int (get_fresh_block_index ())) in - Procname.mangled_objc_block name - | _ -> assert false - - - let get_var_name_mangled name_info var_decl_info = - let clang_name = Ast_utils.get_qualified_name name_info in - let param_idx_opt = var_decl_info.Clang_ast_t.vdi_parm_index_in_function in - let name_string = - match clang_name, param_idx_opt with - | "", Some index -> "__param_" ^ string_of_int index - | "", None -> assert false - | _ -> clang_name in - let mangled = match param_idx_opt with - | Some index -> Mangled.mangled name_string (string_of_int index) - | None -> Mangled.from_string name_string in - name_string, mangled - - let mk_sil_global_var {CFrontend_config.source_file} ?(mk_name=fun _ x -> x) - named_decl_info var_decl_info qt = - let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in - let translation_unit = - match (var_decl_info.Clang_ast_t.vdi_storage_class, - var_decl_info.Clang_ast_t.vdi_init_expr) with - | Some "extern", None -> - (* some compilers simply disregard "extern" when the global is given some initialisation - code, which is why we make sure that [vdi_init_expr] is None here... *) - SourceFile.empty - | _ -> - source_file in - let is_constexpr = var_decl_info.Clang_ast_t.vdi_is_const_expr in - let is_pod = - Ast_utils.get_desugared_type qt.Clang_ast_t.qt_type_ptr - |> Fn.flip Option.bind (function - | Clang_ast_t.RecordType(_, decl_ptr) -> Ast_utils.get_decl decl_ptr - | _ -> None) - |> Option.value_map ~default:true ~f:(function - | Clang_ast_t.CXXRecordDecl(_, _, _, _, _, _, _, {xrdi_is_pod}) - | Clang_ast_t.ClassTemplateSpecializationDecl(_, _, _, _, _, _, _, {xrdi_is_pod}, _) -> - xrdi_is_pod - | _ -> true) in - Pvar.mk_global ~is_constexpr ~is_pod - ~is_static_local:(var_decl_info.Clang_ast_t.vdi_is_static_local) - (mk_name name_string simple_name) translation_unit - - let mk_sil_var trans_unit_ctx named_decl_info decl_info_type_ptr_opt procname outer_procname = - match decl_info_type_ptr_opt with - | Some (decl_info, qt, var_decl_info, should_be_mangled) -> - let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in - if var_decl_info.Clang_ast_t.vdi_is_global then - let mk_name = - if var_decl_info.Clang_ast_t.vdi_is_static_local then - Some (fun name_string _ -> - Mangled.from_string ((Procname.to_string outer_procname) ^ "_" ^ name_string)) - else None in - mk_sil_global_var trans_unit_ctx ?mk_name named_decl_info var_decl_info qt - else if not should_be_mangled then Pvar.mk simple_name procname - else - let start_location = fst decl_info.Clang_ast_t.di_source_range in - let line_opt = start_location.Clang_ast_t.sl_line in - let line_str = match line_opt with | Some line -> string_of_int line | None -> "" in - let mangled = Utils.string_crc_hex32 line_str in - let mangled_name = Mangled.mangled name_string mangled in - Pvar.mk mangled_name procname - | None -> - let name_string = Ast_utils.get_qualified_name named_decl_info in - Pvar.mk (Mangled.from_string name_string) procname - -end diff --git a/infer/src/clang/cFrontend_utils.mli b/infer/src/clang/cFrontend_utils.mli deleted file mode 100644 index 404d0000c..000000000 --- a/infer/src/clang/cFrontend_utils.mli +++ /dev/null @@ -1,253 +0,0 @@ -(* - * Copyright (c) 2013 - 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. - *) - -open! IStd - -(** Module for utility functions for the whole frontend. Includes functions for transformations of - ast nodes and general utility functions such as functions on lists *) - -module Ast_utils : -sig - val string_of_stmt : Clang_ast_t.stmt -> string - - val get_stmts_from_stmt : Clang_ast_t.stmt -> Clang_ast_t.stmt list - - val string_of_decl : Clang_ast_t.decl -> string - - val string_of_unary_operator_kind : Clang_ast_t.unary_operator_kind -> string - - val name_opt_of_name_info_opt : Clang_ast_t.named_decl_info option -> string option - - val property_name : Clang_ast_t.obj_c_property_impl_decl_info -> Clang_ast_t.named_decl_info - - val compare_property_attribute : - Clang_ast_t.property_attribute -> Clang_ast_t.property_attribute -> int - - val generated_ivar_name : - Clang_ast_t.named_decl_info -> Clang_ast_t.named_decl_info - - val equal_property_attribute : - Clang_ast_t.property_attribute -> Clang_ast_t.property_attribute -> bool - - val get_memory_management_attributes : unit -> Clang_ast_t.property_attribute list - - val is_retain : Clang_ast_t.property_attribute option -> bool - - val is_copy : Clang_ast_t.property_attribute option -> bool - - val is_type_nonnull : Clang_ast_t.type_ptr -> bool - - val is_type_nullable : Clang_ast_t.type_ptr -> bool - - val get_fresh_pointer : unit -> Clang_ast_t.pointer - - val get_invalid_pointer : unit -> Clang_ast_t.pointer - - val type_from_unary_expr_or_type_trait_expr_info : - Clang_ast_t.unary_expr_or_type_trait_expr_info -> Clang_ast_t.type_ptr option - - val get_decl : Clang_ast_t.pointer -> Clang_ast_t.decl option - - val get_decl_opt : Clang_ast_t.pointer option -> Clang_ast_t.decl option - - val get_stmt : Clang_ast_t.pointer -> Clang_ast_t.stmt option - - val get_stmt_opt : Clang_ast_t.pointer option -> Clang_ast_t.stmt option - - val get_decl_opt_with_decl_ref : Clang_ast_t.decl_ref option -> Clang_ast_t.decl option - - 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_enum_map : Clang_ast_t.pointer -> Exp.t -> unit - - val add_enum_constant : Clang_ast_t.pointer -> Clang_ast_t.pointer option -> unit - - val get_enum_constant_exp : Clang_ast_t.pointer -> Clang_ast_t.pointer option * Exp.t option - - (** returns sanitized, fully qualified name given name info *) - val get_qualified_name : Clang_ast_t.named_decl_info -> string - - (** returns sanitized unqualified name given name info *) - val get_unqualified_name : Clang_ast_t.named_decl_info -> string - - (** returns qualified class name given member name info *) - val get_class_name_from_member : Clang_ast_t.named_decl_info -> string - - (** looks up clang pointer to type and returns c_type. It requires type_ptr to be `TPtr. *) - val get_type : Clang_ast_t.type_ptr -> Clang_ast_t.c_type option - - (** looks up clang pointer to type and resolves any sugar around it. - See get_type for more info and restrictions *) - val get_desugared_type : Clang_ast_t.type_ptr -> Clang_ast_t.c_type option - - (** returns declaration of the type for certain types - (RecordType, ObjCInterfaceType and None for others *) - val get_decl_from_typ_ptr : Clang_ast_t.type_ptr -> Clang_ast_t.decl option - - (** returns string representation of type_ptr - NOTE: this doesn't expand type, it only converts type_ptr to string *) - val string_of_type_ptr : Clang_ast_t.type_ptr -> string - - val name_of_typedef_type_info : Clang_ast_t.typedef_type_info -> string - - (** returns name of typedef if type_ptr points to Typedef, None otherwise *) - val name_opt_of_typedef_type_ptr : Clang_ast_t.type_ptr -> string option - val string_of_qual_type : Clang_ast_t.qual_type -> string - - val make_name_decl : string -> Clang_ast_t.named_decl_info - - val make_qual_name_decl : string list -> string -> Clang_ast_t.named_decl_info - - type type_ptr_to_sil_type = Tenv.t -> Clang_ast_t.type_ptr -> Typ.t - - val add_type_from_decl_ref : type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl_ref option -> - bool -> unit - - val add_type_from_decl_ref_list : type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl_ref list -> - unit - - val get_function_decl_with_body : Clang_ast_t.pointer -> Clang_ast_t.decl option - - val get_info_from_decl_ref : Clang_ast_t.decl_ref -> - Clang_ast_t.named_decl_info * Clang_ast_t.pointer * Clang_ast_t.type_ptr - - val exists_eventually_st : ('a -> Clang_ast_t.stmt -> bool) -> 'a -> Clang_ast_t.stmt -> bool - - (** true if a declaration is a global variable *) - val is_syntactically_global_var : Clang_ast_t.decl -> bool - - (** true if a declaration is a constexpr variable *) - val is_const_expr_var : Clang_ast_t.decl -> bool - - val is_ptr_to_objc_class : Clang_ast_t.c_type option -> string -> bool - - val full_name_of_decl_opt : Clang_ast_t.decl option -> string - - (** Generates a key for a statement based on its sub-statements and the statement tag. *) - val generate_key_stmt : Clang_ast_t.stmt -> string - - (** Generates a key for a declaration based on its name and the declaration tag. *) - val generate_key_decl : Clang_ast_t.decl -> string - - (** Given an objc impl or interface decl, returns the objc interface decl of - the superclass, if any. *) - val get_super_if : Clang_ast_t.decl option -> Clang_ast_t.decl option - - val get_impl_decl_info : Clang_ast_t.decl -> Clang_ast_t.obj_c_implementation_decl_info option - - (** Given an objc impl decl info, return the super class's list of decls and - its objc impl decl info. *) - val get_super_impl : - Clang_ast_t.obj_c_implementation_decl_info -> - (Clang_ast_t.decl list * - Clang_ast_t.obj_c_implementation_decl_info) - option - - (** Given an objc impl decl info, return its super class implementation decl *) - val get_super_ObjCImplementationDecl : - Clang_ast_t.obj_c_implementation_decl_info -> Clang_ast_t.decl option - - (** Recursively go up the inheritance hierarchy of a given ObjCInterfaceDecl. - Returns true if the passed in decl is an objc interface decl that's an - eventual descendant of one of the classes passed in. - Ancestors param is a list of strings that represent the class names. - Will short-circuit on NSObject and NSProxy since those are known to be - common base classes. - The list of classes to short-circuit on can be overridden via specifying - the named `blacklist` argument. *) - val is_objc_if_descendant : - ?blacklist:string list -> Clang_ast_t.decl option -> string list -> bool - - val type_ptr_to_objc_interface : Clang_ast_types.t_ptr -> Clang_ast_t.decl option - - (** A class method that returns an instance of the class is a factory method. *) - val is_objc_factory_method : Clang_ast_t.decl -> Clang_ast_t.decl -> bool - - val name_of_decl_ref_opt : Clang_ast_t.decl_ref option -> string option -end - -module General_utils : -sig - - type var_info = Clang_ast_t.decl_info * Clang_ast_t.qual_type * Clang_ast_t.var_decl_info * bool - - val string_from_list : string list -> string - - val append_no_duplicates_fields : (Ident.fieldname * Typ.t * Annot.Item.t) list -> - (Ident.fieldname * Typ.t * Annot.Item.t) list -> - (Ident.fieldname * Typ.t * Annot.Item.t) list - - val append_no_duplicates_csu : - Typename.t list -> Typename.t list -> Typename.t list - - val append_no_duplicates_methods : Procname.t list -> Procname.t list -> Procname.t list - - val append_no_duplicated_vars : - (Mangled.t * Typ.t) list -> (Mangled.t * Typ.t) list -> (Mangled.t * Typ.t) list - - val sort_fields : - (Ident.fieldname * Typ.t * Annot.Item.t) list -> - (Ident.fieldname * Typ.t * Annot.Item.t) list - - val sort_fields_tenv : Tenv.t -> unit - - val collect_list_tuples : ('a list * 'b list * 'c list * 'd list * 'e list) list -> - 'a list * 'b list * 'c list * 'd list * 'e list -> - 'a list * 'b list * 'c list * 'd list * 'e list - - val swap_elements_list : 'a list -> 'a list - - val is_static_var : Clang_ast_t.var_decl_info -> bool - - val mk_fresh_block_procname : Procname.t -> Procname.t - - val get_next_block_pvar : Procname.t -> Pvar.t - - val reset_block_counter : unit -> unit - - val zip: 'a list -> 'b list -> ('a * 'b) list - - val list_range: int -> int -> int list - - val replicate: int -> 'a -> 'a list - - val mk_procname_from_objc_method : string -> string -> Procname.objc_cpp_method_kind -> Procname.t - - val mk_procname_from_function : CFrontend_config.translation_unit_context -> string - -> (Clang_ast_t.decl_info * Clang_ast_t.function_decl_info) option -> Procname.t - - val get_mangled_method_name : Clang_ast_t.function_decl_info -> - Clang_ast_t.cxx_method_decl_info -> string option - - val mk_procname_from_cpp_method : - string -> string -> ?meth_decl:Clang_ast_t.decl -> string option -> Procname.t - - val procname_of_decl : CFrontend_config.translation_unit_context -> Clang_ast_t.decl -> Procname.t - - val mk_class_field_name : Clang_ast_t.named_decl_info -> Ident.fieldname - - val get_var_name_mangled : Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info -> - (string * Mangled.t) - - val mk_sil_global_var : CFrontend_config.translation_unit_context -> - ?mk_name:(string -> Mangled.t -> Mangled.t) -> - Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info -> Clang_ast_t.qual_type -> Pvar.t - - val mk_sil_var : CFrontend_config.translation_unit_context -> Clang_ast_t.named_decl_info -> - var_info option -> Procname.t -> Procname.t -> Pvar.t - - (** true if the current language is C++ or ObjC++ *) - val is_cpp_translation : CFrontend_config.translation_unit_context -> bool - - (** true if the current language is ObjC or ObjC++ *) - val is_objc_extension : CFrontend_config.translation_unit_context -> bool - -end diff --git a/infer/src/clang/cGeneral_utils.ml b/infer/src/clang/cGeneral_utils.ml new file mode 100644 index 000000000..a3d607014 --- /dev/null +++ b/infer/src/clang/cGeneral_utils.ml @@ -0,0 +1,296 @@ +(* + * Copyright (c) 2013 - 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. + *) + +open! IStd + +(** General utility functions such as functions on lists *) + +module L = Logging +module F = Format + +type var_info = Clang_ast_t.decl_info * Clang_ast_t.qual_type * Clang_ast_t.var_decl_info * bool + +let rec swap_elements_list l = + match l with + | el1:: el2:: rest -> + el2:: el1:: (swap_elements_list rest) + | [] -> [] + | _ -> assert false + +let rec string_from_list l = + match l with + | [] -> "" + | [item] -> item + | item:: l' -> item^" "^(string_from_list l') + +let rec append_no_duplicates eq list1 list2 = + match list2 with + | el:: rest2 -> + if (IList.mem eq el list1) then + (append_no_duplicates eq list1 rest2) + else (append_no_duplicates eq list1 rest2)@[el] + | [] -> list1 + +let append_no_duplicates_csu list1 list2 = + append_no_duplicates Typename.equal list1 list2 + +let append_no_duplicates_methods list1 list2 = + append_no_duplicates Procname.equal list1 list2 + +let append_no_duplicates_annotations list1 list2 = + let eq (annot1, _) (annot2, _) = annot1.Annot.class_name = annot2.Annot.class_name in + append_no_duplicates eq list1 list2 + +let add_no_duplicates_fields field_tuple l = + let rec replace_field field_tuple l found = + match field_tuple, l with + | (field, typ, annot), ((old_field, old_typ, old_annot) as old_field_tuple :: rest) -> + let ret_list, ret_found = replace_field field_tuple rest found in + if Ident.equal_fieldname field old_field && Typ.equal typ old_typ then + let annotations = append_no_duplicates_annotations annot old_annot in + (field, typ, annotations) :: ret_list, true + else old_field_tuple :: ret_list, ret_found + | _, [] -> [], found in + let new_list, found = replace_field field_tuple l false in + if found then new_list + else field_tuple :: l + +let rec append_no_duplicates_fields list1 list2 = + match list1 with + | field_tuple :: rest -> + let updated_list2 = append_no_duplicates_fields rest list2 in + add_no_duplicates_fields field_tuple updated_list2 + | [] -> list2 + +let sort_fields fields = + let compare (name1, _, _) (name2, _, _) = + Ident.compare_fieldname name1 name2 in + IList.sort compare fields + + +let sort_fields_tenv tenv = + let sort_fields_struct name ({StructTyp.fields} as st) = + ignore (Tenv.mk_struct tenv ~default:st ~fields:(sort_fields fields) name) in + Tenv.iter sort_fields_struct tenv + +let rec collect_list_tuples l (a, a1, b, c, d) = + match l with + | [] -> (a, a1, b, c, d) + | (a', a1', b', c', d'):: l' -> collect_list_tuples l' (a@a', a1@a1', b@b', c@c', d@d') + +let is_static_var var_decl_info = + match var_decl_info.Clang_ast_t.vdi_storage_class with + | Some sc -> sc = CFrontend_config.static + | _ -> false + +let block_procname_with_index defining_proc i = + Config.anonymous_block_prefix ^ + (Procname.to_string defining_proc) ^ + Config.anonymous_block_num_sep ^ + (string_of_int i) + +(* Global counter for anonymous block*) +let block_counter = ref 0 + +(* Returns a fresh index for a new anonymous block *) +let get_fresh_block_index () = + block_counter := !block_counter +1; + !block_counter + +(* Makes a fresh name for a block defined inside the defining procedure.*) +(* It updates the global block_counter *) +let mk_fresh_block_procname defining_proc = + let name = block_procname_with_index defining_proc (get_fresh_block_index ()) in + Procname.mangled_objc_block name + +(* Returns the next fresh name for a block defined inside the defining procedure *) +(* It does not update the global block_counter *) +let get_next_block_pvar defining_proc = + let name = block_procname_with_index defining_proc (!block_counter +1) in + Pvar.mk_tmp name defining_proc + +(* Reset block counter *) +let reset_block_counter () = + block_counter := 0 + +let rec zip xs ys = + match xs, ys with + | [], _ + | _, [] -> [] + | x :: xs, y :: ys -> (x, y) :: zip xs ys + +let list_range i j = + let rec aux n acc = + if n < i then acc else aux (n -1) (n :: acc) + in aux j [] ;; + +let replicate n el = IList.map (fun _ -> el) (list_range 0 (n -1)) + +let mk_class_field_name field_qual_name = + let field_name = field_qual_name.Clang_ast_t.ni_name in + let class_name = CAst_utils.get_class_name_from_member field_qual_name in + Ident.create_fieldname (Mangled.mangled field_name class_name) 0 + +let is_cpp_translation translation_unit_context = + let lang = translation_unit_context.CFrontend_config.lang in + lang = CFrontend_config.CPP || lang = CFrontend_config.ObjCPP + +let is_objc_extension translation_unit_context = + let lang = translation_unit_context.CFrontend_config.lang in + lang = CFrontend_config.ObjC || lang = CFrontend_config.ObjCPP + +let rec get_mangled_method_name function_decl_info method_decl_info = + (* For virtual methods return mangled name of the method from most base class + Go recursively until there is no method in any parent class. All names + of the same method need to be the same, otherwise dynamic dispatch won't + work. *) + let open Clang_ast_t in + match method_decl_info.xmdi_overriden_methods with + | [] -> function_decl_info.fdi_mangled_name + | base1_dr :: _ -> + (let base1 = match CAst_utils.get_decl base1_dr.dr_decl_pointer with + | Some b -> b + | _ -> assert false in + match base1 with + | CXXMethodDecl (_, _, _, fdi, mdi) + | CXXConstructorDecl (_, _, _, fdi, mdi) + | CXXConversionDecl (_, _, _, fdi, mdi) + | CXXDestructorDecl (_, _, _, fdi, mdi) -> + get_mangled_method_name fdi mdi + | _ -> assert false) + +let mk_procname_from_function translation_unit_context name function_decl_info_opt = + let file = + match function_decl_info_opt with + | Some (decl_info, function_decl_info) -> + (match function_decl_info.Clang_ast_t.fdi_storage_class with + | Some "static" -> + let file_opt = (fst decl_info.Clang_ast_t.di_source_range).Clang_ast_t.sl_file in + Option.value_map ~f:SourceFile.to_string ~default:"" file_opt + | _ -> "") + | None -> "" in + let mangled_opt = match function_decl_info_opt with + | Some (_, function_decl_info) -> function_decl_info.Clang_ast_t.fdi_mangled_name + | _ -> None in + let mangled_name = + match mangled_opt with + | Some m when is_cpp_translation translation_unit_context -> m + | _ -> "" in + let mangled = (Utils.string_crc_hex32 file) ^ mangled_name in + if String.length file = 0 && String.length mangled_name = 0 then + Procname.from_string_c_fun name + else + Procname.C (Procname.c name mangled) + +let mk_procname_from_objc_method class_name method_name method_kind = + Procname.ObjC_Cpp + (Procname.objc_cpp class_name method_name method_kind) + +let mk_procname_from_cpp_method class_name method_name ?meth_decl mangled = + let method_kind = match meth_decl with + | Some (Clang_ast_t.CXXConstructorDecl (_, _, _, _, {xmdi_is_constexpr})) -> + Procname.CPPConstructor (mangled, xmdi_is_constexpr) + | _ -> + Procname.CPPMethod mangled in + Procname.ObjC_Cpp + (Procname.objc_cpp class_name method_name method_kind) + +let get_objc_method_name name_info mdi class_name = + let method_name = name_info.Clang_ast_t.ni_name in + let is_instance = mdi.Clang_ast_t.omdi_is_instance_method in + let method_kind = Procname.objc_method_kind_of_bool is_instance in + mk_procname_from_objc_method class_name method_name method_kind + +let procname_of_decl translation_unit_context meth_decl = + let open Clang_ast_t in + match meth_decl with + | FunctionDecl (decl_info, name_info, _, fdi) -> + let name = CAst_utils.get_qualified_name name_info in + let function_info = Some (decl_info, fdi) in + mk_procname_from_function translation_unit_context name function_info + | CXXMethodDecl (_, name_info, _, fdi, mdi) + | CXXConstructorDecl (_, name_info, _, fdi, mdi) + | CXXConversionDecl (_, name_info, _, fdi, mdi) + | CXXDestructorDecl (_, name_info, _, fdi, mdi) -> + let mangled = get_mangled_method_name fdi mdi in + let method_name = CAst_utils.get_unqualified_name name_info in + let class_name = CAst_utils.get_class_name_from_member name_info in + mk_procname_from_cpp_method class_name method_name ~meth_decl mangled + | ObjCMethodDecl (_, name_info, mdi) -> + let class_name = CAst_utils.get_class_name_from_member name_info in + get_objc_method_name name_info mdi class_name + | BlockDecl _ -> + let name = Config.anonymous_block_prefix ^ Config.anonymous_block_num_sep ^ + (string_of_int (get_fresh_block_index ())) in + Procname.mangled_objc_block name + | _ -> assert false + + +let get_var_name_mangled name_info var_decl_info = + let clang_name = CAst_utils.get_qualified_name name_info in + let param_idx_opt = var_decl_info.Clang_ast_t.vdi_parm_index_in_function in + let name_string = + match clang_name, param_idx_opt with + | "", Some index -> "__param_" ^ string_of_int index + | "", None -> assert false + | _ -> clang_name in + let mangled = match param_idx_opt with + | Some index -> Mangled.mangled name_string (string_of_int index) + | None -> Mangled.from_string name_string in + name_string, mangled + +let mk_sil_global_var {CFrontend_config.source_file} ?(mk_name=fun _ x -> x) + named_decl_info var_decl_info qt = + let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in + let translation_unit = + match (var_decl_info.Clang_ast_t.vdi_storage_class, + var_decl_info.Clang_ast_t.vdi_init_expr) with + | Some "extern", None -> + (* some compilers simply disregard "extern" when the global is given some initialisation + code, which is why we make sure that [vdi_init_expr] is None here... *) + SourceFile.empty + | _ -> + source_file in + let is_constexpr = var_decl_info.Clang_ast_t.vdi_is_const_expr in + let is_pod = + CAst_utils.get_desugared_type qt.Clang_ast_t.qt_type_ptr + |> Fn.flip Option.bind (function + | Clang_ast_t.RecordType(_, decl_ptr) -> CAst_utils.get_decl decl_ptr + | _ -> None) + |> Option.value_map ~default:true ~f:(function + | Clang_ast_t.CXXRecordDecl(_, _, _, _, _, _, _, {xrdi_is_pod}) + | Clang_ast_t.ClassTemplateSpecializationDecl(_, _, _, _, _, _, _, {xrdi_is_pod}, _) -> + xrdi_is_pod + | _ -> true) in + Pvar.mk_global ~is_constexpr ~is_pod + ~is_static_local:(var_decl_info.Clang_ast_t.vdi_is_static_local) + (mk_name name_string simple_name) translation_unit + +let mk_sil_var trans_unit_ctx named_decl_info decl_info_type_ptr_opt procname outer_procname = + match decl_info_type_ptr_opt with + | Some (decl_info, qt, var_decl_info, should_be_mangled) -> + let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in + if var_decl_info.Clang_ast_t.vdi_is_global then + let mk_name = + if var_decl_info.Clang_ast_t.vdi_is_static_local then + Some (fun name_string _ -> + Mangled.from_string ((Procname.to_string outer_procname) ^ "_" ^ name_string)) + else None in + mk_sil_global_var trans_unit_ctx ?mk_name named_decl_info var_decl_info qt + else if not should_be_mangled then Pvar.mk simple_name procname + else + let start_location = fst decl_info.Clang_ast_t.di_source_range in + let line_opt = start_location.Clang_ast_t.sl_line in + let line_str = match line_opt with | Some line -> string_of_int line | None -> "" in + let mangled = Utils.string_crc_hex32 line_str in + let mangled_name = Mangled.mangled name_string mangled in + Pvar.mk mangled_name procname + | None -> + let name_string = CAst_utils.get_qualified_name named_decl_info in + Pvar.mk (Mangled.from_string name_string) procname diff --git a/infer/src/clang/cGeneral_utils.mli b/infer/src/clang/cGeneral_utils.mli new file mode 100644 index 000000000..cadc200ba --- /dev/null +++ b/infer/src/clang/cGeneral_utils.mli @@ -0,0 +1,83 @@ +(* + * Copyright (c) 2013 - 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. + *) + +open! IStd + +(** General utility functions such as functions on lists *) + + +type var_info = Clang_ast_t.decl_info * Clang_ast_t.qual_type * Clang_ast_t.var_decl_info * bool + +val string_from_list : string list -> string + +val append_no_duplicates_fields : (Ident.fieldname * Typ.t * Annot.Item.t) list -> + (Ident.fieldname * Typ.t * Annot.Item.t) list -> + (Ident.fieldname * Typ.t * Annot.Item.t) list + +val append_no_duplicates_csu : + Typename.t list -> Typename.t list -> Typename.t list + +val append_no_duplicates_methods : Procname.t list -> Procname.t list -> Procname.t list + +val sort_fields : + (Ident.fieldname * Typ.t * Annot.Item.t) list -> + (Ident.fieldname * Typ.t * Annot.Item.t) list + +val sort_fields_tenv : Tenv.t -> unit + +val collect_list_tuples : ('a list * 'b list * 'c list * 'd list * 'e list) list -> + 'a list * 'b list * 'c list * 'd list * 'e list -> + 'a list * 'b list * 'c list * 'd list * 'e list + +val swap_elements_list : 'a list -> 'a list + +val is_static_var : Clang_ast_t.var_decl_info -> bool + +val mk_fresh_block_procname : Procname.t -> Procname.t + +val get_next_block_pvar : Procname.t -> Pvar.t + +val reset_block_counter : unit -> unit + +val zip: 'a list -> 'b list -> ('a * 'b) list + +val list_range: int -> int -> int list + +val replicate: int -> 'a -> 'a list + +val mk_procname_from_objc_method : string -> string -> Procname.objc_cpp_method_kind -> Procname.t + +val mk_procname_from_function : CFrontend_config.translation_unit_context -> string + -> (Clang_ast_t.decl_info * Clang_ast_t.function_decl_info) option -> Procname.t + +val get_mangled_method_name : Clang_ast_t.function_decl_info -> + Clang_ast_t.cxx_method_decl_info -> string option + +val mk_procname_from_cpp_method : + string -> string -> ?meth_decl:Clang_ast_t.decl -> string option -> Procname.t + +val procname_of_decl : CFrontend_config.translation_unit_context -> Clang_ast_t.decl -> Procname.t + +val mk_class_field_name : Clang_ast_t.named_decl_info -> Ident.fieldname + +val get_var_name_mangled : Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info -> + (string * Mangled.t) + +val mk_sil_global_var : CFrontend_config.translation_unit_context -> + ?mk_name:(string -> Mangled.t -> Mangled.t) -> + Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info -> Clang_ast_t.qual_type -> Pvar.t + +val mk_sil_var : CFrontend_config.translation_unit_context -> Clang_ast_t.named_decl_info -> + var_info option -> Procname.t -> Procname.t -> Pvar.t + +(** true if the current language is C++ or ObjC++ *) +val is_cpp_translation : CFrontend_config.translation_unit_context -> bool + +(** true if the current language is ObjC or ObjC++ *) +val is_objc_extension : CFrontend_config.translation_unit_context -> bool diff --git a/infer/src/clang/cMethod_signature.ml b/infer/src/clang/cMethod_signature.ml index f8d7aa0bc..d25210941 100644 --- a/infer/src/clang/cMethod_signature.ml +++ b/infer/src/clang/cMethod_signature.ml @@ -8,7 +8,6 @@ *) open! IStd -open CFrontend_utils (** Define the signature of a method consisting of its name, its arguments, *) (** return type, location and whether its an instance method. *) @@ -100,7 +99,7 @@ let replace_name_ms ms name = let ms_to_string ms = "Method " ^ (Procname.to_string ms.name) ^ " " ^ IList.to_string - (fun (s1, s2) -> (Mangled.to_string s1) ^ ", " ^ (Ast_utils.string_of_qual_type s2)) + (fun (s1, s2) -> (Mangled.to_string s1) ^ ", " ^ (CAst_utils.string_of_qual_type s2)) ms.args - ^ "->" ^ (Ast_utils.string_of_type_ptr ms.ret_type) ^ " " ^ + ^ "->" ^ (CAst_utils.string_of_type_ptr ms.ret_type) ^ " " ^ Clang_ast_j.string_of_source_range ms.loc diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 837af77a5..370a7a916 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -12,8 +12,6 @@ open! IStd (** Methods for creating a procdesc from a method or function declaration and for resolving a method call and finding the right callee *) -open CFrontend_utils - module L = Logging exception Invalid_declaration @@ -109,11 +107,11 @@ let get_parameters trans_unit_ctx tenv function_method_decl_info = let par_to_ms_par par = match par with | Clang_ast_t.ParmVarDecl (_, name_info, qt, var_decl_info) -> - let _, mangled = General_utils.get_var_name_mangled name_info var_decl_info in + let _, mangled = CGeneral_utils.get_var_name_mangled name_info var_decl_info in let param_typ = CType_decl.type_ptr_to_sil_type tenv qt.Clang_ast_t.qt_type_ptr in let qt_type_ptr = match param_typ with - | Typ.Tstruct _ when General_utils.is_cpp_translation trans_unit_ctx -> + | Typ.Tstruct _ when CGeneral_utils.is_cpp_translation trans_unit_ctx -> Ast_expressions.create_reference_type qt.Clang_ast_t.qt_type_ptr | _ -> qt.Clang_ast_t.qt_type_ptr in (mangled, {qt with qt_type_ptr}) @@ -146,7 +144,7 @@ let build_method_signature trans_unit_ctx tenv decl_info procname function_metho let get_assume_not_null_calls param_decls = let do_one_param decl = match decl with | Clang_ast_t.ParmVarDecl (decl_info, name, qt, _) - when CFrontend_utils.Ast_utils.is_type_nonnull qt.Clang_ast_t.qt_type_ptr -> + when CAst_utils.is_type_nonnull qt.Clang_ast_t.qt_type_ptr -> let assume_call = Ast_expressions.create_assume_not_null_call decl_info name qt.Clang_ast_t.qt_type_ptr in [(`ClangStmt assume_call)] @@ -162,7 +160,7 @@ let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt = match meth_decl, block_data_opt with | FunctionDecl (decl_info, _, qt, fdi), _ -> let func_decl = Func_decl_info (fdi, qt.Clang_ast_t.qt_type_ptr) in - let procname = General_utils.procname_of_decl trans_unit_ctx meth_decl in + let procname = CGeneral_utils.procname_of_decl trans_unit_ctx meth_decl in let ms = build_method_signature trans_unit_ctx tenv decl_info procname func_decl None None in let extra_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in ms, fdi.Clang_ast_t.fdi_body, extra_instrs @@ -170,7 +168,7 @@ let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt = | CXXConstructorDecl (decl_info, _, qt, fdi, mdi), _ | CXXConversionDecl (decl_info, _, qt, fdi, mdi), _ | CXXDestructorDecl (decl_info, _, qt, fdi, mdi), _ -> - let procname = General_utils.procname_of_decl trans_unit_ctx meth_decl in + let procname = CGeneral_utils.procname_of_decl trans_unit_ctx meth_decl in let parent_ptr = Option.value_exn decl_info.di_parent_pointer in let method_decl = Cpp_Meth_decl_info (fdi, mdi, parent_ptr, qt.Clang_ast_t.qt_type_ptr) in let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in @@ -180,7 +178,7 @@ let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt = let init_list_instrs = get_init_list_instrs mdi in (* it will be empty for methods *) ms, fdi.Clang_ast_t.fdi_body, (init_list_instrs @ non_null_instrs) | ObjCMethodDecl (decl_info, _, mdi), _ -> - let procname = General_utils.procname_of_decl trans_unit_ctx meth_decl in + let procname = CGeneral_utils.procname_of_decl trans_unit_ctx meth_decl in let parent_ptr = Option.value_exn decl_info.di_parent_pointer in let method_decl = ObjC_Meth_decl_info (mdi, parent_ptr) in let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in @@ -201,7 +199,7 @@ let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt = let method_signature_of_pointer trans_unit_ctx tenv pointer = try - match Ast_utils.get_decl pointer with + match CAst_utils.get_decl pointer with | Some meth_decl -> let ms, _, _ = method_signature_of_decl trans_unit_ctx tenv meth_decl None in Some ms @@ -211,7 +209,7 @@ let method_signature_of_pointer trans_unit_ctx tenv pointer = let get_method_name_from_clang tenv ms_opt = match ms_opt with | Some ms -> - (match Ast_utils.get_decl_opt (CMethod_signature.ms_get_pointer_to_parent ms) with + (match CAst_utils.get_decl_opt (CMethod_signature.ms_get_pointer_to_parent ms) with | Some decl -> if ObjcProtocol_decl.is_protocol decl then None else @@ -289,7 +287,7 @@ let get_objc_method_data obj_c_message_expr_info = let skip_property_accessor ms = let open Clang_ast_t in let pointer_to_property_opt = CMethod_signature.ms_get_pointer_to_property_opt ms in - match Ast_utils.get_decl_opt pointer_to_property_opt with + match CAst_utils.get_decl_opt pointer_to_property_opt with | Some (ObjCPropertyDecl _) -> true | _ -> false @@ -344,7 +342,7 @@ let sil_method_annotation_of_args args : Annot.Method.t = annot, default_visibility in let arg_to_sil_annot (arg_mangled, {Clang_ast_t.qt_type_ptr}) acc = let arg_name = Mangled.to_string arg_mangled in - if CFrontend_utils.Ast_utils.is_type_nullable qt_type_ptr then + if CAst_utils.is_type_nullable qt_type_ptr then [mk_annot arg_name Annotations.nullable] :: acc else Annot.Item.empty::acc in let param_annots = IList.fold_right arg_to_sil_annot args [] in @@ -353,7 +351,7 @@ let sil_method_annotation_of_args args : Annot.Method.t = retval_annot, param_annots -let is_pointer_to_const type_ptr = match Ast_utils.get_type type_ptr with +let is_pointer_to_const type_ptr = match CAst_utils.get_type type_ptr with | Some PointerType (_, {Clang_ast_t.qt_is_const}) | Some ObjCObjectPointerType (_, {Clang_ast_t.qt_is_const}) | Some RValueReferenceType (_, {Clang_ast_t.qt_is_const}) @@ -464,9 +462,9 @@ let create_procdesc_with_pointer context pointer class_name_opt name = let callee_name = match class_name_opt with | Some class_name -> - General_utils.mk_procname_from_cpp_method class_name name None + CGeneral_utils.mk_procname_from_cpp_method class_name name None | None -> - General_utils.mk_procname_from_function context.translation_unit_context name None in + CGeneral_utils.mk_procname_from_function context.translation_unit_context name None in create_external_procdesc context.cfg callee_name false None; callee_name @@ -482,7 +480,7 @@ let get_procname_from_cpp_lambda context dec = | Clang_ast_t.CXXRecordDecl (_, _, _, _, _, _, _, cxx_rdi) -> (match cxx_rdi.xrdi_lambda_call_operator with | Some dr -> - let name_info, decl_ptr, _ = Ast_utils.get_info_from_decl_ref dr in + let name_info, decl_ptr, _ = CAst_utils.get_info_from_decl_ref dr in create_procdesc_with_pointer context decl_ptr None name_info.ni_name | _ -> assert false (* We should not get here *)) | _ -> assert false (* We should not get here *) diff --git a/infer/src/clang/cTL.ml b/infer/src/clang/cTL.ml index 5e4a9373f..371dbafc0 100644 --- a/infer/src/clang/cTL.ml +++ b/infer/src/clang/cTL.ml @@ -9,8 +9,6 @@ open! IStd -open CFrontend_utils - (* This module defines a language to define checkers. These checkers are intepreted over the AST of the program. A checker is defined by a CTL formula which express a condition saying when the checker should @@ -331,9 +329,9 @@ let transition_decl_to_stmt d trs = | _ -> None let transition_decl_to_decl_via_super d = - match Ast_utils.get_impl_decl_info d with + match CAst_utils.get_impl_decl_info d with | Some idi -> - (match Ast_utils.get_super_ObjCImplementationDecl idi with + (match CAst_utils.get_super_ObjCImplementationDecl idi with | Some d -> Some (Decl d) | _ -> None) | None -> None @@ -351,11 +349,11 @@ let transition_stmt_to_decl_via_pointer stmt = let open Clang_ast_t in match stmt with | ObjCMessageExpr (_, _, _, obj_c_message_expr_info) -> - (match Ast_utils.get_decl_opt obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer with + (match CAst_utils.get_decl_opt obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer with | Some decl -> Some (Decl decl) | None -> None) | DeclRefExpr (_, _, _, decl_ref_expr_info) -> - (match Ast_utils.get_decl_opt_with_decl_ref decl_ref_expr_info.Clang_ast_t.drti_decl_ref with + (match CAst_utils.get_decl_opt_with_decl_ref decl_ref_expr_info.Clang_ast_t.drti_decl_ref with | Some decl -> Some (Decl decl) | None -> None) | _ -> None diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index b00996b08..cf5fa3f24 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -12,9 +12,8 @@ open! IStd (** Translates instructions: (statements and expressions) from the ast into sil *) open CTrans_utils -open CFrontend_utils - open CTrans_utils.Nodes + module L = Logging module CTrans_funct(F: CModule_type.CFrontend) : CModule_type.CTranslation = @@ -43,12 +42,12 @@ struct | None -> (* fall back to our method resolution if clang's fails *) let class_name = CMethod_trans.get_class_name_method_call_from_receiver_kind context obj_c_message_expr_info act_params in - General_utils.mk_procname_from_objc_method class_name selector method_kind in + CGeneral_utils.mk_procname_from_objc_method class_name selector method_kind in let predefined_ms_opt = match proc_name with | Procname.ObjC_Cpp objc_cpp -> let class_name = Procname.objc_cpp_get_class_name objc_cpp in CTrans_models.get_predefined_model_method_signature class_name selector - General_utils.mk_procname_from_objc_method CFrontend_config.ObjC + CGeneral_utils.mk_procname_from_objc_method CFrontend_config.ObjC | _ -> None in match predefined_ms_opt, ms_opt with @@ -108,8 +107,8 @@ struct let procname = Procdesc.get_proc_name procdesc in let mk_field_from_captured_var (var, typ) = let vname = Pvar.get_name var in - let qual_name = Ast_utils.make_qual_name_decl [block_name] (Mangled.to_string vname) in - let fname = General_utils.mk_class_field_name qual_name in + let qual_name = CAst_utils.make_qual_name_decl [block_name] (Mangled.to_string vname) in + let fname = CGeneral_utils.mk_class_field_name qual_name in let item_annot = Annot.Item.empty in fname, typ, item_annot in let fields = IList.map mk_field_from_captured_var captured_vars in @@ -403,7 +402,7 @@ struct match unary_expr_or_type_trait_expr_info.Clang_ast_t.uttei_kind with | `SizeOf -> let tp = - Ast_utils.type_from_unary_expr_or_type_trait_expr_info + CAst_utils.type_from_unary_expr_or_type_trait_expr_info unary_expr_or_type_trait_expr_info in let sizeof_typ = match tp with @@ -449,7 +448,7 @@ struct | _ when CTrans_models.is_retain_builtin name type_ptr -> Some BuiltinDecl.__objc_retain_cf | _ when name = CFrontend_config.malloc && - General_utils.is_objc_extension trans_unit_ctx -> + CGeneral_utils.is_objc_extension trans_unit_ctx -> Some BuiltinDecl.malloc_no_fail | _ -> None @@ -457,10 +456,10 @@ struct let function_deref_trans trans_state decl_ref = let open CContext in let context = trans_state.context in - let name_info, decl_ptr, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in - let decl_opt = Ast_utils.get_function_decl_with_body decl_ptr in + let name_info, decl_ptr, type_ptr = CAst_utils.get_info_from_decl_ref decl_ref in + let decl_opt = CAst_utils.get_function_decl_with_body decl_ptr in Option.iter ~f:(call_translation context) decl_opt; - let name = Ast_utils.get_qualified_name name_info in + let name = CAst_utils.get_qualified_name name_info in let typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in let pname = match get_builtin_pname_opt context.translation_unit_context name decl_opt type_ptr with @@ -472,7 +471,7 @@ struct let open CContext in let context = trans_state.context in let sil_loc = CLocation.get_sil_location stmt_info context in - let name_info, _, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in + let name_info, _, type_ptr = CAst_utils.get_info_from_decl_ref decl_ref in Logging.out_debug "!!!!! Dealing with field '%s' @." name_info.Clang_ast_t.ni_name; let field_typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in let (obj_sil, class_typ) = extract_exp_from_list pre_trans_result.exps @@ -485,7 +484,7 @@ struct | Typ.Tptr (t, _) -> t | t -> t in Logging.out_debug "Type is '%s' @." (Typ.to_string class_typ); - let field_name = General_utils.mk_class_field_name name_info in + let field_name = CGeneral_utils.mk_class_field_name name_info in let field_exp = Exp.Lfield (obj_sil, field_name, class_typ) in (* In certain cases, there is be no LValueToRValue cast, but backend needs dereference*) (* there either way:*) @@ -509,11 +508,11 @@ struct let open CContext in let context = trans_state.context in let sil_loc = CLocation.get_sil_location stmt_info context in - let name_info, decl_ptr, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in - let decl_opt = Ast_utils.get_function_decl_with_body decl_ptr in + let name_info, decl_ptr, type_ptr = CAst_utils.get_info_from_decl_ref decl_ref in + let decl_opt = CAst_utils.get_function_decl_with_body decl_ptr in Option.iter ~f:(call_translation context) decl_opt; - let method_name = Ast_utils.get_unqualified_name name_info in - let class_name = Ast_utils.get_class_name_from_member name_info in + let method_name = CAst_utils.get_unqualified_name name_info in + let class_name = CAst_utils.get_class_name_from_member name_info in Logging.out_debug "!!!!! Dealing with method '%s' @." method_name; let method_typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in let ms_opt = CMethod_trans.method_signature_of_pointer @@ -548,7 +547,7 @@ struct (* unlike field access, for method calls there is no need to expand class type *) (* use qualified method name for builtin matching, but use unqualified name elsewhere *) - let qual_method_name = Ast_utils.get_qualified_name name_info in + let qual_method_name = CAst_utils.get_qualified_name name_info in let pname = match get_builtin_pname_opt context.translation_unit_context qual_method_name decl_opt type_ptr with @@ -565,7 +564,7 @@ struct let destructor_deref_trans trans_state pvar_trans_result class_type_ptr si = let open Clang_ast_t in - let destruct_decl_ref_opt = match Ast_utils.get_decl_from_typ_ptr class_type_ptr with + let destruct_decl_ref_opt = match CAst_utils.get_decl_from_typ_ptr class_type_ptr with | Some CXXRecordDecl (_, _, _ , _, _, _, _, cxx_record_info) | Some ClassTemplateSpecializationDecl (_, _, _, _, _, _, _, cxx_record_info, _) -> cxx_record_info.xrdi_destructor @@ -605,12 +604,12 @@ struct and var_deref_trans trans_state stmt_info (decl_ref : Clang_ast_t.decl_ref) = let context = trans_state.context in - let _, _, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in + let _, _, type_ptr = CAst_utils.get_info_from_decl_ref decl_ref in let ast_typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in let typ = match ast_typ with | Tstruct _ when decl_ref.dr_kind = `ParmVar -> - if General_utils.is_cpp_translation context.translation_unit_context then + if CGeneral_utils.is_cpp_translation context.translation_unit_context then Typ.Tptr (ast_typ, Pk_reference) else ast_typ | _ -> ast_typ in @@ -625,11 +624,11 @@ struct (* place where it is used *) let trans_result' = let is_global_const, init_expr = - match Ast_utils.get_decl decl_ref.dr_decl_pointer with + match CAst_utils.get_decl decl_ref.dr_decl_pointer with | Some VarDecl (_, _, qual_type, vdi) -> ( match ast_typ with | Tstruct _ - when not (General_utils.is_cpp_translation context.translation_unit_context) -> + when not (CGeneral_utils.is_cpp_translation context.translation_unit_context) -> (* Do not convert a global struct to a local because SIL values do not include structs, they must all be heap-allocated *) (false, None) @@ -688,7 +687,7 @@ struct (* evaluates an enum constant *) and enum_const_eval context enum_constant_pointer prev_enum_constant_opt zero = - match Ast_utils.get_decl enum_constant_pointer with + match CAst_utils.get_decl enum_constant_pointer with | Some Clang_ast_t.EnumConstantDecl (_, _, _, enum_constant_decl_info) -> (match enum_constant_decl_info.Clang_ast_t.ecdi_init_expr with | Some stmt -> @@ -707,18 +706,18 @@ struct let zero = Exp.Const (Const.Cint IntLit.zero) in try let (prev_enum_constant_opt, sil_exp_opt) = - Ast_utils.get_enum_constant_exp enum_constant_pointer in + CAst_utils.get_enum_constant_exp enum_constant_pointer in match sil_exp_opt with | Some exp -> exp | None -> let exp = enum_const_eval context enum_constant_pointer prev_enum_constant_opt zero in - Ast_utils.update_enum_map enum_constant_pointer exp; + CAst_utils.update_enum_map enum_constant_pointer exp; exp with Not_found -> zero and enum_constant_trans trans_state decl_ref = let context = trans_state.context in - let _, _, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in + let _, _, type_ptr = CAst_utils.get_info_from_decl_ref decl_ref in let typ = CType_decl.type_ptr_to_sil_type context.CContext.tenv type_ptr in let const_exp = get_enum_constant_expr context decl_ref.Clang_ast_t.dr_decl_pointer in { empty_res_trans with exps = [(const_exp, typ)] } @@ -807,7 +806,7 @@ struct if (is_binary_assign_op binary_operator_info) (* assignment operator result is lvalue in CPP, rvalue in C, *) (* hence the difference *) - && (not (General_utils.is_cpp_translation context.translation_unit_context)) + && (not (CGeneral_utils.is_cpp_translation context.translation_unit_context)) && ((not creating_node) || (is_return_temp trans_state.continuation)) then ( (* We are in this case when an assignment is inside *) (* another operator that creates a node. Eg. another *) @@ -1104,7 +1103,7 @@ struct and block_enumeration_trans trans_state stmt_info stmt_list ei = Logging.out_debug "\n Call to a block enumeration function treated as special case...\n@."; let procname = Procdesc.get_proc_name trans_state.context.CContext.procdesc in - let pvar = CFrontend_utils.General_utils.get_next_block_pvar procname in + let pvar = CGeneral_utils.get_next_block_pvar procname in let transformed_stmt, _ = Ast_expressions.translate_block_enumerate (Pvar.to_string pvar) stmt_info stmt_list ei in instruction trans_state transformed_stmt @@ -1834,7 +1833,7 @@ struct (* This gives the differnece among cast operations kind*) let is_objc_bridged_cast_expr _ stmt = match stmt with | Clang_ast_t.ObjCBridgedCastExpr _ -> true | _ -> false in - let is_objc_bridged = Ast_utils.exists_eventually_st is_objc_bridged_cast_expr () stmt in + let is_objc_bridged = CAst_utils.exists_eventually_st is_objc_bridged_cast_expr () stmt in let cast_inst, cast_exp = cast_operation trans_state cast_kind res_trans_stmt.exps typ sil_loc is_objc_bridged in { res_trans_stmt with @@ -1983,7 +1982,7 @@ struct let dictionary_literal_s = Procname.get_method dictionary_literal_pname in let obj_c_message_expr_info = Ast_expressions.make_obj_c_message_expr_info_class dictionary_literal_s typ None in - let stmts = General_utils.swap_elements_list stmts in + let stmts = CGeneral_utils.swap_elements_list stmts in let stmts = stmts @ [Ast_expressions.create_nil stmt_info] in let message_stmt = Clang_ast_t.ObjCMessageExpr @@ -2046,7 +2045,7 @@ struct | Clang_ast_t.BlockDecl (_, block_decl_info) -> let open CContext in let type_ptr = expr_info.Clang_ast_t.ei_type_ptr in - let block_pname = CFrontend_utils.General_utils.mk_fresh_block_procname procname in + let block_pname = CGeneral_utils.mk_fresh_block_procname procname in let typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in (* We need to set the explicit dependency between the newly created block and the *) (* defining procedure. We add an edge in the call graph.*) @@ -2093,7 +2092,7 @@ struct | _ -> let stmt_res_trans = if is_dyn_array then let init_stmt_info = { stmt_info with - Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer () } in + Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer () } in init_expr_trans trans_state' (var_exp_inside, typ_inside) init_stmt_info (Some stmt) else instruction trans_state' stmt in stmt_res_trans :: rest_stmts_res_trans @@ -2121,7 +2120,7 @@ struct let is_dyn_array = cxx_new_expr_info.Clang_ast_t.xnei_is_array in let size_exp_opt, res_trans_size = if is_dyn_array then - match Ast_utils.get_stmt_opt cxx_new_expr_info.Clang_ast_t.xnei_array_size_expr with + match CAst_utils.get_stmt_opt cxx_new_expr_info.Clang_ast_t.xnei_array_size_expr with | Some stmt -> let trans_state_size = { trans_state_pri with succ_nodes = []; } in let res_trans_size = instruction trans_state_size stmt in @@ -2131,7 +2130,7 @@ struct | None -> Some (Exp.Const (Const.Cint (IntLit.minus_one))), empty_res_trans else None, empty_res_trans in let res_trans_new = cpp_new_trans sil_loc typ size_exp_opt in - let stmt_opt = Ast_utils.get_stmt_opt cxx_new_expr_info.Clang_ast_t.xnei_initializer_expr in + let stmt_opt = CAst_utils.get_stmt_opt cxx_new_expr_info.Clang_ast_t.xnei_initializer_expr in let trans_state_init = { trans_state_pri with succ_nodes = []; } in let var_exp_typ = match res_trans_new.exps with | [var_exp, Typ.Tptr (t, _)] -> (var_exp, t) @@ -2139,7 +2138,7 @@ struct (* Need a new stmt_info for the translation of the initializer, so that it can create nodes *) (* if it needs to, with the same stmt_info it doesn't work. *) let init_stmt_info = { stmt_info with - Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer () } in + Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer () } in let res_trans_init = if is_dyn_array && Typ.is_pointer_to_cpp_class typ then let rec create_stmts stmt_opt size_exp_opt = @@ -2182,7 +2181,7 @@ struct let deleted_type = delete_expr_info.Clang_ast_t.xdei_destroyed_type in (* create stmt_info with new pointer so that destructor call doesn't create a node *) let destruct_stmt_info = { stmt_info with - Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer () } in + Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer () } in (* use empty_res_trans to avoid ending up with same instruction twice *) (* otherwise it would happen due to structutre of all_res_trans *) let this_res_trans_destruct = { empty_res_trans with exps = result_trans_param.exps } in @@ -2290,8 +2289,8 @@ struct let sil_fun = Exp.Const (Const.Cfun fun_name) in let ret_id = Ident.create_fresh Ident.knormal in let type_info_objc = (Exp.Sizeof (typ, None, Subtype.exact), Typ.Tvoid) in - let field_name_decl = Ast_utils.make_qual_name_decl ["type_info"; "std"] "__type_name" in - let field_name = General_utils.mk_class_field_name field_name_decl in + let field_name_decl = CAst_utils.make_qual_name_decl ["type_info"; "std"] "__type_name" in + let field_name = CGeneral_utils.mk_class_field_name field_name_decl in let ret_exp = Exp.Var ret_id in let field_exp = Exp.Lfield (ret_exp, field_name, typ) in let args = [type_info_objc; (field_exp, Typ.Tvoid)] @ res_trans_subexpr.exps in @@ -2572,7 +2571,7 @@ struct | CXXTryStmt (_, stmts) -> (Logging.out "\n!!!!WARNING: found statement %s. \nTranslation need to be improved.... \n" - (Ast_utils.string_of_stmt instr); + (CAst_utils.string_of_stmt instr); compoundStmt_trans trans_state stmts) | ObjCAtThrowStmt (stmt_info, stmts) @@ -2652,7 +2651,7 @@ struct | s -> (Logging.out "\n!!!!WARNING: found statement %s. \nACTION REQUIRED: \ Translation need to be defined. Statement ignored.... \n" - (Ast_utils.string_of_stmt s); + (CAst_utils.string_of_stmt s); assert false) (* Function similar to instruction function, but it takes C++ constructor initializer as diff --git a/infer/src/clang/cTrans_models.ml b/infer/src/clang/cTrans_models.ml index c6986c880..e3c0b0440 100644 --- a/infer/src/clang/cTrans_models.ml +++ b/infer/src/clang/cTrans_models.ml @@ -9,7 +9,6 @@ open! IStd -open CFrontend_utils open Objc_models let is_cf_non_null_alloc pname = @@ -70,9 +69,9 @@ let is_modeled_attribute attr_name = IList.mem String.equal attr_name CFrontend_config.modeled_function_attributes let get_first_param_typedef_string_opt type_ptr = - match Ast_utils.get_desugared_type type_ptr with + match CAst_utils.get_desugared_type type_ptr with | Some Clang_ast_t.FunctionProtoType (_, _, {pti_params_type = [param_ptr]}) -> - Ast_utils.name_opt_of_typedef_type_ptr param_ptr + CAst_utils.name_opt_of_typedef_type_ptr param_ptr | _ -> None let is_release_builtin funct fun_type = diff --git a/infer/src/clang/cTrans_utils.ml b/infer/src/clang/cTrans_utils.ml index bd1ae9a6f..207fb5ce3 100644 --- a/infer/src/clang/cTrans_utils.ml +++ b/infer/src/clang/cTrans_utils.ml @@ -12,8 +12,6 @@ module Hashtbl = Caml.Hashtbl (** Utility methods to support the translation of clang ast constructs into sil instructions. *) -open CFrontend_utils - module L = Logging (* Extract the element of a singleton list. If the list is not a singleton *) @@ -337,7 +335,7 @@ let objc_new_trans trans_state loc stmt_info cls_name function_type = let is_instance = true in let call_flags = { CallFlags.default with CallFlags.cf_virtual = is_instance; } in let pname = - General_utils.mk_procname_from_objc_method + CGeneral_utils.mk_procname_from_objc_method cls_name CFrontend_config.init Procname.ObjCInstanceMethod in CMethod_trans.create_external_procdesc trans_state.context.CContext.cfg pname is_instance None; let args = [(alloc_ret_exp, alloc_ret_type)] in @@ -716,7 +714,7 @@ let is_block_enumerate_function mei = (* be a list of LField expressions *) let var_or_zero_in_init_list tenv e typ ~return_zero:return_zero = let rec var_or_zero_in_init_list' e typ tns = - let open General_utils in + let open CGeneral_utils in match typ with | Typ.Tstruct tn -> ( match Tenv.lookup tenv tn with diff --git a/infer/src/clang/cType_to_sil_type.ml b/infer/src/clang/cType_to_sil_type.ml index 40b6d651d..ca792c8fb 100644 --- a/infer/src/clang/cType_to_sil_type.ml +++ b/infer/src/clang/cType_to_sil_type.ml @@ -9,8 +9,6 @@ open! IStd -open CFrontend_utils - let get_builtin_objc_typename builtin_type = match builtin_type with | `ObjCId -> Typename.TN_csu (Csu.Struct, (Mangled.from_string CFrontend_config.objc_object)) @@ -69,7 +67,7 @@ let rec build_array_type translate_decl tenv type_ptr n_opt = and sil_type_of_attr_type translate_decl tenv type_info attr_info = match type_info.Clang_ast_t.ti_desugared_type with | Some type_ptr -> - (match Ast_utils.get_type type_ptr with + (match CAst_utils.get_type type_ptr with | Some Clang_ast_t.ObjCObjectPointerType (_, {Clang_ast_t.qt_type_ptr}) -> let typ = type_ptr_to_sil_type translate_decl tenv qt_type_ptr in Typ.Tptr (typ, pointer_attribute_of_objc_attribute attr_info) @@ -132,7 +130,7 @@ and decl_ptr_to_sil_type translate_decl tenv decl_ptr = let typ = `DeclPtr decl_ptr in try Clang_ast_types.TypePointerMap.find typ !CFrontend_config.sil_types_map with Not_found -> - match Ast_utils.get_decl decl_ptr with + match CAst_utils.get_decl decl_ptr with | Some (CXXRecordDecl _ as d) | Some (RecordDecl _ as d) | Some (ClassTemplateSpecializationDecl _ as d) @@ -155,10 +153,10 @@ and clang_type_ptr_to_sil_type translate_decl tenv type_ptr = try Clang_ast_types.TypePointerMap.find type_ptr !CFrontend_config.sil_types_map with Not_found -> - (match Ast_utils.get_type type_ptr with + (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 - Ast_utils.update_sil_types_map type_ptr sil_type; + CAst_utils.update_sil_types_map type_ptr sil_type; sil_type | _ -> Typ.Tvoid) diff --git a/infer/src/clang/cVar_decl.ml b/infer/src/clang/cVar_decl.ml index 2ca584d9e..8959148fa 100644 --- a/infer/src/clang/cVar_decl.ml +++ b/infer/src/clang/cVar_decl.ml @@ -12,8 +12,6 @@ open! IStd (** Process variable declarations by saving them as local or global variables. *) (** Computes the local variables of a function or method to be added to the procdesc *) -open CFrontend_utils - module L = Logging let is_custom_var_pointer pointer = @@ -29,11 +27,11 @@ let sil_var_of_decl context var_decl procname = not (is_custom_var_pointer decl_info.Clang_ast_t.di_pointer) in let var_decl_details = Some (decl_info, qual_type, var_decl_info, shoud_be_mangled) in - General_utils.mk_sil_var trans_unit_ctx name_info var_decl_details procname outer_procname + CGeneral_utils.mk_sil_var trans_unit_ctx name_info var_decl_details procname outer_procname | ParmVarDecl (decl_info, name_info, qual_type, var_decl_info) -> let var_decl_details = Some (decl_info, qual_type, var_decl_info, false) in - General_utils.mk_sil_var trans_unit_ctx name_info var_decl_details procname outer_procname + CGeneral_utils.mk_sil_var trans_unit_ctx name_info var_decl_details procname outer_procname | _ -> assert false let sil_var_of_decl_ref context decl_ref procname = @@ -46,11 +44,11 @@ let sil_var_of_decl_ref context decl_ref procname = | `ImplicitParam -> let outer_procname = CContext.get_outer_procname context in let trans_unit_ctx = context.CContext.translation_unit_context in - General_utils.mk_sil_var trans_unit_ctx name None procname outer_procname + CGeneral_utils.mk_sil_var trans_unit_ctx name None procname outer_procname | _ -> if is_custom_var_pointer pointer then Pvar.mk (Mangled.from_string name.Clang_ast_t.ni_name) procname - else match Ast_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with + else match CAst_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with | Some var_decl -> sil_var_of_decl context var_decl procname | None -> assert false diff --git a/infer/src/clang/objcCategory_decl.ml b/infer/src/clang/objcCategory_decl.ml index 3305cc26f..9c14a7f16 100644 --- a/infer/src/clang/objcCategory_decl.ml +++ b/infer/src/clang/objcCategory_decl.ml @@ -9,8 +9,6 @@ open! IStd -open CFrontend_utils - module L = Logging (** In this module an ObjC category declaration or implementation is processed. The category *) @@ -22,7 +20,7 @@ let noname_category class_name = let cat_class_decl dr = match dr.Clang_ast_t.dr_name with - | Some n -> Ast_utils.get_qualified_name n + | Some n -> CAst_utils.get_qualified_name n | _ -> assert false let get_curr_class_from_category name decl_ref_opt = @@ -40,15 +38,15 @@ let get_curr_class_from_category_impl name ocidi = let add_category_decl type_ptr_to_sil_type tenv category_impl_info = let decl_ref_opt = category_impl_info.Clang_ast_t.ocidi_category_decl in - Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true + CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true let add_class_decl type_ptr_to_sil_type tenv category_decl_info = let decl_ref_opt = category_decl_info.Clang_ast_t.odi_class_interface in - Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true + CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true let add_category_implementation type_ptr_to_sil_type tenv category_decl_info = let decl_ref_opt = category_decl_info.Clang_ast_t.odi_implementation in - Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false + CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false let get_base_class_name_from_category decl = let open Clang_ast_t in @@ -61,9 +59,9 @@ let get_base_class_name_from_category decl = | _ -> None in match base_class_pointer_opt with | Some decl_ref -> - (match Ast_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with + (match CAst_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with | Some ObjCInterfaceDecl (_, name_info, _, _, _) -> - Some (Ast_utils.get_qualified_name name_info) + Some (CAst_utils.get_qualified_name name_info) | _ -> None) | None -> None @@ -76,11 +74,11 @@ let process_category type_ptr_to_sil_type tenv curr_class decl_info decl_list = let mang_name = Mangled.from_string class_name in let class_tn_name = Typename.TN_csu (Csu.Class Csu.Objc, mang_name) in let decl_key = `DeclPtr decl_info.Clang_ast_t.di_pointer in - Ast_utils.update_sil_types_map decl_key (Typ.Tstruct class_tn_name); + CAst_utils.update_sil_types_map decl_key (Typ.Tstruct class_tn_name); (match Tenv.lookup tenv class_tn_name with | Some ({ fields; methods } as struct_typ) -> - let new_fields = General_utils.append_no_duplicates_fields decl_fields fields in - let new_methods = General_utils.append_no_duplicates_methods decl_methods methods in + let new_fields = CGeneral_utils.append_no_duplicates_fields decl_fields fields in + let new_methods = CGeneral_utils.append_no_duplicates_methods decl_methods methods in ignore( Tenv.mk_struct tenv ~default:struct_typ ~fields:new_fields ~statics:[] ~methods:new_methods class_tn_name ); @@ -92,7 +90,7 @@ let category_decl type_ptr_to_sil_type tenv decl = let open Clang_ast_t in match decl with | ObjCCategoryDecl (decl_info, name_info, decl_list, _, cdi) -> - let name = Ast_utils.get_qualified_name name_info in + let name = CAst_utils.get_qualified_name name_info in let curr_class = get_curr_class_from_category_decl name cdi in Logging.out_debug "ADDING: ObjCCategoryDecl for '%s'\n" name; let _ = add_class_decl type_ptr_to_sil_type tenv cdi in @@ -105,11 +103,10 @@ let category_impl_decl type_ptr_to_sil_type tenv decl = let open Clang_ast_t in match decl with | ObjCCategoryImplDecl (decl_info, name_info, decl_list, _, cii) -> - let name = Ast_utils.get_qualified_name name_info in + let name = CAst_utils.get_qualified_name name_info in let curr_class = get_curr_class_from_category_impl name cii in Logging.out_debug "ADDING: ObjCCategoryImplDecl for '%s'\n" name; let _ = add_category_decl type_ptr_to_sil_type tenv cii in let typ = process_category type_ptr_to_sil_type tenv curr_class decl_info decl_list in typ | _ -> assert false - diff --git a/infer/src/clang/objcCategory_decl.mli b/infer/src/clang/objcCategory_decl.mli index 40b3d662e..6b5b74ee4 100644 --- a/infer/src/clang/objcCategory_decl.mli +++ b/infer/src/clang/objcCategory_decl.mli @@ -12,11 +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 *) -open CFrontend_utils +val category_decl : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t -val category_decl : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t - -val category_impl_decl : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t +val category_impl_decl : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t val noname_category : string -> string diff --git a/infer/src/clang/objcInterface_decl.ml b/infer/src/clang/objcInterface_decl.ml index 6a3bd71f8..018ec289f 100644 --- a/infer/src/clang/objcInterface_decl.ml +++ b/infer/src/clang/objcInterface_decl.ml @@ -16,8 +16,6 @@ open! IStd (* ObjectiveC doesn't have a notion of static or class fields. *) (* So, in this module we translate a class into a sil srtuct with an empty list of static fields.*) -open CFrontend_utils - module L = Logging let is_pointer_to_objc_class typ = @@ -27,13 +25,13 @@ let is_pointer_to_objc_class typ = let get_super_interface_decl otdi_super = match otdi_super with - | Some dr -> Ast_utils.name_opt_of_name_info_opt dr.Clang_ast_t.dr_name + | Some dr -> CAst_utils.name_opt_of_name_info_opt dr.Clang_ast_t.dr_name | _ -> None let get_protocols protocols = let protocol_names = IList.map ( fun decl -> match decl.Clang_ast_t.dr_name with - | Some name_info -> Ast_utils.get_qualified_name name_info + | Some name_info -> CAst_utils.get_qualified_name name_info | None -> assert false ) protocols in protocol_names @@ -47,30 +45,30 @@ let get_curr_class_impl oi = let open Clang_ast_t in match oi.Clang_ast_t.oidi_class_interface with | Some decl_ref -> - (match Ast_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with + (match CAst_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with | Some ObjCInterfaceDecl (_, name_info, _, _, obj_c_interface_decl_info) -> - let class_name = Ast_utils.get_qualified_name name_info in + let class_name = CAst_utils.get_qualified_name name_info in get_curr_class class_name obj_c_interface_decl_info | _ -> assert false) | _ -> assert false let add_class_decl type_ptr_to_sil_type tenv idi = let decl_ref_opt = idi.Clang_ast_t.oidi_class_interface in - Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true + CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true let add_super_class_decl type_ptr_to_sil_type tenv ocdi = let decl_ref_opt = ocdi.Clang_ast_t.otdi_super in - Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false + CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false let add_protocols_decl type_ptr_to_sil_type tenv protocols = - Ast_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv protocols + CAst_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv protocols let add_categories_decl type_ptr_to_sil_type tenv categories = - Ast_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv categories + CAst_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv categories let add_class_implementation type_ptr_to_sil_type tenv idi = let decl_ref_opt = idi.Clang_ast_t.otdi_implementation in - Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false + CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false (*The superclass is the first element in the list of super classes of structs in the tenv, *) (* then come the protocols and categories. *) @@ -95,11 +93,11 @@ let create_supers_fields type_ptr_to_sil_type tenv curr_class decl_list (* Adds pairs (interface name, interface_type_info) to the global environment. *) let add_class_to_tenv type_ptr_to_sil_type tenv curr_class decl_info name_info decl_list ocidi = - let class_name = Ast_utils.get_qualified_name name_info in + let class_name = CAst_utils.get_qualified_name name_info in Logging.out_debug "ADDING: ObjCInterfaceDecl for '%s'\n" class_name; let interface_name = CType.mk_classname class_name Csu.Objc in let decl_key = `DeclPtr decl_info.Clang_ast_t.di_pointer in - Ast_utils.update_sil_types_map decl_key (Typ.Tstruct interface_name); + CAst_utils.update_sil_types_map decl_key (Typ.Tstruct interface_name); let supers, fields = create_supers_fields type_ptr_to_sil_type tenv curr_class decl_list ocidi.Clang_ast_t.otdi_super @@ -113,14 +111,14 @@ let add_class_to_tenv type_ptr_to_sil_type tenv curr_class decl_info name_info d let fields, (supers : Typename.t list), methods = match Tenv.lookup tenv interface_name with | Some ({ fields; supers; methods }) -> - General_utils.append_no_duplicates_fields fields fields, - General_utils.append_no_duplicates_csu supers supers, - General_utils.append_no_duplicates_methods methods methods + CGeneral_utils.append_no_duplicates_fields fields fields, + CGeneral_utils.append_no_duplicates_csu supers supers, + CGeneral_utils.append_no_duplicates_methods methods methods | _ -> fields, supers, methods in - let fields = General_utils.append_no_duplicates_fields fields fields_sc in + let fields = CGeneral_utils.append_no_duplicates_fields fields fields_sc in (* We add the special hidden counter_field for implementing reference counting *) let modelled_fields = StructTyp.objc_ref_counter_field :: CField_decl.modelled_field name_info in - let all_fields = General_utils.append_no_duplicates_fields modelled_fields fields in + let all_fields = CGeneral_utils.append_no_duplicates_fields modelled_fields fields in Logging.out_debug "Class %s field:\n" class_name; IList.iter (fun (fn, _, _) -> Logging.out_debug "-----> field: '%s'\n" (Ident.fieldname_to_string fn)) all_fields; @@ -140,11 +138,11 @@ let add_missing_methods tenv class_name ck decl_info decl_list curr_class = let decl_methods = ObjcProperty_decl.get_methods curr_class decl_list in let class_tn_name = Typename.TN_csu (Csu.Class ck, (Mangled.from_string class_name)) in let decl_key = `DeclPtr decl_info.Clang_ast_t.di_pointer in - Ast_utils.update_sil_types_map decl_key (Typ.Tstruct class_tn_name); + CAst_utils.update_sil_types_map decl_key (Typ.Tstruct class_tn_name); begin match class_tn_name, Tenv.lookup tenv class_tn_name with | TN_csu (Class _, _), Some ({ statics = []; methods; } as struct_typ) -> - let methods = General_utils.append_no_duplicates_methods methods decl_methods in + let methods = CGeneral_utils.append_no_duplicates_methods methods decl_methods in ignore( Tenv.mk_struct tenv ~default:struct_typ ~methods class_tn_name ) | _ -> () end; @@ -155,7 +153,7 @@ let interface_declaration type_ptr_to_sil_type tenv decl = let open Clang_ast_t in match decl with | ObjCInterfaceDecl (decl_info, name_info, decl_list, _, ocidi) -> - let name = Ast_utils.get_qualified_name name_info in + let name = CAst_utils.get_qualified_name name_info in let curr_class = get_curr_class name ocidi in let typ = add_class_to_tenv type_ptr_to_sil_type tenv curr_class decl_info name_info decl_list ocidi in @@ -172,7 +170,7 @@ let interface_impl_declaration type_ptr_to_sil_type tenv decl = let open Clang_ast_t in match decl with | ObjCImplementationDecl (decl_info, name_info, decl_list, _, idi) -> - let class_name = Ast_utils.get_qualified_name name_info in + let class_name = CAst_utils.get_qualified_name name_info in Logging.out_debug "ADDING: ObjCImplementationDecl for class '%s'\n" class_name; let _ = add_class_decl type_ptr_to_sil_type tenv idi in let curr_class = get_curr_class_impl idi in diff --git a/infer/src/clang/objcInterface_decl.mli b/infer/src/clang/objcInterface_decl.mli index ca4ce2be4..afb9c6c7d 100644 --- a/infer/src/clang/objcInterface_decl.mli +++ b/infer/src/clang/objcInterface_decl.mli @@ -11,12 +11,11 @@ open! IStd (** In this module an ObjC interface declaration is processed. The class is saved in the tenv as a struct with the corresponding fields, potential superclass and list of defined methods *) -open CFrontend_utils -val interface_declaration : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> +val interface_declaration : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t -val interface_impl_declaration : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> +val interface_impl_declaration : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t val is_pointer_to_objc_class : Typ.t -> bool diff --git a/infer/src/clang/objcProperty_decl.ml b/infer/src/clang/objcProperty_decl.ml index 57919a7b2..87e37d11a 100644 --- a/infer/src/clang/objcProperty_decl.ml +++ b/infer/src/clang/objcProperty_decl.ml @@ -17,8 +17,6 @@ open! IStd (* - Second, in the class implementation, if synthetize is available, create the getters and setters, *) (* unless some of these methods has already been created before. *) -open CFrontend_utils - let is_strong_property obj_c_property_decl_info = let attrs = obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes in IList.exists (fun a -> match a with @@ -41,7 +39,8 @@ let get_methods curr_class decl_list = let method_kind = Procname.objc_method_kind_of_bool is_instance in let method_name = name_info.Clang_ast_t.ni_name in Logging.out_debug " ...Adding Method '%s' \n" (class_name^"_"^method_name); - let meth_name = General_utils.mk_procname_from_objc_method class_name method_name method_kind in + let meth_name = + CGeneral_utils.mk_procname_from_objc_method class_name method_name method_kind in meth_name:: list_methods | _ -> list_methods in IList.fold_right get_method decl_list [] diff --git a/infer/src/clang/objcProtocol_decl.ml b/infer/src/clang/objcProtocol_decl.ml index 735529377..13e5f2c26 100644 --- a/infer/src/clang/objcProtocol_decl.ml +++ b/infer/src/clang/objcProtocol_decl.ml @@ -9,19 +9,17 @@ open! IStd -open CFrontend_utils - module L = Logging let add_protocol_super type_ptr_to_sil_type tenv obj_c_protocol_decl_info = let protocols = obj_c_protocol_decl_info.Clang_ast_t.opcdi_protocols in - Ast_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv protocols + CAst_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv protocols let protocol_decl type_ptr_to_sil_type tenv decl = let open Clang_ast_t in match decl with | ObjCProtocolDecl(decl_info, name_info, decl_list, _, obj_c_protocol_decl_info) -> - let name = Ast_utils.get_qualified_name name_info in + let name = CAst_utils.get_qualified_name name_info in let curr_class = CContext.ContextProtocol name in (* Adds pairs (protocol name, protocol_type_info) to the global environment. *) (* Protocol_type_info contains the methods composing the protocol. *) @@ -31,7 +29,7 @@ let protocol_decl type_ptr_to_sil_type tenv decl = let mang_name = Mangled.from_string name in let protocol_name = Typename.TN_csu (Csu.Protocol, mang_name) in let decl_key = `DeclPtr decl_info.Clang_ast_t.di_pointer in - Ast_utils.update_sil_types_map decl_key (Typ.Tstruct protocol_name); + CAst_utils.update_sil_types_map decl_key (Typ.Tstruct protocol_name); let methods = ObjcProperty_decl.get_methods curr_class decl_list in ignore( Tenv.mk_struct tenv ~methods protocol_name ); add_protocol_super type_ptr_to_sil_type tenv obj_c_protocol_decl_info; diff --git a/infer/src/clang/objcProtocol_decl.mli b/infer/src/clang/objcProtocol_decl.mli index b4e436103..f4b302772 100644 --- a/infer/src/clang/objcProtocol_decl.mli +++ b/infer/src/clang/objcProtocol_decl.mli @@ -12,8 +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 *) -open CFrontend_utils - -val protocol_decl : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t +val protocol_decl : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t val is_protocol : Clang_ast_t.decl -> bool diff --git a/infer/src/clang/predicates.ml b/infer/src/clang/predicates.ml index 9487d660a..df003825a 100644 --- a/infer/src/clang/predicates.ml +++ b/infer/src/clang/predicates.ml @@ -9,8 +9,6 @@ open! IStd -open CFrontend_utils - let get_available_attr_ios_sdk decl = let open Clang_ast_t in let decl_info = Clang_ast_proj.get_decl_tuple decl in @@ -30,7 +28,7 @@ let get_ivar_attributes ivar_decl = let open Clang_ast_t in match ivar_decl with | ObjCIvarDecl (ivar_decl_info, _, _, _, _) -> - (match Ast_utils.get_property_of_ivar ivar_decl_info.Clang_ast_t.di_pointer with + (match CAst_utils.get_property_of_ivar ivar_decl_info.Clang_ast_t.di_pointer with | Some ObjCPropertyDecl (_, _, obj_c_property_decl_info) -> obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes | _ -> []) @@ -40,11 +38,11 @@ let get_ivar_attributes ivar_decl = let captured_variables_cxx_ref dec = let capture_var_is_cxx_ref reference_captured_vars captured_var = let decl_ref_opt = captured_var.Clang_ast_t.bcv_variable in - match Ast_utils.get_decl_opt_with_decl_ref decl_ref_opt with + match CAst_utils.get_decl_opt_with_decl_ref decl_ref_opt with | Some VarDecl (_, named_decl_info, qual_type, _) | Some ParmVarDecl (_, named_decl_info, qual_type, _) | Some ImplicitParamDecl (_, named_decl_info, qual_type, _) -> - (match Ast_utils.get_desugared_type qual_type.Clang_ast_t.qt_type_ptr with + (match CAst_utils.get_desugared_type qual_type.Clang_ast_t.qt_type_ptr with | Some RValueReferenceType _ | Some LValueReferenceType _ -> named_decl_info::reference_captured_vars | _ -> reference_captured_vars) @@ -81,25 +79,25 @@ let property_name_contains_word word decl = | _ -> false let is_objc_extension lcxt = - General_utils.is_objc_extension lcxt.CLintersContext.translation_unit_context + CGeneral_utils.is_objc_extension lcxt.CLintersContext.translation_unit_context let is_syntactically_global_var decl = - Ast_utils.is_syntactically_global_var decl + CAst_utils.is_syntactically_global_var decl let is_const_expr_var decl = - Ast_utils.is_const_expr_var decl + CAst_utils.is_const_expr_var decl let decl_ref_is_in names st = match st with | Clang_ast_t.DeclRefExpr (_, _, _, drti) -> (match drti.drti_decl_ref with - | Some dr -> let ndi, _, _ = CFrontend_utils.Ast_utils.get_info_from_decl_ref dr in + | Some dr -> let ndi, _, _ = CAst_utils.get_info_from_decl_ref dr in IList.exists (fun n -> n = ndi.ni_name) names | _ -> false) | _ -> false let call_function_named names st = - Ast_utils.exists_eventually_st decl_ref_is_in names st + CAst_utils.exists_eventually_st decl_ref_is_in names st let is_strong_property decl = match decl with @@ -117,12 +115,12 @@ let is_property_pointer_type decl = let open Clang_ast_t in match decl with | ObjCPropertyDecl (_, _, pdi) -> - (match Ast_utils.get_desugared_type pdi.opdi_type_ptr with + (match CAst_utils.get_desugared_type pdi.opdi_type_ptr with | Some MemberPointerType _ | Some ObjCObjectPointerType _ | Some BlockPointerType _ -> true | Some TypedefType (_, tti) -> - (Ast_utils.name_of_typedef_type_info tti) = CFrontend_config.id_cl + (CAst_utils.name_of_typedef_type_info tti) = CFrontend_config.id_cl | exception Not_found -> false | _ -> false) | _ -> false @@ -136,10 +134,10 @@ let is_ivar_atomic stmt = | Clang_ast_t.ObjCIvarRefExpr (_, _, _, irei) -> let dr_ref = irei.Clang_ast_t.ovrei_decl_ref in let ivar_pointer = dr_ref.Clang_ast_t.dr_decl_pointer in - (match Ast_utils.get_decl ivar_pointer with + (match CAst_utils.get_decl ivar_pointer with | Some d -> let attributes = get_ivar_attributes d in - IList.exists (Ast_utils.equal_property_attribute `Atomic) attributes + IList.exists (CAst_utils.equal_property_attribute `Atomic) attributes | _ -> false) | _ -> false @@ -153,7 +151,7 @@ let is_method_property_accessor_of_ivar stmt context = | Some ObjCMethodDecl (_, _, mdi) -> if mdi.omdi_is_property_accessor then let property_opt = mdi.omdi_property_decl in - match Ast_utils.get_decl_opt_with_decl_ref property_opt with + match CAst_utils.get_decl_opt_with_decl_ref property_opt with | Some ObjCPropertyDecl (_, _, pdi) -> (match pdi.opdi_ivar_decl with | Some decl_ref -> decl_ref.dr_decl_pointer = ivar_pointer @@ -214,8 +212,8 @@ let is_decl nodename decl = let isa classname stmt = match Clang_ast_proj.get_expr_tuple stmt with | Some (_, _, expr_info) -> - let typ = CFrontend_utils.Ast_utils.get_desugared_type expr_info.ei_type_ptr in - CFrontend_utils.Ast_utils.is_ptr_to_objc_class typ classname + let typ = CAst_utils.get_desugared_type expr_info.ei_type_ptr in + CAst_utils.is_ptr_to_objc_class typ classname | _ -> false let decl_unavailable_in_supported_ios_sdk decl =