From 6ad971c875890623bbd74fa649f64272f2d9ba3c Mon Sep 17 00:00:00 2001 From: Dulma Churchill Date: Wed, 30 May 2018 04:39:50 -0700 Subject: [PATCH] [clang] Refactor building method signatures Reviewed By: da319 Differential Revision: D8139862 fbshipit-source-id: ea79568 --- infer/src/IR/Typ.ml | 2 + infer/src/IR/Typ.mli | 3 + infer/src/clang/CMethodProperties.ml | 147 +++++++++++++ infer/src/clang/CMethodProperties.mli | 33 +++ infer/src/clang/CType_decl.ml | 176 ++++++++++++++- infer/src/clang/CType_decl.mli | 13 ++ infer/src/clang/ast_expressions.ml | 2 - infer/src/clang/ast_expressions.mli | 8 - infer/src/clang/cAst_utils.ml | 6 - infer/src/clang/cAst_utils.mli | 2 - infer/src/clang/cFrontend_config.ml | 2 + infer/src/clang/cFrontend_config.mli | 2 + infer/src/clang/cFrontend_decl.ml | 17 +- infer/src/clang/cMethodSignature.ml | 42 ++-- infer/src/clang/cMethodSignature.mli | 14 +- infer/src/clang/cMethod_trans.ml | 294 ++------------------------ infer/src/clang/cMethod_trans.mli | 7 - infer/src/clang/cTrans.ml | 2 +- infer/src/clang/cTrans_models.ml | 20 +- infer/src/clang/cType_to_sil_type.ml | 6 + infer/src/clang/cType_to_sil_type.mli | 2 + 21 files changed, 467 insertions(+), 333 deletions(-) create mode 100644 infer/src/clang/CMethodProperties.ml create mode 100644 infer/src/clang/CMethodProperties.mli diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index da63be53b..8250c7747 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -184,6 +184,8 @@ let mk_array ?default ?quals ?length ?stride elt : t = mk ?default ?quals (Tarray {elt; length; stride}) +let void = mk Tvoid + let void_star = mk (Tptr (mk Tvoid, Pk_pointer)) let merge_quals quals1 quals2 = diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index 354dd13da..8cff031c8 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -112,6 +112,9 @@ val mk : ?default:t -> ?quals:type_quals -> desc -> t val mk_array : ?default:t -> ?quals:type_quals -> ?length:IntLit.t -> ?stride:IntLit.t -> t -> t (** Create an array type from a given element type. If [length] or [stride] value is given, use them as static length and size. *) +val void : t +(** void type *) + val void_star : t (** void* type *) diff --git a/infer/src/clang/CMethodProperties.ml b/infer/src/clang/CMethodProperties.ml new file mode 100644 index 000000000..2bc1ef8d0 --- /dev/null +++ b/infer/src/clang/CMethodProperties.ml @@ -0,0 +1,147 @@ +(* + * Copyright (c) 2018 - 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 extracting properties of functions or method declarations *) + +let get_method_kind meth_decl = + let open Clang_ast_t in + match meth_decl with + | FunctionDecl _ -> + ProcAttributes.C_FUNCTION + | CXXMethodDecl (_, _, _, _, method_decl_info) + | CXXConstructorDecl (_, _, _, _, method_decl_info) + | CXXConversionDecl (_, _, _, _, method_decl_info) + | CXXDestructorDecl (_, _, _, _, method_decl_info) -> + if method_decl_info.Clang_ast_t.xmdi_is_static then ProcAttributes.CPP_CLASS + else ProcAttributes.CPP_INSTANCE + | ObjCMethodDecl (_, _, method_decl_info) -> + if method_decl_info.Clang_ast_t.omdi_is_instance_method then ProcAttributes.OBJC_INSTANCE + else ProcAttributes.OBJC_CLASS + | BlockDecl _ -> + ProcAttributes.BLOCK + | _ -> + raise CFrontend_config.Invalid_declaration + + +let get_return_type method_decl = + let open Clang_ast_t in + match method_decl with + | FunctionDecl (_, _, qt, _) + | CXXMethodDecl (_, _, qt, _, _) + | CXXConstructorDecl (_, _, qt, _, _) + | CXXConversionDecl (_, _, qt, _, _) + | CXXDestructorDecl (_, _, qt, _, _) -> + CType.return_type_of_function_type qt + | ObjCMethodDecl (_, _, omdi) -> + omdi.omdi_result_type + | _ -> + raise CFrontend_config.Invalid_declaration + + +let get_param_decls method_decl = + let open Clang_ast_t in + match method_decl with + | FunctionDecl (_, _, _, function_decl_info) + | CXXMethodDecl (_, _, _, function_decl_info, _) + | CXXConstructorDecl (_, _, _, function_decl_info, _) + | CXXConversionDecl (_, _, _, function_decl_info, _) + | CXXDestructorDecl (_, _, _, function_decl_info, _) -> + function_decl_info.fdi_parameters + | ObjCMethodDecl (_, _, method_decl_info) -> + method_decl_info.omdi_parameters + | BlockDecl (_, block_decl_info) -> + block_decl_info.bdi_parameters + | _ -> + raise CFrontend_config.Invalid_declaration + + +let get_method_body method_decl = + let open Clang_ast_t in + match method_decl with + | FunctionDecl (_, _, _, function_decl_info) + | CXXMethodDecl (_, _, _, function_decl_info, _) + | CXXConstructorDecl (_, _, _, function_decl_info, _) + | CXXConversionDecl (_, _, _, function_decl_info, _) + | CXXDestructorDecl (_, _, _, function_decl_info, _) -> + function_decl_info.fdi_body + | ObjCMethodDecl (_, _, method_decl_info) -> + method_decl_info.omdi_body + | BlockDecl (_, block_decl_info) -> + block_decl_info.bdi_body + | _ -> + raise CFrontend_config.Invalid_declaration + + +let get_language ~is_cpp method_decl = + let open Clang_ast_t in + match method_decl with + | FunctionDecl _ -> + if is_cpp then CFrontend_config.CPP else CFrontend_config.ObjC + | CXXMethodDecl _ | CXXConstructorDecl _ | CXXConversionDecl _ | CXXDestructorDecl _ -> + CFrontend_config.CPP + | ObjCMethodDecl _ | BlockDecl _ -> + CFrontend_config.ObjC + | _ -> + raise CFrontend_config.Invalid_declaration + + +let is_cpp_virtual method_decl = + let open Clang_ast_t in + match method_decl with + | CXXMethodDecl (_, _, _, _, mdi) + | CXXConstructorDecl (_, _, _, _, mdi) + | CXXConversionDecl (_, _, _, _, mdi) + | CXXDestructorDecl (_, _, _, _, mdi) -> + mdi.xmdi_is_virtual + | _ -> + false + + +let is_cpp_nothrow method_decl = + let open Clang_ast_t in + match method_decl with + | FunctionDecl (_, _, _, fdi) + | CXXMethodDecl (_, _, _, fdi, _) + | CXXConstructorDecl (_, _, _, fdi, _) + | CXXConversionDecl (_, _, _, fdi, _) + | CXXDestructorDecl (_, _, _, fdi, _) -> + fdi.fdi_is_no_throw + | _ -> + false + + +let get_init_list_instrs method_decl = + let open Clang_ast_t in + match method_decl with + | CXXMethodDecl (_, _, _, _, mdi) + | CXXConstructorDecl (_, _, _, _, mdi) + | CXXConversionDecl (_, _, _, _, mdi) + | CXXDestructorDecl (_, _, _, _, mdi) -> + let create_custom_instr construct_instr = `CXXConstructorInit construct_instr in + List.map ~f:create_custom_instr mdi.xmdi_cxx_ctor_initializers + | _ -> + [] + + +let get_pointer_to_property method_decl = + let open Clang_ast_t in + match method_decl with + | ObjCMethodDecl (_, _, mdi) -> ( + match mdi.Clang_ast_t.omdi_property_decl with + | Some decl_ref -> + Some decl_ref.Clang_ast_t.dr_decl_pointer + | None -> + None ) + | _ -> + None + + +let is_objc_method method_decl = + match method_decl with Clang_ast_t.ObjCMethodDecl _ -> true | _ -> false diff --git a/infer/src/clang/CMethodProperties.mli b/infer/src/clang/CMethodProperties.mli new file mode 100644 index 000000000..96f08c4d0 --- /dev/null +++ b/infer/src/clang/CMethodProperties.mli @@ -0,0 +1,33 @@ +(* + * Copyright (c) 2018 - 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 extracting properties of functions or method declarations *) + +val get_method_kind : Clang_ast_t.decl -> ProcAttributes.clang_method_kind + +val get_return_type : Clang_ast_t.decl -> Clang_ast_t.qual_type + +val get_param_decls : Clang_ast_t.decl -> Clang_ast_t.decl list + +val get_method_body : Clang_ast_t.decl -> Clang_ast_t.stmt option + +val get_language : is_cpp:bool -> Clang_ast_t.decl -> CFrontend_config.clang_lang + +val is_cpp_virtual : Clang_ast_t.decl -> bool + +val is_cpp_nothrow : Clang_ast_t.decl -> bool + +val get_init_list_instrs : + Clang_ast_t.decl -> [> `CXXConstructorInit of Clang_ast_t.cxx_ctor_initializer] list + +val get_pointer_to_property : Clang_ast_t.decl -> Clang_ast_t.pointer option + +val is_objc_method : Clang_ast_t.decl -> bool diff --git a/infer/src/clang/CType_decl.ml b/infer/src/clang/CType_decl.ml index 421564c10..a3e2f5182 100644 --- a/infer/src/clang/CType_decl.ml +++ b/infer/src/clang/CType_decl.ml @@ -11,6 +11,169 @@ open! IStd (** Processes types and record declarations by adding them to the tenv *) +module BuildMethodSignature = struct + let get_class_parameter_name method_kind = + match method_kind with + | ProcAttributes.CPP_INSTANCE -> + Some (Mangled.from_string CFrontend_config.this) + | ProcAttributes.OBJC_INSTANCE -> + Some (Mangled.from_string CFrontend_config.self) + | _ -> + None + + + let param_type_of_qual_type qual_type_to_sil_type tenv name qual_type = + let typ = qual_type_to_sil_type tenv qual_type in + let is_value = CType.is_value qual_type in + let is_pointer_to_const = CType.is_pointer_to_const qual_type in + let annot = CAst_utils.sil_annot_of_type qual_type in + Some (CMethodSignature.mk_param_type ~is_value ~is_pointer_to_const ~annot name typ) + + + let get_class_param qual_type_to_sil_type tenv method_decl = + let open Clang_ast_t in + match method_decl with + | FunctionDecl _ | BlockDecl _ -> + None + | CXXMethodDecl (decl_info, _, _, _, _) + | CXXConstructorDecl (decl_info, _, _, _, _) + | CXXConversionDecl (decl_info, _, _, _, _) + | CXXDestructorDecl (decl_info, _, _, _, _) + | ObjCMethodDecl (decl_info, _, _) + -> ( + let method_kind = CMethodProperties.get_method_kind method_decl in + match method_kind with + | ProcAttributes.CPP_INSTANCE | ProcAttributes.OBJC_INSTANCE -> ( + match (get_class_parameter_name method_kind, decl_info.di_parent_pointer) with + | Some name, Some parent_pointer -> + let qual_type = CAst_utils.qual_type_of_decl_ptr parent_pointer in + let pointer_qual_type = Ast_expressions.create_pointer_qual_type qual_type in + param_type_of_qual_type qual_type_to_sil_type tenv name pointer_qual_type + | _ -> + None ) + | _ -> + None ) + | _ -> + raise CFrontend_config.Invalid_declaration + + + let should_add_return_param return_type ~is_objc_method = + match return_type.Typ.desc with Tstruct _ -> not is_objc_method | _ -> false + + + let get_return_param qual_type_to_sil_type tenv ~block_return_type method_decl = + let is_objc_method = CMethodProperties.is_objc_method method_decl in + let return_qual_type = + match block_return_type with + | Some return_type -> + CType.return_type_of_function_type return_type + | None -> + CMethodProperties.get_return_type method_decl + in + let return_typ = qual_type_to_sil_type tenv return_qual_type in + if should_add_return_param return_typ ~is_objc_method then + let name = Mangled.from_string CFrontend_config.return_param in + let return_qual_type = Ast_expressions.create_pointer_qual_type return_qual_type in + param_type_of_qual_type qual_type_to_sil_type tenv name return_qual_type + else None + + + (** Returns parameters of a function/method. They will have following order: + 1. normal parameters + 2. return parameter (optional) *) + let get_parameters qual_type_to_sil_type ~is_cpp tenv ~block_return_type method_decl = + let par_to_ms_par par = + match par with + | Clang_ast_t.ParmVarDecl (_, name_info, qt, var_decl_info) -> + let method_decl_info = Clang_ast_proj.get_decl_tuple method_decl in + let _, name = + CGeneral_utils.get_var_name_mangled method_decl_info name_info var_decl_info + in + let param_typ = qual_type_to_sil_type tenv qt in + let typ = + match param_typ.Typ.desc with + | Tstruct _ when is_cpp -> + qual_type_to_sil_type tenv (Ast_expressions.create_reference_qual_type qt) + | _ -> + param_typ + in + let is_pointer_to_const = CType.is_pointer_to_const qt in + let is_value = CType.is_value qt in + let annot = CAst_utils.sil_annot_of_type qt in + CMethodSignature.mk_param_type name typ ~is_value ~is_pointer_to_const ~annot + | _ -> + raise CFrontend_config.Invalid_declaration + in + let params = List.map ~f:par_to_ms_par (CMethodProperties.get_param_decls method_decl) in + let return_param = + Option.to_list (get_return_param qual_type_to_sil_type tenv ~block_return_type method_decl) + in + params @ return_param + + + (** get return type of the function and optionally type of function's return parameter *) + let get_return_val_and_param_types qual_type_to_sil_type tenv ~block_return_type method_decl = + let return_qual_type = + match block_return_type with + | Some return_type -> + CType.return_type_of_function_type return_type + | None -> + CMethodProperties.get_return_type method_decl + in + let return_typ = qual_type_to_sil_type tenv return_qual_type in + let return_typ_annot = CAst_utils.sil_annot_of_type return_qual_type in + let is_objc_method = CMethodProperties.is_objc_method method_decl in + if should_add_return_param return_typ ~is_objc_method then + (Typ.void, Some (CType.add_pointer_to_typ return_typ), Annot.Item.empty) + else (return_typ, None, return_typ_annot) + + + let method_signature_of_decl qual_type_to_sil_type ~is_cpp tenv method_decl ?block_return_type + procname = + let decl_info = Clang_ast_proj.get_decl_tuple method_decl in + let loc = decl_info.Clang_ast_t.di_source_range in + let ret_type, return_param_typ, ret_typ_annot = + get_return_val_and_param_types qual_type_to_sil_type tenv ~block_return_type method_decl + in + let method_kind = CMethodProperties.get_method_kind method_decl in + let pointer_to_parent = decl_info.di_parent_pointer in + let class_param = get_class_param qual_type_to_sil_type tenv method_decl in + let params = + get_parameters qual_type_to_sil_type ~is_cpp tenv ~block_return_type method_decl + in + let attributes = decl_info.Clang_ast_t.di_attributes in + let lang = CMethodProperties.get_language ~is_cpp method_decl in + let is_cpp_virtual = CMethodProperties.is_cpp_virtual method_decl in + let is_cpp_nothrow = CMethodProperties.is_cpp_nothrow method_decl in + let access = decl_info.Clang_ast_t.di_access in + let pointer_to_property_opt = CMethodProperties.get_pointer_to_property method_decl in + { CMethodSignature.name= procname + ; access + ; class_param + ; params + ; ret_type= (ret_type, ret_typ_annot) + ; attributes + ; loc + ; method_kind + ; is_cpp_virtual + ; is_cpp_nothrow + ; lang + ; pointer_to_parent + ; pointer_to_property_opt + ; return_param_typ } + + + let method_signature_body_of_decl qual_type_to_sil_type ~is_cpp tenv method_decl + ?block_return_type procname = + let body = CMethodProperties.get_method_body method_decl in + let init_list_instrs = CMethodProperties.get_init_list_instrs method_decl in + let ms = + method_signature_of_decl qual_type_to_sil_type ~is_cpp tenv method_decl ?block_return_type + procname + in + (ms, body, init_list_instrs) +end + let get_struct_decls decl = let open Clang_ast_t in match decl with @@ -356,8 +519,8 @@ and mk_c_function ?tenv ~is_cpp name function_decl_info_opt = match function_decl_info.Clang_ast_t.fdi_storage_class with | Some "static" (* when we model static functions, we cannot take the file into account to - create a mangled name because the file of the model is different to the real file, - thus the model won't work *) + create a mangled name because the file of the model is different to the real file, + thus the model won't work *) when not (CTrans_models.is_modelled_static_function (QualifiedCppName.to_qual_string name)) -> let file_opt = (fst decl_info.Clang_ast_t.di_source_range).Clang_ast_t.sl_file @@ -444,6 +607,7 @@ and objc_block_procname outer_proc_opt = Typ.Procname.mangled_objc_block name +(* TODO: get the parameters from BuildMethodSignature.get_parameters and pass it to the method names *) and from_decl ?tenv ~is_cpp ?outer_proc meth_decl = let open Clang_ast_t in match meth_decl with @@ -526,6 +690,14 @@ and get_record_struct_type tenv definition_decl : Typ.desc = assert false +let method_signature_body_of_decl = + BuildMethodSignature.method_signature_body_of_decl qual_type_to_sil_type + + +let method_signature_of_decl = BuildMethodSignature.method_signature_of_decl qual_type_to_sil_type + +let should_add_return_param = BuildMethodSignature.should_add_return_param + module CProcname = struct let from_decl = from_decl diff --git a/infer/src/clang/CType_decl.mli b/infer/src/clang/CType_decl.mli index 03f744d16..87e7fb305 100644 --- a/infer/src/clang/CType_decl.mli +++ b/infer/src/clang/CType_decl.mli @@ -47,3 +47,16 @@ val qual_type_to_sil_type : Tenv.t -> Clang_ast_t.qual_type -> Typ.t val class_from_pointer_type : Tenv.t -> Clang_ast_t.qual_type -> Typ.Name.t val get_type_from_expr_info : Clang_ast_t.expr_info -> Tenv.t -> Typ.t + +val method_signature_of_decl : + is_cpp:bool -> Tenv.t -> Clang_ast_t.decl -> ?block_return_type:Clang_ast_t.qual_type + -> Typ.Procname.t -> CMethodSignature.t + +val method_signature_body_of_decl : + is_cpp:bool -> Tenv.t -> Clang_ast_t.decl -> ?block_return_type:Clang_ast_t.qual_type + -> Typ.Procname.t + -> CMethodSignature.t + * Clang_ast_t.stmt option + * [> `CXXConstructorInit of Clang_ast_t.cxx_ctor_initializer] list + +val should_add_return_param : Typ.typ -> is_objc_method:bool -> bool diff --git a/infer/src/clang/ast_expressions.ml b/infer/src/clang/ast_expressions.ml index ed2539426..23a56ccb4 100644 --- a/infer/src/clang/ast_expressions.ml +++ b/infer/src/clang/ast_expressions.ml @@ -43,8 +43,6 @@ let create_char_type = builtin_to_qual_type `Char_S let create_char_star_type ?quals () = create_pointer_qual_type ?quals create_char_type -let create_BOOL_type = builtin_to_qual_type `SChar - let create_class_qual_type ?quals typename = create_qual_type ?quals (Clang_ast_extend.ClassType typename) diff --git a/infer/src/clang/ast_expressions.mli b/infer/src/clang/ast_expressions.mli index d1b769ad0..fd1fcd02b 100644 --- a/infer/src/clang/ast_expressions.mli +++ b/infer/src/clang/ast_expressions.mli @@ -12,20 +12,12 @@ open Clang_ast_t (** This module creates extra ast constructs that are needed for the translation *) -val create_class_qual_type : ?quals:Typ.type_quals -> Typ.Name.t -> qual_type - val create_pointer_qual_type : ?quals:Typ.type_quals -> qual_type -> qual_type val create_reference_qual_type : ?quals:Typ.type_quals -> qual_type -> qual_type val create_char_star_type : ?quals:Typ.type_quals -> unit -> qual_type -val create_id_type : qual_type - -val create_void_type : qual_type - -val create_BOOL_type : qual_type - val make_next_object_exp : stmt_info -> stmt -> Clang_ast_t.stmt -> Clang_ast_t.stmt * Clang_ast_t.stmt diff --git a/infer/src/clang/cAst_utils.ml b/infer/src/clang/cAst_utils.ml index 34e1e1c8f..30d98f4be 100644 --- a/infer/src/clang/cAst_utils.ml +++ b/infer/src/clang/cAst_utils.ml @@ -200,12 +200,6 @@ let name_opt_of_typedef_qual_type qual_type = 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 "") - (Clang_ast_extend.type_ptr_to_string qt_type_ptr) - - let qual_type_of_decl_ptr decl_ptr = { (* This function needs to be in this module - CAst_utils can't depend on Ast_expressions *) diff --git a/infer/src/clang/cAst_utils.mli b/infer/src/clang/cAst_utils.mli index ee39525af..66fcde04e 100644 --- a/infer/src/clang/cAst_utils.mli +++ b/infer/src/clang/cAst_utils.mli @@ -64,8 +64,6 @@ val name_of_typedef_type_info : Clang_ast_t.typedef_type_info -> QualifiedCppNam val name_opt_of_typedef_qual_type : Clang_ast_t.qual_type -> QualifiedCppName.t option -val string_of_qual_type : Clang_ast_t.qual_type -> string - type qual_type_to_sil_type = Tenv.t -> Clang_ast_t.qual_type -> Typ.t val qual_type_of_decl_ptr : Clang_ast_t.pointer -> Clang_ast_t.qual_type diff --git a/infer/src/clang/cFrontend_config.ml b/infer/src/clang/cFrontend_config.ml index 925f129d5..3944c66c8 100644 --- a/infer/src/clang/cFrontend_config.ml +++ b/infer/src/clang/cFrontend_config.ml @@ -40,6 +40,8 @@ let incorrect_assumption position source_range ?ast_node fmt = type translation_unit_context = {lang: clang_lang; source_file: SourceFile.t} +exception Invalid_declaration + (** Constants *) let alloc = "alloc" diff --git a/infer/src/clang/cFrontend_config.mli b/infer/src/clang/cFrontend_config.mli index e5b0ccc4f..327fb18ae 100644 --- a/infer/src/clang/cFrontend_config.mli +++ b/infer/src/clang/cFrontend_config.mli @@ -41,6 +41,8 @@ val incorrect_assumption : type translation_unit_context = {lang: clang_lang; source_file: SourceFile.t} +exception Invalid_declaration + (** Constants *) val alloc : string diff --git a/infer/src/clang/cFrontend_decl.ml b/infer/src/clang/cFrontend_decl.ml index 9ee36b135..e3eed3cc1 100644 --- a/infer/src/clang/cFrontend_decl.ml +++ b/infer/src/clang/cFrontend_decl.ml @@ -106,13 +106,20 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron | None -> ([], None) in + let is_cpp = CGeneral_utils.is_cpp_translation trans_unit_ctx in + let procname, block_return_type = + match block_data_opt with + | Some (_, block_return_type, procname, _) -> + (procname, Some block_return_type) + | _ -> + (CType_decl.CProcname.from_decl ~is_cpp ~tenv func_decl, None) + in let ms, body_opt, extra_instrs = - CMethod_trans.method_signature_of_decl trans_unit_ctx tenv func_decl block_data_opt + CType_decl.method_signature_body_of_decl ~is_cpp tenv func_decl ?block_return_type procname in match body_opt with | Some body -> (* Only in the case the function declaration has a defined body we create a procdesc *) - let procname = ms.CMethodSignature.name in let return_param_typ_opt = ms.CMethodSignature.return_param_typ in if CMethod_trans.create_local_procdesc trans_unit_ctx cfg tenv ms [body] captured_vars then @@ -127,9 +134,11 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron let process_method_decl ?(set_objc_accessor_attr= false) ?(is_destructor= false) trans_unit_ctx tenv cfg curr_class meth_decl ~is_objc = + let is_cpp = CGeneral_utils.is_cpp_translation trans_unit_ctx in try let ms, body_opt, extra_instrs = - CMethod_trans.method_signature_of_decl trans_unit_ctx tenv meth_decl None + let procname = CType_decl.CProcname.from_decl ~is_cpp ~tenv meth_decl in + CType_decl.method_signature_body_of_decl ~is_cpp tenv meth_decl procname in match body_opt with | Some body -> @@ -407,7 +416,7 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron Option.value_exn (Pvar.get_initializer_pname global) in let ms = - CMethodSignature.mk procname [] Ast_expressions.create_void_type [] + CMethodSignature.mk procname None [] (Typ.void, Annot.Item.empty) [] decl_info.Clang_ast_t.di_source_range ProcAttributes.C_FUNCTION trans_unit_ctx.CFrontend_config.lang None None None `None in diff --git a/infer/src/clang/cMethodSignature.ml b/infer/src/clang/cMethodSignature.ml index 33897b0fa..124e22fc8 100644 --- a/infer/src/clang/cMethodSignature.ml +++ b/infer/src/clang/cMethodSignature.ml @@ -14,11 +14,20 @@ open! IStd module F = Format +type param_type = + {name: Mangled.t; typ: Typ.t; is_pointer_to_const: bool; is_value: bool; annot: Annot.Item.t} + +let mk_param_type ?(is_value= false) ?(is_pointer_to_const= false) ?(annot= Annot.Item.empty) name + typ = + {name; typ; is_value; is_pointer_to_const; annot} + + type t = { name: Typ.Procname.t ; access: Clang_ast_t.access_specifier - ; args: (Mangled.t * Clang_ast_t.qual_type) list - ; ret_type: Clang_ast_t.qual_type + ; class_param: param_type option + ; params: param_type list + ; ret_type: Typ.t * Annot.Item.t ; attributes: Clang_ast_t.attribute list ; loc: Clang_ast_t.source_range ; method_kind: ProcAttributes.clang_method_kind @@ -31,24 +40,25 @@ type t = return_param_typ: Typ.t option } (* A method is a getter if it has a link to a property and *) -(* it has 1 argument (this includes self) *) -let is_getter {pointer_to_property_opt; args} = - Option.is_some pointer_to_property_opt && Int.equal (List.length args) 1 +(* it has 0 arguments *) +let is_getter {pointer_to_property_opt; params} = + Option.is_some pointer_to_property_opt && Int.equal (List.length params) 0 (* A method is a setter if it has a link to a property and *) -(* it has 2 argument (this includes self) *) -let is_setter {pointer_to_property_opt; args} = - Option.is_some pointer_to_property_opt && Int.equal (List.length args) 2 +(* it has 1 argument *) +let is_setter {pointer_to_property_opt; params} = + Option.is_some pointer_to_property_opt && Int.equal (List.length params) 1 -let mk name args ret_type attributes loc method_kind ?is_cpp_virtual ?is_cpp_nothrow lang - pointer_to_parent pointer_to_property_opt return_param_typ access = +let mk name class_param params ret_type attributes loc method_kind ?is_cpp_virtual ?is_cpp_nothrow + lang pointer_to_parent pointer_to_property_opt return_param_typ access = let is_cpp_virtual = Option.value is_cpp_virtual ~default:false in let is_cpp_nothrow = Option.value is_cpp_nothrow ~default:false in { name ; access - ; args + ; class_param + ; params ; ret_type ; attributes ; loc @@ -62,15 +72,9 @@ let mk name args ret_type attributes loc method_kind ?is_cpp_virtual ?is_cpp_not let pp fmt ms = - let pp_arg fmt (mangled, qual_type) = - F.fprintf fmt "%a, %a" Mangled.pp mangled - (Pp.to_string ~f:CAst_utils.string_of_qual_type) - qual_type - in + let pp_param fmt {name; typ} = F.fprintf fmt "%a, %a" Mangled.pp name (Typ.pp Pp.text) typ in Format.fprintf fmt "Method %a [%a]->%a %a" (Pp.to_string ~f:Typ.Procname.to_string) - ms.name (Pp.comma_seq pp_arg) ms.args - (Pp.to_string ~f:Clang_ast_extend.type_ptr_to_string) - ms.ret_type.Clang_ast_t.qt_type_ptr + ms.name (Pp.comma_seq pp_param) ms.params (Typ.pp Pp.text) (fst ms.ret_type) (Pp.to_string ~f:Clang_ast_j.string_of_source_range) ms.loc diff --git a/infer/src/clang/cMethodSignature.mli b/infer/src/clang/cMethodSignature.mli index b6404d2f4..ac687fe29 100644 --- a/infer/src/clang/cMethodSignature.mli +++ b/infer/src/clang/cMethodSignature.mli @@ -12,11 +12,15 @@ open! IStd (** Define the signature of a method consisting of its name, its arguments, return type, location and whether its an instance method. *) +type param_type = + {name: Mangled.t; typ: Typ.t; is_pointer_to_const: bool; is_value: bool; annot: Annot.Item.t} + type t = { name: Typ.Procname.t ; access: Clang_ast_t.access_specifier - ; args: (Mangled.t * Clang_ast_t.qual_type) list - ; ret_type: Clang_ast_t.qual_type + ; class_param: param_type option + ; params: param_type list + ; ret_type: Typ.t * Annot.Item.t ; attributes: Clang_ast_t.attribute list ; loc: Clang_ast_t.source_range ; method_kind: ProcAttributes.clang_method_kind @@ -33,10 +37,14 @@ val is_getter : t -> bool val is_setter : t -> bool val mk : - Typ.Procname.t -> (Mangled.t * Clang_ast_t.qual_type) list -> Clang_ast_t.qual_type + Typ.Procname.t -> param_type option -> param_type list -> Typ.t * Annot.Item.t -> Clang_ast_t.attribute list -> Clang_ast_t.source_range -> ProcAttributes.clang_method_kind -> ?is_cpp_virtual:bool -> ?is_cpp_nothrow:bool -> CFrontend_config.clang_lang -> Clang_ast_t.pointer option -> Clang_ast_t.pointer option -> Typ.t option -> Clang_ast_t.access_specifier -> t val pp : Format.formatter -> t -> unit + +val mk_param_type : + ?is_value:bool -> ?is_pointer_to_const:bool -> ?annot:Annot.Item.t -> Mangled.t -> Typ.t + -> param_type diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 51519f61d..88d02517e 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -14,8 +14,6 @@ open! IStd module L = Logging -exception Invalid_declaration - (** When the methoc call is MCStatic, means that it is a class method. When it is MCVirtual, it means that it is an instance method and that the method to be called will be determined at runtime. If it is MCNoVirtual it means that it is an instance method but that the method to be @@ -24,224 +22,17 @@ type method_call_type = MCVirtual | MCNoVirtual | MCStatic [@@deriving compare] let equal_method_call_type = [%compare.equal : method_call_type] -type function_method_decl_info = - | Func_decl_info of Clang_ast_t.function_decl_info * Clang_ast_t.qual_type - | Cpp_Meth_decl_info of - Clang_ast_t.function_decl_info - * Clang_ast_t.cxx_method_decl_info - * Clang_ast_t.pointer - * Clang_ast_t.qual_type - | ObjC_Meth_decl_info of Clang_ast_t.obj_c_method_decl_info * Clang_ast_t.pointer - | Block_decl_info of Clang_ast_t.block_decl_info * Clang_ast_t.qual_type * CContext.t - -let get_method_kind function_method_decl_info = - match function_method_decl_info with - | Func_decl_info _ -> - ProcAttributes.C_FUNCTION - | Block_decl_info _ -> - ProcAttributes.BLOCK - | Cpp_Meth_decl_info (_, method_decl_info, _, _) -> - if method_decl_info.Clang_ast_t.xmdi_is_static then ProcAttributes.CPP_CLASS - else ProcAttributes.CPP_INSTANCE - | ObjC_Meth_decl_info (method_decl_info, _) -> - if method_decl_info.Clang_ast_t.omdi_is_instance_method then ProcAttributes.OBJC_INSTANCE - else ProcAttributes.OBJC_CLASS - - -let get_original_return_type function_method_decl_info = - match function_method_decl_info with - | Func_decl_info (_, typ) | Cpp_Meth_decl_info (_, _, _, typ) | Block_decl_info (_, typ, _) -> - CType.return_type_of_function_type typ - | ObjC_Meth_decl_info (method_decl_info, _) -> - method_decl_info.Clang_ast_t.omdi_result_type - - -let get_class_param function_method_decl_info = - match get_method_kind function_method_decl_info with - | ProcAttributes.CPP_INSTANCE | ProcAttributes.OBJC_INSTANCE -> ( - match function_method_decl_info with - | Cpp_Meth_decl_info (_, _, class_decl_ptr, _) -> - let class_type = CAst_utils.qual_type_of_decl_ptr class_decl_ptr in - [(Mangled.from_string CFrontend_config.this, class_type)] - | ObjC_Meth_decl_info (_, class_decl_ptr) -> - let class_type = CAst_utils.qual_type_of_decl_ptr class_decl_ptr in - [(Mangled.from_string CFrontend_config.self, class_type)] - | _ -> - [] ) - | _ -> - [] - - -let should_add_return_param return_type ~is_objc_method = - match return_type.Typ.desc with Tstruct _ -> not is_objc_method | _ -> false - - -let is_objc_method function_method_decl_info = - match function_method_decl_info with ObjC_Meth_decl_info _ -> true | _ -> false - - -let get_return_param tenv function_method_decl_info = - let is_objc_method = is_objc_method function_method_decl_info in - let return_qual_type = get_original_return_type function_method_decl_info in - let return_typ = CType_decl.qual_type_to_sil_type tenv return_qual_type in - if should_add_return_param return_typ ~is_objc_method then - [ ( Mangled.from_string CFrontend_config.return_param - , Ast_expressions.create_pointer_qual_type return_qual_type ) ] - else [] - - -let get_param_decls function_method_decl_info = - match function_method_decl_info with - | Func_decl_info (function_decl_info, _) | Cpp_Meth_decl_info (function_decl_info, _, _, _) -> - function_decl_info.Clang_ast_t.fdi_parameters - | ObjC_Meth_decl_info (method_decl_info, _) -> - method_decl_info.Clang_ast_t.omdi_parameters - | Block_decl_info (block_decl_info, _, _) -> - block_decl_info.Clang_ast_t.bdi_parameters - - -let get_language trans_unit_ctx function_method_decl_info = - match function_method_decl_info with - | Func_decl_info (_, _) -> - trans_unit_ctx.CFrontend_config.lang - | Cpp_Meth_decl_info _ -> - CFrontend_config.CPP - | ObjC_Meth_decl_info _ -> - CFrontend_config.ObjC - | Block_decl_info _ -> - CFrontend_config.ObjC - - -let is_cpp_virtual function_method_decl_info = - match function_method_decl_info with - | Cpp_Meth_decl_info (_, mdi, _, _) -> - mdi.Clang_ast_t.xmdi_is_virtual - | _ -> - false - - -let is_cpp_nothrow function_method_decl_info = - match function_method_decl_info with - | Func_decl_info (fdi, _) | Cpp_Meth_decl_info (fdi, _, _, _) -> - fdi.Clang_ast_t.fdi_is_no_throw - | _ -> - false - - -(** Returns parameters of a function/method. They will have following order: - 1. self/this parameter (optional, only for methods) - 2. normal parameters - 3. return parameter (optional) *) -let get_parameters trans_unit_ctx tenv decl_info 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 = CGeneral_utils.get_var_name_mangled decl_info name_info var_decl_info in - let param_typ = CType_decl.qual_type_to_sil_type tenv qt in - let new_qt = - match param_typ.Typ.desc with - | Tstruct _ when CGeneral_utils.is_cpp_translation trans_unit_ctx -> - Ast_expressions.create_reference_qual_type qt - | _ -> - qt - in - (mangled, new_qt) - | _ -> - assert false - in - let pars = List.map ~f:par_to_ms_par (get_param_decls function_method_decl_info) in - get_class_param function_method_decl_info @ pars - @ get_return_param tenv function_method_decl_info - - -(** get return type of the function and optionally type of function's return parameter *) -let get_return_val_and_param_types tenv function_method_decl_info = - let return_qual_type = get_original_return_type function_method_decl_info in - let return_typ = CType_decl.qual_type_to_sil_type tenv return_qual_type in - let is_objc_method = is_objc_method function_method_decl_info in - if should_add_return_param return_typ ~is_objc_method then - (Ast_expressions.create_void_type, Some (CType.add_pointer_to_typ return_typ)) - else (return_qual_type, None) - - -let build_method_signature trans_unit_ctx tenv decl_info procname function_method_decl_info - parent_pointer pointer_to_property_opt = - let source_range = decl_info.Clang_ast_t.di_source_range in - let tp, return_param_type_opt = get_return_val_and_param_types tenv function_method_decl_info in - let method_kind = get_method_kind function_method_decl_info in - let parameters = get_parameters trans_unit_ctx tenv decl_info function_method_decl_info in - let attributes = decl_info.Clang_ast_t.di_attributes in - let lang = get_language trans_unit_ctx function_method_decl_info in - let is_cpp_virtual = is_cpp_virtual function_method_decl_info in - let is_cpp_nothrow = is_cpp_nothrow function_method_decl_info in - let access = decl_info.Clang_ast_t.di_access in - CMethodSignature.mk procname parameters tp attributes source_range method_kind ~is_cpp_virtual - ~is_cpp_nothrow lang parent_pointer pointer_to_property_opt return_param_type_opt access - - -let get_init_list_instrs method_decl_info = - let create_custom_instr construct_instr = `CXXConstructorInit construct_instr in - List.map ~f:create_custom_instr method_decl_info.Clang_ast_t.xmdi_cxx_ctor_initializers - - -let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt = - let open Clang_ast_t in - let is_cpp = CGeneral_utils.is_cpp_translation trans_unit_ctx in - match (meth_decl, block_data_opt) with - | FunctionDecl (decl_info, _, qt, fdi), _ -> - let func_decl = Func_decl_info (fdi, qt) in - let procname = CType_decl.CProcname.from_decl ~is_cpp ~tenv meth_decl in - let ms = build_method_signature trans_unit_ctx tenv decl_info procname func_decl None None in - (ms, fdi.Clang_ast_t.fdi_body, []) - | CXXMethodDecl (decl_info, _, qt, fdi, mdi), _ - | CXXConstructorDecl (decl_info, _, qt, fdi, mdi), _ - | CXXConversionDecl (decl_info, _, qt, fdi, mdi), _ - | CXXDestructorDecl (decl_info, _, qt, fdi, mdi), _ -> - let procname = CType_decl.CProcname.from_decl ~is_cpp ~tenv 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) in - let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in - let ms = - build_method_signature trans_unit_ctx tenv decl_info procname method_decl parent_pointer - None - in - 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) - | ObjCMethodDecl (decl_info, _, mdi), _ -> - let procname = CType_decl.CProcname.from_decl ~is_cpp ~tenv 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 - let pointer_to_property_opt = - match mdi.Clang_ast_t.omdi_property_decl with - | Some decl_ref -> - Some decl_ref.Clang_ast_t.dr_decl_pointer - | None -> - None - in - let ms = - build_method_signature trans_unit_ctx tenv decl_info procname method_decl parent_pointer - pointer_to_property_opt - in - (ms, mdi.omdi_body, []) - | BlockDecl (decl_info, bdi), Some (outer_context, tp, procname, _) -> - let func_decl = Block_decl_info (bdi, tp, outer_context) in - let ms = build_method_signature trans_unit_ctx tenv decl_info procname func_decl None None in - (ms, bdi.bdi_body, []) - | _ -> - raise Invalid_declaration - - let method_signature_of_pointer trans_unit_ctx tenv pointer = + let is_cpp = CGeneral_utils.is_cpp_translation trans_unit_ctx in try match CAst_utils.get_decl pointer with | Some meth_decl -> - let ms, _, _ = method_signature_of_decl trans_unit_ctx tenv meth_decl None in + let procname = CType_decl.CProcname.from_decl ~is_cpp ~tenv meth_decl in + let ms = CType_decl.method_signature_of_decl ~is_cpp tenv meth_decl procname in Some ms | None -> None - with Invalid_declaration -> None + with CFrontend_config.Invalid_declaration -> None let get_method_name_from_clang tenv ms_opt = @@ -335,42 +126,6 @@ let get_objc_method_data obj_c_message_expr_info = (selector, pointer, MCStatic) -let get_formal_parameters tenv ms = - let rec defined_parameters pl = - match pl with - | [] -> - [] - | (mangled, qual_type) :: pl' -> - let should_add_pointer name ms = - let is_objc_self = - String.equal name CFrontend_config.self - && CFrontend_config.equal_clang_lang ms.CMethodSignature.lang CFrontend_config.ObjC - in - let is_cxx_this = - String.equal name CFrontend_config.this - && CFrontend_config.equal_clang_lang ms.CMethodSignature.lang CFrontend_config.CPP - in - is_objc_self - && ProcAttributes.equal_clang_method_kind ms.CMethodSignature.method_kind - ProcAttributes.OBJC_INSTANCE - || is_cxx_this - in - let qt = - if should_add_pointer (Mangled.to_string mangled) ms then - Ast_expressions.create_pointer_qual_type qual_type - else qual_type - in - let typ = CType_decl.qual_type_to_sil_type tenv qt in - (mangled, typ) :: defined_parameters pl' - in - defined_parameters ms.CMethodSignature.args - - -let get_return_type tenv ms = - let return_type = ms.CMethodSignature.ret_type in - CType_decl.qual_type_to_sil_type tenv return_type - - let sil_func_attributes_of_attributes attrs = let rec do_translation acc al = match al with @@ -403,31 +158,24 @@ let should_create_procdesc cfg procname defined set_objc_accessor_attr = true -let sil_method_annotation_of_args args method_type : Annot.Method.t = - let args_types = List.map ~f:snd args in - let param_annots = List.map ~f:CAst_utils.sil_annot_of_type args_types in - let retval_annot = CAst_utils.sil_annot_of_type method_type in - (retval_annot, param_annots) - - (** Returns a list of the indices of expressions in [args] which point to const-typed values. Each index is offset by [shift]. *) -let get_const_args_indices ~shift args = +let get_const_params_indices ~shift params = let i = ref shift in let rec aux result = function | [] -> List.rev result - | (_, qual_type) :: tl -> + | ({is_pointer_to_const}: CMethodSignature.param_type) :: tl -> incr i ; - if CType.is_pointer_to_const qual_type then aux (!i - 1 :: result) tl else aux result tl + if is_pointer_to_const then aux (!i - 1 :: result) tl else aux result tl in - aux [] args + aux [] params -let get_byval_args_indices ~shift args = - List.filter_mapi args ~f:(fun index (_, qual_type) -> +let get_byval_params_indices ~shift params = + List.filter_mapi params ~f:(fun index ({is_value}: CMethodSignature.param_type) -> let index' = index + shift in - Option.some_if (CType.is_value qual_type) index' ) + Option.some_if is_value index' ) let get_objc_property_accessor tenv ms = @@ -473,8 +221,6 @@ let create_local_procdesc ?(set_objc_accessor_attr= false) trans_unit_ctx cfg te let proc_name = ms.CMethodSignature.name in let pname = Typ.Procname.to_string proc_name in let attributes = sil_func_attributes_of_attributes ms.CMethodSignature.attributes in - let method_ret_type = ms.CMethodSignature.ret_type in - let method_annotation = sil_method_annotation_of_args ms.CMethodSignature.args method_ret_type in let clang_method_kind = ms.CMethodSignature.method_kind in let is_cpp_nothrow = ms.CMethodSignature.is_cpp_nothrow in let access = @@ -489,16 +235,22 @@ let create_local_procdesc ?(set_objc_accessor_attr= false) trans_unit_ctx cfg te PredSymb.Protected in let create_new_procdesc () = - let formals = get_formal_parameters tenv ms in + let all_params = Option.to_list ms.CMethodSignature.class_param @ ms.CMethodSignature.params in + let params_annots = + List.map ~f:(fun ({annot}: CMethodSignature.param_type) -> annot) all_params + in + let return_annot = snd ms.CMethodSignature.ret_type in + let method_annotation = (return_annot, params_annots) in + let formals = + List.map ~f:(fun ({name; typ}: CMethodSignature.param_type) -> (name, typ)) all_params + in let captured_mangled = List.map ~f:(fun (var, t) -> (Pvar.get_name var, t)) captured in (* Captured variables for blocks are treated as parameters *) let formals = captured_mangled @ formals in let const_formals = - get_const_args_indices ~shift:(List.length captured_mangled) ms.CMethodSignature.args - in - let by_vals = - get_byval_args_indices ~shift:(List.length captured_mangled) ms.CMethodSignature.args + get_const_params_indices ~shift:(List.length captured_mangled) all_params in + let by_vals = get_byval_params_indices ~shift:(List.length captured_mangled) all_params in let source_range = ms.CMethodSignature.loc in L.(debug Capture Verbose) "@\nCreating a new procdesc for function: '%s'@\n@." pname ; L.(debug Capture Verbose) "@\nms = %a@\n@." CMethodSignature.pp ms ; @@ -512,7 +264,7 @@ let create_local_procdesc ?(set_objc_accessor_attr= false) trans_unit_ctx cfg te CLocation.location_of_source_range ~pick_location:`End trans_unit_ctx.CFrontend_config.source_file source_range in - let ret_type = get_return_type tenv ms in + let ret_type = fst ms.CMethodSignature.ret_type in let objc_property_accessor = if set_objc_accessor_attr then get_objc_property_accessor tenv ms else None in diff --git a/infer/src/clang/cMethod_trans.mli b/infer/src/clang/cMethod_trans.mli index 22c934672..d050441a4 100644 --- a/infer/src/clang/cMethod_trans.mli +++ b/infer/src/clang/cMethod_trans.mli @@ -20,8 +20,6 @@ type method_call_type = MCVirtual | MCNoVirtual | MCStatic [@@deriving compare] val equal_method_call_type : method_call_type -> method_call_type -> bool -val should_add_return_param : Typ.t -> is_objc_method:bool -> bool - val create_local_procdesc : ?set_objc_accessor_attr:bool -> CFrontend_config.translation_unit_context -> Cfg.t -> Tenv.t -> CMethodSignature.t -> Clang_ast_t.stmt list -> (Pvar.t * Typ.t) list -> bool @@ -40,11 +38,6 @@ val get_class_name_method_call_from_clang : CFrontend_config.translation_unit_context -> Tenv.t -> Clang_ast_t.obj_c_message_expr_info -> Typ.Name.t option -val method_signature_of_decl : - CFrontend_config.translation_unit_context -> Tenv.t -> Clang_ast_t.decl - -> CModule_type.block_data option - -> CMethodSignature.t * Clang_ast_t.stmt option * CModule_type.instr_type list - val method_signature_of_pointer : CFrontend_config.translation_unit_context -> Tenv.t -> Clang_ast_t.pointer -> CMethodSignature.t option diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 9bc5f6786..70f00921a 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -239,7 +239,7 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s let ret_id_typ = (Ident.create_fresh Ident.knormal, return_type) in let ret_id', params, initd_exps, ret_exps = (* Assumption: should_add_return_param will return true only for struct types *) - if CMethod_trans.should_add_return_param return_type ~is_objc_method then + if CType_decl.should_add_return_param return_type ~is_objc_method then let param_type = Typ.mk (Typ.Tptr (return_type, Typ.Pk_pointer)) in let var_exp = match trans_state.var_exp_typ with diff --git a/infer/src/clang/cTrans_models.ml b/infer/src/clang/cTrans_models.ml index 32f48a1b4..3d393b40c 100644 --- a/infer/src/clang/cTrans_models.ml +++ b/infer/src/clang/cTrans_models.ml @@ -75,7 +75,7 @@ let get_predefined_ms_method condition class_name method_name method_kind mk_pro mk_procname class_name method_name method_kind in let ms = - CMethodSignature.mk procname arguments return_type attributes + CMethodSignature.mk procname None arguments return_type attributes (CAst_utils.dummy_source_range ()) ProcAttributes.C_FUNCTION lang None None None `None in @@ -88,21 +88,25 @@ let get_predefined_ms_stringWithUTF8String class_name method_name mk_procname la class_equal class_name CFrontend_config.nsstring_cl && String.equal method_name CFrontend_config.string_with_utf8_m in - let id_type = Ast_expressions.create_id_type in + let id_type = CType_to_sil_type.type_of_builtin_type_kind `ObjCId in let char_star_type = - Ast_expressions.create_char_star_type ~quals:(Typ.mk_type_quals ~is_const:true ()) () + let char_type = CType_to_sil_type.type_of_builtin_type_kind ~is_const:true `Char_S in + Typ.Tptr (char_type, Typ.Pk_pointer) |> Typ.mk ~quals:(Typ.mk_type_quals ()) in - let args = [(Mangled.from_string "x", char_star_type)] in + let param_name = Mangled.from_string "x" in + let params = [CMethodSignature.mk_param_type param_name char_star_type] in get_predefined_ms_method condition class_name method_name Typ.Procname.ObjC_Cpp.ObjCClassMethod - mk_procname lang args id_type [] None + mk_procname lang params (id_type, Annot.Item.empty) [] None let get_predefined_ms_is_kind_of_class class_name method_name mk_procname lang = let condition = String.equal method_name CFrontend_config.is_kind_of_class in - let class_type = Ast_expressions.create_class_qual_type class_name in - let args = [(Mangled.from_string CFrontend_config.self, class_type)] in + let class_type = CType_to_sil_type.type_of_builtin_type_kind `ObjCClass in + let name = Mangled.from_string CFrontend_config.self in + let params = [CMethodSignature.mk_param_type name class_type] in + let bool_type = CType_to_sil_type.type_of_builtin_type_kind `Bool in get_predefined_ms_method condition class_name method_name - Typ.Procname.ObjC_Cpp.ObjCInstanceMethod mk_procname lang args Ast_expressions.create_BOOL_type + Typ.Procname.ObjC_Cpp.ObjCInstanceMethod mk_procname lang params (bool_type, Annot.Item.empty) [] (Some BuiltinDecl.__instanceof) diff --git a/infer/src/clang/cType_to_sil_type.ml b/infer/src/clang/cType_to_sil_type.ml index 504951ef8..d6c1b5368 100644 --- a/infer/src/clang/cType_to_sil_type.ml +++ b/infer/src/clang/cType_to_sil_type.ml @@ -75,6 +75,12 @@ let type_desc_of_builtin_type_kind builtin_type_kind = Typ.Tvoid +let type_of_builtin_type_kind ?(is_const= false) builtin_type_kind = + let desc = type_desc_of_builtin_type_kind builtin_type_kind in + let quals = Typ.mk_type_quals ~is_const () in + Typ.mk ~quals desc + + let pointer_attribute_of_objc_attribute attr_info = match attr_info.Clang_ast_t.ati_lifetime with | `OCL_None | `OCL_Strong -> diff --git a/infer/src/clang/cType_to_sil_type.mli b/infer/src/clang/cType_to_sil_type.mli index 82b0c1b6a..dddfbec40 100644 --- a/infer/src/clang/cType_to_sil_type.mli +++ b/infer/src/clang/cType_to_sil_type.mli @@ -11,5 +11,7 @@ open! IStd val get_builtin_objc_typename : [< `ObjCClass | `ObjCId] -> Typ.Name.t +val type_of_builtin_type_kind : ?is_const:bool -> Clang_ast_t.builtin_type_kind -> Typ.t + val qual_type_to_sil_type : (Tenv.t -> Clang_ast_t.decl -> Typ.desc) -> Tenv.t -> Clang_ast_t.qual_type -> Typ.t