From 3c04f3270924f08befa6791f844e46967c15fbe0 Mon Sep 17 00:00:00 2001 From: Dino Distefano Date: Thu, 20 Sep 2018 05:50:45 -0700 Subject: [PATCH] hadoc const version Reviewed By: jvillard Differential Revision: D9850969 fbshipit-source-id: 25102d5bb --- Makefile | 2 +- infer/src/clang/cPredicates.ml | 38 +++++++++++++++++- infer/src/clang/cPredicates.mli | 7 +++- infer/src/clang/cTL.ml | 6 ++- .../codetoanalyze/cpp/linters/cxxconst.cpp | 40 +++++++++++++++++++ .../codetoanalyze/cpp/linters/extracopy.al | 11 ++--- .../codetoanalyze/cpp/linters/issues.exp | 21 +++------- 7 files changed, 99 insertions(+), 26 deletions(-) create mode 100644 infer/tests/codetoanalyze/cpp/linters/cxxconst.cpp diff --git a/Makefile b/Makefile index 1f3dabcfb..adf28c360 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ ifeq ($(HAS_OBJC),yes) BUILD_SYSTEMS_TESTS += objc_getters_setters objc_missing_fld objc_retain_cycles objc_retain_cycles_weak DIRECT_TESTS += \ objc_frontend objc_errors objc_linters objc_ioslints objcpp_errors objcpp_nullable \ - objcpp_frontend objcpp_linters objc_linters-for-test-only objcpp_linters-for-test-only \ + objcpp_frontend objcpp_linters cpp_linters objc_linters-for-test-only objcpp_linters-for-test-only \ objc_linters-def-folder objc_nullable objc_liveness objcpp_liveness objc_uninit ifneq ($(XCODE_SELECT),no) BUILD_SYSTEMS_TESTS += xcodebuild_no_xcpretty diff --git a/infer/src/clang/cPredicates.ml b/infer/src/clang/cPredicates.ml index 3de6ee5e1..abae8b867 100644 --- a/infer/src/clang/cPredicates.ml +++ b/infer/src/clang/cPredicates.ml @@ -507,7 +507,7 @@ let is_const_expr_var an = match an with Ctl_parser_types.Decl d -> CAst_utils.is_const_expr_var d | _ -> false -let is_const an = +let is_qual_type_const an = match an with | Ctl_parser_types.Stmt s -> ( match Clang_ast_proj.get_expr_tuple s with @@ -519,6 +519,42 @@ let is_const an = false +let has_init_list_const_expr an = + let rec fold lexp = List.fold ~f:(fun acc e -> is_const_expr' e && acc) ~init:true lexp + and is_const_expr' exp = + let open Clang_ast_t in + let res = + match exp with + | IntegerLiteral _ | StringLiteral _ -> + true + | DeclRefExpr (_, _, _, drei) -> ( + match drei.drti_decl_ref with + | Some dr -> ( + match dr.dr_kind with `EnumConstant -> true | _ -> false ) + | _ -> + false ) + | CallExpr (_, _ :: params, _) -> + fold params + | _ -> ( + match Clang_ast_proj.get_expr_tuple exp with + | Some (_, sub_exps, _) -> + fold sub_exps + | _ -> + false ) + in + L.(debug Analysis Verbose) + "@\n\n[has_init_list_const_expr] EVALUATE EXP '%a' result = '%b'@\n" + (Pp.to_string ~f:Clang_ast_proj.get_stmt_kind_string) + exp res ; + res + in + match an with + | Ctl_parser_types.Stmt (Clang_ast_t.InitListExpr (_, sub_exps, _)) -> + fold sub_exps + | _ -> + false + + let decl_ref_name ?kind name st = match st with | Clang_ast_t.DeclRefExpr (_, _, _, drti) -> ( diff --git a/infer/src/clang/cPredicates.mli b/infer/src/clang/cPredicates.mli index cbdae78fb..a1b6c0ca1 100644 --- a/infer/src/clang/cPredicates.mli +++ b/infer/src/clang/cPredicates.mli @@ -42,8 +42,11 @@ val is_static_local_var : Ctl_parser_types.ast_node -> bool val is_const_expr_var : Ctl_parser_types.ast_node -> bool (** 'is_const_expr_var an' is true iff an is a 'const' variable declaration *) -val is_const : Ctl_parser_types.ast_node -> bool -(** 'is_const an' is true iff an is a 'const' expression *) +val is_qual_type_const : Ctl_parser_types.ast_node -> bool +(** 'is_qual_type_const an' is true iff an is a qual_type 'const' expression *) + +val has_init_list_const_expr : Ctl_parser_types.ast_node -> bool +(** 'has_init_list_const_expr' is true iff for an InitListExpr where all subexpressions are const expression *) 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' *) diff --git a/infer/src/clang/cTL.ml b/infer/src/clang/cTL.ml index c388c100a..8eca1a94d 100644 --- a/infer/src/clang/cTL.ml +++ b/infer/src/clang/cTL.ml @@ -998,8 +998,10 @@ let rec eval_Atomic pred_name_ args an lcxt = CPredicates.is_class an cname | "is_const_var", [], an -> CPredicates.is_const_expr_var an - | "is_const", [], an -> - CPredicates.is_const an + | "is_qual_type_const", [], an -> + CPredicates.is_qual_type_const an + | "has_init_list_const_expr", [], an -> + CPredicates.has_init_list_const_expr an | "is_decl", [], an -> CPredicates.is_decl an | "is_enum_constant", [cname], an -> diff --git a/infer/tests/codetoanalyze/cpp/linters/cxxconst.cpp b/infer/tests/codetoanalyze/cpp/linters/cxxconst.cpp new file mode 100644 index 000000000..8b5ac6b0e --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/linters/cxxconst.cpp @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018-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. + */ +#include +#include +#include + +using namespace std; + +enum VALUE { + VALUE1, + VALUE2, +}; + +vector global_v = {1, 2, 3}; + +struct A { + int a; + int b; +}; + +int f(int x) { return x + 1; } + +int test(int x) { + A a{1, 2}; + pair p = {3, 4}; + vector v1; + vector v2{1}; // const + static vector v3 = {1, 2}; + vector v4 = {VALUE1, VALUE2}; // const + vector v5 = {f(1), f(2), 3}; // const + vector v6 = {f(x), 2, 3}; + + map m1{{"a", 1}, {"b", 2}}; + + return a.a + p.first; +} diff --git a/infer/tests/codetoanalyze/cpp/linters/extracopy.al b/infer/tests/codetoanalyze/cpp/linters/extracopy.al index 9f53663a7..b015e576b 100644 --- a/infer/tests/codetoanalyze/cpp/linters/extracopy.al +++ b/infer/tests/codetoanalyze/cpp/linters/extracopy.al @@ -48,19 +48,20 @@ DEFINE-CHECKER ITERATOR = { }; -DEFINE-CHECKER CXX11_CONSTANT_EXPR = { +DEFINE-CHECKER CONSTANT_EXPR = { - LET eventually_const_sub_expr = HOLDS-NEXT WITH-TRANSITION InitExpr - (is_const HOLDS-EVENTUALLY); + LET eventually_const_sub_expr = + HOLDS-NEXT WITH-TRANSITION InitExpr + (has_init_list_const_expr HOLDS-EVENTUALLY); - LET not_static_and_not_global = NOT (is_global_var OR is_static_local_var); + LET not_static_and_not_global = NOT (is_global_var OR is_static_local_var); SET report_when = WHEN not_static_and_not_global AND (is_init_expr_cxx11_constant() OR eventually_const_sub_expr) HOLDS-IN-NODE VarDecl; - SET message = "Found cxx11 constant expression"; + SET message = "Found constant expression"; SET mode = "ON"; }; diff --git a/infer/tests/codetoanalyze/cpp/linters/issues.exp b/infer/tests/codetoanalyze/cpp/linters/issues.exp index b4429e64e..4c07cc210 100644 --- a/infer/tests/codetoanalyze/cpp/linters/issues.exp +++ b/infer/tests/codetoanalyze/cpp/linters/issues.exp @@ -1,21 +1,12 @@ -codetoanalyze/cpp/linters/cxxconst.cpp, test, 24, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/cxxconst.cpp, test, 27, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/cxxconst.cpp, test, 29, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/cxxconst.cpp, test, 30, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/cxxconst.cpp, test, 31, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/cxxconst.cpp, test, 33, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/extracopy.cpp, test_a, 27, CXX11_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, 33, CONSTANT_EXPR, no_bucket, WARNING, [] +codetoanalyze/cpp/linters/cxxconst.cpp, test, 34, CONSTANT_EXPR, no_bucket, WARNING, [] +codetoanalyze/cpp/linters/cxxconst.cpp, test, 37, CONSTANT_EXPR, no_bucket, WARNING, [] codetoanalyze/cpp/linters/extracopy.cpp, test_a, 27, EXTRA_COPY, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/extracopy.cpp, test_a, 28, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/extracopy.cpp, test_const_exp, 53, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/extracopy.cpp, test_map, 36, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/extracopy.cpp, test_map, 37, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] +codetoanalyze/cpp/linters/extracopy.cpp, test_map, 36, CONSTANT_EXPR, no_bucket, WARNING, [] codetoanalyze/cpp/linters/extracopy.cpp, test_map, 37, EXTRA_COPY, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/extracopy.cpp, test_map, 40, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/extracopy.cpp, test_map, 43, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] codetoanalyze/cpp/linters/iter.cpp, test, 11, ITERATOR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/iter.cpp, test, 12, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] codetoanalyze/cpp/linters/iter.cpp, test, 12, EXTRA_COPY, no_bucket, WARNING, [] codetoanalyze/cpp/linters/iter.cpp, test, 12, ITERATOR, no_bucket, WARNING, [] -codetoanalyze/cpp/linters/type_namespace.cpp, test, 11, CXX11_CONSTANT_EXPR, no_bucket, WARNING, [] codetoanalyze/cpp/linters/type_namespace.cpp, test, 11, NAMESPACE_STRING, no_bucket, WARNING, []