From d4337abcb47506d9e1a6da1f71827a17eed8445d Mon Sep 17 00:00:00 2001 From: Dino Distefano Date: Tue, 1 May 2018 09:51:50 -0700 Subject: [PATCH] Added predicate for C++ copy constructors Reviewed By: dulmarod Differential Revision: D7829738 fbshipit-source-id: 73be42f --- Makefile | 2 +- facebook-clang-plugins | 2 +- infer/src/clang/cPredicates.ml | 9 ++++++++ infer/src/clang/cPredicates.mli | 3 +++ infer/src/clang/cTL.ml | 2 ++ .../cpp/linters-for-test-only/Makefile | 18 ++++++++++++++++ .../cpp/linters-for-test-only/issues.exp | 1 + .../linters-for-test-only/linters_example.al | 13 ++++++++++++ .../test_constructor.cpp | 21 +++++++++++++++++++ 9 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 infer/tests/codetoanalyze/cpp/linters-for-test-only/Makefile create mode 100644 infer/tests/codetoanalyze/cpp/linters-for-test-only/issues.exp create mode 100644 infer/tests/codetoanalyze/cpp/linters-for-test-only/linters_example.al create mode 100644 infer/tests/codetoanalyze/cpp/linters-for-test-only/test_constructor.cpp diff --git a/Makefile b/Makefile index 0531e9a6d..f1919be37 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,7 @@ BUILD_SYSTEMS_TESTS += \ DIRECT_TESTS += \ c_biabduction c_bufferoverrun c_errors c_frontend c_performance \ cpp_bufferoverrun cpp_errors cpp_frontend cpp_liveness cpp_ownership cpp_quandary \ - cpp_racerd cpp_siof cpp_uninit cpp_nullable cpp_conflicts \ + cpp_racerd cpp_siof cpp_uninit cpp_nullable cpp_conflicts cpp_linters-for-test-only \ ifneq ($(BUCK),no) BUILD_SYSTEMS_TESTS += buck-clang-db buck_flavors buck_flavors_run buck_flavors_deterministic diff --git a/facebook-clang-plugins b/facebook-clang-plugins index b639c067d..c29650957 160000 --- a/facebook-clang-plugins +++ b/facebook-clang-plugins @@ -1 +1 @@ -Subproject commit b639c067dbad75be0f0fb92bc8d1bd0732d453de +Subproject commit c29650957f6fcb8c82aa5da2c7b9971ede8677ac diff --git a/infer/src/clang/cPredicates.ml b/infer/src/clang/cPredicates.ml index 5947aa4ae..af9ca847b 100644 --- a/infer/src/clang/cPredicates.ml +++ b/infer/src/clang/cPredicates.ml @@ -930,3 +930,12 @@ let is_method_called_by_superclass an = match obj_c_message_expr_info.omei_receiver_kind with `SuperInstance -> true | _ -> false ) | _ -> false + + +let is_cxx_copy_constructor an = + let open Clang_ast_t in + match an with + | Ctl_parser_types.Stmt (CXXConstructExpr (_, _, _, xcei)) -> + xcei.xcei_is_copy_constructor + | _ -> + false diff --git a/infer/src/clang/cPredicates.mli b/infer/src/clang/cPredicates.mli index 77ea65f06..37af73307 100644 --- a/infer/src/clang/cPredicates.mli +++ b/infer/src/clang/cPredicates.mli @@ -181,3 +181,6 @@ val is_decl : Ctl_parser_types.ast_node -> bool val get_ast_node_type_ptr : Ctl_parser_types.ast_node -> Clang_ast_t.type_ptr option 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 *) diff --git a/infer/src/clang/cTL.ml b/infer/src/clang/cTL.ml index 13c82f458..10494946b 100644 --- a/infer/src/clang/cTL.ml +++ b/infer/src/clang/cTL.ml @@ -1068,6 +1068,8 @@ let rec eval_Atomic pred_name_ args an lcxt = CPredicates.within_available_class_block lcxt an | "is_method_called_by_superclass", [], an -> CPredicates.is_method_called_by_superclass an + | "is_cxx_copy_constructor", [], an -> + CPredicates.is_cxx_copy_constructor an | _ -> L.(die ExternalError) "Undefined Predicate or wrong set of arguments: '%s'" pred_name diff --git a/infer/tests/codetoanalyze/cpp/linters-for-test-only/Makefile b/infer/tests/codetoanalyze/cpp/linters-for-test-only/Makefile new file mode 100644 index 000000000..113eabb16 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/linters-for-test-only/Makefile @@ -0,0 +1,18 @@ +# Copyright (c) 2016 - present Facebook, Inc. +# All rights reserved. +# +# This source code is licensed under the BSD style license found in the +# LICENSE file in the root directory of this source tree. An additional grant +# of patent rights can be found in the PATENTS file in the same directory. + +TESTS_DIR = ../../.. + +ANALYZER = linters +CLANG_OPTIONS = -std=c++11 -c +INFER_OPTIONS = --cxx --linters-def-file linters_example.al --project-root $(TESTS_DIR) +INFERPRINT_OPTIONS = --issues-tests + +SOURCES = \ + $(wildcard *.cpp) + +include $(TESTS_DIR)/clang.make diff --git a/infer/tests/codetoanalyze/cpp/linters-for-test-only/issues.exp b/infer/tests/codetoanalyze/cpp/linters-for-test-only/issues.exp new file mode 100644 index 000000000..aca44f83b --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/linters-for-test-only/issues.exp @@ -0,0 +1 @@ +codetoanalyze/cpp/linters-for-test-only/test_constructor.cpp, g, 19, FIND_CXX_COPY_CONSTRUCTOR, 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 new file mode 100644 index 000000000..a4d7a3c88 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/linters-for-test-only/linters_example.al @@ -0,0 +1,13 @@ +DEFINE-CHECKER FIND_CXX_COPY_CONSTRUCTOR = { + +LET is_copy_constructor = + is_node("CXXConstructExpr") AND is_cxx_copy_constructor(); + +SET report_when = + IN-NODE VarDecl WITH-TRANSITION InitExpr + (is_copy_constructor HOLDS-EVENTUALLY ) + HOLDS-EVENTUALLY; + +SET message = "Found Copy Constructor"; + +}; diff --git a/infer/tests/codetoanalyze/cpp/linters-for-test-only/test_constructor.cpp b/infer/tests/codetoanalyze/cpp/linters-for-test-only/test_constructor.cpp new file mode 100644 index 000000000..23d195b7a --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/linters-for-test-only/test_constructor.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018 - present Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ +struct A { + int a, b, c, d; +}; + +const A& f() { + static A a; + return a; +} + +int g() { + auto x = f(); + return x.a + x.b; +}