[clang IR] Change Fieldname.t to store typename

Summary:
add more structured info into `Fieldname.t`

update-submodule: facebook-clang-plugins

Reviewed By: jberdine

Differential Revision: D5309930

fbshipit-source-id: ab2c366
master
Andrzej Kotulski 8 years ago committed by Facebook Github Bot
parent 61aa7aaae5
commit a864b4068f

@ -1 +1 @@
Subproject commit c7b64f0852dd3e9eacc2c5608461909994e4f425 Subproject commit 71ada2c9994be2af8e8915e45d1c61c9d6a53d62

@ -235,7 +235,7 @@ let recognize_exception exn =
(Localise.from_string "Match failure", (Localise.from_string "Match failure",
Localise.no_desc, Some ml_loc, Exn_developer, High, None, Nocat) Localise.no_desc, Some ml_loc, Exn_developer, High, None, Nocat)
| Missing_fld (fld, ml_loc) -> | Missing_fld (fld, ml_loc) ->
let desc = Localise.verbatim_desc (Typ.Fieldname.to_string fld) in let desc = Localise.verbatim_desc (Typ.Fieldname.to_full_string fld) in
(Localise.from_string "Missing_fld" ~hum:"Missing Field", (Localise.from_string "Missing_fld" ~hum:"Missing Field",
desc, Some ml_loc, Exn_developer, Medium, None, Nocat) desc, Some ml_loc, Exn_developer, Medium, None, Nocat)
| Premature_nil_termination (desc, ml_loc) -> | Premature_nil_termination (desc, ml_loc) ->

@ -1030,8 +1030,7 @@ let java_proc_return_typ pname_java :t => {
}; };
module Fieldname = { module Fieldname = {
type clang_field_info = {qual_class: QualifiedCppName.t, field_name: string} type clang_field_info = {class_name: Name.t, field_name: string} [@@deriving compare];
[@@deriving compare];
type t = type t =
| Hidden /* Backend relies that Hidden is the smallest (first) field in Abs.should_raise_objc_leak */ | Hidden /* Backend relies that Hidden is the smallest (first) field in Abs.should_raise_objc_leak */
| Clang clang_field_info | Clang clang_field_info
@ -1046,7 +1045,7 @@ module Fieldname = {
module Set = Caml.Set.Make T; module Set = Caml.Set.Make T;
module Map = Caml.Map.Make T; module Map = Caml.Map.Make T;
module Clang = { module Clang = {
let from_qualified qual_class field_name => Clang {qual_class, field_name}; let from_class_name class_name field_name => Clang {class_name, field_name};
}; };
module Java = { module Java = {
let from_string n => Java n; let from_string n => Java n;
@ -1071,6 +1070,11 @@ module Fieldname = {
| _ => s | _ => s
} }
}; };
let to_full_string fname =>
switch fname {
| Clang {class_name, field_name} => Name.to_string class_name ^ "::" ^ field_name
| _ => to_string fname
};
/** Convert a fieldname to a flat string without path. */ /** Convert a fieldname to a flat string without path. */
let to_flat_string fn => { let to_flat_string fn => {
@ -1114,7 +1118,7 @@ module Fieldname = {
}; };
let clang_get_qual_class = let clang_get_qual_class =
fun fun
| Clang {qual_class} => Some qual_class | Clang {class_name} => Some (Name.qual_name class_name)
| _ => None; | _ => None;
/** hidded fieldname constant */ /** hidded fieldname constant */

@ -490,11 +490,7 @@ module Fieldname: {
/** Map for fieldnames */ /** Map for fieldnames */
module Map: Caml.Map.S with type key = t; module Map: Caml.Map.S with type key = t;
module Clang: { module Clang: {let from_class_name: Name.t => string => t;};
/** Create a clang field name from qualified c++ name */
let from_qualified: QualifiedCppName.t => string => t;
};
module Java: { module Java: {
/** Create a java field name from string */ /** Create a java field name from string */
@ -503,6 +499,7 @@ module Fieldname: {
/** Convert a field name to a string. */ /** Convert a field name to a string. */
let to_string: t => string; let to_string: t => string;
let to_full_string: t => string;
/** Convert a fieldname to a simplified string with at most one-level path. */ /** Convert a fieldname to a simplified string with at most one-level path. */
let to_simplified_string: t => string; let to_simplified_string: t => string;

@ -90,9 +90,10 @@ let rec get_struct_fields tenv decl =
| CXXRecordDecl (_, _, _, _, decl_list, _, _, _) | CXXRecordDecl (_, _, _, _, decl_list, _, _, _)
| RecordDecl (_, _, _, _, decl_list, _, _) -> decl_list | RecordDecl (_, _, _, _, decl_list, _, _) -> decl_list
| _ -> [] in | _ -> [] in
let class_tname = get_record_typename ~tenv decl in
let do_one_decl decl = match decl with let do_one_decl decl = match decl with
| FieldDecl (_, name_info, qt, _) -> | FieldDecl (_, {ni_name}, qt, _) ->
let id = CGeneral_utils.mk_class_field_name name_info in let id = CGeneral_utils.mk_class_field_name class_tname ni_name in
let typ = qual_type_to_sil_type tenv qt in let typ = qual_type_to_sil_type tenv qt in
let annotation_items = [] in (* For the moment we don't use them*) let annotation_items = [] in (* For the moment we don't use them*)
[(id, typ, annotation_items)] [(id, typ, annotation_items)]
@ -140,10 +141,14 @@ and get_record_typename ?tenv decl =
| ObjCInterfaceDecl (_, name_info, _, _, _), _ | ObjCInterfaceDecl (_, name_info, _, _, _), _
| ObjCImplementationDecl (_, name_info, _, _, _), _ | ObjCImplementationDecl (_, name_info, _, _, _), _
| ObjCProtocolDecl (_, name_info, _, _, _), _ | ObjCProtocolDecl (_, name_info, _, _, _), _ ->
| ObjCCategoryDecl (_, name_info, _, _, _), _
| ObjCCategoryImplDecl (_, name_info, _, _, _), _ ->
CAst_utils.get_qualified_name name_info |> Typ.Name.Objc.from_qual_name CAst_utils.get_qualified_name name_info |> Typ.Name.Objc.from_qual_name
| ObjCCategoryDecl (_, _, _, _, {odi_class_interface=Some {dr_name}}), _
| ObjCCategoryImplDecl (_, _, _, _, {ocidi_class_interface=Some {dr_name}}), _ -> (
match dr_name with
| Some name_info ->
CAst_utils.get_qualified_name name_info |> Typ.Name.Objc.from_qual_name
| None -> assert false)
| _ -> assert false | _ -> assert false
(** fetches list of superclasses for C++ classes *) (** fetches list of superclasses for C++ classes *)

@ -35,14 +35,14 @@ let fields_superclass tenv interface_decl_info =
| _ -> []) | _ -> [])
| _ -> [] | _ -> []
let build_sil_field qual_type_to_sil_type tenv field_name qual_type prop_attributes = let build_sil_field qual_type_to_sil_type tenv class_tname field_name qual_type prop_attributes =
let prop_atts = List.map ~f:Clang_ast_j.string_of_property_attribute prop_attributes in let prop_atts = List.map ~f:Clang_ast_j.string_of_property_attribute prop_attributes in
let annotation_from_type t = let annotation_from_type t =
match t.Typ.desc with match t.Typ.desc with
| Typ.Tptr (_, Typ.Pk_objc_weak) -> [Config.weak] | Typ.Tptr (_, Typ.Pk_objc_weak) -> [Config.weak]
| Typ.Tptr (_, Typ.Pk_objc_unsafe_unretained) -> [Config.unsafe_unret] | Typ.Tptr (_, Typ.Pk_objc_unsafe_unretained) -> [Config.unsafe_unret]
| _ -> [] in | _ -> [] in
let fname = CGeneral_utils.mk_class_field_name field_name in let fname = CGeneral_utils.mk_class_field_name class_tname field_name.Clang_ast_t.ni_name in
let typ = qual_type_to_sil_type tenv qual_type in let typ = qual_type_to_sil_type tenv qual_type in
let item_annotations = match prop_atts with let item_annotations = match prop_atts with
| [] -> | [] ->
@ -55,11 +55,11 @@ let build_sil_field qual_type_to_sil_type tenv field_name qual_type prop_attribu
fname, typ, item_annotations fname, typ, item_annotations
(* Given a list of declarations in an interface returns a list of fields *) (* Given a list of declarations in an interface returns a list of fields *)
let rec get_fields qual_type_to_sil_type tenv decl_list = let rec get_fields qual_type_to_sil_type tenv class_tname decl_list =
let open Clang_ast_t in let open Clang_ast_t in
let add_field name_info (qt : qual_type) attributes decl_list' = let add_field name_info (qt : qual_type) attributes decl_list' =
let fields = get_fields qual_type_to_sil_type tenv decl_list' in let fields = get_fields qual_type_to_sil_type tenv class_tname decl_list' in
let field_tuple = build_sil_field qual_type_to_sil_type tenv let field_tuple = build_sil_field qual_type_to_sil_type tenv class_tname
name_info qt attributes in name_info qt attributes in
CGeneral_utils.append_no_duplicates_fields [field_tuple] fields in CGeneral_utils.append_no_duplicates_fields [field_tuple] fields in
match decl_list with match decl_list with
@ -70,11 +70,11 @@ let rec get_fields qual_type_to_sil_type tenv decl_list =
| Some (ObjCIvarDecl (_, name_info, qual_type, _, _)) -> | Some (ObjCIvarDecl (_, name_info, qual_type, _, _)) ->
let attributes = obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes in let attributes = obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes in
add_field name_info qual_type attributes decl_list' add_field name_info qual_type attributes decl_list'
| _ -> get_fields qual_type_to_sil_type tenv decl_list') | _ -> get_fields qual_type_to_sil_type tenv class_tname decl_list')
| ObjCIvarDecl (_, name_info, qual_type, _, _) :: decl_list' -> | ObjCIvarDecl (_, name_info, qual_type, _, _) :: decl_list' ->
add_field name_info qual_type [] decl_list' add_field name_info qual_type [] decl_list'
| _ :: decl_list' -> | _ :: decl_list' ->
get_fields qual_type_to_sil_type tenv decl_list' get_fields qual_type_to_sil_type tenv class_tname decl_list'
(* Add potential extra fields defined only in the implementation of the class *) (* Add potential extra fields defined only in the implementation of the class *)
(* to the info given in the interface. Update the tenv accordingly. *) (* to the info given in the interface. Update the tenv accordingly. *)
@ -95,9 +95,8 @@ let modelled_fields_in_classes =
let modelled_field class_name_info = let modelled_field class_name_info =
let modelled_field_in_class res (class_name, field_name, typ) = let modelled_field_in_class res (class_name, field_name, typ) =
if String.equal class_name class_name_info.Clang_ast_t.ni_name then if String.equal class_name class_name_info.Clang_ast_t.ni_name then
let class_name_qualified = class_name_info.Clang_ast_t.ni_qual_name in let class_tname = Typ.Name.Objc.from_string class_name in
let field_name_qualified = CAst_utils.make_qual_name_decl class_name_qualified field_name in let name = Typ.Fieldname.Clang.from_class_name class_tname field_name in
let name = CGeneral_utils.mk_class_field_name field_name_qualified in
(name, typ, Annot.Item.empty) :: res (name, typ, Annot.Item.empty) :: res
else res in else res in
List.fold ~f:modelled_field_in_class ~init:[] modelled_fields_in_classes List.fold ~f:modelled_field_in_class ~init:[] modelled_fields_in_classes

@ -13,8 +13,8 @@ open! IStd
type field_type = Typ.Fieldname.t * Typ.t * (Annot.t * bool) list type field_type = Typ.Fieldname.t * Typ.t * (Annot.t * bool) list
val get_fields : CAst_utils.qual_type_to_sil_type -> Tenv.t -> Clang_ast_t.decl list -> val get_fields : CAst_utils.qual_type_to_sil_type -> Tenv.t -> Typ.Name.t ->
field_type list Clang_ast_t.decl list -> field_type list
val fields_superclass : Tenv.t -> Clang_ast_t.obj_c_interface_decl_info -> field_type list val fields_superclass : Tenv.t -> Clang_ast_t.obj_c_interface_decl_info -> field_type list

@ -99,10 +99,8 @@ let list_range i j =
let replicate n el = List.map ~f:(fun _ -> el) (list_range 0 (n -1)) let replicate n el = List.map ~f:(fun _ -> el) (list_range 0 (n -1))
let mk_class_field_name field_qual_name = let mk_class_field_name class_tname field_name =
let field_name = field_qual_name.Clang_ast_t.ni_name in Typ.Fieldname.Clang.from_class_name class_tname field_name
let class_name = CAst_utils.get_class_name_from_member field_qual_name in
Typ.Fieldname.Clang.from_qualified class_name field_name
let is_cpp_translation translation_unit_context = let is_cpp_translation translation_unit_context =
let lang = translation_unit_context.CFrontend_config.lang in let lang = translation_unit_context.CFrontend_config.lang in

@ -43,7 +43,7 @@ val list_range: int -> int -> int list
val replicate: int -> 'a -> 'a list val replicate: int -> 'a -> 'a list
val mk_class_field_name : Clang_ast_t.named_decl_info -> Typ.Fieldname.t val mk_class_field_name : Typ.Name.t -> string -> Typ.Fieldname.t
val get_var_name_mangled : Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info -> val get_var_name_mangled : Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info ->
(string * Mangled.t) (string * Mangled.t)

@ -371,8 +371,13 @@ let get_objc_property_accessor ms =
| Some (ObjCPropertyDecl (_, _, obj_c_property_decl_info)) -> | Some (ObjCPropertyDecl (_, _, obj_c_property_decl_info)) ->
let ivar_decl_ref = obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl in let ivar_decl_ref = obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl in
(match CAst_utils.get_decl_opt_with_decl_ref ivar_decl_ref with (match CAst_utils.get_decl_opt_with_decl_ref ivar_decl_ref with
| Some ObjCIvarDecl (_, named_decl_info, _, _, _) -> | Some ObjCIvarDecl (_ , {ni_name}, _, _, _) ->
let field_name = CGeneral_utils.mk_class_field_name named_decl_info in let class_tname = match CMethod_signature.ms_get_name ms with
| Typ.Procname.ObjC_Cpp objc_cpp ->
Typ.Procname.objc_cpp_get_class_type_name objc_cpp
| _ -> assert false
in
let field_name = CGeneral_utils.mk_class_field_name class_tname ni_name in
if CMethod_signature.ms_is_getter ms then if CMethod_signature.ms_is_getter ms then
Some (ProcAttributes.Objc_getter field_name) Some (ProcAttributes.Objc_getter field_name)
else if CMethod_signature.ms_is_setter ms then else if CMethod_signature.ms_is_setter ms then

@ -108,8 +108,8 @@ struct
let procname = Procdesc.get_proc_name procdesc in let procname = Procdesc.get_proc_name procdesc in
let mk_field_from_captured_var (var, typ) = let mk_field_from_captured_var (var, typ) =
let vname = Pvar.get_name var in let vname = Pvar.get_name var in
let qual_name = CAst_utils.make_qual_name_decl [block_name] (Mangled.to_string vname) in let tname = Typ.Name.C.from_string block_name in
let fname = CGeneral_utils.mk_class_field_name qual_name in let fname = CGeneral_utils.mk_class_field_name tname (Mangled.to_string vname) in
let item_annot = Annot.Item.empty in let item_annot = Annot.Item.empty in
fname, typ, item_annot in fname, typ, item_annot in
let fields = List.map ~f:mk_field_from_captured_var captured_vars in let fields = List.map ~f:mk_field_from_captured_var captured_vars in
@ -494,8 +494,9 @@ struct
let open CContext in let open CContext in
let context = trans_state.context in let context = trans_state.context in
let sil_loc = CLocation.get_sil_location stmt_info context in let sil_loc = CLocation.get_sil_location stmt_info context in
let name_info, _, qual_type = CAst_utils.get_info_from_decl_ref decl_ref in let name_info, decl_ptr, qual_type = CAst_utils.get_info_from_decl_ref decl_ref in
L.(debug Capture Verbose) "!!!!! Dealing with field '%s' @." name_info.Clang_ast_t.ni_name; let field_string = name_info.Clang_ast_t.ni_name in
L.(debug Capture Verbose) "!!!!! Dealing with field '%s' @." field_string;
let field_typ = CType_decl.qual_type_to_sil_type context.tenv qual_type in let field_typ = CType_decl.qual_type_to_sil_type context.tenv qual_type in
let (obj_sil, class_typ) = extract_exp_from_list pre_trans_result.exps let (obj_sil, class_typ) = extract_exp_from_list pre_trans_result.exps
"WARNING: in Field dereference we expect to know the object@\n" in "WARNING: in Field dereference we expect to know the object@\n" in
@ -507,7 +508,16 @@ struct
| Typ.Tptr (t, _) -> t | Typ.Tptr (t, _) -> t
| _ -> class_typ in | _ -> class_typ in
L.(debug Capture Verbose) "Type is '%s' @." (Typ.to_string class_typ); L.(debug Capture Verbose) "Type is '%s' @." (Typ.to_string class_typ);
let field_name = CGeneral_utils.mk_class_field_name name_info in let class_tname = match CAst_utils.get_decl decl_ptr with
| Some FieldDecl ({di_parent_pointer}, _, _, _)
| Some ObjCIvarDecl ({di_parent_pointer}, _, _, _, _) -> (
match CAst_utils.get_decl_opt di_parent_pointer with
| Some decl -> CType_decl.get_record_typename ~tenv:context.tenv decl
| _ -> assert false
)
| _ -> assert false (* di_parent_pointer should be always set for fields/ivars *)
in
let field_name = CGeneral_utils.mk_class_field_name class_tname field_string in
let field_exp = Exp.Lfield (obj_sil, field_name, class_typ) in let field_exp = Exp.Lfield (obj_sil, field_name, class_typ) in
(* In certain cases, there is be no LValueToRValue cast, but backend needs dereference*) (* In certain cases, there is be no LValueToRValue cast, but backend needs dereference*)
(* there either way:*) (* there either way:*)
@ -2343,8 +2353,9 @@ struct
let void_typ = Typ.mk Tvoid in let void_typ = Typ.mk Tvoid in
let type_info_objc = (Exp.Sizeof {typ; nbytes=None; dynamic_length=None; subtype=Subtype.exact}, let type_info_objc = (Exp.Sizeof {typ; nbytes=None; dynamic_length=None; subtype=Subtype.exact},
void_typ) in void_typ) in
let field_name_decl = CAst_utils.make_qual_name_decl ["type_info"; "std"] "__type_name" in let class_tname =
let field_name = CGeneral_utils.mk_class_field_name field_name_decl in Typ.Name.Cpp.from_qual_name Typ.NoTemplate (QualifiedCppName.of_list ["std"; "type_info"]) in
let field_name = CGeneral_utils.mk_class_field_name class_tname "__type_name" in
let ret_exp = Exp.Var ret_id in let ret_exp = Exp.Var ret_id in
let field_exp = Exp.Lfield (ret_exp, field_name, typ) in let field_exp = Exp.Lfield (ret_exp, field_name, typ) in
let args = type_info_objc :: (field_exp, void_typ) :: res_trans_subexpr.exps in let args = type_info_objc :: (field_exp, void_typ) :: res_trans_subexpr.exps in

@ -66,8 +66,8 @@ let get_base_class_name_from_category decl =
(* Add potential extra fields defined only in the category *) (* Add potential extra fields defined only in the category *)
(* to the corresponding class. Update the tenv accordingly.*) (* to the corresponding class. Update the tenv accordingly.*)
let process_category qual_type_to_sil_type tenv class_name decl_info decl_list = let process_category qual_type_to_sil_type tenv class_name decl_info decl_list =
let decl_fields = CField_decl.get_fields qual_type_to_sil_type tenv decl_list in
let class_tn_name = Typ.Name.Objc.from_qual_name class_name in let class_tn_name = Typ.Name.Objc.from_qual_name class_name in
let decl_fields = CField_decl.get_fields qual_type_to_sil_type tenv class_tn_name decl_list in
let class_tn_desc = Typ.Tstruct class_tn_name in let class_tn_desc = Typ.Tstruct class_tn_name in
let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in
CAst_utils.update_sil_types_map decl_key class_tn_desc; CAst_utils.update_sil_types_map decl_key class_tn_desc;

@ -65,12 +65,12 @@ let get_interface_supers super_opt protocols =
let super_classes = super_class@protocol_names in let super_classes = super_class@protocol_names in
super_classes super_classes
let create_supers_fields qual_type_to_sil_type tenv decl_list let create_supers_fields qual_type_to_sil_type tenv class_tname decl_list
otdi_super otdi_protocols = otdi_super otdi_protocols =
let super = get_super_interface_decl otdi_super in let super = get_super_interface_decl otdi_super in
let protocols = get_protocols otdi_protocols in let protocols = get_protocols otdi_protocols in
let supers = get_interface_supers super protocols in let supers = get_interface_supers super protocols in
let fields = CField_decl.get_fields qual_type_to_sil_type tenv decl_list in let fields = CField_decl.get_fields qual_type_to_sil_type tenv class_tname decl_list in
supers, fields supers, fields
(* Adds pairs (interface name, interface_type_info) to the global environment. *) (* Adds pairs (interface name, interface_type_info) to the global environment. *)
@ -82,7 +82,7 @@ let add_class_to_tenv qual_type_to_sil_type tenv decl_info name_info decl_list o
let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in
CAst_utils.update_sil_types_map decl_key interface_desc; CAst_utils.update_sil_types_map decl_key interface_desc;
let decl_supers, decl_fields = let decl_supers, decl_fields =
create_supers_fields qual_type_to_sil_type tenv decl_list create_supers_fields qual_type_to_sil_type tenv interface_name decl_list
ocidi.Clang_ast_t.otdi_super ocidi.Clang_ast_t.otdi_super
ocidi.Clang_ast_t.otdi_protocols in ocidi.Clang_ast_t.otdi_protocols in
let fields_sc = CField_decl.fields_superclass tenv ocidi in let fields_sc = CField_decl.fields_superclass tenv ocidi in
@ -140,9 +140,9 @@ let interface_impl_declaration qual_type_to_sil_type tenv decl =
L.(debug Capture Verbose) L.(debug Capture Verbose)
"ADDING: ObjCImplementationDecl for class '%a'@\n" QualifiedCppName.pp class_name; "ADDING: ObjCImplementationDecl for class '%a'@\n" QualifiedCppName.pp class_name;
let _ = add_class_decl qual_type_to_sil_type tenv idi in let _ = add_class_decl qual_type_to_sil_type tenv idi in
let fields = CField_decl.get_fields qual_type_to_sil_type tenv decl_list in
CField_decl.add_missing_fields tenv class_name fields;
let class_tn_name = Typ.Name.Objc.from_qual_name class_name in let class_tn_name = Typ.Name.Objc.from_qual_name class_name in
let fields = CField_decl.get_fields qual_type_to_sil_type tenv class_tn_name decl_list in
CField_decl.add_missing_fields tenv class_name fields;
let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in let decl_key = Clang_ast_extend.DeclPtr decl_info.Clang_ast_t.di_pointer in
let class_desc = Typ.Tstruct class_tn_name in let class_desc = Typ.Tstruct class_tn_name in
CAst_utils.update_sil_types_map decl_key class_desc; CAst_utils.update_sil_types_map decl_key class_desc;

Loading…
Cancel
Save