[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.
master
Dulma Rodriguez 9 years ago
parent 1e96e56145
commit 0b0cd0d38d

@ -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<a.count *)
@ -621,34 +621,38 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
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
let objects_name = Ast_utils.make_name_decl CFrontend_config.objects in
let var_decl = Clang_ast_t.VarDecl (di, objects_name, qt, vdi) in
Clang_ast_t.DeclStmt (fresh_stmt_info stmt_info, [init], [var_decl]), [(CFrontend_config.objects, di.Clang_ast_t.di_pointer, qt)] in
let make_object_cast_decl_ref_expr objects =
match objects with
| Clang_ast_t.DeclStmt (si, _, [Clang_ast_t.VarDecl (di, name, qt, vdi)]) ->
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

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

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

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

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

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

@ -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 _ -> ()

@ -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)] }

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

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

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

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

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

Loading…
Cancel
Save