diff --git a/infer/src/clang/ast_expressions.ml b/infer/src/clang/ast_expressions.ml index 1d783ec81..aeb029fbc 100644 --- a/infer/src/clang/ast_expressions.ml +++ b/infer/src/clang/ast_expressions.ml @@ -83,34 +83,78 @@ let create_qual_type s = { qt_type_ptr = Ast_utils.get_invalid_pointer (); } -let create_pointer_type s = - create_qual_type (s^" *") +let create_qual_type_with_just_pointer pointer = + { + Clang_ast_t.qt_raw = ""; + qt_desugared = None; + qt_type_ptr = pointer; + } -let create_int_type () = create_qual_type "int" +let get_constant_qual_type s = + let pointer = CFrontend_config.type_pointer_prefix ^ s in + { + Clang_ast_t.qt_raw = s; + qt_desugared = None; + qt_type_ptr = pointer + } -let create_void_type () = create_qual_type "void *" +(* Whenever new type are added manually to the translation here, *) +(* they should be added to the map in cTypes_decl too!! *) +let create_int_type = + get_constant_qual_type "int" -let create_id_type () = create_qual_type "id" +let create_void_type = + get_constant_qual_type "void" -let create_char_type () = create_qual_type "char *" +let create_void_star_type = + get_constant_qual_type "void *" -(* pointer needs to be set when we start using these, non trivial to do though *) -let create_BOOL_type () = { - Clang_ast_t.qt_raw = "BOOL"; - qt_desugared = Some ("signed char"); - qt_type_ptr = Ast_utils.get_invalid_pointer (); -} +let create_id_type = + get_constant_qual_type CFrontend_config.id_cl + +let create_nsarray_star_type = + get_constant_qual_type (CFrontend_config.nsarray_cl ^ " *") + +let create_char_star_type = + get_constant_qual_type "char *" + +let create_BOOL_type = + get_constant_qual_type "signed char" -let create_void_unsigned_long_type () = create_qual_type "void *(unsigned long)" +let create_unsigned_long_type = + get_constant_qual_type "unsigned long" -let create_unsigned_long_type () = create_qual_type "unsigned long" +let create_void_unsigned_long_type = + get_constant_qual_type "void *(unsigned long)" -let create_void_void_type () = create_qual_type "void (void *)" +let create_void_void_type = + get_constant_qual_type "void (void *)" + +let create_class_type class_name = + { + Clang_ast_t.qt_raw = ""; + qt_desugared = None; + qt_type_ptr = "custom_class_name*" ^ class_name; + } + +let create_struct_type struct_name = + { + Clang_ast_t.qt_raw = ""; + qt_desugared = None; + qt_type_ptr = "custom_struct_name*" ^ struct_name; + } + +let create_pointer_type class_type = + { + Clang_ast_t.qt_raw = ""; + qt_desugared = None; + qt_type_ptr = "custom_pointer_"^class_type.Clang_ast_t.qt_type_ptr + } let create_integer_literal stmt_info n = let stmt_info = dummy_stmt_info () in let expr_info = { - Clang_ast_t.ei_qual_type = create_int_type (); + Clang_ast_t.ei_qual_type = create_int_type; ei_value_kind = `RValue; ei_object_kind = `Ordinary; } in @@ -123,7 +167,7 @@ let create_integer_literal stmt_info n = let create_cstyle_cast_expr stmt_info stmts qt = let expr_info = { - Clang_ast_t.ei_qual_type = create_void_type (); + Clang_ast_t.ei_qual_type = create_void_type; ei_value_kind = `RValue; ei_object_kind = `Ordinary; } in @@ -135,7 +179,7 @@ let create_cstyle_cast_expr stmt_info stmts qt = let create_parent_expr stmt_info stmts = let expr_info = { - Clang_ast_t.ei_qual_type = create_void_type (); + Clang_ast_t.ei_qual_type = create_void_type; ei_value_kind = `RValue; ei_object_kind = `Ordinary; } in @@ -155,10 +199,9 @@ let create_implicit_cast_expr stmt_info stmts typ cast_kind = let create_nil stmt_info = let integer_literal = create_integer_literal stmt_info "0" in - let cstyle_cast_expr = create_cstyle_cast_expr stmt_info [integer_literal] (create_int_type ()) in + let cstyle_cast_expr = create_cstyle_cast_expr stmt_info [integer_literal] create_int_type in let paren_expr = create_parent_expr stmt_info [cstyle_cast_expr] in - let implicit_cast_expr = create_implicit_cast_expr stmt_info [paren_expr] (create_id_type ()) `NullToPointer in - implicit_cast_expr + create_implicit_cast_expr stmt_info [paren_expr] create_id_type `NullToPointer let dummy_stmt () = let pointer = Ast_utils.get_fresh_pointer () in @@ -201,7 +244,7 @@ let make_obj_c_message_expr_info_instance sel = { let make_obj_c_message_expr_info_class selector qt = { Clang_ast_t.omei_selector = selector; - omei_receiver_kind = `Class (create_qual_type qt); + omei_receiver_kind = `Class (create_class_type qt); omei_is_definition_found = false; omei_decl_pointer = None (* TODO look into it *) } @@ -262,7 +305,7 @@ let make_cast_expr qt di decl_ref_expr_info objc_kind = (* Build AST expression self.field_name as `LValue *) let make_self_field class_type di qt field_name = - let qt_class = create_qual_type class_type in + let qt_class = create_pointer_type (create_class_type class_type) in let expr_info = make_expr_info_with_objc_kind qt `ObjCProperty in let stmt_info = make_stmt_info di in let cast_exp = make_cast_expr qt_class di (make_decl_ref_expr_info (make_decl_ref_self di.Clang_ast_t.di_pointer qt_class)) `ObjCProperty in @@ -310,7 +353,7 @@ let make_general_expr_info qt vk ok = { } let make_ObjCBoolLiteralExpr stmt_info value = - let ei = make_expr_info (create_BOOL_type ()) in + let ei = make_expr_info create_BOOL_type in Clang_ast_t.ObjCBoolLiteralExpr((fresh_stmt_info stmt_info),[], ei, value) let make_decl_ref_exp_var (var_name, var_qt, var_ptr) var_kind stmt_info = @@ -354,7 +397,7 @@ let make_next_object_exp stmt_info item items = Clang_ast_t.DeclRefExpr (stmt_info_var, [], expr_info, decl_ref_expr_info), var_type | _ -> assert false in - let message_call = make_message_expr (create_qual_type CFrontend_config.id_cl) + let message_call = make_message_expr create_id_type CFrontend_config.next_object items stmt_info false in let boi = { Clang_ast_t.boi_kind = `Assign } in make_binary_stmt var_decl_ref message_call stmt_info (make_expr_info_with_objc_kind var_type `ObjCProperty) boi @@ -386,7 +429,7 @@ let translate_dispatch_function block_name stmt_info stmt_list ei n = let block_var_decl = VarDecl(decl_info, block_name_info, ei.ei_qual_type, var_decl_info) in let decl_stmt = DeclStmt(stmt_info,[], [block_var_decl]) in - let expr_info_call = make_general_expr_info (create_void_type ()) `XValue `Ordinary in + let expr_info_call = make_general_expr_info create_void_type `XValue `Ordinary in let expr_info_dre = make_expr_info_with_objc_kind qt `Ordinary in let decl_ref = make_decl_ref_qt `Var stmt_info.si_pointer block_name false qt in let decl_ref_expr_info = make_decl_ref_expr_info decl_ref in @@ -412,8 +455,7 @@ let build_OpaqueValueExpr si source_expr ei = let opaque_value_expr_info = { Clang_ast_t.ovei_source_expr = Some source_expr } in Clang_ast_t.OpaqueValueExpr (si, [], ei, opaque_value_expr_info) -let pseudo_object_qt () = - create_qual_type CFrontend_config.pseudo_object_type +let pseudo_object_qt () = create_class_type CFrontend_config.pseudo_object_type (* Create expression PseudoObjectExpr for 'o.m' *) let build_PseudoObjectExpr qt_m o_cast_decl_ref_exp mname = @@ -436,7 +478,7 @@ let build_PseudoObjectExpr qt_m o_cast_decl_ref_exp mname = let create_call stmt_info decl_pointer function_name qt parameters = let expr_info_call = { - Clang_ast_t.ei_qual_type = create_void_type (); + Clang_ast_t.ei_qual_type = create_void_type; ei_value_kind = `XValue; ei_object_kind = `Ordinary } in @@ -502,12 +544,15 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = let build_stop pstop = match pstop with | Clang_ast_t.ParmVarDecl (di, name, qt, _) -> - let qt_fun = create_void_unsigned_long_type () in + let qt_fun = create_void_unsigned_long_type in + let type_opt = Some create_BOOL_type in let parameter = Clang_ast_t.UnaryExprOrTypeTraitExpr ((fresh_stmt_info stmt_info), [], - make_expr_info (create_unsigned_long_type ()), - { Clang_ast_t.uttei_kind = `SizeOf; Clang_ast_t.uttei_qual_type = Some (create_BOOL_type ()) }) in - let malloc = create_call (fresh_stmt_info stmt_info) di.Clang_ast_t.di_pointer CFrontend_config.malloc qt_fun [parameter] in + make_expr_info create_unsigned_long_type, + { Clang_ast_t.uttei_kind = `SizeOf; Clang_ast_t.uttei_qual_type = type_opt}) in + let pointer = di.Clang_ast_t.di_pointer in + let stmt_info = fresh_stmt_info stmt_info in + let malloc = create_call stmt_info pointer CFrontend_config.malloc qt_fun [parameter] in let init_exp = create_implicit_cast_expr (fresh_stmt_info stmt_info) [malloc] qt `BitCast in make_DeclStmt (fresh_stmt_info stmt_info) di qt name (Some init_exp) | _ -> assert false in @@ -529,11 +574,11 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = let free_stop pstop = match pstop with | Clang_ast_t.ParmVarDecl (di, name, qt, _) -> - let qt_fun = create_void_void_type () in + let qt_fun = create_void_void_type in let decl_ref = make_decl_ref_qt `Var di.Clang_ast_t.di_pointer name.Clang_ast_t.ni_name false qt in let cast = cast_expr decl_ref qt in let parameter = - create_implicit_cast_expr (fresh_stmt_info stmt_info) [cast] (create_void_type ()) `BitCast in + create_implicit_cast_expr (fresh_stmt_info stmt_info) [cast] create_void_type `BitCast in create_call (fresh_stmt_info stmt_info) di.Clang_ast_t.di_pointer CFrontend_config.free qt_fun [parameter] | _ -> assert false in @@ -542,7 +587,8 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = let idx_decl_stmt, idx_decl_ref_exp, idx_cast, idx_qt = build_idx_decl pidx in let rhs = build_PseudoObjectExpr idx_qt array_decl_ref_exp CFrontend_config.count in let lt = { Clang_ast_t.boi_kind = `LT } in - Clang_ast_t.BinaryOperator (fresh_stmt_info stmt_info, [idx_cast; rhs], make_expr_info (create_int_type ()), lt) in + let exp_info = make_expr_info create_int_type in + Clang_ast_t.BinaryOperator (fresh_stmt_info stmt_info, [idx_cast; rhs], exp_info, lt) in (* idx++ *) let un_op idx_decl_ref_expr qt_idx = @@ -579,7 +625,7 @@ 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 qt = create_qual_type CFrontend_config.ns_array_ptr in + let qt = create_pointer_type (create_class_type CFrontend_config.nsarray_cl) 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 var_decl = Clang_ast_t.VarDecl (di, make_name_decl CFrontend_config.objects, qt, vdi) in @@ -611,12 +657,12 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = let make_block_call block_qt object_cast idx_cast stop_cast = let decl_ref = make_decl_ref_invalid `Var block_name false block_qt in let fun_cast = cast_expr decl_ref block_qt in - let ei_call = make_expr_info (create_void_type ()) in + let ei_call = make_expr_info create_void_type in Clang_ast_t.CallExpr (fresh_stmt_info stmt_info, [fun_cast; object_cast; idx_cast; stop_cast], ei_call) in (* build statement "if (stop) break;" *) let build_if_stop stop_cast = - let bool_qt = create_BOOL_type () in + let bool_qt = create_BOOL_type in let ei = make_expr_info bool_qt in let unary_op = Clang_ast_t.UnaryOperator (fresh_stmt_info stmt_info, [stop_cast], ei, { Clang_ast_t.uoi_kind = `Deref; uoi_is_postfix = true }) in let cond = create_implicit_cast_expr (fresh_stmt_info stmt_info) [unary_op] bool_qt `LValueToRValue in @@ -691,4 +737,5 @@ let create_assume_not_null_call decl_info var_name var_type = let null_expr = create_integer_literal stmt_info "0" in let bin_op = make_binary_stmt decl_ref_exp_cast null_expr stmt_info (make_lvalue_obc_prop_expr_info var_type) boi in let parameters = [bin_op] in - create_call stmt_info var_decl_ptr (Procname.to_string SymExec.ModelBuiltins.__infer_assume) (create_void_type ()) parameters + let procname = Procname.to_string SymExec.ModelBuiltins.__infer_assume in + create_call stmt_info var_decl_ptr procname create_void_type parameters diff --git a/infer/src/clang/ast_expressions.mli b/infer/src/clang/ast_expressions.mli index eede81d66..752b95089 100644 --- a/infer/src/clang/ast_expressions.mli +++ b/infer/src/clang/ast_expressions.mli @@ -23,7 +23,33 @@ val dummy_stmt_info : unit -> stmt_info val create_qual_type : string -> qual_type -val create_pointer_type : string -> qual_type +val create_char_star_type : qual_type + +val create_id_type : qual_type + +val create_nsarray_star_type : qual_type + +val create_void_type : qual_type + +val create_int_type : qual_type + +val create_void_star_type : qual_type + +val create_BOOL_type : qual_type + +val create_unsigned_long_type : qual_type + +val create_void_unsigned_long_type : qual_type + +val create_void_void_type : qual_type + +val create_class_type : string -> qual_type + +val create_struct_type : string -> qual_type + +val create_pointer_type : qual_type -> qual_type + +val create_qual_type_with_just_pointer : Clang_ast_t.pointer -> qual_type val make_objc_ivar_decl : decl_info -> qual_type -> obj_c_property_impl_decl_info -> string -> decl @@ -51,8 +77,6 @@ val create_nil : stmt_info -> stmt val create_implicit_cast_expr : stmt_info -> stmt list -> qual_type -> cast_kind -> stmt -val create_char_type : unit -> qual_type - val make_message_expr : qual_type -> string -> stmt -> stmt_info -> bool -> stmt val make_compound_stmt : stmt list -> stmt_info -> stmt diff --git a/infer/src/clang/cContext.ml b/infer/src/clang/cContext.ml index 7816c9c58..f35766a66 100644 --- a/infer/src/clang/cContext.ml +++ b/infer/src/clang/cContext.ml @@ -287,9 +287,6 @@ let curr_class_hash curr_class = | ContextProtocol name -> Hashtbl.hash name | ContextNoCls -> Hashtbl.hash "no class" -let get_qt_curr_class curr_class = - (get_curr_class_name curr_class)^" *" - let get_captured_vars context = context.captured_vars let create_curr_class tenv class_name = diff --git a/infer/src/clang/cContext.mli b/infer/src/clang/cContext.mli index 35bc2bd12..555d410fd 100644 --- a/infer/src/clang/cContext.mli +++ b/infer/src/clang/cContext.mli @@ -58,8 +58,6 @@ val get_curr_class : t -> curr_class val get_curr_class_name : curr_class -> string -val get_qt_curr_class : curr_class -> string - val curr_class_to_string : curr_class -> string val curr_class_compare : curr_class -> curr_class -> int diff --git a/infer/src/clang/cFrontend_config.ml b/infer/src/clang/cFrontend_config.ml index 350fcb6d0..ce7345db1 100644 --- a/infer/src/clang/cFrontend_config.ml +++ b/infer/src/clang/cFrontend_config.ml @@ -161,3 +161,7 @@ let strong_attribtue = "__strong" let unsafe_unretained_attribute = "__unsafe_unretained" let autoreleasing_atribute = "__autoreleasing" + +let type_pointer_prefix = "internal_type" + +let nsarray_cl = "NSArray" diff --git a/infer/src/clang/cFrontend_config.mli b/infer/src/clang/cFrontend_config.mli index 99ab3e6d4..301694fd3 100644 --- a/infer/src/clang/cFrontend_config.mli +++ b/infer/src/clang/cFrontend_config.mli @@ -158,3 +158,7 @@ val strong_attribtue : string val unsafe_unretained_attribute : string val autoreleasing_atribute : string + +val type_pointer_prefix : string + +val nsarray_cl : string diff --git a/infer/src/clang/cMethod_signature.ml b/infer/src/clang/cMethod_signature.ml index d8770b5ad..180d83d91 100644 --- a/infer/src/clang/cMethod_signature.ml +++ b/infer/src/clang/cMethod_signature.ml @@ -12,8 +12,8 @@ type method_signature = { _name : Procname.t; - _args : (string * string * Clang_ast_t.stmt option) list; (* (name, type, default value) *) - _ret_type : string; + _args : (string * Clang_ast_t.qual_type * Clang_ast_t.stmt option) list; + _ret_type : Clang_ast_t.qual_type; _attributes : Clang_ast_t.attribute list; _loc : Clang_ast_t.source_range; _is_instance : bool; @@ -57,6 +57,9 @@ let replace_name_ms ms name = let ms_to_string ms = let gen = if ms._is_generated then " (generated)" else "" in - "Method "^(Procname.to_string ms._name)^gen^" "^ - (Utils.list_to_string (fun (s1, s2, _) -> s1^", "^s2) ms._args)^"->"^ms._ret_type^" "^ + "Method " ^ (Procname.to_string ms._name) ^ gen ^ " " ^ + Utils.list_to_string + (fun (s1, s2, _) -> s1 ^ ", " ^ (Clang_ast_j.string_of_qual_type s2)) + ms._args + ^ "->" ^ (Clang_ast_j.string_of_qual_type ms._ret_type) ^ " " ^ Clang_ast_j.string_of_source_range ms._loc diff --git a/infer/src/clang/cMethod_signature.mli b/infer/src/clang/cMethod_signature.mli index 4c0c13666..de21518f9 100644 --- a/infer/src/clang/cMethod_signature.mli +++ b/infer/src/clang/cMethod_signature.mli @@ -14,9 +14,10 @@ type method_signature val ms_get_name : method_signature -> Procname.t -val ms_get_args : method_signature -> (string * string * Clang_ast_t.stmt option) list +val ms_get_args : method_signature -> + (string * Clang_ast_t.qual_type * Clang_ast_t.stmt option) list -val ms_get_ret_type : method_signature -> string +val ms_get_ret_type : method_signature -> Clang_ast_t.qual_type val ms_get_attributes : method_signature -> Clang_ast_t.attribute list @@ -24,8 +25,9 @@ val ms_get_loc : method_signature -> Clang_ast_t.source_range val ms_is_instance : method_signature -> bool -val make_ms : Procname.t -> (string * string * Clang_ast_t.stmt option) list -> string -> Clang_ast_t.attribute list -> - Clang_ast_t.source_range -> bool -> bool -> method_signature +val make_ms : Procname.t -> (string * Clang_ast_t.qual_type * Clang_ast_t.stmt option) list -> + Clang_ast_t.qual_type -> Clang_ast_t.attribute list -> Clang_ast_t.source_range -> bool -> bool -> + method_signature val replace_name_ms : method_signature -> Procname.t -> method_signature diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index 3d319922e..a6889e407 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -28,10 +28,10 @@ type method_call_type = | MCStatic type function_method_decl_info = - | Func_decl_info of Clang_ast_t.function_decl_info * string - | Cpp_Meth_decl_info of Clang_ast_t.function_decl_info * string (* class_name *) * string (* ret_type *) + | 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 * string * Clang_ast_t.qual_type | ObjC_Meth_decl_info of Clang_ast_t.obj_c_method_decl_info * string - | Block_decl_info of Clang_ast_t.block_decl_info * string + | Block_decl_info of Clang_ast_t.block_decl_info * Clang_ast_t.qual_type let is_instance_method function_method_decl_info is_instance = match function_method_decl_info with @@ -44,8 +44,12 @@ let is_instance_method function_method_decl_info is_instance = let get_class_param function_method_decl_info = if (is_instance_method function_method_decl_info false) then match function_method_decl_info with - | Cpp_Meth_decl_info (_, class_name, _) -> [(CFrontend_config.this, class_name, None)] - | ObjC_Meth_decl_info (_, class_name) -> [(CFrontend_config.self, class_name, None)] + | Cpp_Meth_decl_info (_, class_name, _) -> + let class_type = Ast_expressions.create_struct_type class_name in + [(CFrontend_config.this, class_type, None)] + | ObjC_Meth_decl_info (_, class_name) -> + let class_type = Ast_expressions.create_class_type class_name in + [(CFrontend_config.self, class_type, None)] | _ -> [] else [] @@ -61,9 +65,7 @@ let get_parameters function_method_decl_info = match par with | Clang_ast_t.ParmVarDecl (decl_info, name_info, qtype, var_decl_info) -> let name = name_info.Clang_ast_t.ni_name in - Printing.log_out "Adding param '%s' " name; - Printing.log_out "with pointer %s@." decl_info.Clang_ast_t.di_pointer; - (name, CTypes.get_type qtype, var_decl_info.Clang_ast_t.vdi_init_expr) + (name, qtype, var_decl_info.Clang_ast_t.vdi_init_expr) | _ -> assert false in let pars = list_map par_to_ms_par (get_param_decls function_method_decl_info) in @@ -73,10 +75,9 @@ let get_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) -> typ - | ObjC_Meth_decl_info (method_decl_info, _) -> - let qt = method_decl_info.Clang_ast_t.omdi_result_type in - CTypes.get_type qt + | Block_decl_info (_, typ) -> + Ast_expressions.create_qual_type_with_just_pointer (CTypes.return_type_of_function_type typ) + | ObjC_Meth_decl_info (method_decl_info, _) -> method_decl_info.Clang_ast_t.omdi_result_type let build_method_signature decl_info procname function_method_decl_info is_instance is_anonym_block is_generated = let source_range = decl_info.Clang_ast_t.di_source_range in @@ -91,7 +92,7 @@ let method_signature_of_decl class_name_opt meth_decl block_data_opt = match meth_decl, block_data_opt, class_name_opt with | FunctionDecl (decl_info, name_info, qt, fdi), _, _ -> let name = name_info.ni_name in - let func_decl = Func_decl_info (fdi, CTypes.get_type qt) in + let func_decl = Func_decl_info (fdi, qt) in let procname = General_utils.mk_procname_from_function name (CTypes.get_type qt) in let ms = build_method_signature decl_info procname func_decl false false false in ms, fdi.Clang_ast_t.fdi_body, fdi.Clang_ast_t.fdi_parameters @@ -99,7 +100,7 @@ let method_signature_of_decl class_name_opt meth_decl block_data_opt = let method_name = name_info.Clang_ast_t.ni_name in let typ = CTypes.get_type qt in let procname = General_utils.mk_procname_from_cpp_method class_name method_name typ in - let method_decl = Cpp_Meth_decl_info (fdi, class_name, typ) in + let method_decl = Cpp_Meth_decl_info (fdi, class_name, qt) in let ms = build_method_signature decl_info procname method_decl false false false in ms, fdi.Clang_ast_t.fdi_body, fdi.Clang_ast_t.fdi_parameters | ObjCMethodDecl (decl_info, name_info, mdi), _, Some class_name -> @@ -113,7 +114,7 @@ let method_signature_of_decl class_name_opt meth_decl block_data_opt = ms, mdi.omdi_body, mdi.omdi_parameters | BlockDecl (decl_info, decl_list, decl_context_info, bdi), Some (qt, is_instance, procname, _, _), _ -> - let func_decl = Block_decl_info (bdi, CTypes.get_type qt) in + let func_decl = Block_decl_info (bdi, qt) in let ms = build_method_signature decl_info procname func_decl is_instance true false in ms, bdi.bdi_body, bdi.bdi_parameters | _ -> raise Invalid_declaration @@ -151,7 +152,9 @@ let get_class_selector_instance context obj_c_message_expr_info act_params = let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in let pointer = obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer in match obj_c_message_expr_info.Clang_ast_t.omei_receiver_kind with - | `Class qt -> (CTypes.get_type qt, selector, pointer, MCStatic) + | `Class qt -> + let sil_type = CTypes_decl.qual_type_to_sil_type context.CContext.tenv qt in + ((CTypes.classname_of_type sil_type), selector, pointer, MCStatic) | `Instance -> (match act_params with | (instance_obj, Sil.Tptr(t, _)):: _ @@ -173,7 +176,7 @@ let get_formal_parameters tenv ms = let qt = if (name = CFrontend_config.self && CMethod_signature.ms_is_instance ms) then (Ast_expressions.create_pointer_type raw_type) - else Ast_expressions.create_qual_type raw_type in + else raw_type in let typ = CTypes_decl.qual_type_to_sil_type tenv qt in (name, typ):: defined_parameters pl' in defined_parameters (CMethod_signature.ms_get_args ms) @@ -208,9 +211,8 @@ let captured_vars_from_block_info context cvl = list_flatten (f cvl) let get_return_type tenv ms = - let qt = CMethod_signature.ms_get_ret_type ms in - CTypes_decl.qual_type_to_sil_type tenv - (Ast_expressions.create_qual_type (CTypes.get_function_return_type qt)) + let return_type = CMethod_signature.ms_get_ret_type ms in + CTypes_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 diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index b2edbfabc..36215e0b2 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -184,8 +184,9 @@ struct f trans_state stmt with Self.SelfClassException class_name -> let typ = CTypes_decl.type_name_to_sil_type trans_state.context.CContext.tenv class_name in + let expanded_type = CTypes.expand_structured_type trans_state.context.CContext.tenv typ in { empty_res_trans with - exps = [(Sil.Sizeof(typ, Sil.Subtype.exact), Sil.Tint Sil.IULong)] } + exps = [(Sil.Sizeof(expanded_type, Sil.Subtype.exact), Sil.Tint Sil.IULong)] } (* Execute translation of e forcing to release priority (if it's not free) and then setting it back.*) (* This is used in conditional operators where we need to force the priority to be free for the *) @@ -320,11 +321,10 @@ struct if CTrans_models.is_modeled_builtin name then ("infer" ^ name) else name in let qt = CTypes.get_raw_qual_type_decl_ref_exp_info decl_ref_expr_info in - let pname, type_opt = + let pname = match qt with - | Some v -> - (General_utils.mk_procname_from_function name v, CTypes_decl.parse_func_type name v) - | None -> (Procname.from_string_c_fun name, None) in + | Some v -> General_utils.mk_procname_from_function name v + | None -> Procname.from_string_c_fun name in CMethod_trans.create_procdesc_with_pointer context (Some pointer) pname; let address_of_function = not context.CContext.is_callee_expression in (* If we are not translating a callee expression, then the address of the function is being taken.*) @@ -1541,7 +1541,7 @@ struct "WARNING: in MemberExpr we expect the translation of the stmt to return an expression\n" in let class_typ = (match class_typ with - | Sil.Tptr (t, _) -> CTypes_decl.expand_structured_type trans_state.context.CContext.tenv t + | Sil.Tptr (t, _) -> CTypes.expand_structured_type trans_state.context.CContext.tenv t | t -> t) in match decl_ref.Clang_ast_t.dr_kind with | `Field | `ObjCIvar -> @@ -1552,7 +1552,12 @@ struct let tenv = trans_state.context.CContext.tenv in (match ObjcInterface_decl.find_field tenv field_name (Some class_typ) false with | Some (fn, _, _) -> Sil.Lfield (obj_sil, fn, class_typ) - | None -> assert false) in + | None -> + let class_name = CTypes.classname_of_type class_typ in + let default_name = (General_utils.mk_class_field_name class_name field_name) in + Printing.log_out "Warning: Field not found %s in class %s " field_name + (Sil.typ_to_string class_typ); + Sil.Lfield (obj_sil, default_name, class_typ)) in { result_trans_exp_stmt with exps = [(exp, field_typ)] } | `CXXMethod -> @@ -1685,7 +1690,7 @@ struct and objCStringLiteral_trans trans_state stmt_info stmts info = let stmts = [Ast_expressions.create_implicit_cast_expr stmt_info stmts - (Ast_expressions.create_char_type ()) `ArrayToPointerDecay] in + Ast_expressions.create_char_star_type `ArrayToPointerDecay] in let typ = CTypes_decl.class_from_pointer_type trans_state.context.CContext.tenv info.Clang_ast_t.ei_qual_type in let obj_c_message_expr_info = Ast_expressions.make_obj_c_message_expr_info_class CFrontend_config.string_with_utf8_m typ in diff --git a/infer/src/clang/cTrans_models.ml b/infer/src/clang/cTrans_models.ml index 447b0b3e7..2f37ee057 100644 --- a/infer/src/clang/cTrans_models.ml +++ b/infer/src/clang/cTrans_models.ml @@ -135,14 +135,15 @@ let get_predefined_ms_stringWithUTF8String class_name method_name mk_procname = let condition = class_name = CFrontend_config.nsstring_cl && method_name = CFrontend_config.string_with_utf8_m in + let id_type = Ast_expressions.create_id_type in get_predefined_ms_method condition class_name method_name Procname.Class_objc_method - mk_procname [("x", "char *", None)] CFrontend_config.id_cl [] None + mk_procname [("x", Ast_expressions.create_char_star_type, None)] id_type [] None let get_predefined_ms_retain_release class_name method_name mk_procname = let condition = is_retain_or_release method_name in let return_type = if is_retain_method method_name || is_autorelease_method method_name - then CFrontend_config.id_cl else CFrontend_config.void in + then Ast_expressions.create_id_type else Ast_expressions.create_void_type in get_predefined_ms_method condition CFrontend_config.nsobject_cl method_name Procname.Instance_objc_method mk_procname [(CFrontend_config.self, class_name, None)] return_type [] (get_builtinname method_name) @@ -150,22 +151,25 @@ let get_predefined_ms_autoreleasepool_init class_name method_name mk_procname = let condition = method_name = CFrontend_config.init && class_name = CFrontend_config.nsautorelease_pool_cl in + let class_type = Ast_expressions.create_class_type class_name in get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method - mk_procname [(CFrontend_config.self, class_name, None)] CFrontend_config.void [] None + mk_procname [(CFrontend_config.self, class_type, None)] Ast_expressions.create_void_type [] None let get_predefined_ms_nsautoreleasepool_release class_name method_name mk_procname = let condition = (method_name = CFrontend_config.release || method_name = CFrontend_config.drain) && class_name = CFrontend_config.nsautorelease_pool_cl in + let class_type = Ast_expressions.create_class_type class_name in get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method - mk_procname [(CFrontend_config.self, class_name, None)] - CFrontend_config.void [] (Some SymExec.ModelBuiltins.__objc_release_autorelease_pool) + mk_procname [(CFrontend_config.self, class_type, None)] + Ast_expressions.create_void_type [] (Some SymExec.ModelBuiltins.__objc_release_autorelease_pool) let get_predefined_model_method_signature class_name method_name mk_procname = match get_predefined_ms_nsautoreleasepool_release class_name method_name mk_procname with | Some ms -> Some ms | None -> - match get_predefined_ms_retain_release class_name method_name mk_procname with + let class_type = Ast_expressions.create_class_type class_name in + match get_predefined_ms_retain_release class_type method_name mk_procname with | Some ms -> Some ms | None -> match get_predefined_ms_stringWithUTF8String class_name method_name mk_procname with diff --git a/infer/src/clang/cTrans_utils.ml b/infer/src/clang/cTrans_utils.ml index 3613d86a7..b19c553f3 100644 --- a/infer/src/clang/cTrans_utils.ml +++ b/infer/src/clang/cTrans_utils.ml @@ -278,8 +278,9 @@ let create_alloc_instrs context sil_loc function_type fname = | Sil.Tptr (styp, Sil.Pk_objc_weak) | Sil.Tptr (styp, Sil.Pk_objc_unsafe_unretained) | Sil.Tptr (styp, Sil.Pk_objc_autoreleasing) -> - function_type, CTypes_decl.expand_structured_type context.CContext.tenv styp + function_type, styp | _ -> Sil.Tptr (function_type, Sil.Pk_pointer), function_type in + let function_type_np = CTypes.expand_structured_type context.CContext.tenv function_type_np in let sizeof_exp = Sil.Sizeof (function_type_np, Sil.Subtype.exact) in let exp = (sizeof_exp, Sil.Tint Sil.IULong) in let ret_id = Ident.create_fresh Ident.knormal in @@ -333,8 +334,8 @@ let cpp_new_trans trans_state sil_loc stmt_info function_type = let create_cast_instrs context exp cast_from_typ cast_to_typ sil_loc = let ret_id = Ident.create_fresh Ident.knormal in - let cast_typ_no_pointer = - CTypes_decl.expand_structured_type context.CContext.tenv (CTypes.remove_pointer_to_typ cast_to_typ) in + let typ = CTypes.remove_pointer_to_typ cast_to_typ in + let cast_typ_no_pointer = CTypes.expand_structured_type context.CContext.tenv typ in let sizeof_exp = Sil.Sizeof (cast_typ_no_pointer, Sil.Subtype.exact) in let pname = SymExec.ModelBuiltins.__objc_cast in let args = [(exp, cast_from_typ); (sizeof_exp, Sil.Tint Sil.IULong)] in diff --git a/infer/src/clang/cTypes.ml b/infer/src/clang/cTypes.ml index 051c34d77..a134cb044 100644 --- a/infer/src/clang/cTypes.ml +++ b/infer/src/clang/cTypes.ml @@ -13,20 +13,6 @@ open Utils open CFrontend_utils module L = Logging -let get_function_return_type s = - let regexp = Str.regexp_string " (" in - let matches = try let _ = Str.search_forward regexp s 0 in true with Not_found -> false in - let regexp' = - if matches then regexp - else Str.regexp_string "(" in (* match e.g. "char *()" *) - let buf = Str.split regexp' s in - match buf with - | ret:: _ -> - let ret'= String.trim ret in - Printing.log_out "return type ='%s'@." ret'; - ret' - | _ -> assert false - let get_type qt = match qt.Clang_ast_t.qt_desugared with | Some t -> t diff --git a/infer/src/clang/cTypes.mli b/infer/src/clang/cTypes.mli index fdea7c2d6..e42544e3b 100644 --- a/infer/src/clang/cTypes.mli +++ b/infer/src/clang/cTypes.mli @@ -23,8 +23,6 @@ val search_enum_type_by_name : Sil.tenv -> string -> Sil.const option val classname_of_type : Sil.typ -> string -val get_function_return_type : string -> string - val mk_classname : string -> Sil.typename val mk_structname : string -> Sil.typename diff --git a/infer/src/clang/cTypes_decl.ml b/infer/src/clang/cTypes_decl.ml index 8306d0878..2aa73e6e4 100644 --- a/infer/src/clang/cTypes_decl.ml +++ b/infer/src/clang/cTypes_decl.ml @@ -15,26 +15,57 @@ open CFrontend_utils module L = Logging exception Typename_not_found -(* Adds the predefined types objc_class which is a struct, and Class, *) -(* which is a pointer to objc_class. *) -let add_predefined_types tenv = +let add_predefined_objc_types tenv = let objc_class_mangled = Mangled.from_string CFrontend_config.objc_class in let objc_class_name = Sil.TN_csu (Sil.Class, objc_class_mangled) in let objc_class_type_info = Sil.Tstruct ([], [], Sil.Struct, Some (Mangled.from_string CFrontend_config.objc_class), [], [], []) in Sil.tenv_add tenv objc_class_name objc_class_type_info; - let mn = Mangled.from_string CFrontend_config.class_type in - let class_typename = Sil.TN_typedef(mn) in - let class_typ = Sil.Tptr ((Sil.Tvar - (Sil.TN_csu (Sil.Struct, objc_class_mangled))), Sil.Pk_pointer) in + let class_typename = CType_to_sil_type.get_builtin_objc_typename `ObjCClass in + let class_typ = Sil.Tvar (Sil.TN_csu (Sil.Struct, objc_class_mangled)) in Sil.tenv_add tenv class_typename class_typ; let typename_objc_object = Sil.TN_csu (Sil.Struct, Mangled.from_string CFrontend_config.objc_object) in - let id_typedef = Sil.Tptr (Sil.Tvar (typename_objc_object), Sil.Pk_pointer) in - let id_typename = Sil.TN_typedef (Mangled.from_string CFrontend_config.id_cl) in + let id_typedef = Sil.Tvar (typename_objc_object) in + let id_typename = CType_to_sil_type.get_builtin_objc_typename `ObjCId in Sil.tenv_add tenv id_typename id_typedef +(* Whenever new type are added manually to the translation in ast_expressions, *) +(* they should be added here too!! *) +let add_predefined_basic_types tenv = + let open Ast_expressions in + let open Clang_ast_t in + let add_basic_type qt 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 qt.Clang_ast_t.qt_type_ptr sil_type in + let add_pointer_type qt sil_type = + let pointer_type = CTypes.add_pointer_to_typ sil_type in + Ast_utils.update_sil_types_map qt.Clang_ast_t.qt_type_ptr pointer_type in + let add_function_type qt return_type = + (* We translate function types as the return type of the function *) + Ast_utils.update_sil_types_map qt.Clang_ast_t.qt_type_ptr 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 = Sil.Tvar (CTypes.mk_classname CFrontend_config.nsarray_cl) in + let sil_id_type = CType_to_sil_type.get_builtin_objc_type `ObjCId in + add_basic_type create_int_type `Int; + add_basic_type create_void_type `Void; + add_basic_type create_char_star_type `Char_S; + add_basic_type create_BOOL_type `SChar; + add_basic_type create_unsigned_long_type `ULong; + add_pointer_type create_void_star_type sil_void_type; + add_pointer_type create_char_star_type sil_char_type; + add_pointer_type create_char_star_type sil_char_type; + add_pointer_type create_nsarray_star_type sil_nsarray_type; + add_pointer_type create_id_type sil_id_type; + add_function_type create_void_unsigned_long_type sil_void_type; + add_function_type create_void_void_type sil_void_type + +let add_predefined_types tenv = + add_predefined_objc_types tenv; + add_predefined_basic_types tenv + let rec search_for_named_type tenv typ = let search typename = match typename with diff --git a/infer/src/clang/objcProperty_decl.ml b/infer/src/clang/objcProperty_decl.ml index 978f33e70..c516240ae 100644 --- a/infer/src/clang/objcProperty_decl.ml +++ b/infer/src/clang/objcProperty_decl.ml @@ -270,8 +270,9 @@ let make_getter curr_class prop_name prop_type = match getter with | Some (ObjCMethodDecl(di, name_info, mdi), _) -> let dummy_info = Ast_expressions.dummy_decl_info_in_curr_file di in + let class_name = CContext.get_curr_class_name curr_class in let deref_self_field = Ast_expressions.make_deref_self_field - (CContext.get_qt_curr_class curr_class) dummy_info mdi.Clang_ast_t.omdi_result_type ivar_name in + class_name dummy_info mdi.Clang_ast_t.omdi_result_type ivar_name in let body = ReturnStmt(Ast_expressions.make_stmt_info dummy_info, [deref_self_field]) in let mdi'= Ast_expressions.make_method_decl_info mdi body in let generated_name_info = create_generated_method_name name_info in @@ -302,7 +303,7 @@ let make_setter curr_class prop_name prop_type = let stmt_info = Ast_expressions.make_stmt_info dummy_info in let rhs_exp = Ast_expressions.make_cast_expr qt_param di decl_ref_expr_info' `ObjCProperty in let lhs_exp = Ast_expressions.make_self_field - (CContext.get_qt_curr_class curr_class) di qt_param ivar_name in + (CContext.get_curr_class_name curr_class) di qt_param ivar_name in let boi = { Clang_ast_t.boi_kind = `Assign } in let setter = Ast_expressions.make_binary_stmt lhs_exp rhs_exp stmt_info expr_info boi in let memory_management_attribute = (get_memory_management_attribute attributes) in