[IR][clang] Use qualified cpp name in fields, improve errdesc.ml

Summary:
Improve type of `Fieldname.t` in `Clang` variant - make it store qualified classname and method name.
Based on those changes, fix matching in `Errdesc` to use `QualifiedCppName.Match` instead of string comparisons

Reviewed By: jberdine

Differential Revision: D4746735

fbshipit-source-id: 6f52413
master
Andrzej Kotulski 8 years ago committed by Facebook Github Bot
parent 71702a13dc
commit ade5a06cd4

@ -10,9 +10,11 @@ open! IStd;
let module Hashtbl = Caml.Hashtbl;
type clang_field_info = {qual_class: QualifiedCppName.t, field_name: string} [@@deriving compare];
type t =
| Hidden /* Backend relies that Hidden is the smallest (first) field in Abs.should_raise_objc_leak */
| Clang Mangled.t
| Clang clang_field_info
| Java string
[@@deriving compare];
@ -31,14 +33,10 @@ let module Map = Caml.Map.Make {
};
let module Clang = {
/** Create a field name with the given position (field number in the CSU) */
let create (n: Mangled.t) => Clang n;
let from_qualified qual_class field_name => Clang {qual_class, field_name};
};
let module Java = {
/** Create a field name with the given position (field number in the CSU) */
let from_string n => Java n;
};
@ -48,15 +46,7 @@ let to_string =
fun
| Hidden => hidden_str
| Java fname => fname
| Clang fname => Mangled.to_string fname;
/** Convert a fieldname to a string, including the mangled part. */
let to_complete_string =
fun
| Hidden => hidden_str
| Java fname => fname
| Clang fname => Mangled.to_string_full fname;
| Clang {field_name} => field_name;
/** Convert a fieldname to a simplified string with at most one-level path. */
@ -85,8 +75,8 @@ let to_flat_string fn => {
let pp f =>
fun
| Hidden => Format.fprintf f "%s" hidden_str
| Java fname => Format.fprintf f "%s" fname
| Clang fname => Mangled.pp f fname;
| Java field_name
| Clang {field_name} => Format.fprintf f "%s" field_name;
let pp_latex style f fn => Latex.pp_string style f (to_string fn);
@ -119,6 +109,11 @@ let java_is_outer_instance fn => {
}
};
let clang_get_qual_class =
fun
| Clang {qual_class} => Some qual_class
| _ => None;
/** hidded fieldname constant */
let hidden = Hidden;

@ -26,13 +26,13 @@ let module Map: Caml.Map.S with type key = t;
let module Clang: {
/** Create a clang field name */
let create: Mangled.t => t;
/** Create a clang field name from qualified c++ name */
let from_qualified: QualifiedCppName.t => string => t;
};
let module Java: {
/** Create a java field name */
/** Create a java field name from string */
let from_string: string => t;
};
@ -41,10 +41,6 @@ let module Java: {
let to_string: t => string;
/** Convert a fieldname to a string, including the mangled part. */
let to_complete_string: t => string;
/** Convert a fieldname to a simplified string with at most one-level path. */
let to_simplified_string: t => string;
@ -73,6 +69,10 @@ let java_get_field: t => string;
let java_is_outer_instance: t => bool;
/** get qualified classname of a field if it's coming from clang frontend. returns None otherwise */
let clang_get_qual_class: t => option QualifiedCppName.t;
/** hidded fieldname constant */
let hidden: t;

@ -8,7 +8,9 @@
*/
open! IStd;
type t = list string;
type t = list string [@@deriving compare];
let equal = [%compare.equal : t];
let empty = [];

@ -8,12 +8,13 @@
*/
open! IStd;
type t;
type t [@@deriving compare];
/** empty qualified name */
let empty: t;
let equal: t => t => bool;
/** attempts to parse the argument into a list::of::possibly::templated<T>::qualifiers */
let of_qual_string: string => t;
@ -26,7 +27,6 @@ let to_qual_string: t => string;
/** append qualifier to the end (innermost scope) of the qualified name */
let append_qualifier: t => qual::string => t;
/** returns list of qualifers */
let to_list: t => list string;

@ -884,11 +884,14 @@ let module Procname = {
/** Pretty print a set of proc names */
let pp_set fmt set => Set.iter (fun pname => F.fprintf fmt "%a " pp pname) set;
let objc_cpp_get_class_qualifiers objc_cpp => QualifiedCppName.of_qual_string (
Name.name objc_cpp.class_name
);
let get_qualifiers pname =>
switch pname {
| C {name} => QualifiedCppName.of_qual_string name
| ObjC_Cpp objc_cpp =>
QualifiedCppName.of_qual_string (Name.name objc_cpp.class_name) |>
objc_cpp_get_class_qualifiers objc_cpp |>
QualifiedCppName.append_qualifier qual::objc_cpp.method_name
| _ => QualifiedCppName.empty
};

@ -427,7 +427,12 @@ let module Procname: {
/** Convert a proc name to a filename. */
let to_filename: t => string;
/** get qualifiers of C/objc/C++ method/function */
let get_qualifiers: t => QualifiedCppName.t;
/** get qualifiers of a class owning objc/C++ method */
let objc_cpp_get_class_qualifiers: objc_cpp => QualifiedCppName.t;
};

@ -16,35 +16,33 @@ module L = Logging
module F = Format
module DExp = DecompiledExp
let mutex_class = ["std"; "mutex"]
let vector_class = ["std"; "vector"]
let vector_matcher = QualifiedCppName.Match.of_fuzzy_qual_names ["std::vector"]
let mutex_matcher = QualifiedCppName.Match.of_fuzzy_qual_names ["std::mutex"]
let is_one_of_classes class_name classes =
List.exists ~f:(fun wrapper_class ->
List.for_all ~f:(fun wrapper_class_substring ->
String.is_substring ~substring:wrapper_class_substring class_name) wrapper_class)
classes
let is_one_of_classes = QualifiedCppName.Match.match_qualifiers
let is_method_of_objc_cpp_class pname classes =
let is_method_of_objc_cpp_class pname matcher =
match pname with
| Typ.Procname.ObjC_Cpp name ->
let class_name = Typ.Procname.objc_cpp_get_class_name name in
is_one_of_classes class_name classes
| Typ.Procname.ObjC_Cpp objc_cpp ->
let class_qual_opt = Typ.Procname.objc_cpp_get_class_qualifiers objc_cpp in
is_one_of_classes matcher class_qual_opt
| _ -> false
let is_mutex_method pname =
is_method_of_objc_cpp_class pname [mutex_class]
is_method_of_objc_cpp_class pname mutex_matcher
let is_vector_method pname =
is_method_of_objc_cpp_class pname [vector_class]
is_method_of_objc_cpp_class pname vector_matcher
let is_special_field class_names field_name_opt field =
let complete_fieldname = Fieldname.to_complete_string field in
let is_special_field matcher field_name_opt field =
let field_name = Fieldname.to_flat_string field in
let class_qual_opt = Fieldname.clang_get_qual_class field in
let field_ok =
match field_name_opt with
| Some field_name -> String.is_substring ~substring:field_name complete_fieldname
| Some field_name' -> String.equal field_name' field_name
| None -> true in
is_one_of_classes complete_fieldname class_names && field_ok
field_ok && Option.value_map ~f:(is_one_of_classes matcher) ~default:false class_qual_opt
(** Check whether the hpred is a |-> representing a resource in the Racquire state *)
let hpred_is_open_resource tenv prop = function
@ -842,9 +840,9 @@ let create_dereference_desc tenv
else
desc
| Some (DExp.Darrow (dexp, fieldname)) ->
if is_special_field [mutex_class] (Some "null_if_locked") fieldname then
if is_special_field mutex_matcher (Some "null_if_locked") fieldname then
Localise.desc_double_lock None (DExp.to_string dexp) loc
else if is_special_field [vector_class] (Some "beginPtr") fieldname then
else if is_special_field vector_matcher (Some "beginPtr") fieldname then
Localise.desc_empty_vector_access None (DExp.to_string dexp) loc
else
desc

@ -102,7 +102,8 @@ let replicate n el = List.map ~f:(fun _ -> el) (list_range 0 (n -1))
let mk_class_field_name field_qual_name =
let field_name = field_qual_name.Clang_ast_t.ni_name in
let class_name = CAst_utils.get_class_name_from_member field_qual_name in
Fieldname.Clang.create (Mangled.mangled field_name class_name)
let qual_class_name = QualifiedCppName.of_qual_string class_name in
Fieldname.Clang.from_qualified qual_class_name field_name
let is_cpp_translation translation_unit_context =
let lang = translation_unit_context.CFrontend_config.lang in

Loading…
Cancel
Save