From 1f2b0d415244f1eb4680d4725b734824ea93450a Mon Sep 17 00:00:00 2001 From: David Lively Date: Tue, 18 Dec 2018 18:30:04 -0800 Subject: [PATCH] Add new predicate has_cxx_qual_name and macro %cxx_full_name% Reviewed By: jvillard Differential Revision: D13490505 fbshipit-source-id: df66224d6 --- infer/src/clang/cFrontend_errors.ml | 2 ++ infer/src/clang/cPredicates.ml | 8 +++++++ infer/src/clang/cPredicates.mli | 5 ++++ infer/src/clang/cTL.ml | 2 ++ infer/src/clang/ctl_parser_types.ml | 23 +++++++++++++++++++ infer/src/clang/ctl_parser_types.mli | 2 ++ .../cpp/linters-for-test-only/issues.exp | 6 +++++ .../linters-for-test-only/linters_example.al | 5 ++++ 8 files changed, 53 insertions(+) diff --git a/infer/src/clang/cFrontend_errors.ml b/infer/src/clang/cFrontend_errors.ml index b85532f8d..533c3d3f7 100644 --- a/infer/src/clang/cFrontend_errors.ml +++ b/infer/src/clang/cFrontend_errors.ml @@ -127,6 +127,8 @@ let evaluate_place_holder context ph an = MF.monospaced_to_string (Ctl_parser_types.stmt_node_child_type an) | "%name%" -> MF.monospaced_to_string (Ctl_parser_types.ast_node_name an) + | "%cxx_full_name%" -> + MF.monospaced_to_string (Ctl_parser_types.ast_node_cxx_full_name an) | _ -> L.die InternalError "helper function %s is unknown" ph diff --git a/infer/src/clang/cPredicates.ml b/infer/src/clang/cPredicates.ml index cc6f2d6da..9211f97ae 100644 --- a/infer/src/clang/cPredicates.ml +++ b/infer/src/clang/cPredicates.ml @@ -1412,6 +1412,14 @@ let is_cxx_copy_constructor an = false +let has_cxx_full_name an qual_name_re = + match Ctl_parser_types.ast_node_cxx_full_name an with + | "" -> + false + | full_name -> + ALVar.compare_str_with_alexp full_name qual_name_re + + let is_cxx_method_overriding an qual_name_re = let rec overrides_named (decl_refs : Clang_ast_t.decl_ref list) (qnre : ALVar.alexp) = List.exists diff --git a/infer/src/clang/cPredicates.mli b/infer/src/clang/cPredicates.mli index 45bd99d85..5823b59e1 100644 --- a/infer/src/clang/cPredicates.mli +++ b/infer/src/clang/cPredicates.mli @@ -487,6 +487,11 @@ val is_method_called_by_superclass : Ctl_parser_types.ast_node -> bool val is_cxx_copy_constructor : Ctl_parser_types.ast_node -> bool (** true if the current node is a C++ copy constructor *) +val has_cxx_full_name : Ctl_parser_types.ast_node -> ALVar.alexp -> bool +(** true iff node has C++ fully qualified name (w/class and namespace) + * matching the given regexp + *) + val is_cxx_method_overriding : Ctl_parser_types.ast_node -> ALVar.alexp option -> bool (** * True iff the current node is a CXXMethodDecl node and is overriding a diff --git a/infer/src/clang/cTL.ml b/infer/src/clang/cTL.ml index 4227683c1..857305838 100644 --- a/infer/src/clang/cTL.ml +++ b/infer/src/clang/cTL.ml @@ -973,6 +973,8 @@ let rec eval_Atomic pred_name_ args an lcxt = CPredicates.context_in_synchronized_block lcxt | "declaration_has_name", [decl_name], an -> CPredicates.declaration_has_name an decl_name + | "has_cxx_full_name", [qual_name_re], an -> + CPredicates.has_cxx_full_name an qual_name_re | "declaration_ref_name", [decl_name], an -> CPredicates.declaration_ref_name an decl_name | "decl_unavailable_in_supported_ios_sdk", [], an -> diff --git a/infer/src/clang/ctl_parser_types.ml b/infer/src/clang/ctl_parser_types.ml index 3f5dc3f31..dfe78614e 100644 --- a/infer/src/clang/ctl_parser_types.ml +++ b/infer/src/clang/ctl_parser_types.ml @@ -80,6 +80,29 @@ let rec ast_node_name an = "" +let rec ast_node_cxx_full_name an = + let full_name qual_name = "::" ^ String.concat ~sep:"::" (List.rev qual_name) in + let open Clang_ast_t in + match an with + | Decl dec -> ( + match Clang_ast_proj.get_named_decl_tuple dec with + | Some (_, n) -> + full_name n.Clang_ast_t.ni_qual_name + | None -> + "" ) + | Stmt (DeclRefExpr (_, _, _, {drti_decl_ref= Some dr})) -> + let ndi, _, _ = CAst_utils.get_info_from_decl_ref dr in + full_name ndi.ni_qual_name + | Stmt (OpaqueValueExpr (_, _, _, {ovei_source_expr= Some stmt})) + | Stmt (ImplicitCastExpr (_, [stmt], _, _)) + | Stmt (PseudoObjectExpr (_, stmt :: _, _)) + | Stmt (ParenExpr (_, [stmt], _)) + | Stmt (CallExpr (_, stmt :: _, _)) -> + ast_node_cxx_full_name (Stmt stmt) + | _ -> + "" + + let ast_node_kind node = match node with | Stmt stmt -> diff --git a/infer/src/clang/ctl_parser_types.mli b/infer/src/clang/ctl_parser_types.mli index fc03acf87..1a7a20a9e 100644 --- a/infer/src/clang/ctl_parser_types.mli +++ b/infer/src/clang/ctl_parser_types.mli @@ -15,6 +15,8 @@ val ast_node_equal : ast_node -> ast_node -> bool val ast_node_name : ast_node -> string +val ast_node_cxx_full_name : ast_node -> string + val ast_node_type : ast_node -> string val ast_node_kind : ast_node -> string diff --git a/infer/tests/codetoanalyze/cpp/linters-for-test-only/issues.exp b/infer/tests/codetoanalyze/cpp/linters-for-test-only/issues.exp index a6d7c141c..7b61a32d9 100644 --- a/infer/tests/codetoanalyze/cpp/linters-for-test-only/issues.exp +++ b/infer/tests/codetoanalyze/cpp/linters-for-test-only/issues.exp @@ -3,10 +3,16 @@ codetoanalyze/cpp/linters-for-test-only/test_constructor.cpp, g, 17, FIND_CXX_CO codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, B_bar, 16, FIND_CXX_METHOD_OVERRIDES, no_bucket, WARNING, [] codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, B_foo, 14, FIND_CXX_METHOD_OVERRIDES, no_bucket, WARNING, [] codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, Foo::Bar::SvIf_async_tm_poke, 36, FIND_CXX_METHOD_OVERRIDES, no_bucket, WARNING, [] +codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, Foo::Bar::SvIf_async_tm_poke, 36, FIND_NODES_WITH_CXX_FULL_NAME, no_bucket, WARNING, [] codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, Foo::Bar::SvIf_future_poke, 37, FIND_CXX_METHOD_OVERRIDES, no_bucket, WARNING, [] +codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, Foo::Bar::SvIf_future_poke, 37, FIND_NODES_WITH_CXX_FULL_NAME, no_bucket, WARNING, [] +codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, Foo::Bar::SvIf_poke, 35, FIND_NODES_WITH_CXX_FULL_NAME, no_bucket, WARNING, [] codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, Foo::Bar::SvIf_semifuture_poke, 38, FIND_CXX_METHOD_OVERRIDES, no_bucket, WARNING, [] +codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, Foo::Bar::SvIf_semifuture_poke, 38, FIND_NODES_WITH_CXX_FULL_NAME, no_bucket, WARNING, [] +codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, Foo::Bar::SvIf_~SvIf, 34, FIND_NODES_WITH_CXX_FULL_NAME, no_bucket, WARNING, [] codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, FooBarService_async_tm_poke, 50, FIND_CXX_METHOD_OVERRIDES, no_bucket, WARNING, [] codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, FooBarService_future_poke, 51, FIND_CXX_METHOD_OVERRIDES, no_bucket, WARNING, [] codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, FooBarService_future_poke, 51, FIND_CXX_METHOD_OVERRIDES_MATCHING, no_bucket, WARNING, [] codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, FooBarService_poke, 49, FIND_CXX_METHOD_OVERRIDES, no_bucket, WARNING, [] codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, FooBarService_semifuture_poke, 52, FIND_CXX_METHOD_OVERRIDES, no_bucket, WARNING, [] +codetoanalyze/cpp/linters-for-test-only/test_overrides.cpp, Linters_dummy_method, 32, FIND_NODES_WITH_CXX_FULL_NAME, no_bucket, WARNING, [] diff --git a/infer/tests/codetoanalyze/cpp/linters-for-test-only/linters_example.al b/infer/tests/codetoanalyze/cpp/linters-for-test-only/linters_example.al index 9b0ade99a..57ecb1af7 100644 --- a/infer/tests/codetoanalyze/cpp/linters-for-test-only/linters_example.al +++ b/infer/tests/codetoanalyze/cpp/linters-for-test-only/linters_example.al @@ -37,3 +37,8 @@ DEFINE-CHECKER FIND_CXX_METHOD_OVERRIDES_MATCHING = { HOLDS-IN-NODE CXXMethodDecl; SET message = "%decl_name% overriding matching method"; }; + +DEFINE-CHECKER FIND_NODES_WITH_CXX_FULL_NAME = { + SET report_when = has_cxx_full_name(REGEXP("::Foo::Bar::")); + SET message = "%cxx_full_name% matches"; +};