From 5aedc7e71cf324698abf037f5169f493efdf7dbe Mon Sep 17 00:00:00 2001 From: David Lively Date: Tue, 12 Mar 2019 06:11:33 -0700 Subject: [PATCH] [AL] expose source loc of decl referenced by decl_ref Reviewed By: ddino Differential Revision: D14404449 fbshipit-source-id: e546600bd --- infer/src/clang/cFrontend_errors.ml | 11 ++- infer/src/clang/cPredicates.ml | 14 +++- infer/src/clang/cPredicates.mli | 5 ++ infer/src/clang/cTL.ml | 2 + infer/src/clang/ctl_parser_types.ml | 70 +++++++++++-------- infer/src/clang/ctl_parser_types.mli | 4 +- .../cpp/linters-for-test-only/issues.exp | 1 + .../linters-for-test-only/linters_example.al | 5 ++ .../linters-for-test-only/test_includer.cpp | 2 +- 9 files changed, 80 insertions(+), 34 deletions(-) diff --git a/infer/src/clang/cFrontend_errors.ml b/infer/src/clang/cFrontend_errors.ml index 228249302..bfb841151 100644 --- a/infer/src/clang/cFrontend_errors.ml +++ b/infer/src/clang/cFrontend_errors.ml @@ -136,7 +136,16 @@ let evaluate_place_holder context ph an = * necessarily the same as the translation unit's source file. *) MF.monospaced_to_string - (SourceFile.to_rel_path (SourceFile.create (Ctl_parser_types.get_source_file an))) + (Option.value_map + ~f:(fun sf -> SourceFile.to_rel_path (SourceFile.create sf)) + ~default:"" + (Ctl_parser_types.get_source_file an)) + | "%ref_source_file%" -> + MF.monospaced_to_string + (Option.value_map + ~f:(fun sf -> SourceFile.to_rel_path (SourceFile.create sf)) + ~default:"" + (Ctl_parser_types.get_referenced_decl_source_file 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 0e44b981a..5f6cb8151 100644 --- a/infer/src/clang/cPredicates.ml +++ b/infer/src/clang/cPredicates.ml @@ -1468,6 +1468,16 @@ let is_init_expr_cxx11_constant an = false +let source_file_matches src_file path_re = + Option.value_map + ~f:(fun sf -> + ALVar.compare_str_with_alexp (SourceFile.to_rel_path (SourceFile.create sf)) path_re ) + ~default:false src_file + + let is_in_source_file an path_re = - let src_file = Ctl_parser_types.get_source_file an in - ALVar.compare_str_with_alexp (SourceFile.to_rel_path (SourceFile.create src_file)) path_re + source_file_matches (Ctl_parser_types.get_source_file an) path_re + + +let is_referencing_decl_from_source_file an path_re = + source_file_matches (Ctl_parser_types.get_referenced_decl_source_file an) path_re diff --git a/infer/src/clang/cPredicates.mli b/infer/src/clang/cPredicates.mli index fa971dd3a..c5b64a991 100644 --- a/infer/src/clang/cPredicates.mli +++ b/infer/src/clang/cPredicates.mli @@ -502,6 +502,11 @@ val is_in_source_file : Ctl_parser_types.ast_node -> ALVar.alexp -> bool * True iff the source file path of the given node matches the given regexp or string. *) +val is_referencing_decl_from_source_file : Ctl_parser_types.ast_node -> ALVar.alexp -> bool +(** + * True iff the given node is a DeclRefExpr referencing a decl whose source file path matches the given regexp or string. + *) + 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 1fc0c0b89..ec9335727 100644 --- a/infer/src/clang/cTL.ml +++ b/infer/src/clang/cTL.ml @@ -1171,6 +1171,8 @@ let rec eval_Atomic pred_name_ args an lcxt = CPredicates.cxx_construct_expr_has_no_parameters an | "is_in_source_file", [path_re], an -> CPredicates.is_in_source_file an path_re + | "is_referencing_decl_from_source_file", [path_re], an -> + CPredicates.is_referencing_decl_from_source_file an path_re | _ -> L.(die ExternalError) "Undefined Predicate or wrong set of arguments: '%s'" pred_name diff --git a/infer/src/clang/ctl_parser_types.ml b/infer/src/clang/ctl_parser_types.ml index 8c91501f0..74b94e29c 100644 --- a/infer/src/clang/ctl_parser_types.ml +++ b/infer/src/clang/ctl_parser_types.ml @@ -84,12 +84,11 @@ let decl_cxx_fully_qualified_name (decl : Clang_ast_t.decl) = match Clang_ast_proj.get_var_decl_tuple decl with | Some (_, ndi, _, {vdi_is_global= false}) -> ndi.ni_name - | _ -> ( - match Clang_ast_proj.get_named_decl_tuple decl with - | Some (_, ndi) -> - "::" ^ String.concat ~sep:"::" (List.rev ndi.ni_qual_name) - | None -> - "" ) + | _ -> + Option.value_map + ~f:(fun (_, ndi) -> "::" ^ String.concat ~sep:"::" (List.rev ndi.Clang_ast_t.ni_qual_name)) + ~default:"" + (Clang_ast_proj.get_named_decl_tuple decl) let ast_node_cxx_fully_qualified_name an = @@ -97,22 +96,16 @@ let ast_node_cxx_fully_qualified_name an = match an with | Decl decl -> decl_cxx_fully_qualified_name decl - | Stmt (DeclRefExpr (_, _, _, {drti_decl_ref= Some dr})) -> ( - match CAst_utils.get_decl dr.dr_decl_pointer with - | Some decl -> - decl_cxx_fully_qualified_name decl - | None -> - "" ) - | Stmt stmt -> ( - match Clang_ast_proj.get_cxx_construct_expr_tuple stmt with - | Some (_, _, _, xcei) -> ( - match CAst_utils.get_decl xcei.xcei_decl_ref.dr_decl_pointer with - | Some decl -> - decl_cxx_fully_qualified_name decl - | None -> - "" ) - | None -> - "" ) + | Stmt (DeclRefExpr (_, _, _, {drti_decl_ref= Some dr})) -> + Option.value_map ~f:decl_cxx_fully_qualified_name ~default:"" + (CAst_utils.get_decl dr.dr_decl_pointer) + | Stmt stmt -> + Option.value_map + ~f:(fun (_, _, _, xcei) -> + Option.value_map ~f:decl_cxx_fully_qualified_name ~default:"" + (CAst_utils.get_decl xcei.xcei_decl_ref.dr_decl_pointer) ) + ~default:"" + (Clang_ast_proj.get_cxx_construct_expr_tuple stmt) let ast_node_kind node = @@ -622,11 +615,30 @@ let get_source_range an = decl_info.di_source_range -let get_source_file an = - match get_source_range an with - | {sl_file= Some sf}, _ -> - sf - | _, {sl_file= Some sf} -> - sf +let get_source_file_of_range (range : Clang_ast_t.source_range) = + match range with {sl_file= Some sf}, _ | _, {sl_file= Some sf} -> Some sf | _ -> None + + +let get_source_file an = get_source_file_of_range (get_source_range an) + +let get_decl_source_file an = + let di = Clang_ast_proj.get_decl_tuple an in + Option.value_map ~f:(fun x -> Some x) ~default:None (get_source_file_of_range di.di_source_range) + + +let get_decl_ref_source_file (dr : Clang_ast_t.decl_ref) = + Option.value_map ~f:get_decl_source_file ~default:None (CAst_utils.get_decl dr.dr_decl_pointer) + + +let get_referenced_decl_source_file an = + let open Clang_ast_t in + match an with + | Stmt (DeclRefExpr (_, _, _, {drti_decl_ref= Some dr})) -> + get_decl_ref_source_file dr + | Stmt stmt -> + Option.value_map + ~f:(fun (_, _, _, xcei) -> get_decl_ref_source_file xcei.xcei_decl_ref) + ~default:None + (Clang_ast_proj.get_cxx_construct_expr_tuple stmt) | _ -> - assert false + None diff --git a/infer/src/clang/ctl_parser_types.mli b/infer/src/clang/ctl_parser_types.mli index 51318a351..7a77db619 100644 --- a/infer/src/clang/ctl_parser_types.mli +++ b/infer/src/clang/ctl_parser_types.mli @@ -84,4 +84,6 @@ val c_type_equal : Clang_ast_t.c_type -> abs_ctype -> bool val abs_ctype_to_string : abs_ctype -> string -val get_source_file : ast_node -> Clang_ast_t.source_file +val get_source_file : ast_node -> Clang_ast_t.source_file option + +val get_referenced_decl_source_file : ast_node -> Clang_ast_t.source_file option 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 9682c1adf..9b3d4ad4b 100644 --- a/infer/tests/codetoanalyze/cpp/linters-for-test-only/issues.exp +++ b/infer/tests/codetoanalyze/cpp/linters-for-test-only/issues.exp @@ -11,6 +11,7 @@ codetoanalyze/cpp/linters-for-test-only/test_fully_qualified_names.cpp, Linters_ codetoanalyze/cpp/linters-for-test-only/test_fully_qualified_names.cpp, Linters_dummy_method, 28, FIND_NODES_WITH_CXX_FULL_NAME, no_bucket, WARNING, [] codetoanalyze/cpp/linters-for-test-only/test_fully_qualified_names.cpp, Linters_dummy_method, 39, FIND_NODES_WITH_CXX_FULL_NAME, no_bucket, WARNING, [] codetoanalyze/cpp/linters-for-test-only/test_included.h, Bazoo_fibble, 11, FIND_CXX_METHODS_FROM_HEADER_FILE, no_bucket, WARNING, [] +codetoanalyze/cpp/linters-for-test-only/test_includer.cpp, Bazowey_frazzle, 11, FIND_REF_FROM_SRC_FILE, no_bucket, WARNING, [] 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, [] 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 95d632e2c..e76bcc7eb 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 @@ -53,3 +53,8 @@ DEFINE-CHECKER FIND_LISTED_SYMBOLS = { SET report_when = NOT is_decl() AND has_cxx_fully_qualified_name_in_custom_symbols("test"); SET message = "found usage of %cxx_fully_qualified_name%"; }; + +DEFINE-CHECKER FIND_REF_FROM_SRC_FILE = { + SET report_when = is_referencing_decl_from_source_file(REGEXP("/test_included.h$")); + SET message = "found ref from %ref_source_file%"; +}; diff --git a/infer/tests/codetoanalyze/cpp/linters-for-test-only/test_includer.cpp b/infer/tests/codetoanalyze/cpp/linters-for-test-only/test_includer.cpp index c28c8e12b..804bd868a 100644 --- a/infer/tests/codetoanalyze/cpp/linters-for-test-only/test_includer.cpp +++ b/infer/tests/codetoanalyze/cpp/linters-for-test-only/test_includer.cpp @@ -8,5 +8,5 @@ #include "test_included.h" struct Bazowey { - void frazzle(); + void frazzle() { Bazoo().fibble(); } };