diff --git a/infer/src/clang/cFrontend_config.ml b/infer/src/clang/cFrontend_config.ml index e5b1f7f5f..b8f1991e9 100644 --- a/infer/src/clang/cFrontend_config.ml +++ b/infer/src/clang/cFrontend_config.ml @@ -166,3 +166,5 @@ let autoreleasing_atribute = "__autoreleasing" let type_pointer_prefix = "internal_type" let nsarray_cl = "NSArray" + +let infer = "infer" diff --git a/infer/src/clang/cFrontend_config.mli b/infer/src/clang/cFrontend_config.mli index 33c718d64..090742417 100644 --- a/infer/src/clang/cFrontend_config.mli +++ b/infer/src/clang/cFrontend_config.mli @@ -163,3 +163,5 @@ val autoreleasing_atribute : string val type_pointer_prefix : string val nsarray_cl : string + +val infer : string diff --git a/infer/src/clang/cFrontend_utils.ml b/infer/src/clang/cFrontend_utils.ml index adccfd536..9eabc3905 100644 --- a/infer/src/clang/cFrontend_utils.ml +++ b/infer/src/clang/cFrontend_utils.ml @@ -420,9 +420,28 @@ struct let mk_class_field_name class_name field_name = Ident.create_fieldname (Mangled.mangled field_name (class_name^"_"^field_name)) 0 - let mk_procname_from_function name type_name = - let type_name_crc = CRC.crc16 type_name in - Procname.mangled_c_fun name type_name_crc + let mk_procname_from_function name function_decl_info_opt type_name = + 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" -> + (match (fst decl_info.Clang_ast_t.di_source_range).Clang_ast_t.sl_file with + | Some file -> file + | None -> "") + | _ -> "") + | None -> "" in + let type_string = + match !CFrontend_config.language with + | CFrontend_config.CPP + | CFrontend_config.OBJCPP -> type_name + | _ -> "" in + let mangled = file ^ type_string in + if String.length mangled == 0 then + Procname.from_string_c_fun name + else + let crc = CRC.crc16 mangled in + Procname.mangled_c_fun name crc let mk_procname_from_objc_method class_name method_name method_kind = let mangled = Procname.mangled_of_objc_method_kind method_kind in diff --git a/infer/src/clang/cFrontend_utils.mli b/infer/src/clang/cFrontend_utils.mli index 73953cf9f..8e870ea17 100644 --- a/infer/src/clang/cFrontend_utils.mli +++ b/infer/src/clang/cFrontend_utils.mli @@ -132,7 +132,8 @@ sig val mk_procname_from_objc_method : string -> string -> Procname.objc_method_kind -> Procname.t - val mk_procname_from_function : string -> string -> Procname.t + val mk_procname_from_function : string -> + (Clang_ast_t.decl_info * Clang_ast_t.function_decl_info) option -> string -> Procname.t val mk_procname_from_cpp_method : string -> string -> string -> Procname.t diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index a6889e407..6a16a6494 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -93,7 +93,9 @@ let method_signature_of_decl class_name_opt meth_decl block_data_opt = | FunctionDecl (decl_info, name_info, qt, fdi), _, _ -> let name = name_info.ni_name 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 type_string = CTypes.get_type qt in + let function_info = Some (decl_info, fdi) in + let procname = General_utils.mk_procname_from_function name function_info type_string 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 | CXXMethodDecl (decl_info, name_info, qt, fdi), _, Some class_name -> @@ -312,18 +314,22 @@ let create_external_procdesc cfg proc_name is_objc_inst_method type_opt = } in () -let create_procdesc_with_pointer context pointer_opt callee_name = +let create_procdesc_with_pointer context pointer class_name_opt name qt = let open CContext in - let callee_ms_opt = - match pointer_opt with - | Some pointer -> - (match method_signature_of_pointer None pointer with - | Some callee_ms -> Some callee_ms - | None -> None) - | None -> None in - match callee_ms_opt with - | Some callee_ms -> ignore (create_local_procdesc context.cfg context.tenv callee_ms [] [] false) - | None -> create_external_procdesc context.cfg callee_name false None + match method_signature_of_pointer class_name_opt pointer with + | Some callee_ms -> + ignore (create_local_procdesc context.cfg context.tenv callee_ms [] [] false); + CMethod_signature.ms_get_name callee_ms + | None -> + let type_name = qt.Clang_ast_t.qt_raw in + let callee_name = + match class_name_opt with + | Some class_name -> + General_utils.mk_procname_from_cpp_method class_name name type_name + | None -> + General_utils.mk_procname_from_function name None type_name in + create_external_procdesc context.cfg callee_name false None; + callee_name let instance_to_method_call_type instance = if instance then MCVirtual diff --git a/infer/src/clang/cMethod_trans.mli b/infer/src/clang/cMethod_trans.mli index ab035aead..898b6d9ff 100644 --- a/infer/src/clang/cMethod_trans.mli +++ b/infer/src/clang/cMethod_trans.mli @@ -37,4 +37,5 @@ val method_signature_of_decl : string option -> Clang_ast_t.decl -> CModule_type val method_signature_of_pointer : string option -> Clang_ast_t.pointer -> CMethod_signature.method_signature option -val create_procdesc_with_pointer : CContext.t -> Clang_ast_t.pointer option -> Procname.t -> unit +val create_procdesc_with_pointer : CContext.t -> Clang_ast_t.pointer -> string option -> + string -> Clang_ast_t.qual_type -> Procname.t diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 36215e0b2..d23af9bf4 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -297,7 +297,8 @@ struct Printing.log_out " priority node free = '%s'\n@." (string_of_bool (PriorityNode.is_priority_free trans_state)); let context = trans_state.context in - let typ = CTypes_decl.qual_type_to_sil_type context.tenv expr_info.Clang_ast_t.ei_qual_type in + let qt = expr_info.Clang_ast_t.ei_qual_type in + let typ = CTypes_decl.qual_type_to_sil_type context.tenv qt in let name = get_name_decl_ref_exp_info decl_ref_expr_info stmt_info in let procname = Cfg.Procdesc.get_proc_name context.procdesc in let pointer = CTrans_utils.get_decl_pointer decl_ref_expr_info in @@ -317,15 +318,10 @@ struct (Sil.Const(Sil.Cint Sil.Int.zero))) in { root_nodes = []; leaf_nodes = []; ids = []; instrs = []; exps = [(const_exp, typ)]} ) else if is_function then ( - let name = - 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 = - match qt with - | 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; + if CTrans_models.is_modeled_builtin name then + Procname.from_string_c_fun (CFrontend_config.infer ^ name) + else CMethod_trans.create_procdesc_with_pointer context pointer None name qt in 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.*) (* As e.g. in fun_ptr = foo; *) @@ -641,8 +637,6 @@ struct | Sil.Const (Sil.Cfun pn) -> pn | _ -> assert false (* method pointer not implemented, this shouldn't happen *) in let class_name_opt = Some (Procname.c_get_class callee_pname) in - let pointer_opt = CTrans_utils.pointer_of_call_expr fun_exp_stmt in - CMethod_trans.create_procdesc_with_pointer context pointer_opt callee_pname; let params_stmt = CTrans_utils.assign_default_params params_stmt class_name_opt fun_exp_stmt ~is_cxx_method:true in (* As we may have nodes coming from different parameters we need to *) (* call instruction for each parameter and collect the results *) @@ -1526,13 +1520,14 @@ struct (* function used in the computation for both Member_Expr and ObjCIVarRefExpr *) and do_memb_ivar_ref_exp trans_state expr_info stmt_info stmt_list decl_ref = + let context = trans_state.context in let field_name = match decl_ref.Clang_ast_t.dr_name with | Some s -> s.Clang_ast_t.ni_name | _ -> assert false in let field_qt = match decl_ref.Clang_ast_t.dr_qual_type with | Some t -> t | _ -> assert false in - let field_typ = CTypes_decl.qual_type_to_sil_type trans_state.context.CContext.tenv field_qt in + let field_typ = CTypes_decl.qual_type_to_sil_type context.CContext.tenv field_qt in Printing.log_out "!!!!! Dealing with field '%s' @." field_name; let exp_stmt = extract_stmt_from_singleton stmt_list "WARNING: in MemberExpr there must be only one stmt defining its expression.\n" in @@ -1541,7 +1536,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.expand_structured_type trans_state.context.CContext.tenv t + | Sil.Tptr (t, _) -> CTypes.expand_structured_type context.CContext.tenv t | t -> t) in match decl_ref.Clang_ast_t.dr_kind with | `Field | `ObjCIvar -> @@ -1549,7 +1544,7 @@ struct | Sil.Tvoid -> Sil.exp_minus_one | _ -> Printing.log_out "Type is '%s' @." (Sil.typ_to_string class_typ); - let tenv = trans_state.context.CContext.tenv in + let tenv = 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 -> @@ -1562,11 +1557,12 @@ struct exps = [(exp, field_typ)] } | `CXXMethod -> (* consider using context.CContext.is_callee_expression to deal with pointers to methods? *) - let raw_type = field_qt.Clang_ast_t.qt_raw in let class_name = match class_typ with Sil.Tptr (t, _) | t -> CTypes.classname_of_type t in - let pname = General_utils.mk_procname_from_cpp_method class_name field_name raw_type in + let pointer = decl_ref.Clang_ast_t.dr_decl_pointer in + let pname = CMethod_trans.create_procdesc_with_pointer context pointer (Some class_name) + field_name field_qt in let method_exp = (Sil.Const (Sil.Cfun pname), field_typ) in - Cfg.set_procname_priority trans_state.context.CContext.cfg pname; + Cfg.set_procname_priority context.CContext.cfg pname; { result_trans_exp_stmt with exps = [method_exp; (obj_sil, class_typ)] } | _ -> assert false