From 0b0cd0d38de7ec5a161bae3424232262ae925796 Mon Sep 17 00:00:00 2001 From: Dulma Rodriguez Date: Wed, 30 Sep 2015 12:28:56 -0100 Subject: [PATCH] [clang] Using qual names for fields Summary: Using the qualified names of fields to create mangled names. This removes the need to search for the fields in the tenv when translating a field access. That was only done to build the correct mangled name, The rest of the changes are using the qualified names for ivars and property names in the property module, which is needed to make it work. Basically a big chain of changes of using qualified names to make the code compile. --- infer/src/clang/ast_expressions.ml | 53 +++++++++-------- infer/src/clang/ast_expressions.mli | 13 ++-- infer/src/clang/cField_decl.ml | 21 ++++--- infer/src/clang/cField_decl.mli | 4 +- infer/src/clang/cFrontend_utils.ml | 32 +++++++--- infer/src/clang/cFrontend_utils.mli | 16 +++-- infer/src/clang/cMethod_decl.ml | 6 +- infer/src/clang/cTrans.ml | 28 +++------ infer/src/clang/cTypes_decl.ml | 2 +- infer/src/clang/objcInterface_decl.ml | 82 -------------------------- infer/src/clang/objcInterface_decl.mli | 3 - infer/src/clang/objcProperty_decl.ml | 51 +++++++++------- infer/src/clang/objcProperty_decl.mli | 35 +++++++---- 13 files changed, 148 insertions(+), 198 deletions(-) diff --git a/infer/src/clang/ast_expressions.ml b/infer/src/clang/ast_expressions.ml index af9a7dad2..b1a490c29 100644 --- a/infer/src/clang/ast_expressions.ml +++ b/infer/src/clang/ast_expressions.ml @@ -242,15 +242,10 @@ let make_obj_c_message_expr_info_class selector qt = { omei_decl_pointer = None (* TODO look into it *) } -let make_name_decl name = { - Clang_ast_t.ni_name = name; - ni_qual_name = [name]; -} - let make_decl_ref k decl_ptr name is_hidden qt_opt = { Clang_ast_t.dr_kind = k; dr_decl_pointer = decl_ptr; - dr_name = Some (make_name_decl name); + dr_name = Some name; dr_is_hidden = is_hidden ; dr_qual_type = qt_opt } @@ -267,7 +262,7 @@ let make_decl_ref_invalid k name is_hidden qt = let make_decl_ref_self ptr qt = { Clang_ast_t.dr_kind = `ImplicitParam; dr_decl_pointer = ptr; - dr_name = Some (make_name_decl "self"); + dr_name = Some (Ast_utils.make_name_decl "self"); dr_is_hidden = false ; dr_qual_type = Some qt } @@ -331,7 +326,7 @@ let make_objc_ivar_decl decl_info qt property_impl_decl_info ivar_name = Clang_ast_t.ovdi_is_synthesize = true; (* NOTE: We set true here because we use this definition to synthesize the getter/setter*) ovdi_access_control = `Private; } in - Clang_ast_t.ObjCIvarDecl(decl_info, make_name_decl ivar_name, qt, field_decl_info, obj_c_ivar_decl_info) + Clang_ast_t.ObjCIvarDecl(decl_info, ivar_name, qt, field_decl_info, obj_c_ivar_decl_info) let make_expr_info qt = { Clang_ast_t.ei_qual_type = qt; @@ -378,9 +373,8 @@ let make_next_object_exp stmt_info item items = let var_decl_ref, var_type = match item with | Clang_ast_t.DeclStmt (stmt_info, _, [Clang_ast_t.VarDecl(di, name_info, var_type, _)]) -> - let var_name = name_info.Clang_ast_t.ni_name in let decl_ptr = di.Clang_ast_t.di_pointer in - let decl_ref = make_decl_ref_qt `Var decl_ptr var_name false var_type in + let decl_ref = make_decl_ref_qt `Var decl_ptr name_info false var_type in let stmt_info_var = { Clang_ast_t.si_pointer = di.Clang_ast_t.di_pointer; si_source_range = di.Clang_ast_t.di_source_range @@ -409,7 +403,7 @@ let translate_dispatch_function block_name stmt_info stmt_list ei n = let block_expr = try Utils.list_nth stmt_list (n + 1) with Not_found -> assert false in - let block_name_info = make_name_decl block_name in + let block_name_info = Ast_utils.make_name_decl block_name in let open Clang_ast_t in match block_expr with | BlockExpr (bsi, bsl, bei, bd) -> @@ -424,7 +418,7 @@ let translate_dispatch_function block_name stmt_info stmt_list ei n = let expr_info_call = make_general_expr_info create_void_star_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 = make_decl_ref_qt `Var stmt_info.si_pointer block_name_info false qt in let decl_ref_expr_info = make_decl_ref_expr_info decl_ref in let cast_info_call = { cei_cast_kind = `LValueToRValue; cei_base_path =[]} in let decl_ref_exp = DeclRefExpr(stmt_info, [], expr_info_dre, decl_ref_expr_info) in @@ -456,9 +450,11 @@ let build_PseudoObjectExpr qt_m o_cast_decl_ref_exp mname = | Clang_ast_t.ImplicitCastExpr (si, stmt_list, ei, cast_expr_info) -> let ove = build_OpaqueValueExpr si o_cast_decl_ref_exp ei in let ei_opre = make_expr_info (pseudo_object_qt ()) in + let count_name = Ast_utils.make_name_decl CFrontend_config.count in + let pointer = si.Clang_ast_t.si_pointer in let obj_c_property_ref_expr_info = { Clang_ast_t.oprei_kind = - `PropertyRef (make_decl_ref_no_qt `ObjCProperty si.Clang_ast_t.si_pointer CFrontend_config.count false); + `PropertyRef (make_decl_ref_no_qt `ObjCProperty pointer count_name false); oprei_is_super_receiver = false; oprei_is_messaging_getter = true; oprei_is_messaging_setter = false; @@ -520,7 +516,8 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = (* qt_idx idx = 0; *) let idx_decl_stmt = make_DeclStmt (fresh_stmt_info stmt_info) di_idx qt_idx name_idx (Some zero) in let idx_ei = make_expr_info qt_idx in - let idx_decl_ref = make_decl_ref_qt `Var di_idx.Clang_ast_t.di_pointer name_idx.Clang_ast_t.ni_name false qt_idx in + let pointer = di_idx.Clang_ast_t.di_pointer in + let idx_decl_ref = make_decl_ref_qt `Var pointer name_idx false qt_idx in let idx_drei = make_decl_ref_expr_info idx_decl_ref in let idx_decl_ref_exp = make_decl_ref_exp stmt_info idx_ei idx_drei in let idx_cast = create_implicit_cast_expr (fresh_stmt_info stmt_info) [idx_decl_ref_exp] qt_idx `LValueToRValue in @@ -545,7 +542,8 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = { 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 malloc_name = Ast_utils.make_name_decl CFrontend_config.malloc in + let malloc = create_call stmt_info pointer malloc_name 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 @@ -554,7 +552,7 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = let stop_equal_no pstop = match pstop with | Clang_ast_t.ParmVarDecl (di, name, qt, _) -> - let decl_ref = make_decl_ref_qt `Var di.Clang_ast_t.di_pointer name.Clang_ast_t.ni_name false qt in + let decl_ref = make_decl_ref_qt `Var di.Clang_ast_t.di_pointer name false qt in let cast = cast_expr decl_ref qt in let postfix_deref = { Clang_ast_t.uoi_kind = `Deref; uoi_is_postfix = true } in let lhs = Clang_ast_t.UnaryOperator (fresh_stmt_info stmt_info, [cast], ei, postfix_deref) in @@ -568,11 +566,13 @@ let translate_block_enumerate block_name stmt_info stmt_list ei = match pstop with | Clang_ast_t.ParmVarDecl (di, name, qt, _) -> 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 decl_ref = make_decl_ref_qt `Var di.Clang_ast_t.di_pointer name false qt in let cast = cast_expr decl_ref qt in + let free_name = Ast_utils.make_name_decl CFrontend_config.free in let parameter = create_implicit_cast_expr (fresh_stmt_info stmt_info) [cast] create_void_star_type `BitCast in - create_call (fresh_stmt_info stmt_info) di.Clang_ast_t.di_pointer CFrontend_config.free qt_fun [parameter] + let pointer = di.Clang_ast_t.di_pointer in + create_call (fresh_stmt_info stmt_info) pointer free_name qt_fun [parameter] | _ -> assert false in (* idx - let decl_ref = make_decl_ref_qt `Var si.Clang_ast_t.si_pointer name.Clang_ast_t.ni_name false qt in + let decl_ref = make_decl_ref_qt `Var si.Clang_ast_t.si_pointer name false qt in cast_expr decl_ref qt | _ -> assert false in let build_cast_decl_ref_expr_from_parm p = match p with | Clang_ast_t.ParmVarDecl (di, name, qt, _) -> - let decl_ref = make_decl_ref_qt `Var di.Clang_ast_t.di_pointer name.Clang_ast_t.ni_name false qt in + let decl_ref = make_decl_ref_qt `Var di.Clang_ast_t.di_pointer name false qt in cast_expr decl_ref qt | _ -> assert false in + let qual_block_name = Ast_utils.make_name_decl block_name in + let make_block_decl be = match be with | Clang_ast_t.BlockExpr (bsi, _, bei, _) -> let di = { empty_decl_info with Clang_ast_t.di_pointer = Ast_utils.get_fresh_pointer () } in let vdi = { empty_var_decl_info with Clang_ast_t.vdi_init_expr = Some (be) } in - let var_decl = Clang_ast_t.VarDecl (di, make_name_decl block_name, bei.Clang_ast_t.ei_qual_type, vdi) in + let qt = bei.Clang_ast_t.ei_qual_type in + let var_decl = Clang_ast_t.VarDecl (di, qual_block_name, qt, vdi) in Clang_ast_t.DeclStmt (bsi, [be], [var_decl]), [(block_name, di.Clang_ast_t.di_pointer, bei.Clang_ast_t.ei_qual_type)] | _ -> assert false in 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 decl_ref = make_decl_ref_invalid `Var qual_block_name false block_qt in let fun_cast = cast_expr decl_ref block_qt in let ei_call = make_expr_info create_void_star_type in Clang_ast_t.CallExpr (fresh_stmt_info stmt_info, [fun_cast; object_cast; idx_cast; stop_cast], ei_call) in @@ -731,4 +735,5 @@ let create_assume_not_null_call decl_info var_name var_type = let bin_op = make_binary_stmt decl_ref_exp_cast null_expr stmt_info (make_lvalue_obc_prop_expr_info var_type) boi in let parameters = [bin_op] in let procname = Procname.to_string SymExec.ModelBuiltins.__infer_assume in - create_call stmt_info var_decl_ptr procname create_void_star_type parameters + let qual_procname = Ast_utils.make_name_decl procname in + create_call stmt_info var_decl_ptr qual_procname create_void_star_type parameters diff --git a/infer/src/clang/ast_expressions.mli b/infer/src/clang/ast_expressions.mli index e2b473d2a..c56a643e3 100644 --- a/infer/src/clang/ast_expressions.mli +++ b/infer/src/clang/ast_expressions.mli @@ -49,15 +49,16 @@ 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 +val make_objc_ivar_decl : decl_info -> qual_type -> obj_c_property_impl_decl_info -> + named_decl_info -> decl -val make_deref_self_field : string -> decl_info -> qual_type -> string -> stmt +val make_deref_self_field : string -> decl_info -> qual_type -> named_decl_info -> stmt val make_stmt_info : decl_info -> stmt_info val make_method_decl_info : obj_c_method_decl_info -> stmt -> obj_c_method_decl_info -val make_decl_ref_qt : decl_kind -> pointer -> string -> bool -> qual_type -> decl_ref +val make_decl_ref_qt : decl_kind -> pointer -> named_decl_info -> bool -> qual_type -> decl_ref val make_decl_ref_expr_info : decl_ref -> decl_ref_expr_info @@ -67,7 +68,7 @@ val make_expr_info : qual_type -> expr_info val make_cast_expr : qual_type -> decl_info -> decl_ref_expr_info -> object_kind -> stmt -val make_self_field : string -> decl_info -> qual_type -> string -> stmt +val make_self_field : string -> decl_info -> qual_type -> named_decl_info -> stmt val make_next_object_exp : stmt_info -> stmt -> Clang_ast_t.stmt -> Clang_ast_t.stmt @@ -79,7 +80,7 @@ val make_message_expr : qual_type -> string -> stmt -> stmt_info -> bool -> stmt val make_compound_stmt : stmt list -> stmt_info -> stmt -val make_decl_ref_exp_var : string * qual_type * pointer -> decl_kind -> stmt_info -> stmt +val make_decl_ref_exp_var : named_decl_info * qual_type * pointer -> decl_kind -> stmt_info -> stmt val make_binary_stmt : stmt -> stmt -> stmt_info -> expr_info -> binary_operator_info -> stmt @@ -95,4 +96,4 @@ val translate_block_enumerate : string -> stmt_info -> stmt list -> expr_info (* !x <=> x?0:1 *) val trans_negation_with_conditional : stmt_info -> expr_info -> stmt list -> stmt -val create_assume_not_null_call : decl_info -> string -> qual_type -> stmt +val create_assume_not_null_call : decl_info -> named_decl_info -> qual_type -> stmt diff --git a/infer/src/clang/cField_decl.ml b/infer/src/clang/cField_decl.ml index dbe8ef1f2..5ad7af89a 100644 --- a/infer/src/clang/cField_decl.ml +++ b/infer/src/clang/cField_decl.ml @@ -47,13 +47,13 @@ let get_field_www name_field fl = "WARNING: In MemberExpr there must be only one type defininf for the struct. Returning (NO_FIELD_NAME, Tvoid)\n" (Ident.create_fieldname (Mangled.from_string "NO_FIELD_NAME") 0, Sil.Tvoid) -let build_sil_field tenv class_name field_name qual_type prop_atts = +let build_sil_field tenv field_name qual_type prop_atts = let annotation_from_type t = match t with | Sil.Tptr (_, Sil.Pk_objc_weak) -> [Config.weak] | Sil.Tptr (_, Sil.Pk_objc_unsafe_unretained) -> [Config.unsafe_unret] | _ -> [] in - let fname = General_utils.mk_class_field_name class_name field_name in + let fname = General_utils.mk_class_field_name field_name in let typ = CTypes_decl.qual_type_to_sil_type tenv qual_type in let item_annotations = match prop_atts with | [] -> @@ -64,27 +64,27 @@ let build_sil_field tenv class_name field_name qual_type prop_atts = (* From an ivar look for its property and if it finds it returns its attributes *) let ivar_property curr_class ivar = - Printing.log_out "Checking if a property is defined for the ivar: '%s'@." ivar; + Printing.log_out "Checking if a property is defined for the ivar: '%s'@." + ivar.Clang_ast_t.ni_name; match ObjcProperty_decl.Property.find_property_name_from_ivar curr_class ivar with | Some pname' -> - (Printing.log_out "Found property name from ivar: '%s'" pname'; + (Printing.log_out "Found property name from ivar: '%s'" pname'.Clang_ast_t.ni_name; try let _, atts, _, _, _, _ = ObjcProperty_decl.Property.find_property curr_class pname' in atts with Not_found -> - Printing.log_out "Didn't find property for pname '%s'" pname'; + Printing.log_out "Didn't find property for pname '%s'" pname'.Clang_ast_t.ni_name; []) - | None -> Printing.log_out "No property found for ivar '%s'@." ivar; + | None -> Printing.log_out "No property found for ivar '%s'@." ivar.Clang_ast_t.ni_name; [] let build_sil_field_property curr_class tenv field_name qual_type prop_attributes_opt = - let class_name = CContext.get_curr_class_name curr_class in let prop_attributes = match prop_attributes_opt with | Some prop_attributes -> prop_attributes | None -> ivar_property curr_class field_name in let atts_str = list_map Clang_ast_j.string_of_property_attribute prop_attributes in - build_sil_field tenv class_name field_name qual_type atts_str + build_sil_field tenv field_name qual_type atts_str (* Given a list of declarations in an interface returns a list of fields *) let rec get_fields tenv curr_class decl_list = @@ -93,11 +93,10 @@ let rec get_fields tenv curr_class decl_list = | [] -> [] | ObjCIvarDecl (decl_info, name_info, qual_type, field_decl_info, obj_c_ivar_decl_info) :: decl_list' -> let fields = get_fields tenv curr_class decl_list' in - let field_name = name_info.Clang_ast_t.ni_name in (* Doing a post visit here. Adding Ivar after all the declaration have been visited so that *) (* ivar names will be added in the property list. *) - Printing.log_out " ...Adding Instance Variable '%s' @." field_name; - let (fname, typ, ia) = build_sil_field_property curr_class tenv field_name qual_type None in + Printing.log_out " ...Adding Instance Variable '%s' @." name_info.Clang_ast_t.ni_name; + let (fname, typ, ia) = build_sil_field_property curr_class tenv name_info qual_type None in Printing.log_out " ...Resulting sil field: (%s) with attributes:@." ((Ident.fieldname_to_string fname) ^":"^(Sil.typ_to_string typ)); list_iter (fun (ia', _) -> list_iter (fun a -> Printing.log_out " '%s'@." a) ia'.Sil.parameters) ia; diff --git a/infer/src/clang/cField_decl.mli b/infer/src/clang/cField_decl.mli index f534b2b0e..400f1f3c1 100644 --- a/infer/src/clang/cField_decl.mli +++ b/infer/src/clang/cField_decl.mli @@ -19,7 +19,7 @@ val get_fields : Sil.tenv -> CContext.curr_class -> Clang_ast_t.decl list -> fie val fields_superclass : Sil.tenv -> Clang_ast_t.obj_c_interface_decl_info -> field_type list -val build_sil_field_property : CContext.curr_class -> Sil.tenv -> string -> Clang_ast_t.qual_type -> - Clang_ast_t.property_attribute list option -> field_type +val build_sil_field_property : CContext.curr_class -> Sil.tenv -> Clang_ast_t.named_decl_info -> + Clang_ast_t.qual_type -> Clang_ast_t.property_attribute list option -> field_type val add_missing_fields : Sil.tenv -> string -> field_type list -> unit diff --git a/infer/src/clang/cFrontend_utils.ml b/infer/src/clang/cFrontend_utils.ml index 37ebb2953..820e8b6f2 100644 --- a/infer/src/clang/cFrontend_utils.ml +++ b/infer/src/clang/cFrontend_utils.ml @@ -153,17 +153,33 @@ struct | name :: qualifiers -> list_fold_right (fun el res -> res ^ el ^ "::") qualifiers "" + let make_name_decl name = { + Clang_ast_t.ni_name = name; + ni_qual_name = [name]; + } + + let make_qual_name_decl class_name name = { + Clang_ast_t.ni_name = name; + ni_qual_name = [name; class_name]; + } + let property_name property_impl_decl_info = - let no_property_name = "WARNING_NO_PROPERTY_NAME" in + let no_property_name = make_name_decl "WARNING_NO_PROPERTY_NAME" in match property_impl_decl_info.Clang_ast_t.opidi_property_decl with | Some decl_ref -> (match decl_ref.Clang_ast_t.dr_name with - | Some n -> n.Clang_ast_t.ni_name + | Some n -> n | _ -> no_property_name) | None -> no_property_name let generated_ivar_name property_name = - "_"^property_name + match property_name.Clang_ast_t.ni_qual_name with + | [name; class_name] -> + let ivar_name = "_" ^ name in + { Clang_ast_t.ni_name = ivar_name; + ni_qual_name = [ivar_name; class_name] + } + | _ -> make_name_decl property_name.Clang_ast_t.ni_name let property_attribute_compare att1 att2 = match att1, att2 with @@ -230,7 +246,7 @@ struct | [] -> None | attr:: rest -> match attr with - | `Getter getter -> name_opt_of_name_info_opt getter.Clang_ast_t.dr_name + | `Getter getter -> getter.Clang_ast_t.dr_name | _ -> (getter_attribute_opt rest) let rec setter_attribute_opt attributes = @@ -238,7 +254,7 @@ struct | [] -> None | attr:: rest -> match attr with - | `Setter setter -> name_opt_of_name_info_opt setter.Clang_ast_t.dr_name + | `Setter setter -> setter.Clang_ast_t.dr_name | _ -> (setter_attribute_opt rest) let pointer_counter = ref 0 @@ -425,8 +441,10 @@ struct let replicate n el = list_map (fun i -> el) (list_range 0 (n -1)) - let mk_class_field_name class_name field_name = - Ident.create_fieldname (Mangled.mangled field_name (class_name^"_"^field_name)) 0 + let mk_class_field_name field_qual_name = + let field_name = field_qual_name.Clang_ast_t.ni_name in + let prefix = Ast_utils.get_qualifier_string field_qual_name in + Ident.create_fieldname (Mangled.mangled field_name prefix) 0 let mk_procname_from_function name function_decl_info_opt qt = let file = diff --git a/infer/src/clang/cFrontend_utils.mli b/infer/src/clang/cFrontend_utils.mli index e61a41967..64d0e2fe9 100644 --- a/infer/src/clang/cFrontend_utils.mli +++ b/infer/src/clang/cFrontend_utils.mli @@ -46,17 +46,19 @@ sig val name_opt_of_name_info_opt : Clang_ast_t.named_decl_info option -> string option - val property_name : Clang_ast_t.obj_c_property_impl_decl_info -> string + val property_name : Clang_ast_t.obj_c_property_impl_decl_info -> Clang_ast_t.named_decl_info val property_attribute_compare : Clang_ast_t.property_attribute -> Clang_ast_t.property_attribute -> int - val generated_ivar_name : string -> string + val generated_ivar_name : Clang_ast_t.named_decl_info -> Clang_ast_t.named_decl_info val property_attribute_eq : Clang_ast_t.property_attribute -> Clang_ast_t.property_attribute -> bool - val getter_attribute_opt : Clang_ast_t.property_attribute list -> string option + val getter_attribute_opt : Clang_ast_t.property_attribute list -> + Clang_ast_t.named_decl_info option - val setter_attribute_opt : Clang_ast_t.property_attribute list -> string option + val setter_attribute_opt : Clang_ast_t.property_attribute list -> + Clang_ast_t.named_decl_info option val get_memory_management_attributes : unit -> Clang_ast_t.property_attribute list @@ -92,6 +94,10 @@ sig val string_of_qual_type : Clang_ast_t.qual_type -> string + val make_name_decl : string -> Clang_ast_t.named_decl_info + + val make_qual_name_decl : string -> string -> Clang_ast_t.named_decl_info + end module General_utils : @@ -139,7 +145,7 @@ sig val mk_procname_from_cpp_method : string -> string -> Clang_ast_t.qual_type -> Procname.t - val mk_class_field_name : string -> string -> Ident.fieldname + val mk_class_field_name : Clang_ast_t.named_decl_info -> Ident.fieldname end diff --git a/infer/src/clang/cMethod_decl.ml b/infer/src/clang/cMethod_decl.ml index e261fd7c3..f4be07d89 100644 --- a/infer/src/clang/cMethod_decl.ml +++ b/infer/src/clang/cMethod_decl.ml @@ -43,9 +43,8 @@ struct | decl:: rest -> let rest_assume_calls = add_assume_not_null_calls rest attributes in (match decl with - | Clang_ast_t.ParmVarDecl(decl_info, name_info, qtype, var_decl_info) + | Clang_ast_t.ParmVarDecl (decl_info, name, qtype, var_decl_info) when CFrontend_utils.Ast_utils.is_type_nonnull qtype attributes -> - let name = name_info.Clang_ast_t.ni_name in let assume_call = Ast_expressions.create_assume_not_null_call decl_info name qtype in assume_call:: rest_assume_calls | _ -> rest_assume_calls) @@ -134,7 +133,8 @@ struct process_method_decl tenv cg cfg namespace curr_class dec ~is_objc:true | ObjCPropertyImplDecl (decl_info, property_impl_decl_info) -> let pname = Ast_utils.property_name property_impl_decl_info in - Printing.log_out "ADDING: ObjCPropertyImplDecl for property '%s' " pname; + Printing.log_out "ADDING: ObjCPropertyImplDecl for property '%s' " + pname.Clang_ast_t.ni_name; let getter_setter = ObjcProperty_decl.make_getter_setter curr_class decl_info pname in list_iter (process_one_method_decl tenv cg cfg curr_class namespace) getter_setter | EmptyDecl _ | ObjCIvarDecl _ | ObjCPropertyDecl _ -> () diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 553ea4cbb..6f38ba80d 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -97,7 +97,8 @@ struct let procdesc = trans_state.context.CContext.procdesc in let procname = Cfg.Procdesc.get_proc_name procdesc in let mk_field_from_captured_var (vname, typ, b) = - let fname = General_utils.mk_class_field_name block_name (Mangled.to_string vname) in + let qual_name = Ast_utils.make_qual_name_decl block_name (Mangled.to_string vname) in + let fname = General_utils.mk_class_field_name qual_name in let item_annot = Sil.item_annotation_empty in fname, typ, item_annot in let fields = list_map mk_field_from_captured_var captured_vars in @@ -1518,13 +1519,13 @@ struct 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 + | Some s -> s | _ -> 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 context.CContext.tenv field_qt in - Printing.log_out "!!!!! Dealing with field '%s' @." field_name; + Printing.log_out "!!!!! Dealing with field '%s' @." field_name.Clang_ast_t.ni_name; let exp_stmt = extract_stmt_from_singleton stmt_list "WARNING: in MemberExpr there must be only one stmt defining its expression.\n" in let result_trans_exp_stmt = instruction trans_state exp_stmt in @@ -1536,27 +1537,16 @@ struct | t -> t) in match decl_ref.Clang_ast_t.dr_kind with | `Field | `ObjCIvar -> - let exp = match class_typ with - | Sil.Tvoid -> Sil.exp_minus_one - | _ -> - Printing.log_out "Type is '%s' @." (Sil.typ_to_string class_typ); - 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 -> - 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)] } + Printing.log_out "Type is '%s' @." (Sil.typ_to_string class_typ); + let fn = General_utils.mk_class_field_name field_name in + let exp = Sil.Lfield (obj_sil, fn, class_typ) in + { result_trans_exp_stmt with exps = [(exp, field_typ)] } | `CXXMethod -> (* consider using context.CContext.is_callee_expression to deal with pointers to methods? *) let class_name = match class_typ with Sil.Tptr (t, _) | t -> CTypes.classname_of_type t 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 + field_name.Clang_ast_t.ni_name field_qt in let method_exp = (Sil.Const (Sil.Cfun pname), field_typ) in Cfg.set_procname_priority context.CContext.cfg pname; { result_trans_exp_stmt with exps = [method_exp; (obj_sil, class_typ)] } diff --git a/infer/src/clang/cTypes_decl.ml b/infer/src/clang/cTypes_decl.ml index ee004b846..ffb23ad50 100644 --- a/infer/src/clang/cTypes_decl.ml +++ b/infer/src/clang/cTypes_decl.ml @@ -142,7 +142,7 @@ let rec get_struct_fields tenv record_name namespace decl_list = let open Clang_ast_t in let do_one_decl decl = match decl with | FieldDecl (_, name_info, qual_type, _) -> - let id = General_utils.mk_class_field_name record_name name_info.Clang_ast_t.ni_name in + let id = General_utils.mk_class_field_name name_info in let typ = qual_type_to_sil_type tenv qual_type in let annotation_items = [] in (* For the moment we don't use them*) [(id, typ, annotation_items)] diff --git a/infer/src/clang/objcInterface_decl.ml b/infer/src/clang/objcInterface_decl.ml index 912da5ac0..0001e5b2f 100644 --- a/infer/src/clang/objcInterface_decl.ml +++ b/infer/src/clang/objcInterface_decl.ml @@ -151,85 +151,3 @@ let interface_impl_declaration tenv class_name decl_list idi = CField_decl.add_missing_fields tenv class_name fields; add_missing_methods tenv class_name decl_list curr_class; curr_class - -(* search for definition of interface with non empty set of fields that may come after their use.*) -(* Typical example: *) -(* ...Partial definition of the interface I*) -(* :::: [later in the AST]*) -(* ...use of a field of I*) -(* ::: [later in the AST] *) -(* ...Full definition of the interface I *) -let lookup_late_defined_interface tenv cname = - let rec scan decls = - let open Clang_ast_t in - match decls with - | [] -> () - | ObjCInterfaceDecl (decl_info, name_info, decl_list, decl_context_info, obj_c_interface_decl_info) - :: decls' - when (Mangled.from_string name_info.Clang_ast_t.ni_name) = cname -> - scan decls' - | ObjCInterfaceDecl (decl_info, name_info, decl_list, decl_context_info, oi_decl_info) - :: decls' - when (Mangled.from_string name_info.Clang_ast_t.ni_name) = cname -> - (* Assumption: here we assume that the first interface declaration with non empty set of fields is the *) - (* correct one. So we stop. *) - let name = name_info.Clang_ast_t.ni_name in - ignore (interface_declaration tenv decl_info name decl_list oi_decl_info) - | _:: decls' -> scan decls' in - scan !CFrontend_config.global_translation_unit_decls - -(* Finds the field nfield in a Tstruc. If the Tstrct is a class and the field is not found *) -(* the search is extended in a recursive way to the hierarchy of superclasses. *) -let rec find_field tenv nfield str searched_late_defined = - (* let add_namespace_to_namefield cname = - match namespace with - | Some _ -> nfield - | None -> (Mangled.to_string cname)^"_"^nfield in *) - let print_error name_field fields = - Printing.log_err "\nFaild to find name field '%s'\n\n" (Ident.fieldname_to_string name_field) ; - Printing.log_err "In the following list of fields\n"; - list_iter (fun (fn, _, _) -> Printing.log_err "\nField name: '%s'\n\n" (Ident.fieldname_to_string fn)) fields; - Printing.print_failure_info "" in - let rec search_super s = - match s with - | [] -> None - | (Sil.Class, sname):: s' -> - Printing.log_err "@. ....Searching field in superclass (Class, '%s')@." (Mangled.to_string sname); - let str' = Sil.tenv_lookup tenv (Sil.TN_csu(Sil.Class, sname)) in - (match find_field tenv nfield str' searched_late_defined with - | Some field -> Some field - | None -> search_super s') - | (Sil.Protocol, sname):: s' -> - Printing.log_err "@. ... Searching field in protocol (Protocol, '%s')@." (Mangled.to_string sname); - search_super s' - | (Sil.Struct, sname):: s' -> - Printing.log_err "@. ... Searching field in struct (Struct, '%s')@." (Mangled.to_string sname); - None - | (Sil.Union, sname):: s' -> - Printing.log_err "@. ... Searching field in (Union, '%s')@." (Mangled.to_string sname); - None in - match str with - | Some Sil.Tstruct (sf, nsf, Sil.Struct, Some cname, _, _, _) - | Some Sil.Tstruct (sf, nsf, Sil.Union, Some cname, _, _, _) -> - (let name_field = General_utils.mk_class_field_name (Mangled.to_string cname) nfield in - try - Some (list_find (fun (fn, _, _) -> Sil.fld_equal fn name_field) (sf@nsf)) - with Not_found -> - print_error name_field (sf@nsf); None) - | Some Sil.Tstruct (sf, nsf, Sil.Class, Some cname, super, _, _) -> - (let name_field = General_utils.mk_class_field_name (Mangled.to_string cname) nfield in - try - Some (list_find (fun (fn, _, _) -> Sil.fld_equal fn name_field) (sf@nsf)) - with Not_found -> - (* if we have already searched for late defined interfaces we check recursively *) - (* whether the field is defined in the hiearchy of superclasses.*) - (* If we don't find it we stop, giving error. *) - print_error name_field (sf@nsf); - if searched_late_defined then search_super super - else ( - Printing.log_err "@. Search late defined...@.@."; - (* if we don't find the field the first thing we do is scanning later definitions of interfaces. *) - lookup_late_defined_interface tenv cname; - let str' = Sil.tenv_lookup tenv (Sil.TN_csu(Sil.Class, cname)) in - find_field tenv nfield str' true)) - | _ -> None diff --git a/infer/src/clang/objcInterface_decl.mli b/infer/src/clang/objcInterface_decl.mli index a9f3e9017..19059b4d9 100644 --- a/infer/src/clang/objcInterface_decl.mli +++ b/infer/src/clang/objcInterface_decl.mli @@ -14,9 +14,6 @@ val interface_declaration : Sil.tenv -> Clang_ast_t.decl_info -> string -> Clang_ast_t.decl list -> Clang_ast_t.obj_c_interface_decl_info -> CContext.curr_class -val find_field : Sil.tenv -> string -> Sil.typ option -> bool -> - (Ident.fieldname * Sil.typ * Sil.item_annotation) option - val interface_impl_declaration : Sil.tenv -> string -> Clang_ast_t.decl list -> Clang_ast_t.obj_c_implementation_decl_info -> CContext.curr_class diff --git a/infer/src/clang/objcProperty_decl.ml b/infer/src/clang/objcProperty_decl.ml index c516240ae..c2275a6f5 100644 --- a/infer/src/clang/objcProperty_decl.ml +++ b/infer/src/clang/objcProperty_decl.ml @@ -28,7 +28,8 @@ type prop_getter_setter = string * (Clang_ast_t.decl * bool) option (** A property type is a tuple: *) (** (qual_type, property attributes, decl_info, (getter_name, getter), (setter_name, setter), ivar name) *) type property_type = Clang_ast_t.qual_type * Clang_ast_t.property_attribute list * - Clang_ast_t.decl_info * prop_getter_setter * prop_getter_setter * string option + Clang_ast_t.decl_info * prop_getter_setter * prop_getter_setter * + Clang_ast_t.named_decl_info option (** A table that record the property defined in the interface and its getter/setter. *) (** This info used later on in the implementation if the getter/setter need to automatically *) @@ -38,34 +39,36 @@ sig type t - type property_key = (CContext.curr_class * string) + type property_key = (CContext.curr_class * Clang_ast_t.named_decl_info) val property_key_to_string : property_key -> string val reset_property_table: unit -> unit - val find_property : CContext.curr_class -> string -> property_type + val find_property : CContext.curr_class -> Clang_ast_t.named_decl_info -> property_type - val find_properties_class : CContext.curr_class -> (string * property_type) list + val find_properties_class : CContext.curr_class -> + (Clang_ast_t.named_decl_info * property_type) list val is_mem_property : property_key -> bool val replace_property : property_key -> property_type -> unit - val add_property : property_key -> Clang_ast_t.qual_type -> - Clang_ast_t.property_attribute list -> Clang_ast_t.decl_info -> unit + val add_property : property_key -> Clang_ast_t.qual_type -> Clang_ast_t.property_attribute list -> + Clang_ast_t.decl_info -> unit val print_property_table : unit -> unit - val find_property_name_from_ivar : CContext.curr_class -> string -> string option + val find_property_name_from_ivar : CContext.curr_class -> Clang_ast_t.named_decl_info -> + Clang_ast_t.named_decl_info option end module Property: PropertySig = struct - type property_key = (CContext.curr_class * string) + type property_key = (CContext.curr_class * Clang_ast_t.named_decl_info) let property_key_to_string (curr_class, property_name) = - ((CContext.curr_class_to_string curr_class)^"-"^property_name) + ((CContext.curr_class_to_string curr_class) ^ "-" ^ property_name.Clang_ast_t.ni_name) (** Hash table to implement error logs *) module PropertyTableHash = Hashtbl.Make (struct @@ -76,7 +79,7 @@ struct let equal (curr_class1, property_name1) (curr_class2, property_name2) = CContext.curr_class_equal curr_class1 curr_class2 && - (String.compare property_name1 property_name2 == 0) + (String.compare property_name1.Clang_ast_t.ni_name property_name2.Clang_ast_t.ni_name = 0) end) @@ -141,19 +144,19 @@ struct let get_getter_name prop_name attributes = match Ast_utils.getter_attribute_opt attributes with - | Some name -> name - | None -> prop_name + | Some name -> name.Clang_ast_t.ni_name + | None -> prop_name.Clang_ast_t.ni_name let get_setter_name prop_name attributes = + let open Clang_ast_t in match Ast_utils.setter_attribute_opt attributes with - | Some name -> name - | None -> "set"^(String.capitalize prop_name)^":" + | Some name -> name.Clang_ast_t.ni_name + | None -> "set" ^ (String.capitalize prop_name.ni_name) ^ ":" let add_property (curr_class, property_name) qt attributes decl_info = let key = (curr_class, property_name) in let getter_name = get_getter_name property_name attributes in let setter_name = get_setter_name property_name attributes in - Printing.log_out " ...Using '%s' in property table\n" (property_key_to_string key); PropertyTableHash.add property_table key (qt, attributes, decl_info, (getter_name, None), (setter_name, None), None) end @@ -167,7 +170,7 @@ let find_properties_class = Property.find_properties_class let get_ivarname_property pidi = match pidi.Clang_ast_t.opidi_ivar_decl with | Some dr -> (match dr.Clang_ast_t.dr_name with - | Some n -> n.Clang_ast_t.ni_name + | Some n -> n | _ -> assert false) | _ -> (* If ivar is not defined than we need to take the name of the property to define ivar*) Ast_utils.property_name pidi @@ -219,18 +222,21 @@ let method_is_property_accesor cls method_name = let prepare_dynamic_property curr_class decl_info property_impl_decl_info = let pname = Ast_utils.property_name property_impl_decl_info in + let prop_name = pname.Clang_ast_t.ni_name in let res = (try let qt', atts, di, getter, setter, _ = Property.find_property curr_class pname in let ivar = (match property_impl_decl_info.Clang_ast_t.opidi_ivar_decl with | Some dr -> (match dr.Clang_ast_t.dr_name with - | Some name_info -> name_info.Clang_ast_t.ni_name + | Some name_info -> name_info | None -> assert false) | None -> Ast_utils.generated_ivar_name pname) in (* update property info with proper ivar name *) Property.replace_property (curr_class, pname) (qt', atts, di, getter, setter, Some ivar); - Printing.log_out "Updated property table by adding ivar name for property pname '%s'\n" pname; + Printing.log_out "Updated property table by adding ivar name for property '%s'\n" + prop_name; Some (qt', ivar) - with Not_found -> L.err "Property '%s' not found in the table. Ivar not updated and qual_type not found.@." pname; + with Not_found -> + L.err "Property '%s' not found in the table. Ivar not updated.@." prop_name; None) in match property_impl_decl_info.Clang_ast_t.opidi_implementation, res with | `Dynamic, Some (qt, ivar) -> @@ -292,7 +298,7 @@ let make_setter curr_class prop_name prop_type = | Some (ObjCMethodDecl(di, name, mdi), _) when not (is_property_read_only attributes) -> let dummy_info = Ast_expressions.dummy_decl_info_in_curr_file di in let param_name, qt_param = (match mdi.Clang_ast_t.omdi_parameters with - | [ParmVarDecl(_, name_info, qt_param, _)] -> name_info.Clang_ast_t.ni_name, qt_param + | [ParmVarDecl(_, name_info, qt_param, _)] -> name_info, qt_param | _ -> assert false) in let is_hidden = false in let decl_ptr = Ast_utils.get_invalid_pointer () in @@ -344,7 +350,7 @@ let make_getter_setter curr_class decl_info prop_name = try Property.find_property curr_class prop_name with _ -> - Printing.log_out "Property %s not found@." prop_name; + Printing.log_out "Property %s not found@." prop_name.Clang_ast_t.ni_name; assert false in (make_getter curr_class prop_name prop_type)@ (make_setter curr_class prop_name prop_type) @@ -356,7 +362,8 @@ let add_properties_to_table curr_class decl_list = let pname = name_info.Clang_ast_t.ni_name in Printing.log_out "ADDING: ObjCPropertyDecl for property '%s' " pname; Printing.log_out " pointer= '%s' \n" decl_info.Clang_ast_t.di_pointer; - Property.add_property (curr_class, pname) pdi.Clang_ast_t.opdi_qual_type pdi.Clang_ast_t.opdi_property_attributes decl_info; + Property.add_property (curr_class, name_info) pdi.Clang_ast_t.opdi_qual_type + pdi.Clang_ast_t.opdi_property_attributes decl_info; | _ -> () in list_iter add_property_to_table decl_list diff --git a/infer/src/clang/objcProperty_decl.mli b/infer/src/clang/objcProperty_decl.mli index e16981aba..27803a1a7 100644 --- a/infer/src/clang/objcProperty_decl.mli +++ b/infer/src/clang/objcProperty_decl.mli @@ -13,33 +13,36 @@ type prop_getter_setter = string * (Clang_ast_t.decl * bool) option (** A property type is a tuple: *) (** (qual_type, property attributes, decl_info, (getter_name, getter), (setter_name, setter), ivar name ) *) type property_type = Clang_ast_t.qual_type * Clang_ast_t.property_attribute list * - Clang_ast_t.decl_info * prop_getter_setter * prop_getter_setter * string option + Clang_ast_t.decl_info * prop_getter_setter * prop_getter_setter * + Clang_ast_t.named_decl_info option module type PropertySig = sig type t - type property_key = (CContext.curr_class * string) + type property_key = (CContext.curr_class * Clang_ast_t.named_decl_info) val property_key_to_string : property_key -> string val reset_property_table: unit -> unit - val find_property : CContext.curr_class -> string -> property_type + val find_property : CContext.curr_class -> Clang_ast_t.named_decl_info -> property_type - val find_properties_class : CContext.curr_class -> (string * property_type) list + val find_properties_class : CContext.curr_class -> + (Clang_ast_t.named_decl_info * property_type) list val is_mem_property : property_key -> bool val replace_property : property_key -> property_type -> unit - val add_property : property_key -> Clang_ast_t.qual_type -> - Clang_ast_t.property_attribute list -> Clang_ast_t.decl_info -> unit + val add_property : property_key -> Clang_ast_t.qual_type -> Clang_ast_t.property_attribute list -> + Clang_ast_t.decl_info -> unit val print_property_table : unit -> unit - val find_property_name_from_ivar : CContext.curr_class -> string -> string option + val find_property_name_from_ivar : CContext.curr_class -> Clang_ast_t.named_decl_info -> + Clang_ast_t.named_decl_info option end @@ -59,14 +62,20 @@ val print_property_table : unit -> unit val is_property_read_only : Clang_ast_t.property_attribute list -> bool -val find_properties_class : CContext.curr_class -> (string * property_type) list +val find_properties_class : CContext.curr_class -> + (Clang_ast_t.named_decl_info * property_type) list -val make_getter : CContext.curr_class -> string -> property_type -> Clang_ast_t.decl list +val make_getter : CContext.curr_class -> Clang_ast_t.named_decl_info -> property_type -> + Clang_ast_t.decl list -val make_setter : CContext.curr_class -> string -> property_type -> Clang_ast_t.decl list +val make_setter : CContext.curr_class -> Clang_ast_t.named_decl_info -> property_type -> + Clang_ast_t.decl list -val make_getter_setter : CContext.curr_class -> Clang_ast_t.decl_info -> string -> Clang_ast_t.decl list +val make_getter_setter : CContext.curr_class -> Clang_ast_t.decl_info -> + Clang_ast_t.named_decl_info -> Clang_ast_t.decl list -val method_is_property_accesor : CContext.curr_class -> string -> (string * property_type * bool) option +val method_is_property_accesor : CContext.curr_class -> string -> + (Clang_ast_t.named_decl_info * property_type * bool) option -val get_ivar_name : string -> string option -> string +val get_ivar_name : Clang_ast_t.named_decl_info -> Clang_ast_t.named_decl_info option -> + Clang_ast_t.named_decl_info