diff --git a/infer/src/clang/ComponentKit.ml b/infer/src/clang/ComponentKit.ml index 192961968..7ceabd169 100644 --- a/infer/src/clang/ComponentKit.ml +++ b/infer/src/clang/ComponentKit.ml @@ -86,7 +86,7 @@ let mutable_local_vars_advice context decl = | _ -> false in match decl with - | Clang_ast_t.VarDecl(decl_info, _, qual_type, _) -> + | Clang_ast_t.VarDecl(decl_info, named_decl_info, qual_type, _) -> let is_const_ref = match Ast_utils.get_type qual_type.qt_type_ptr with | Some LValueReferenceType (_, {Clang_ast_t.qt_is_const}) -> qt_is_const @@ -95,11 +95,13 @@ let mutable_local_vars_advice context decl = let condition = is_ck_context context decl && (not (Ast_utils.is_syntactically_global_var decl)) && (not is_const) - && not (is_of_whitelisted_type qual_type) in + && not (is_of_whitelisted_type qual_type) + && not decl_info.di_is_implicit in if condition then Some { CIssue.issue = CIssue.Mutable_local_variable_in_component_file; - CIssue.description = "Local variables should be const to avoid reassignment"; + CIssue.description = "Local variable '" ^ named_decl_info.ni_name + ^ "' should be const to avoid reassignment"; CIssue.suggestion = Some "Add a const (after the asterisk for pointer types)."; CIssue.loc = CFrontend_checkers.location_from_dinfo context decl_info } diff --git a/infer/tests/codetoanalyze/objcpp/linters/componentkit/MutableLocalVariablesTest.mm b/infer/tests/codetoanalyze/objcpp/linters/componentkit/MutableLocalVariablesTest.mm index a4e4b031b..4bfc083db 100644 --- a/infer/tests/codetoanalyze/objcpp/linters/componentkit/MutableLocalVariablesTest.mm +++ b/infer/tests/codetoanalyze/objcpp/linters/componentkit/MutableLocalVariablesTest.mm @@ -9,6 +9,9 @@ #import +#include +#include + #import "FakeComponentKitHeader.h" @interface CKLabelComponent : CKCompositeComponent @@ -37,6 +40,7 @@ NSString* foo = @"HI"; // error _foo = foo; } + return nil; } @end @@ -100,5 +104,25 @@ class BarClass { NSError const* __autoreleasing* e2; // no error NSError* const* e3 = &e; // no error NSError* const* const e4 = &e; // no error + + // implicit vars (e.g. ones generated in a for loop statement) + const std::vector const_vector_of_const_int = {1, 2, 3}; + for (int i : const_vector_of_const_int) { // error + printf("%d", i); + } + for (const int i : const_vector_of_const_int) { + printf("%d", i); + } + for (auto i : const_vector_of_const_int) { // auto != const int; error + printf("%d", i); + } + for (const auto i : const_vector_of_const_int) { + printf("%d", i); + } + for (auto& i : const_vector_of_const_int) { // auto == const int; no error + printf("%d", i); + } + + return nil; } @end diff --git a/infer/tests/codetoanalyze/objcpp/linters/issues.exp b/infer/tests/codetoanalyze/objcpp/linters/issues.exp index b6e90f22a..d440fa9ce 100644 --- a/infer/tests/codetoanalyze/objcpp/linters/issues.exp +++ b/infer/tests/codetoanalyze/objcpp/linters/issues.exp @@ -8,14 +8,16 @@ componentkit/InitializerWithSideEffectTest.mm, __objc_anonymous_block_______1, 3 componentkit/InitializerWithSideEffectTest.mm, __objc_anonymous_block_______2, 41, COMPONENT_INITIALIZER_WITH_SIDE_EFFECTS componentkit/MultipleFactoryMethodsTest.h, Linters_dummy_method, 18, COMPONENT_WITH_MULTIPLE_FACTORY_METHODS componentkit/MultipleFactoryMethodsTest.h, Linters_dummy_method, 27, COMPONENT_WITH_MULTIPLE_FACTORY_METHODS -componentkit/MutableLocalVariablesTest.mm, BarComponent_new, 85, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE -componentkit/MutableLocalVariablesTest.mm, BarComponent_new, 87, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE -componentkit/MutableLocalVariablesTest.mm, FooComponent_newWithString:, 48, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE -componentkit/MutableLocalVariablesTest.mm, FooComponent_newWithString:, 53, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE -componentkit/MutableLocalVariablesTest.mm, FooComponent_newWithString:, 55, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE +componentkit/MutableLocalVariablesTest.mm, BarComponent_new, 89, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE +componentkit/MutableLocalVariablesTest.mm, BarComponent_new, 91, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE +componentkit/MutableLocalVariablesTest.mm, BarComponent_new, 110, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE +componentkit/MutableLocalVariablesTest.mm, BarComponent_new, 116, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE +componentkit/MutableLocalVariablesTest.mm, FooComponent_newWithString:, 52, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE +componentkit/MutableLocalVariablesTest.mm, FooComponent_newWithString:, 57, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE componentkit/MutableLocalVariablesTest.mm, FooComponent_newWithString:, 59, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE -componentkit/MutableLocalVariablesTest.mm, FooComponent_newWithString:, 64, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE -componentkit/MutableLocalVariablesTest.mm, SomeClass_init, 37, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE +componentkit/MutableLocalVariablesTest.mm, FooComponent_newWithString:, 63, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE +componentkit/MutableLocalVariablesTest.mm, FooComponent_newWithString:, 68, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE +componentkit/MutableLocalVariablesTest.mm, SomeClass_init, 40, MUTABLE_LOCAL_VARIABLE_IN_COMPONENT_FILE componentkit/UnconventionalSuperclassTest.h, Linters_dummy_method, 17, COMPONENT_WITH_UNCONVENTIONAL_SUPERCLASS cxx_reference_in_block/block.mm, A_foo3:param2:, 37, CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK cxx_reference_in_block/block.mm, A_foo:, 20, CXX_REFERENCE_CAPTURED_IN_OBJC_BLOCK