Removing predicates _strict

Reviewed By: dulmarod

Differential Revision: D4863173

fbshipit-source-id: 671ef75
master
Dino Distefano 8 years ago committed by Facebook Github Bot
parent 96727152f3
commit 5bb41cc18c

@ -81,10 +81,10 @@ DEFINE-CHECKER BAD_POINTER_COMPARISON = {
DEFINE-CHECKER REGISTERED_OBSERVER_BEING_DEALLOCATED = {
LET exists_method_calling_addObserver =
call_method_strict("addObserver:selector:name:object:") HOLDS-EVENTUALLY;
call_method("addObserver:selector:name:object:") HOLDS-EVENTUALLY;
LET exists_method_calling_addObserverForName =
call_method_strict("addObserverForName:object:queue:usingBlock:") HOLDS-EVENTUALLY;
call_method("addObserverForName:object:queue:usingBlock:") HOLDS-EVENTUALLY;
LET add_observer =
exists_method_calling_addObserver OR exists_method_calling_addObserverForName;
@ -95,10 +95,10 @@ DEFINE-CHECKER REGISTERED_OBSERVER_BEING_DEALLOCATED = {
HOLDS-EVENTUALLY;
LET exists_method_calling_removeObserver =
call_method_strict("removeObserver:") HOLDS-EVENTUALLY;
call_method("removeObserver:") HOLDS-EVENTUALLY;
LET exists_method_calling_removeObserverName =
call_method_strict("removeObserver:name:object:") HOLDS-EVENTUALLY;
call_method("removeObserver:name:object:") HOLDS-EVENTUALLY;
LET remove_observer =
exists_method_calling_removeObserver OR exists_method_calling_removeObserverName;
@ -137,11 +137,11 @@ DEFINE-CHECKER REGISTERED_OBSERVER_BEING_DEALLOCATED = {
DEFINE-CHECKER STRONG_DELEGATE_WARNING = {
LET name_contains_delegate = property_name_contains_word(REGEXP("[dD]elegate"));
LET name_contains_delegate = property_named(REGEXP("[dD]elegate"));
LET name_does_not_contain_delegates =
NOT property_name_contains_word(REGEXP("[dD]elegates"));
NOT property_named(REGEXP("[dD]elegates"));
LET name_does_not_contains_queue =
NOT property_name_contains_word(REGEXP("[qQ]ueue"));
NOT property_named(REGEXP("[qQ]ueue"));
SET report_when =
WHEN

@ -238,18 +238,6 @@ let is_const_expr_var decl =
| Clang_ast_t.VarDecl (_, _ ,_, vdi) -> vdi.vdi_is_const_expr
| _ -> false
let is_ptr_to_objc_class typ class_name =
match typ with
| Some Clang_ast_t.ObjCObjectPointerType (_, {Clang_ast_t.qt_type_ptr}) ->
(match get_desugared_type qt_type_ptr with
| Some ObjCInterfaceType (_, ptr) ->
(match get_decl ptr with
| Some ObjCInterfaceDecl (_, ndi, _, _, _) ->
String.equal ndi.ni_name class_name
| _ -> false)
| _ -> false)
| _ -> false
let full_name_of_decl_opt decl_opt =
match decl_opt with
| Some decl ->

@ -92,8 +92,6 @@ val is_syntactically_global_var : Clang_ast_t.decl -> bool
(** true if a declaration is a constexpr variable *)
val is_const_expr_var : Clang_ast_t.decl -> bool
val is_ptr_to_objc_class : Clang_ast_t.c_type option -> string -> bool
val full_name_of_decl_opt : Clang_ast_t.decl option -> QualifiedCppName.t
(** Generates a key for a statement based on its sub-statements and the statement tag. *)

@ -63,12 +63,22 @@ type t = ALVar.formula_id * ALVar.alexp list(* (name, [param1,...,paramK]) *)
(* true if and only if a substring of container matches the regular
expression defined by contained
*)
let str_match_regex container contained =
let rexp = Str.regexp contained in
let str_match_regex container re =
let rexp = Str.regexp re in
try
Str.search_forward rexp container 0 >= 0
with Not_found -> false
let compare_str_with_alexp s ae =
match ae with
| ALVar.Const s' ->
String.equal s s'
| ALVar.Regexp re -> str_match_regex s re
| _ ->
Logging.out "[WARNING]: ALVAR expression '%s' is not a constant or regexp\n"
(ALVar.alexp_to_string ae);
false
let pp_predicate fmt (_name, _arglist) =
let name = ALVar.formula_id_to_string _name in
let arglist = List.map ~f:ALVar.alexp_to_string _arglist in
@ -77,54 +87,34 @@ let pp_predicate fmt (_name, _arglist) =
let is_declaration_kind decl s =
String.equal (Clang_ast_proj.get_decl_kind_string decl) s
let _is_objc_interface_named comp an expected_name =
(* is an objc interface with name expected_name *)
let is_objc_interface_named an expected_name =
match an with
| Ctl_parser_types.Decl Clang_ast_t.ObjCInterfaceDecl(_, ni, _, _, _) ->
comp ni.ni_name expected_name
compare_str_with_alexp ni.ni_name expected_name
| _ -> false
(* is an objc interface with name expected_name *)
let is_objc_interface_named_strict an expected_name =
_is_objc_interface_named (String.equal) an expected_name
(* is an objc interface with name expected_name *)
let is_objc_interface_named an expected_name =
_is_objc_interface_named (str_match_regex) an expected_name
let _is_object_of_class_named comp receiver cname =
(* checkes whether an object is of a certain class *)
let is_object_of_class_named receiver cname =
let open Clang_ast_t in
match receiver with
| PseudoObjectExpr (_, _, ei)
| ImplicitCastExpr (_, _, ei, _)
| ParenExpr (_, _, ei) ->
(match CAst_utils.qual_type_to_objc_interface ei.ei_qual_type with
| Some interface -> comp (Ctl_parser_types.Decl interface) cname
| Some interface ->
is_objc_interface_named (Ctl_parser_types.Decl interface) cname
| _ -> false)
| _ -> false
(* checkes whether an object is of a certain class *)
let is_object_of_class_named_strict receiver cname =
_is_object_of_class_named (is_objc_interface_named_strict) receiver cname
(* checkes whether an object is of a certain class *)
let is_object_of_class_named receiver cname =
_is_object_of_class_named (is_objc_interface_named) receiver cname
let _call_method comp an m =
(* an |= call_method(m) where the name must be exactly m *)
let call_method an m =
match an with
| Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, _, _, omei)) ->
comp omei.omei_selector m
compare_str_with_alexp omei.omei_selector m
| _ -> false
(* an |= call_method(m) where the name must be exactly m *)
let call_method_strict an m =
_call_method (String.equal) an m
(* an |= call_method(m) where we check is the name contains m *)
let call_method an m =
_call_method (str_match_regex) an m
let is_receiver_kind_class comp omei cname =
let is_receiver_kind_class omei cname =
let open Clang_ast_t in
match omei.omei_receiver_kind with
| `Class ptr ->
@ -132,48 +122,34 @@ let is_receiver_kind_class comp omei cname =
| Some ObjCInterfaceType (_, ptr) ->
(match CAst_utils.get_decl ptr with
| Some ObjCInterfaceDecl (_, ndi, _, _, _) ->
comp ndi.ni_name cname
compare_str_with_alexp ndi.ni_name cname
| _ -> false)
| _ -> false)
| _ -> false
let _call_class_method comp an cname mname =
match an with
| Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, _, _, omei)) ->
is_receiver_kind_class comp omei cname &&
comp omei.omei_selector mname
| _ -> false
let call_class_method_strict an cname mname =
_call_class_method (String.equal) an cname mname
let call_class_method an cname mname =
_call_class_method (str_match_regex) an cname mname
let _call_instance_method comp an cname mname =
match an with
| Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, receiver :: _, _, omei)) ->
is_object_of_class_named receiver cname &&
comp omei.omei_selector mname
| Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, _, _, omei)) ->
is_receiver_kind_class omei cname &&
compare_str_with_alexp omei.omei_selector mname
| _ -> false
(* an is a node calling method mname of class cname.
The equality is strict.
*)
let call_instance_method_strict an cname mname =
_call_instance_method (String.equal) an cname mname
(* an is a node calling method whose name contains mname of a
class whose name contains cname.
*)
let call_instance_method an cname mname =
_call_instance_method (str_match_regex) an cname mname
match an with
| Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, receiver :: _, _, omei)) ->
is_object_of_class_named receiver cname &&
compare_str_with_alexp omei.omei_selector mname
| _ -> false
let property_name_contains_word word an =
let property_named an name =
match an with
| Ctl_parser_types.Decl decl ->
(match Clang_ast_proj.get_named_decl_tuple decl with
| Some (_, n) -> str_match_regex n.Clang_ast_t.ni_name word
| Some (_, n) ->
compare_str_with_alexp n.Clang_ast_t.ni_name name
| _ -> false)
| _ -> false
@ -195,11 +171,11 @@ let decl_ref_is_in names st =
| Clang_ast_t.DeclRefExpr (_, _, _, drti) ->
(match drti.drti_decl_ref with
| Some dr -> let ndi, _, _ = CAst_utils.get_info_from_decl_ref dr in
List.exists ~f:(String.equal ndi.ni_name) names
List.exists ~f:(compare_str_with_alexp ndi.ni_name) names
| _ -> false)
| _ -> false
let call_function_named names an =
let call_function_named an names =
match an with
| Ctl_parser_types.Stmt st ->
CAst_utils.exists_eventually_st decl_ref_is_in names st
@ -291,70 +267,72 @@ let is_objc_dealloc context =
let captures_cxx_references an =
List.length (captured_variables_cxx_ref an) > 0
let is_binop_with_kind str_kind an =
let is_binop_with_kind an alexp_kind =
let str_kind = ALVar.alexp_to_string alexp_kind in
if not (Clang_ast_proj.is_valid_binop_kind_name str_kind) then
failwith ("Binary operator kind " ^ str_kind ^ " is not valid");
match an with
| Ctl_parser_types.Stmt (Clang_ast_t.BinaryOperator (_, _, _, boi)) ->
String.equal (Clang_ast_proj.string_of_binop_kind boi.boi_kind) str_kind
compare_str_with_alexp (Clang_ast_proj.string_of_binop_kind boi.boi_kind) alexp_kind
| _ -> false
let is_unop_with_kind str_kind an =
let is_unop_with_kind an alexp_kind =
let str_kind = ALVar.alexp_to_string alexp_kind in
if not (Clang_ast_proj.is_valid_unop_kind_name str_kind) then
failwith ("Unary operator kind " ^ str_kind ^ " is not valid");
match an with
| Ctl_parser_types.Stmt (Clang_ast_t.UnaryOperator (_, _, _, uoi)) ->
String.equal (Clang_ast_proj.string_of_unop_kind uoi.uoi_kind) str_kind
compare_str_with_alexp (Clang_ast_proj.string_of_unop_kind uoi.uoi_kind) alexp_kind
| _ -> false
let is_node nodename an =
if not (Clang_ast_proj.is_valid_astnode_kind nodename) then
failwith ("Node " ^ nodename ^ " is not a valid AST node");
let is_node an nodename =
let nodename_str = ALVar.alexp_to_string nodename in
if not (Clang_ast_proj.is_valid_astnode_kind nodename_str) then
failwith ("Node " ^ nodename_str ^ " is not a valid AST node");
let an_str = match an with
| Ctl_parser_types.Stmt s -> Clang_ast_proj.get_stmt_kind_string s
| Ctl_parser_types.Decl d -> Clang_ast_proj.get_decl_kind_string d in
String.equal nodename an_str
compare_str_with_alexp an_str nodename
let is_ptr_to_objc_class typ class_name =
match typ with
| Some Clang_ast_t.ObjCObjectPointerType (_, {Clang_ast_t.qt_type_ptr}) ->
(match CAst_utils.get_desugared_type qt_type_ptr with
| Some ObjCInterfaceType (_, ptr) ->
(match CAst_utils.get_decl ptr with
| Some ObjCInterfaceDecl (_, ndi, _, _, _) ->
compare_str_with_alexp ndi.ni_name class_name
| _ -> false)
| _ -> false)
| _ -> false
(* node an is of class classname *)
let isa classname an =
let isa an classname =
match an with
| Ctl_parser_types.Stmt stmt ->
(match Clang_ast_proj.get_expr_tuple stmt with
| Some (_, _, expr_info) ->
let typ = CAst_utils.get_desugared_type expr_info.ei_qual_type.qt_type_ptr in
CAst_utils.is_ptr_to_objc_class typ classname
is_ptr_to_objc_class typ classname
| _ -> false)
| _ -> false
let _declaration_has_name comp an name =
(* an is a declaration whose name contains a regexp defined by re *)
let declaration_has_name an name =
match an with
| Ctl_parser_types.Decl d ->
(match Clang_ast_proj.get_named_decl_tuple d with
| Some (_, ndi) -> comp ndi.ni_name name
| Some (_, ndi) -> compare_str_with_alexp ndi.ni_name name
| _ -> false)
| _ -> false
(* an is a declaration whose name contains a regexp defined by re *)
let declaration_has_name an re =
_declaration_has_name (str_match_regex) an re
(* an is a declaration called precisely name *)
let declaration_has_name_strict an name =
_declaration_has_name (String.equal) an name
let _is_class comp an re =
let is_class an re =
match an with
| Ctl_parser_types.Decl (Clang_ast_t.ObjCInterfaceDecl _)
| Ctl_parser_types.Decl (Clang_ast_t.ObjCImplementationDecl _) ->
_declaration_has_name comp an re
declaration_has_name an re
| _ -> false
let is_class an re =
_is_class (str_match_regex) an re
let is_class_strict an name =
_is_class (String.equal) an name
let decl_unavailable_in_supported_ios_sdk (cxt : CLintersContext.context) an =
let allowed_os_versions =
match Config.iphoneos_target_sdk_version,
@ -415,10 +393,10 @@ let type_ptr_equal_type type_ptr type_str =
| _ -> Logging.out "Couldn't find type....\n"; false
let method_return_type an typ =
let method_return_type an _typ =
Logging.out "\n Executing method_return_type...";
match an with
| Ctl_parser_types.Decl (Clang_ast_t.ObjCMethodDecl (_, _, mdi)) ->
match an, _typ with
| Ctl_parser_types.Decl (Clang_ast_t.ObjCMethodDecl (_, _, mdi)), ALVar.Const typ ->
Logging.out "\n with parameter `%s`...." typ;
let qual_type = mdi.Clang_ast_t.omdi_result_type in
type_ptr_equal_type qual_type.Clang_ast_t.qt_type_ptr typ

@ -13,23 +13,15 @@ type t = ALVar.formula_id * ALVar.alexp list (* (name, [param1,...,paramK]) *)
val captured_variables_cxx_ref : Ctl_parser_types.ast_node -> Clang_ast_t.named_decl_info list
val call_method_strict : Ctl_parser_types.ast_node -> string -> bool
val call_method : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val call_method : Ctl_parser_types.ast_node -> string -> bool
val call_class_method : Ctl_parser_types.ast_node -> ALVar.alexp -> ALVar.alexp -> bool
val call_class_method : Ctl_parser_types.ast_node -> string -> string -> bool
val call_instance_method : Ctl_parser_types.ast_node -> ALVar.alexp -> ALVar.alexp -> bool
val call_class_method_strict : Ctl_parser_types.ast_node -> string -> string -> bool
val is_objc_interface_named : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val call_instance_method : Ctl_parser_types.ast_node -> string -> string -> bool
val call_instance_method_strict : Ctl_parser_types.ast_node -> string -> string -> bool
val is_objc_interface_named_strict : Ctl_parser_types.ast_node -> string -> bool
val is_objc_interface_named : Ctl_parser_types.ast_node -> string -> bool
val property_name_contains_word : string -> Ctl_parser_types.ast_node -> bool
val property_named : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val is_objc_extension : CLintersContext.context -> bool
@ -37,7 +29,7 @@ val is_syntactically_global_var : Ctl_parser_types.ast_node -> bool
val is_const_expr_var : Ctl_parser_types.ast_node -> bool
val call_function_named : string list -> Ctl_parser_types.ast_node -> bool
val call_function_named : Ctl_parser_types.ast_node -> ALVar.alexp list -> bool
val is_strong_property : Ctl_parser_types.ast_node -> bool
@ -49,7 +41,8 @@ val context_in_synchronized_block : CLintersContext.context -> bool
val is_ivar_atomic : Ctl_parser_types.ast_node -> bool
val is_method_property_accessor_of_ivar : Ctl_parser_types.ast_node -> CLintersContext.context -> bool
val is_method_property_accessor_of_ivar :
Ctl_parser_types.ast_node -> CLintersContext.context -> bool
val is_objc_constructor : CLintersContext.context -> bool
@ -57,28 +50,24 @@ val is_objc_dealloc : CLintersContext.context -> bool
val captures_cxx_references : Ctl_parser_types.ast_node -> bool
val is_binop_with_kind : string -> Ctl_parser_types.ast_node -> bool
val is_unop_with_kind : string -> Ctl_parser_types.ast_node -> bool
val isa : string -> Ctl_parser_types.ast_node -> bool
val is_binop_with_kind : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val is_node : string -> Ctl_parser_types.ast_node -> bool
val is_unop_with_kind : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val declaration_has_name : Ctl_parser_types.ast_node -> string -> bool
val isa : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val declaration_has_name_strict : Ctl_parser_types.ast_node -> string -> bool
val is_node : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val is_class : Ctl_parser_types.ast_node -> string -> bool
val declaration_has_name : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val is_class_strict : Ctl_parser_types.ast_node -> string -> bool
val is_class : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val pp_predicate : Format.formatter -> t -> unit
val decl_unavailable_in_supported_ios_sdk : CLintersContext.context -> Ctl_parser_types.ast_node
-> bool
val decl_unavailable_in_supported_ios_sdk :
CLintersContext.context -> Ctl_parser_types.ast_node -> bool
val method_return_type : Ctl_parser_types.ast_node -> string -> bool
val method_return_type : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val get_available_attr_ios_sdk : Ctl_parser_types.ast_node -> string option

@ -594,30 +594,22 @@ let next_state_via_transition an trans =
(* evaluate an atomic formula (i.e. a predicate) on a ast node an and a
linter context lcxt. That is: an, lcxt |= pred_name(params) *)
let rec eval_Atomic _pred_name _args an lcxt =
let rec eval_Atomic _pred_name args an lcxt =
let pred_name = ALVar.formula_id_to_string _pred_name in
let args = List.map ~f:ALVar.alexp_to_string _args in
match pred_name, args, an with
| "call_method", [m], an -> CPredicates.call_method an m
| "call_method_strict", [m], an -> CPredicates.call_method_strict an m
| "call_class_method", [c; m], an ->
CPredicates.call_class_method an c m
| "call_class_method_strict", [c; m], an ->
CPredicates.call_class_method_strict an c m
| "call_instance_method", [c; m], an ->
CPredicates.call_instance_method an c m
| "call_instance_method_strict", [c; m], an ->
CPredicates.call_instance_method_strict an c m
| "is_objc_interface_named", [name], an ->
CPredicates.is_objc_interface_named an name
| "is_objc_interface_named_strict", [name], an ->
CPredicates.is_objc_interface_named_strict an name
| "property_name_contains_word", [word], an ->
CPredicates.property_name_contains_word word an
| "property_named", [word], an ->
CPredicates.property_named an word
| "is_objc_extension", [], _ -> CPredicates.is_objc_extension lcxt
| "is_global_var", [], an -> CPredicates.is_syntactically_global_var an
| "is_const_var", [], an -> CPredicates.is_const_expr_var an
| "call_function_named", args, an -> CPredicates.call_function_named args an
| "call_function_named", args, an -> CPredicates.call_function_named an args
| "is_strong_property", [], an -> CPredicates.is_strong_property an
| "is_assign_property", [], an -> CPredicates.is_assign_property an
| "is_property_pointer_type", [], an -> CPredicates.is_property_pointer_type an
@ -629,18 +621,15 @@ let rec eval_Atomic _pred_name _args an lcxt =
| "is_objc_constructor", [], _ -> CPredicates.is_objc_constructor lcxt
| "is_objc_dealloc", [], _ -> CPredicates.is_objc_dealloc lcxt
| "captures_cxx_references", [], _ -> CPredicates.captures_cxx_references an
| "is_binop_with_kind", [str_kind], an ->
CPredicates.is_binop_with_kind str_kind an
| "is_unop_with_kind", [str_kind], an ->
CPredicates.is_unop_with_kind str_kind an
| "is_node", [nodename], an -> CPredicates.is_node nodename an
| "isa", [classname], an -> CPredicates.isa classname an
| "is_binop_with_kind", [kind], an ->
CPredicates.is_binop_with_kind an kind
| "is_unop_with_kind", [kind], an ->
CPredicates.is_unop_with_kind an kind
| "is_node", [nodename], an -> CPredicates.is_node an nodename
| "isa", [classname], an -> CPredicates.isa an classname
| "declaration_has_name", [decl_name], an ->
CPredicates.declaration_has_name an decl_name
| "declaration_has_name_strict", [decl_name], an ->
CPredicates.declaration_has_name_strict an decl_name
| "is_class", [cname], an -> CPredicates.is_class an cname
| "is_class_strict", [cname], an -> CPredicates.is_class_strict an cname
| "decl_unavailable_in_supported_ios_sdk", [], an ->
CPredicates.decl_unavailable_in_supported_ios_sdk lcxt an
| "within_responds_to_selector_block", [], an ->

@ -22,7 +22,7 @@ DEFINE-CHECKER MACRO_TEST1 = {
LET call_two_methods(x,y) = call_method(x) OR call_method(y);
SET report_when = call_two_methods("foo", "bar");
SET report_when = call_two_methods("foo:", "bar");
SET message = "Error message here";
@ -33,7 +33,7 @@ DEFINE-CHECKER MACRO_TEST2 = {
LET my_macro_to_call_method_of_class(x,y) = call_instance_method(y,x);
SET report_when = my_macro_to_call_method_of_class("foo", "A");
SET report_when = my_macro_to_call_method_of_class("foo:", "A");
SET message = "Error message here";
@ -46,7 +46,7 @@ DEFINE-CHECKER MACRO_TEST3 = {
LET call_my_macro(t,v) = my_macro_to_call_method_of_class(t,v);
SET report_when = call_my_macro("foo", "A");
SET report_when = call_my_macro("foo:", "A");
SET message = "Error message here";

Loading…
Cancel
Save