From 7a434adea83a4dbd74a8a832b4bfd4eac6aa4f6d Mon Sep 17 00:00:00 2001 From: Ryan Rhee Date: Mon, 26 Sep 2016 08:39:35 -0700 Subject: [PATCH] [componentkit][const] Whitelist certain classes Reviewed By: martinoluca Differential Revision: D3911399 fbshipit-source-id: c523779 --- infer/src/clang/ComponentKit.ml | 17 ++++++++++++++++- .../componentkit/FakeComponentKitHeader.h | 15 +++++++++++++++ .../objcpp/linters/componentkit/Test.mm | 7 +++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/infer/src/clang/ComponentKit.ml b/infer/src/clang/ComponentKit.ml index 05ac2d16e..42c96b10f 100644 --- a/infer/src/clang/ComponentKit.ml +++ b/infer/src/clang/ComponentKit.ml @@ -74,6 +74,20 @@ and contains_ck_impl decl_list = const NSString *y; ``` *) let mutable_local_vars_advice context decl = + let rec get_referenced_type (qual_type: Clang_ast_t.qual_type) : Clang_ast_t.decl option = + let typ_opt = Ast_utils.get_desugared_type qual_type.qt_type_ptr in + match (typ_opt : Clang_ast_t.c_type option) with + | Some RecordType (_, decl_ptr) -> Ast_utils.get_decl decl_ptr + | Some LValueReferenceType (_, inner_qual_type) -> get_referenced_type inner_qual_type + | _ -> None in + + let is_of_whitelisted_type qual_type = + let whitelist = ["CKComponentScope"; "FBTrackingNodeScope"; "FBTrackingCodeScope"] in + match get_referenced_type qual_type with + | Some CXXRecordDecl (_, ndi, _, _, _, _, _, _) -> + IList.mem string_equal ndi.ni_name whitelist + | _ -> false in + match decl with | Clang_ast_t.VarDecl(decl_info, _, qual_type, _) -> let is_const_ref = match Ast_utils.get_type qual_type.qt_type_ptr with @@ -85,7 +99,8 @@ let mutable_local_vars_advice context decl = && Ast_utils.is_in_main_file decl && General_utils.is_objc_extension && (not (Ast_utils.is_syntactically_global_var decl)) - && (not is_const) in + && (not is_const) + && not (is_of_whitelisted_type qual_type) in if condition then Some { CIssue.issue = CIssue.Mutable_local_variable_in_component_file; diff --git a/infer/tests/codetoanalyze/objcpp/linters/componentkit/FakeComponentKitHeader.h b/infer/tests/codetoanalyze/objcpp/linters/componentkit/FakeComponentKitHeader.h index e43200079..9785cd334 100644 --- a/infer/tests/codetoanalyze/objcpp/linters/componentkit/FakeComponentKitHeader.h +++ b/infer/tests/codetoanalyze/objcpp/linters/componentkit/FakeComponentKitHeader.h @@ -24,3 +24,18 @@ typedef struct { NSString* string; } LabelAttributes; typedef struct { int thisStructIsEmpty; } ViewAttributes; typedef struct { int thisStructIsEmpty; } CKSize; + +// Mimic importing CKComponentScope + +class CKComponentScope { + public: + CKComponentScope(Class __unsafe_unretained componentClass, + id identifier = nil, + id (^initialStateCreator)(void) = nil); + ~CKComponentScope(); + int a; + + private: + CKComponentScope(const CKComponentScope&) = delete; + CKComponentScope& operator=(const CKComponentScope&) = delete; +}; diff --git a/infer/tests/codetoanalyze/objcpp/linters/componentkit/Test.mm b/infer/tests/codetoanalyze/objcpp/linters/componentkit/Test.mm index b6d021afe..98d602e03 100644 --- a/infer/tests/codetoanalyze/objcpp/linters/componentkit/Test.mm +++ b/infer/tests/codetoanalyze/objcpp/linters/componentkit/Test.mm @@ -86,5 +86,12 @@ class BarClass { const BarClass& s2 = s1; // no error BarClass& s3 = s1; // error const BarClass s4 = {.a = 3}; // no error + + // Whitelisted C++ class + CKComponentScope w1(self); // no error + const CKComponentScope& w2 = w1; // no error + CKComponentScope& w3 = w1; // no error + // const CKComponentScope w4 = {.a = 3}; // Can't, lacks default ctor + const CKComponentScope w4(self); // no error } @end