Skipping reporting global variable warning on known non-expensive cases.

Reviewed By: dulmarod

Differential Revision: D3298191

fbshipit-source-id: 8b3a38b
master
Dino Distefano 9 years ago committed by Facebook Github Bot 0
parent 438a4b430b
commit aae1dbac3d

@ -1 +1 @@
Subproject commit f5c1bd411f95ba797e0e0e5c15a562d91eb6a6c9 Subproject commit ba3d4b9066cc57c413581d2efe909add94b4366f

@ -55,6 +55,7 @@ let empty_var_decl_info = {
vdi_is_static_local = false; vdi_is_static_local = false;
vdi_is_module_private = false; vdi_is_module_private = false;
vdi_is_nrvo_variable = false; vdi_is_nrvo_variable = false;
vdi_is_const_expr = false;
vdi_init_expr = None; vdi_init_expr = None;
vdi_parm_index_in_function = None; vdi_parm_index_in_function = None;
} }

@ -59,12 +59,33 @@ let rec is_self s =
| _ -> false) | _ -> false)
| _ -> false | _ -> false
let is_function_or_method_call _ st = let decl_ref_is_in names st =
match st with match st with
| Clang_ast_t.CallExpr _ (* for C *) | Clang_ast_t.DeclRefExpr (_, _, _, drti) ->
(match drti.drti_decl_ref with
| Some dr -> let ndi, _, _ = CFrontend_utils.Ast_utils.get_info_from_decl_ref dr in
IList.exists (fun n -> n = ndi.ni_name) names
| _ -> false)
| _ -> false
let call_function_named st names =
Ast_utils.exists_eventually_st decl_ref_is_in names st
let rec eventually_makes_a_call exp =
CFrontend_utils.Ast_utils.exists_eventually_st is_expensive_function_or_method_call () exp
and is_expensive_function_or_method_call _ st =
let white_list_functions = ["CGPointMake"] in
let open Clang_ast_t in
match st with
| CallExpr (_, st :: _, _) -> (* for C *)
not (call_function_named st white_list_functions)
| CXXConstructExpr (_, stmt_list, _, _) ->
(* Assumption: constructor is expensive iff it has a call inside *)
(IList.exists eventually_makes_a_call) stmt_list
| CXXTemporaryObjectExpr _ (* for C++ *)
| CXXMemberCallExpr _ | CXXOperatorCallExpr _ | CXXMemberCallExpr _ | CXXOperatorCallExpr _
| CXXConstructExpr _ | CXXTemporaryObjectExpr _ (* for C++ *) | ObjCMessageExpr _ -> true (* for ObjC *)
| Clang_ast_t.ObjCMessageExpr _ -> true (* for ObjC *)
| _ -> false | _ -> false
(* Call method m and on the pn parameter pred holds *) (* Call method m and on the pn parameter pred holds *)
@ -88,17 +109,15 @@ let dec_body_eventually atomic_pred param dec =
(* true if a variable is initialized with a method/function call.*) (* true if a variable is initialized with a method/function call.*)
(* implemented as decl |= EF is_function_or_method_call *) (* implemented as decl |= EF is_function_or_method_call *)
let is_initialized_with_call decl = let is_initialized_with_expensive_call decl =
match decl with match decl with
| Clang_ast_t.VarDecl (_, _ ,_, vdi) -> | Clang_ast_t.VarDecl (_, _ ,_, vdi) ->
(match vdi.vdi_init_expr with (match vdi.vdi_init_expr with
| Some init_expr -> | Some init_expr ->
CFrontend_utils.Ast_utils.exists_eventually_st is_function_or_method_call () init_expr eventually_makes_a_call init_expr
| _ -> false) | _ -> false)
| _ -> false | _ -> false
(* === Warnings on properties === *) (* === Warnings on properties === *)
(* Assing Pointer Warning: a property with a pointer type should not be declared `assign` *) (* Assing Pointer Warning: a property with a pointer type should not be declared `assign` *)
@ -149,7 +168,8 @@ let global_var_init_with_calls_warning decl =
| None -> assert false (* we cannot be here *) in | None -> assert false (* we cannot be here *) in
let condition = (CFrontend_utils.Ast_utils.is_objc () || CFrontend_utils.Ast_utils.is_objcpp ()) let condition = (CFrontend_utils.Ast_utils.is_objc () || CFrontend_utils.Ast_utils.is_objcpp ())
&& CFrontend_utils.Ast_utils.is_global_var decl && CFrontend_utils.Ast_utils.is_global_var decl
&& is_initialized_with_call decl in && (not (CFrontend_utils.Ast_utils.is_const_expr_var decl))
&& is_initialized_with_expensive_call decl in
if condition then if condition then
Some { Some {
name = "GLOBAL_VARIABLE_INITIALIZED_WITH_FUNCTION_OR_METHOD_CALL"; name = "GLOBAL_VARIABLE_INITIALIZED_WITH_FUNCTION_OR_METHOD_CALL";

@ -404,6 +404,11 @@ struct
| Clang_ast_t.VarDecl (_, _ ,_, vdi) -> vdi.vdi_is_global | Clang_ast_t.VarDecl (_, _ ,_, vdi) -> vdi.vdi_is_global
| _ -> false | _ -> false
let is_const_expr_var decl =
match decl with
| Clang_ast_t.VarDecl (_, _ ,_, vdi) -> vdi.vdi_is_const_expr
| _ -> false
let is_objc () = let is_objc () =
match Config.clang_lang with match Config.clang_lang with
| Config.OBJC -> true | Config.OBJC -> true

@ -138,6 +138,9 @@ sig
(* true if a declaration is a global variable *) (* true if a declaration is a global variable *)
val is_global_var : Clang_ast_t.decl -> bool val is_global_var : Clang_ast_t.decl -> bool
(* true if a declaration is a constexpr variable *)
val is_const_expr_var : Clang_ast_t.decl -> bool
(* true if CFrontend_config.language is set ot ObjC *) (* true if CFrontend_config.language is set ot ObjC *)
val is_objc : unit -> bool val is_objc : unit -> bool

@ -7,7 +7,8 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
#import <Foundation/NSObject.h> #import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
@interface A : NSObject @interface A : NSObject
+ (int)bar; + (int)bar;
@ -34,6 +35,19 @@ static const float kLineSize = 1 / [A scale]; // Error
static const float ok = 37; static const float ok = 37;
const NSRange NSNotFoundRange =
(NSRange){.location = NSNotFound, .length = 0}; // OK
const static CFRange FBCFNotFoundRange =
(CFRange){.location = kCFNotFound, .length = 7}; // OK
const CGPoint offset = CGPointMake(0, 0); // OK
constexpr double square(double x) { return x * x; }
const int dmv = 17;
constexpr double max1 = 1.4 * square(dmv); // OK
void bla() { void bla() {
static const int kInsets = foo(); // Error static const int kInsets = foo(); // Error

@ -7,7 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory. * of patent rights can be found in the PATENTS file in the same directory.
*/ */
package endtoend.objc; package endtoend.objcpp;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
import static utils.matchers.ResultContainsLineNumbers.containsLines; import static utils.matchers.ResultContainsLineNumbers.containsLines;
@ -52,7 +52,7 @@ public class GlobalVarTest {
assertThat( assertThat(
"Results should contain " + GLOBAL_VARIABLE_INITIALIZED_WITH_FUNCTION_OR_METHOD_CALL, "Results should contain " + GLOBAL_VARIABLE_INITIALIZED_WITH_FUNCTION_OR_METHOD_CALL,
inferResults, inferResults,
containsLines(new int[]{29, 31, 33})); containsLines(new int[]{30, 32, 34}));
} }
} }

@ -195,6 +195,9 @@ public class InferRunner {
case CPP: case CPP:
stdParam = "-std=c++11"; stdParam = "-std=c++11";
break; break;
case ObjCPP:
stdParam = "-std=c++11";
break;
} }
return stdParam; return stdParam;
} }

Loading…
Cancel
Save