Add support for qualified functions and a call_qualified_function predicate

Reviewed By: ddino

Differential Revision: D14401963

fbshipit-source-id: 8d080324a
master
Lee Howes 6 years ago committed by Facebook Github Bot
parent 5aedc7e71c
commit 5c2ef731ff

@ -593,13 +593,16 @@ let has_init_list_const_expr an =
false false
let decl_ref_name ?kind name st = let decl_ref_name qualified ?kind name st =
match st with match st with
| Clang_ast_t.DeclRefExpr (_, _, _, drti) -> ( | Clang_ast_t.DeclRefExpr (_, _, _, drti) -> (
match drti.drti_decl_ref with match drti.drti_decl_ref with
| Some dr -> ( | Some dr -> (
let ndi, _, _ = CAst_utils.get_info_from_decl_ref dr in let ndi, _, _ = CAst_utils.get_info_from_decl_ref dr in
let has_right_name = ALVar.compare_str_with_alexp ndi.ni_name name in let qname =
if qualified then String.concat ~sep:"::" (List.rev ndi.ni_qual_name) else ndi.ni_name
in
let has_right_name = ALVar.compare_str_with_alexp qname name in
match kind with match kind with
| Some decl_kind -> | Some decl_kind ->
has_right_name && PolyVariantEqual.( = ) dr.Clang_ast_t.dr_kind decl_kind has_right_name && PolyVariantEqual.( = ) dr.Clang_ast_t.dr_kind decl_kind
@ -612,13 +615,21 @@ let decl_ref_name ?kind name st =
let declaration_ref_name ?kind an name = let declaration_ref_name ?kind an name =
match an with Ctl_parser_types.Stmt st -> decl_ref_name ?kind name st | _ -> false match an with Ctl_parser_types.Stmt st -> decl_ref_name false ?kind name st | _ -> false
let call_function an name = let call_function an name =
match an with match an with
| Ctl_parser_types.Stmt st -> | Ctl_parser_types.Stmt st ->
CAst_utils.exists_eventually_st (decl_ref_name ~kind:`Function) name st CAst_utils.exists_eventually_st (decl_ref_name false ~kind:`Function) name st
| _ ->
false
let call_qualified_function an name =
match an with
| Ctl_parser_types.Stmt st ->
CAst_utils.exists_eventually_st (decl_ref_name true ~kind:`Function) name st
| _ -> | _ ->
false false
@ -626,7 +637,7 @@ let call_function an name =
let is_enum_constant an name = let is_enum_constant an name =
match an with match an with
| Ctl_parser_types.Stmt st -> | Ctl_parser_types.Stmt st ->
decl_ref_name ~kind:`EnumConstant name st decl_ref_name false ~kind:`EnumConstant name st
| _ -> | _ ->
false false
@ -984,7 +995,7 @@ let is_receiver_self an =
match an with match an with
| Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, fst_param :: _, _, _)) -> | Ctl_parser_types.Stmt (Clang_ast_t.ObjCMessageExpr (_, fst_param :: _, _, _)) ->
CAst_utils.exists_eventually_st CAst_utils.exists_eventually_st
(decl_ref_name ~kind:`ImplicitParam) (decl_ref_name false ~kind:`ImplicitParam)
(ALVar.Const CFrontend_config.self) fst_param (ALVar.Const CFrontend_config.self) fst_param
| _ -> | _ ->
false false

@ -54,6 +54,9 @@ val has_init_list_const_expr : Ctl_parser_types.ast_node -> bool
val call_function : Ctl_parser_types.ast_node -> ALVar.alexp -> bool val call_function : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
(** 'call_function an name' is true iff an is a call to a function whose name contains 'name' *) (** 'call_function an name' is true iff an is a call to a function whose name contains 'name' *)
val call_qualified_function : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
(** 'call_function an name' is true iff an is a call to a function whose fully qualified name contains 'name' *)
val is_strong_property : Ctl_parser_types.ast_node -> bool val is_strong_property : Ctl_parser_types.ast_node -> bool
(** 'is_strong_property an' is true iff an denotes a objc property declaration with 'strong' attribute *) (** 'is_strong_property an' is true iff an denotes a objc property declaration with 'strong' attribute *)

@ -961,6 +961,8 @@ let rec eval_Atomic pred_name_ args an lcxt =
CPredicates.call_class_method an m CPredicates.call_class_method an m
| "call_function", [m], an -> | "call_function", [m], an ->
CPredicates.call_function an m CPredicates.call_function an m
| "call_qualified_function", [m], an ->
CPredicates.call_qualified_function an m
| "call_instance_method", [m], an -> | "call_instance_method", [m], an ->
CPredicates.call_instance_method an m CPredicates.call_instance_method an m
| "call_method", [m], an -> | "call_method", [m], an ->

@ -6,7 +6,7 @@
TESTS_DIR = ../../.. TESTS_DIR = ../../..
CLANG_OPTIONS = -std=c++11 -c CLANG_OPTIONS = -std=c++11 -c
INFER_OPTIONS = --no-capture --linters-only --linters-def-file extracopy.al --no-filtering --debug-exceptions --project-root $(TESTS_DIR) \ INFER_OPTIONS = --no-capture --linters-only --linters-def-file extracopy.al --linters-def-file call_function.al --no-filtering --debug-exceptions --project-root $(TESTS_DIR) \
--enable-issue-type GLOBAL_VARIABLE_INITIALIZED_WITH_FUNCTION_OR_METHOD_CALL --enable-issue-type GLOBAL_VARIABLE_INITIALIZED_WITH_FUNCTION_OR_METHOD_CALL
INFERPRINT_OPTIONS = --issues-tests INFERPRINT_OPTIONS = --issues-tests

@ -0,0 +1,15 @@
// Copyright (c) 2019-present, Facebook, Inc.
//
// This source code is licensed under the MIT license found in the
// LICENSE file in the root directory of this source tree.
DEFINE-CHECKER CALL_FUNCTION = {
SET report_when =
WHEN call_qualified_function("anamespace::the_function") OR call_function("the_other_function")
HOLDS-IN-NODE CallExpr;
SET message = "the_function and the_other_function are not to be called";
SET suggestion = "Call something else.";
SET severity = "WARNING";
SET mode = "ON";
};

@ -0,0 +1,35 @@
/*
* Copyright (c) 2019-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
namespace anamespace {
void the_function() {}
void the_other_function() {}
} // namespace anamespace
namespace anothernamespace {
void the_function() {}
void the_other_function() {}
} // namespace anothernamespace
int main() {
anamespace::the_function();
anothernamespace::the_function();
anamespace::the_other_function();
anothernamespace::the_other_function();
{
using namespace anamespace;
the_function();
the_other_function();
}
{
using namespace anothernamespace;
the_function();
the_other_function();
}
return 0;
}

@ -1,3 +1,9 @@
codetoanalyze/cpp/linters/call_function.cpp, main, 18, CALL_FUNCTION, no_bucket, WARNING, []
codetoanalyze/cpp/linters/call_function.cpp, main, 20, CALL_FUNCTION, no_bucket, WARNING, []
codetoanalyze/cpp/linters/call_function.cpp, main, 21, CALL_FUNCTION, no_bucket, WARNING, []
codetoanalyze/cpp/linters/call_function.cpp, main, 24, CALL_FUNCTION, no_bucket, WARNING, []
codetoanalyze/cpp/linters/call_function.cpp, main, 25, CALL_FUNCTION, no_bucket, WARNING, []
codetoanalyze/cpp/linters/call_function.cpp, main, 30, CALL_FUNCTION, no_bucket, WARNING, []
codetoanalyze/cpp/linters/cxxconst.cpp, test, 28, CONSTANT_EXPR, no_bucket, WARNING, [] codetoanalyze/cpp/linters/cxxconst.cpp, test, 28, CONSTANT_EXPR, no_bucket, WARNING, []
codetoanalyze/cpp/linters/cxxconst.cpp, test, 31, CONSTANT_EXPR, no_bucket, WARNING, [] codetoanalyze/cpp/linters/cxxconst.cpp, test, 31, CONSTANT_EXPR, no_bucket, WARNING, []
codetoanalyze/cpp/linters/cxxconst.cpp, test, 33, CONSTANT_EXPR, no_bucket, WARNING, [] codetoanalyze/cpp/linters/cxxconst.cpp, test, 33, CONSTANT_EXPR, no_bucket, WARNING, []

Loading…
Cancel
Save