[Infer] Write a has_visibility_attribute predicate for AL

Reviewed By: dulmarod

Differential Revision: D5575154

fbshipit-source-id: 677a7af
master
Meng Zhang 7 years ago committed by Facebook Github Bot
parent df77ef423e
commit cdc54563d4

@ -632,3 +632,42 @@ let using_namespace an namespace =
-> false )
| _
-> false
let rec get_decl_attributes_for_callexpr an =
let open Clang_ast_t in
let open Ctl_parser_types in
match an with
| Stmt CallExpr (_, func :: _, _)
-> get_decl_attributes_for_callexpr (Stmt func)
| Stmt ImplicitCastExpr (_, [stmt], _, _)
-> get_decl_attributes_for_callexpr (Stmt stmt)
| Stmt DeclRefExpr (_, _, _, drti) -> (
match CAst_utils.get_decl_opt_with_decl_ref drti.drti_decl_ref with
| Some decl
-> let decl_info = Clang_ast_proj.get_decl_tuple decl in
decl_info.di_attributes
| None
-> [] )
| _
-> []
let has_visibility_attribute an visibility =
let open Clang_ast_t in
let rec has_visibility_attr attrs param =
match attrs with
| []
-> false
| (VisibilityAttr attr_info) :: rest
-> if List.exists ~f:(fun s -> String.equal param (String.strip s)) attr_info.ai_parameters
then true
else has_visibility_attr rest param
| _ :: rest
-> has_visibility_attr rest param
in
let attributes = get_decl_attributes_for_callexpr an in
match visibility with ALVar.Const vis -> has_visibility_attr attributes vis | _ -> false
let has_used_attribute an =
let open Clang_ast_t in
let attributes = get_decl_attributes_for_callexpr an in
List.exists ~f:(fun attr -> match attr with UsedAttr _ -> true | _ -> false) attributes

@ -97,3 +97,7 @@ val receiver_method_call : Ctl_parser_types.ast_node -> Clang_ast_t.decl option
val is_at_selector_with_name : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
(** an is an expression @selector with whose name in the language of re *)
val has_visibility_attribute : Ctl_parser_types.ast_node -> ALVar.alexp -> bool
val has_used_attribute : Ctl_parser_types.ast_node -> bool

@ -796,6 +796,10 @@ let rec eval_Atomic _pred_name args an lcxt =
-> CPredicates.is_at_selector_with_name an name
| "has_type_subprotocol_of", [protname], an
-> CPredicates.has_type_subprotocol_of an protname
| "has_visibility_attribute", [vis], an
-> CPredicates.has_visibility_attribute an vis
| "has_used_attribute", [], an
-> CPredicates.has_used_attribute an
| _
-> failwith ("ERROR: Undefined Predicate or wrong set of arguments: '" ^ pred_name ^ "'")

@ -87,3 +87,11 @@ codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m4, 76, TEST_BU
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m7, 79, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m8, 80, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/subclassing.m, TestType_m9, 81, TEST_BUILTIN_TYPE, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 31, TEST_DEFAULT_VISIBILITY, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 32, TEST_DEFAULT_VISIBILITY, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 33, TEST_HIDDEN_VISIBILITY, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 34, TEST_HIDDEN_VISIBILITY, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 35, TEST_USED_ATTRIBUTE, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 36, TEST_DEFAULT_VISIBILITY, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 36, TEST_DEFAULT_VISIBILITY_WITH_USED_ATTRIBUTE, []
codetoanalyze/objc/linters-for-test-only/visibility.c, bar, 36, TEST_USED_ATTRIBUTE, []

@ -348,3 +348,31 @@ DEFINE-CHECKER ENUM_CONSTANTS = {
SET report_when = is_at_selector_with_name("actionButtonTapped:");
SET message = "Found @selector(actionButtonTapped:)";
};
DEFINE-CHECKER TEST_DEFAULT_VISIBILITY = {
SET report_when =
WHEN has_visibility_attribute("Default")
HOLDS-IN-NODE CallExpr;
SET message = "%name% has default visibility";
};
DEFINE-CHECKER TEST_HIDDEN_VISIBILITY = {
SET report_when =
WHEN has_visibility_attribute("Hidden")
HOLDS-IN-NODE CallExpr;
SET message = "%name% has hidden visibility";
};
DEFINE-CHECKER TEST_USED_ATTRIBUTE = {
SET report_when =
WHEN has_used_attribute()
HOLDS-IN-NODE CallExpr;
SET message = "%name% has used attribute";
};
DEFINE-CHECKER TEST_DEFAULT_VISIBILITY_WITH_USED_ATTRIBUTE = {
SET report_when =
WHEN has_visibility_attribute("Default") AND has_used_attribute
HOLDS-IN-NODE CallExpr;
SET message = "%name% has default visibility and used attribute";
};

@ -0,0 +1,37 @@
/*
* Copyright (c) 2015 - 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.
*/
#include <stdlib.h>
void foo_with_default_visibility() __attribute__((visibility("default")));
// protected will appear as Default in the AST
void foo_with_protected_visibility() __attribute__((visibility("protected")));
// internal will appear as Hidden in the AST
void foo_with_internal_visibility() __attribute__((visibility("internal")));
void foo_with_hidden_visibility() __attribute__((visibility("hidden")));
void foo_with_used_attribute() __attribute__((used));
void foo() __attribute__((visibility("default"))) __attribute__((used));
void foo_with_default_visibility() {}
void foo_with_protected_visibility() {}
void foo_with_internal_visibility() {}
void foo_with_hidden_visibility() {}
void foo_with_used_attribute() {}
void foo() {}
void bar() {
foo_with_default_visibility();
foo_with_protected_visibility();
foo_with_internal_visibility();
foo_with_hidden_visibility();
foo_with_used_attribute();
foo();
}
Loading…
Cancel
Save