From fbcf418ea46de5f1bc776434a77ad268eb63f4ca Mon Sep 17 00:00:00 2001 From: Sungkeun Cho Date: Thu, 8 Apr 2021 03:42:49 -0700 Subject: [PATCH] [ConfigImpact] Loosen compares of field names and ungated callees Summary: To avoid too big abstract states due to instantiated templates in C++, this diff loosens the compare functions of field names and ungated callees. Reviewed By: ezgicicek Differential Revision: D27625775 fbshipit-source-id: e33e9d34c --- infer/src/IR/Fieldname.ml | 2 ++ infer/src/IR/Fieldname.mli | 3 ++ infer/src/IR/Procname.ml | 45 ++++++++++++++++++++++++++ infer/src/IR/Procname.mli | 3 ++ infer/src/IR/QualifiedCppName.ml | 2 ++ infer/src/IR/QualifiedCppName.mli | 3 ++ infer/src/IR/Typ.ml | 33 +++++++++++++++++++ infer/src/IR/Typ.mli | 3 ++ infer/src/cost/ConfigImpactAnalysis.ml | 8 +++-- infer/src/istd/ICompare.ml | 10 ++++++ infer/src/istd/ICompare.mli | 10 ++++++ 11 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 infer/src/istd/ICompare.ml create mode 100644 infer/src/istd/ICompare.mli diff --git a/infer/src/IR/Fieldname.ml b/infer/src/IR/Fieldname.ml index ac248c773..990fc82d1 100644 --- a/infer/src/IR/Fieldname.ml +++ b/infer/src/IR/Fieldname.ml @@ -15,6 +15,8 @@ type t = Typ.Name.t t_ [@@deriving compare, equal, yojson_of] let loose_compare = compare_t_ Typ.Name.loose_compare +let compare_name = compare_t_ Typ.Name.compare_name + let make class_name field_name = {class_name; field_name} let get_class_name {class_name} = class_name diff --git a/infer/src/IR/Fieldname.mli b/infer/src/IR/Fieldname.mli index 279dcc21b..a70125d13 100644 --- a/infer/src/IR/Fieldname.mli +++ b/infer/src/IR/Fieldname.mli @@ -14,6 +14,9 @@ type t [@@deriving compare, equal, yojson_of] val loose_compare : t -> t -> int (** Similar to compare, but addresses [CStruct x] and [CppClass x] as equal. *) +val compare_name : t -> t -> int +(** Similar to compare, but compares only names, except template arguments. *) + val make : Typ.Name.t -> string -> t (** create a field of the given class and fieldname *) diff --git a/infer/src/IR/Procname.ml b/infer/src/IR/Procname.ml index 81dc5df97..659c0a9ef 100644 --- a/infer/src/IR/Procname.ml +++ b/infer/src/IR/Procname.ml @@ -524,6 +524,51 @@ type t = let equal = [%compare.equal: t] +let rec compare_name x y = + let open ICompare in + match (x, y) with + | ( CSharp {class_name= class_name1; method_name= method_name1} + , CSharp {class_name= class_name2; method_name= method_name2} ) + | ( Java {class_name= class_name1; method_name= method_name1} + , Java {class_name= class_name2; method_name= method_name2} ) + | ( ObjC_Cpp {class_name= class_name1; method_name= method_name1} + , ObjC_Cpp {class_name= class_name2; method_name= method_name2} ) -> + Typ.Name.compare_name class_name1 class_name2 + <*> fun () -> String.compare method_name1 method_name2 + | CSharp _, _ -> + -1 + | _, CSharp _ -> + 1 + | Java _, _ -> + -1 + | _, Java _ -> + 1 + | C {name= name1}, C {name= name2} -> + QualifiedCppName.compare_name name1 name2 + | C _, _ -> + -1 + | _, C _ -> + 1 + | Linters_dummy_method, Linters_dummy_method -> + 0 + | Linters_dummy_method, _ -> + -1 + | _, Linters_dummy_method -> + 1 + | Block _, Block _ -> + 0 + | Block _, _ -> + -1 + | _, Block _ -> + 1 + | ObjC_Cpp _, _ -> + -1 + | _, ObjC_Cpp _ -> + 1 + | WithBlockParameters (x, _), WithBlockParameters (y, _) -> + compare_name x y + + (** hash function for procname *) let hash = Hashtbl.hash diff --git a/infer/src/IR/Procname.mli b/infer/src/IR/Procname.mli index 508896e1b..5675a9d08 100644 --- a/infer/src/IR/Procname.mli +++ b/infer/src/IR/Procname.mli @@ -231,6 +231,9 @@ val block_of_procname : t -> Block.t val equal : t -> t -> bool +val compare_name : t -> t -> int +(** Similar to compare, but compares only names, except parameter types and template arguments. *) + val get_class_type_name : t -> Typ.Name.t option val get_class_name : t -> string option diff --git a/infer/src/IR/QualifiedCppName.ml b/infer/src/IR/QualifiedCppName.ml index 6f3ac4588..fe3b0fa04 100644 --- a/infer/src/IR/QualifiedCppName.ml +++ b/infer/src/IR/QualifiedCppName.ml @@ -24,6 +24,8 @@ let strip_template_args quals = List.map ~f:no_template_name quals +let compare_name quals1 quals2 = compare (strip_template_args quals1) (strip_template_args quals2) + let append_template_args_to_last quals ~args = match quals with | [last; _] when String.contains last '<' -> diff --git a/infer/src/IR/QualifiedCppName.mli b/infer/src/IR/QualifiedCppName.mli index eccbe187e..21053af3b 100644 --- a/infer/src/IR/QualifiedCppName.mli +++ b/infer/src/IR/QualifiedCppName.mli @@ -32,6 +32,9 @@ val strip_template_args : t -> t - input: std::shared_ptr::shared_ptr - output: std::shared_ptr::shared_ptr *) +val compare_name : t -> t -> int +(** similar to compare, but compares only names, except template arguments *) + val append_template_args_to_last : t -> args:string -> t (** append template arguments to the last qualifier. Fails if qualified name is empty or it already has template args *) diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index 06d8e49b4..64cafcdb0 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -374,6 +374,39 @@ module Name = struct compare x y + let rec compare_name x y = + let open ICompare in + match (x, y) with + | ( (CStruct name1 | CUnion name1 | CppClass {name= name1}) + , (CStruct name2 | CUnion name2 | CppClass {name= name2}) ) -> + QualifiedCppName.compare_name name1 name2 + | (CStruct _ | CUnion _ | CppClass _), _ -> + -1 + | _, (CStruct _ | CUnion _ | CppClass _) -> + 1 + | CSharpClass name1, CSharpClass name2 -> + String.compare (CSharpClassName.classname name1) (CSharpClassName.classname name2) + | CSharpClass _, _ -> + -1 + | _, CSharpClass _ -> + 1 + | JavaClass name1, JavaClass name2 -> + String.compare (JavaClassName.classname name1) (JavaClassName.classname name2) + | JavaClass _, _ -> + -1 + | _, JavaClass _ -> + 1 + | ObjcClass (name1, names1), ObjcClass (name2, names2) -> + QualifiedCppName.compare_name name1 name2 + <*> fun () -> List.compare compare_name names1 names2 + | ObjcClass _, _ -> + -1 + | _, ObjcClass _ -> + 1 + | ObjcProtocol name1, ObjcProtocol name2 -> + QualifiedCppName.compare_name name1 name2 + + let hash = Hashtbl.hash let qual_name = function diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index de199d76b..05e636b20 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -155,6 +155,9 @@ module Name : sig val loose_compare : t -> t -> int (** Similar to compare, but addresses [CStruct x] and [CppClass x] as equal. *) + val compare_name : t -> t -> int + (** Similar to compare, but compares only names, except template arguments. *) + val equal : t -> t -> bool (** Equality for typenames *) diff --git a/infer/src/cost/ConfigImpactAnalysis.ml b/infer/src/cost/ConfigImpactAnalysis.ml index 1c259118b..0d1320ff3 100644 --- a/infer/src/cost/ConfigImpactAnalysis.ml +++ b/infer/src/cost/ConfigImpactAnalysis.ml @@ -41,7 +41,7 @@ module ConfigChecks = AbstractDomain.SafeInvertedMap (ConfigName) (Branch) module Field = struct include Fieldname - let compare = Fieldname.loose_compare + let compare = Fieldname.compare_name end module Fields = AbstractDomain.FiniteSet (Field) @@ -58,8 +58,12 @@ module FieldChecks = struct end module UncheckedCallee = struct + type callee_name = Procname.t + + let compare_callee_name = Procname.compare_name + type t = - { callee: Procname.t + { callee: callee_name ; location: Location.t [@compare.ignore] ; call_type: call_type [@compare.ignore] } [@@deriving compare] diff --git a/infer/src/istd/ICompare.ml b/infer/src/istd/ICompare.ml new file mode 100644 index 000000000..3b5fe8bc8 --- /dev/null +++ b/infer/src/istd/ICompare.ml @@ -0,0 +1,10 @@ +(* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +open! IStd + +let ( <*> ) x y = if x <> 0 then x else y () diff --git a/infer/src/istd/ICompare.mli b/infer/src/istd/ICompare.mli new file mode 100644 index 000000000..f3b8f45dc --- /dev/null +++ b/infer/src/istd/ICompare.mli @@ -0,0 +1,10 @@ +(* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + *) + +open! IStd + +val ( <*> ) : int -> (unit -> int) -> int