[clang] C function names depend only on their name (and their file is they are static, and their type if we are in C++)

Summary:
C function names depend only on their name (and their file is they are static, and their type if we are in C++)
This is more in sync with the actual semantics of C function names than the previous implementation.
master
Dulma Rodriguez 9 years ago
parent 6606df245c
commit fd853f97ca

@ -166,3 +166,5 @@ let autoreleasing_atribute = "__autoreleasing"
let type_pointer_prefix = "internal_type" let type_pointer_prefix = "internal_type"
let nsarray_cl = "NSArray" let nsarray_cl = "NSArray"
let infer = "infer"

@ -163,3 +163,5 @@ val autoreleasing_atribute : string
val type_pointer_prefix : string val type_pointer_prefix : string
val nsarray_cl : string val nsarray_cl : string
val infer : string

@ -420,9 +420,28 @@ struct
let mk_class_field_name class_name field_name = let mk_class_field_name class_name field_name =
Ident.create_fieldname (Mangled.mangled field_name (class_name^"_"^field_name)) 0 Ident.create_fieldname (Mangled.mangled field_name (class_name^"_"^field_name)) 0
let mk_procname_from_function name type_name = let mk_procname_from_function name function_decl_info_opt type_name =
let type_name_crc = CRC.crc16 type_name in let file =
Procname.mangled_c_fun name type_name_crc 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 mk_procname_from_objc_method class_name method_name method_kind =
let mangled = Procname.mangled_of_objc_method_kind method_kind in let mangled = Procname.mangled_of_objc_method_kind method_kind in

@ -132,7 +132,8 @@ sig
val mk_procname_from_objc_method : string -> string -> Procname.objc_method_kind -> Procname.t 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 val mk_procname_from_cpp_method : string -> string -> string -> Procname.t

@ -93,7 +93,9 @@ let method_signature_of_decl class_name_opt meth_decl block_data_opt =
| FunctionDecl (decl_info, name_info, qt, fdi), _, _ -> | FunctionDecl (decl_info, name_info, qt, fdi), _, _ ->
let name = name_info.ni_name in let name = name_info.ni_name in
let func_decl = Func_decl_info (fdi, 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 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 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 ms, fdi.Clang_ast_t.fdi_body, fdi.Clang_ast_t.fdi_parameters
| CXXMethodDecl (decl_info, name_info, qt, fdi), _, Some class_name -> | 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 } 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 open CContext in
let callee_ms_opt = match method_signature_of_pointer class_name_opt pointer with
match pointer_opt with | Some callee_ms ->
| Some pointer -> ignore (create_local_procdesc context.cfg context.tenv callee_ms [] [] false);
(match method_signature_of_pointer None pointer with CMethod_signature.ms_get_name callee_ms
| Some callee_ms -> Some callee_ms | None ->
| None -> None) let type_name = qt.Clang_ast_t.qt_raw in
| None -> None in let callee_name =
match callee_ms_opt with match class_name_opt with
| Some callee_ms -> ignore (create_local_procdesc context.cfg context.tenv callee_ms [] [] false) | Some class_name ->
| None -> create_external_procdesc context.cfg callee_name false None 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 = let instance_to_method_call_type instance =
if instance then MCVirtual if instance then MCVirtual

@ -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 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

@ -297,7 +297,8 @@ struct
Printing.log_out " priority node free = '%s'\n@." Printing.log_out " priority node free = '%s'\n@."
(string_of_bool (PriorityNode.is_priority_free trans_state)); (string_of_bool (PriorityNode.is_priority_free trans_state));
let context = trans_state.context in 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 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 procname = Cfg.Procdesc.get_proc_name context.procdesc in
let pointer = CTrans_utils.get_decl_pointer decl_ref_expr_info 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 (Sil.Const(Sil.Cint Sil.Int.zero))) in
{ root_nodes = []; leaf_nodes = []; ids = []; instrs = []; exps = [(const_exp, typ)]} { root_nodes = []; leaf_nodes = []; ids = []; instrs = []; exps = [(const_exp, typ)]}
) else if is_function then ( ) 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 = let pname =
match qt with if CTrans_models.is_modeled_builtin name then
| Some v -> General_utils.mk_procname_from_function name v Procname.from_string_c_fun (CFrontend_config.infer ^ name)
| None -> Procname.from_string_c_fun name in else CMethod_trans.create_procdesc_with_pointer context pointer None name qt in
CMethod_trans.create_procdesc_with_pointer context (Some pointer) pname;
let address_of_function = not context.CContext.is_callee_expression 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.*) (* If we are not translating a callee expression, then the address of the function is being taken.*)
(* As e.g. in fun_ptr = foo; *) (* As e.g. in fun_ptr = foo; *)
@ -641,8 +637,6 @@ struct
| Sil.Const (Sil.Cfun pn) -> pn | Sil.Const (Sil.Cfun pn) -> pn
| _ -> assert false (* method pointer not implemented, this shouldn't happen *) in | _ -> assert false (* method pointer not implemented, this shouldn't happen *) in
let class_name_opt = Some (Procname.c_get_class callee_pname) 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 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 *) (* As we may have nodes coming from different parameters we need to *)
(* call instruction for each parameter and collect the results *) (* 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 *) (* 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 = 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 let field_name = match decl_ref.Clang_ast_t.dr_name with
| Some s -> s.Clang_ast_t.ni_name | Some s -> s.Clang_ast_t.ni_name
| _ -> assert false in | _ -> assert false in
let field_qt = match decl_ref.Clang_ast_t.dr_qual_type with let field_qt = match decl_ref.Clang_ast_t.dr_qual_type with
| Some t -> t | Some t -> t
| _ -> assert false in | _ -> 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; Printing.log_out "!!!!! Dealing with field '%s' @." field_name;
let exp_stmt = extract_stmt_from_singleton stmt_list let exp_stmt = extract_stmt_from_singleton stmt_list
"WARNING: in MemberExpr there must be only one stmt defining its expression.\n" in "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 "WARNING: in MemberExpr we expect the translation of the stmt to return an expression\n" in
let class_typ = let class_typ =
(match class_typ with (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 | t -> t) in
match decl_ref.Clang_ast_t.dr_kind with match decl_ref.Clang_ast_t.dr_kind with
| `Field | `ObjCIvar -> | `Field | `ObjCIvar ->
@ -1549,7 +1544,7 @@ struct
| Sil.Tvoid -> Sil.exp_minus_one | Sil.Tvoid -> Sil.exp_minus_one
| _ -> | _ ->
Printing.log_out "Type is '%s' @." (Sil.typ_to_string class_typ); 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 (match ObjcInterface_decl.find_field tenv field_name (Some class_typ) false with
| Some (fn, _, _) -> Sil.Lfield (obj_sil, fn, class_typ) | Some (fn, _, _) -> Sil.Lfield (obj_sil, fn, class_typ)
| None -> | None ->
@ -1562,11 +1557,12 @@ struct
exps = [(exp, field_typ)] } exps = [(exp, field_typ)] }
| `CXXMethod -> | `CXXMethod ->
(* consider using context.CContext.is_callee_expression to deal with pointers to methods? *) (* 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 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 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)] } { result_trans_exp_stmt with exps = [method_exp; (obj_sil, class_typ)] }
| _ -> assert false | _ -> assert false

Loading…
Cancel
Save