[linters] Add transition to parameters by position in the parameters list

Reviewed By: ddino

Differential Revision: D5911586

fbshipit-source-id: 263b7dc
master
Dulma Churchill 7 years ago committed by Facebook Github Bot
parent d694038abd
commit 652af47da7

@ -690,28 +690,6 @@ let within_available_class_block (cxt: CLintersContext.context) an =
| _ | _
-> false -> false
let objc_method_has_nth_parameter_of_type an _num _typ =
let open Clang_ast_t in
let num =
match _num with
| ALVar.Const n -> (
try int_of_string n
with Failure _ -> -1 )
| _
-> -1
in
match (num, an, _typ) with
| -1, _, _
-> false
| _, Ctl_parser_types.Decl ObjCMethodDecl (_, _, omdi), ALVar.Const typ -> (
match List.nth omdi.omdi_parameters num with
| Some ParmVarDecl (_, _, qt, _)
-> type_ptr_equal_type qt.qt_type_ptr typ
| _
-> false )
| _, _, _
-> false
let using_namespace an namespace = let using_namespace an namespace =
let open Clang_ast_t in let open Clang_ast_t in
match an with match an with
@ -766,3 +744,15 @@ let has_used_attribute an =
let open Clang_ast_t in let open Clang_ast_t in
let attributes = get_decl_attributes_for_callexpr an in let attributes = get_decl_attributes_for_callexpr an in
List.exists ~f:(fun attr -> match attr with UsedAttr _ -> true | _ -> false) attributes List.exists ~f:(fun attr -> match attr with UsedAttr _ -> true | _ -> false) attributes
let has_value an al_exp =
let open Clang_ast_t in
let open Ctl_parser_types in
match an with
| Stmt IntegerLiteral (_, _, _, integer_literal_info)
-> let value = integer_literal_info.Clang_ast_t.ili_value in
ALVar.compare_str_with_alexp value al_exp
| Stmt StringLiteral (_, _, _, s)
-> ALVar.compare_str_with_alexp s al_exp
| _
-> false

@ -95,6 +95,8 @@ val class_unavailable_in_supported_ios_sdk :
val has_type : Ctl_parser_types.ast_node -> ALVar.alexp -> bool val has_type : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val has_value : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val method_return_type : Ctl_parser_types.ast_node -> ALVar.alexp -> bool val method_return_type : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val has_type_subprotocol_of : Ctl_parser_types.ast_node -> ALVar.alexp -> bool val has_type_subprotocol_of : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
@ -106,9 +108,6 @@ val get_selector : Ctl_parser_types.ast_node -> string option
val within_responds_to_selector_block : val within_responds_to_selector_block :
CLintersContext.context -> Ctl_parser_types.ast_node -> bool CLintersContext.context -> Ctl_parser_types.ast_node -> bool
val objc_method_has_nth_parameter_of_type :
Ctl_parser_types.ast_node -> ALVar.alexp -> ALVar.alexp -> bool
val using_namespace : Ctl_parser_types.ast_node -> ALVar.alexp -> bool val using_namespace : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val receiver_class_method_call : Ctl_parser_types.ast_node -> Clang_ast_t.decl option val receiver_class_method_call : Ctl_parser_types.ast_node -> Clang_ast_t.decl option

@ -24,6 +24,7 @@ type transitions =
| InitExpr (** decl to stmt *) | InitExpr (** decl to stmt *)
| Super (** decl to decl *) | Super (** decl to decl *)
| ParameterName of ALVar.alexp (** stmt to stmt, decl to decl *) | ParameterName of ALVar.alexp (** stmt to stmt, decl to decl *)
| ParameterPos of ALVar.alexp (** stmt to stmt, decl to decl *)
| Parameters (** stmt to stmt, decl to decl *) | Parameters (** stmt to stmt, decl to decl *)
| Cond | Cond
| PointerToDecl (** stmt to decl *) | PointerToDecl (** stmt to decl *)
@ -32,7 +33,7 @@ type transitions =
let is_transition_to_successor trans = let is_transition_to_successor trans =
match trans with match trans with
| Body | InitExpr | FieldName _ | Fields | ParameterName _ | Parameters | Cond | Body | InitExpr | FieldName _ | Fields | ParameterName _ | ParameterPos _ | Parameters | Cond
-> true -> true
| Super | PointerToDecl | Protocol | Super | PointerToDecl | Protocol
-> false -> false
@ -143,6 +144,8 @@ module Debug = struct
-> Format.pp_print_string fmt "Super" -> Format.pp_print_string fmt "Super"
| ParameterName name | ParameterName name
-> Format.pp_print_string fmt ("ParameterName " ^ ALVar.alexp_to_string name) -> Format.pp_print_string fmt ("ParameterName " ^ ALVar.alexp_to_string name)
| ParameterPos pos
-> Format.pp_print_string fmt ("ParameterPos " ^ ALVar.alexp_to_string pos)
| Parameters | Parameters
-> Format.pp_print_string fmt "Parameters" -> Format.pp_print_string fmt "Parameters"
| Cond | Cond
@ -708,21 +711,62 @@ let parameter_of_corresp_name method_name args name =
| None | None
-> None -> None
let transition_via_parameter_name an name = let parameter_of_corresp_pos args pos =
let pos_int =
match pos with
| ALVar.Const n -> (
try int_of_string n
with Failure _ -> -1 )
| _
-> -1
in
List.nth args pos_int
let transition_via_specified_parameter ~pos an key =
let invalid_param_name_use () =
Logging.die InternalError "Transition ParameterName is only available for ObjC methods"
in
let node_opt_to_ast_node_list f arg_stmt_opt =
match arg_stmt_opt with Some arg -> [f arg] | None -> []
in
let apply_decl arg = Decl arg in
let apply_stmt arg = Stmt arg in
match an with match an with
| Stmt ObjCMessageExpr (_, stmt_list, _, omei) | Stmt ObjCMessageExpr (_, stmt_list, _, omei)
-> ( -> let method_name = omei.omei_selector in
let arg_stmt_opt = parameter_of_corresp_name omei.omei_selector stmt_list name in let parameter_of_corresp_key =
match arg_stmt_opt with Some arg -> [Stmt arg] | None -> [] ) if pos then parameter_of_corresp_pos else parameter_of_corresp_name method_name
in
let arg_stmt_opt = parameter_of_corresp_key stmt_list key in
node_opt_to_ast_node_list apply_stmt arg_stmt_opt
| Stmt CallExpr (_, _ :: args, _)
-> let parameter_of_corresp_key =
if pos then parameter_of_corresp_pos else invalid_param_name_use ()
in
let arg_stmt_opt = parameter_of_corresp_key args key in
node_opt_to_ast_node_list apply_stmt arg_stmt_opt
| Decl ObjCMethodDecl (_, named_decl_info, omdi) | Decl ObjCMethodDecl (_, named_decl_info, omdi)
-> ( -> let method_name = named_decl_info.ni_name in
let arg_decl_opt = let parameter_of_corresp_key =
parameter_of_corresp_name named_decl_info.ni_name omdi.omdi_parameters name if pos then parameter_of_corresp_pos else parameter_of_corresp_name method_name
in in
match arg_decl_opt with Some arg -> [Decl arg] | None -> [] ) let arg_decl_opt = parameter_of_corresp_key omdi.omdi_parameters key in
node_opt_to_ast_node_list apply_decl arg_decl_opt
| Decl FunctionDecl (_, _, _, fdi)
| Decl CXXMethodDecl (_, _, _, fdi, _)
| Decl CXXConstructorDecl (_, _, _, fdi, _)
-> let parameter_of_corresp_key =
if pos then parameter_of_corresp_pos else invalid_param_name_use ()
in
let arg_decl_opt = parameter_of_corresp_key fdi.fdi_parameters key in
node_opt_to_ast_node_list apply_decl arg_decl_opt
| _ | _
-> [] -> []
let transition_via_parameter_name an name = transition_via_specified_parameter an name ~pos:false
let transition_via_parameter_pos an pos = transition_via_specified_parameter an pos ~pos:true
let transition_via_fields an = let transition_via_fields an =
let open Clang_ast_t in let open Clang_ast_t in
match an with match an with
@ -789,6 +833,8 @@ let next_state_via_transition an trans =
-> transition_stmt_to_decl_via_pointer st -> transition_stmt_to_decl_via_pointer st
| an, ParameterName name | an, ParameterName name
-> transition_via_parameter_name an name -> transition_via_parameter_name an name
| an, ParameterPos pos
-> transition_via_parameter_pos an pos
| _, _ | _, _
-> [] -> []
@ -836,6 +882,8 @@ let rec eval_Atomic _pred_name args an lcxt =
-> CPredicates.has_cast_kind an name -> CPredicates.has_cast_kind an name
| "has_type", [typ], an | "has_type", [typ], an
-> CPredicates.has_type an typ -> CPredicates.has_type an typ
| "has_value", [typ], an
-> CPredicates.has_value an typ
| "isa", [classname], an | "isa", [classname], an
-> CPredicates.isa an classname -> CPredicates.isa an classname
| "is_assign_property", [], an | "is_assign_property", [], an
@ -890,8 +938,6 @@ let rec eval_Atomic _pred_name args an lcxt =
-> CPredicates.method_return_type an typ -> CPredicates.method_return_type an typ
| "within_responds_to_selector_block", [], an | "within_responds_to_selector_block", [], an
-> CPredicates.within_responds_to_selector_block lcxt an -> CPredicates.within_responds_to_selector_block lcxt an
| "objc_method_has_nth_parameter_of_type", [num; typ], an
-> CPredicates.objc_method_has_nth_parameter_of_type an num typ
| "using_namespace", [namespace], an | "using_namespace", [namespace], an
-> CPredicates.using_namespace an namespace -> CPredicates.using_namespace an namespace
| "is_at_selector_with_name", [name], an | "is_at_selector_with_name", [name], an

@ -22,6 +22,7 @@ type transitions =
| InitExpr (** decl to stmt *) | InitExpr (** decl to stmt *)
| Super (** decl to decl *) | Super (** decl to decl *)
| ParameterName of ALVar.alexp (** stmt to stmt, decl to decl *) | ParameterName of ALVar.alexp (** stmt to stmt, decl to decl *)
| ParameterPos of ALVar.alexp (** stmt to stmt, decl to decl *)
| Parameters (** stmt to stmt, decl to decl *) | Parameters (** stmt to stmt, decl to decl *)
| Cond | Cond
| PointerToDecl (** stmt to decl *) | PointerToDecl (** stmt to decl *)

@ -75,6 +75,7 @@ rule token = parse
| "FieldName" { FIELD_NAME } | "FieldName" { FIELD_NAME }
| "Parameters" { PARAMETERS } | "Parameters" { PARAMETERS }
| "ParameterName" { PARAMETER_NAME } | "ParameterName" { PARAMETER_NAME }
| "ParameterPos" { PARAMETER_POS }
| "Body" {BODY} | "Body" {BODY}
| "Protocol" {PROTOCOL} | "Protocol" {PROTOCOL}
| "InitExpr" {INIT_EXPR} | "InitExpr" {INIT_EXPR}

@ -83,6 +83,7 @@
%token FIELD_NAME %token FIELD_NAME
%token PARAMETERS %token PARAMETERS
%token PARAMETER_NAME %token PARAMETER_NAME
%token PARAMETER_POS
%token POINTER_TO_DECL %token POINTER_TO_DECL
%token PROTOCOL %token PROTOCOL
%token EOF %token EOF
@ -244,6 +245,7 @@ transition_label:
| INIT_EXPR { Some CTL.InitExpr } | INIT_EXPR { Some CTL.InitExpr }
| PARAMETERS { Some CTL.Parameters } | PARAMETERS { Some CTL.Parameters }
| PARAMETER_NAME alexp { Some (CTL.ParameterName $2) } | PARAMETER_NAME alexp { Some (CTL.ParameterName $2) }
| PARAMETER_POS alexp { Some (CTL.ParameterPos $2) }
| POINTER_TO_DECL { Some CTL.PointerToDecl } | POINTER_TO_DECL { Some CTL.PointerToDecl }
| PROTOCOL { Some CTL.Protocol } | PROTOCOL { Some CTL.Protocol }
; ;

@ -73,7 +73,7 @@ codetoanalyze/objc/linters-for-test-only/subclassing.m, Linters_dummy_method, 53
codetoanalyze/objc/linters-for-test-only/subclassing.m, Linters_dummy_method, 53, SUBCLASSING_TEST_EXAMPLE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, Linters_dummy_method, 53, SUBCLASSING_TEST_EXAMPLE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, Linters_dummy_method, 111, TEST_TYPEDEF_CHECK, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, Linters_dummy_method, 111, TEST_TYPEDEF_CHECK, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, Linters_dummy_method, 119, TEST_TYPEDEF_CHECK, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, Linters_dummy_method, 119, TEST_TYPEDEF_CHECK, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, Linters_dummy_method, 123, TEST_TYPEDEF_CHECK, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, Linters_dummy_method, 125, TEST_TYPEDEF_CHECK, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m1, 73, TEST_BUILTIN_TYPE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m1, 73, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m10, 82, TEST_BUILTIN_TYPE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m10, 82, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m11, 83, TEST_BUILTIN_TYPE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m11, 83, TEST_BUILTIN_TYPE, []
@ -93,13 +93,14 @@ codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m24, 100, TEST_
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m25, 101, TEST_BUILTIN_TYPE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m25, 101, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m26, 102, TEST_BUILTIN_TYPE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m26, 102, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m26, 103, TEST_BUILTIN_TYPE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m26, 103, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m26, 103, TEST_NTH_PARAM_TYPE_CHECK, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m26, 105, TEST_NTH_PARAM_TYPE_CHECK, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m26, 105, TEST_PARAM_TYPE_CHECK, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m26, 105, TEST_PARAM_TYPE_CHECK, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m3, 75, TEST_BUILTIN_TYPE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m3, 75, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m4, 76, TEST_BUILTIN_TYPE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m4, 76, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m7, 79, TEST_BUILTIN_TYPE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m7, 79, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m8, 80, TEST_BUILTIN_TYPE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m8, 80, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m9, 81, TEST_BUILTIN_TYPE, [] codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m9, 81, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, bar, 129, TEST_NTH_PARAM_TYPE_CHECK_FUNCTION, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 31, TEST_DEFAULT_VISIBILITY, [] codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 31, TEST_DEFAULT_VISIBILITY, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 32, TEST_DEFAULT_VISIBILITY, [] codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 32, TEST_DEFAULT_VISIBILITY, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 33, TEST_HIDDEN_VISIBILITY, [] codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 33, TEST_HIDDEN_VISIBILITY, []

@ -211,12 +211,21 @@ DEFINE-CHECKER TEST_PARAM_TYPE_CHECK2 = {
}; };
DEFINE-CHECKER TEST_NTH_PARAM_TYPE_CHECK = { DEFINE-CHECKER TEST_NTH_PARAM_TYPE_CHECK = {
SET report_when = SET report_when =
WHEN WHEN
objc_method_has_nth_parameter_of_type("2", "REGEXP('This.+')*") HOLDS-NEXT WITH-TRANSITION ParameterPos "2"
HOLDS-IN-NODE ObjCMethodDecl; (has_type("REGEXP('This.+')*"))
HOLDS-IN-NODE ObjCMethodDecl;
SET message = "Found a method with nth parameter of type....";
SET severity = "LIKE";
};
DEFINE-CHECKER TEST_NTH_PARAM_TYPE_CHECK_FUNCTION = {
SET report_when =
WHEN
HOLDS-NEXT WITH-TRANSITION ParameterPos "1"
(has_value("2") HOLDS-EVENTUALLY)
HOLDS-IN-NODE CallExpr;
SET message = "Found a method with nth parameter of type...."; SET message = "Found a method with nth parameter of type....";
SET severity = "LIKE"; SET severity = "LIKE";
}; };

@ -118,6 +118,12 @@ typedef struct {
my_pS p; my_pS p;
typedef struct Node { struct my_listNode* next; } my_listNode; typedef struct Node {
struct my_listNode* next;
} my_listNode;
my_listNode ln; my_listNode ln;
void foo(int n, int m) {}
void bar() { foo(0, 2); }

Loading…
Cancel
Save