diff --git a/infer/src/IR/Pvar.re b/infer/src/IR/Pvar.re index d2862ce53..c3a796dc5 100644 --- a/infer/src/IR/Pvar.re +++ b/infer/src/IR/Pvar.re @@ -26,7 +26,9 @@ type pvar_kind = | Abduced_retvar Procname.t Location.t /** synthetic variable to represent return value */ | Abduced_ref_param Procname.t t Location.t /** synthetic variable to represent param passed by reference */ - | Global_var (DB.source_file, bool, bool) /** global variable: translation unit + is it compile constant? + is it POD? */ + | Global_var (DB.source_file, bool, bool, bool) + /** global variable: translation unit + is it compile constant? + is it POD? + is it a static + local? */ | Seed_var /** variable used to store the initial value of formal parameters */ [@@deriving compare] /** Names for program variables. */ @@ -64,11 +66,12 @@ let rec _pp f pv => { } else { F.fprintf f "%a$%a%a|abducedRefParam" Procname.pp n Location.pp l Mangled.pp name } - | Global_var (fname, is_const, is_pod) => + | Global_var (fname, is_const, is_pod, _) => F.fprintf f "#GB<%a%s%s>$%a" - DB.source_file_pp fname + DB.source_file_pp + fname (if is_const {"|const"} else {""}) ( if (not is_pod) { @@ -227,6 +230,12 @@ let is_global pv => | _ => false }; +let is_static_local pv => + switch pv.pv_kind { + | Global_var (_, _, _, true) => true + | _ => false + }; + /** Check if a pvar is the special "this" var */ let is_this pvar => Mangled.equal (get_name pvar) (Mangled.from_string "this"); @@ -296,10 +305,16 @@ let mk_callee (name: Mangled.t) (proc_name: Procname.t) :t => { /** create a global variable with the given name */ -let mk_global is_constexpr::is_constexpr=false is_pod::is_pod=true (name: Mangled.t) fname :t => { +let mk_global + is_constexpr::is_constexpr=false + is_pod::is_pod=true + is_static_local::is_static_local=false + (name: Mangled.t) + fname + :t => { pv_hash: name_hash name, pv_name: name, - pv_kind: Global_var (fname, is_constexpr, is_pod) + pv_kind: Global_var (fname, is_constexpr, is_pod, is_static_local) }; @@ -324,19 +339,19 @@ let mk_abduced_ref_param (proc_name: Procname.t) (pv: t) (loc: Location.t) :t => let get_source_file pvar => switch pvar.pv_kind { - | Global_var (f, _, _) => Some f + | Global_var (f, _, _, _) => Some f | _ => None }; let is_compile_constant pvar => switch pvar.pv_kind { - | Global_var (_, b, _) => b + | Global_var (_, b, _, _) => b | _ => false }; let is_pod pvar => switch pvar.pv_kind { - | Global_var (_, _, b) => b + | Global_var (_, _, b, _) => b | _ => true }; diff --git a/infer/src/IR/Pvar.rei b/infer/src/IR/Pvar.rei index d23c9199b..58e43a1ec 100644 --- a/infer/src/IR/Pvar.rei +++ b/infer/src/IR/Pvar.rei @@ -62,11 +62,15 @@ let is_abduced: t => bool; let is_callee: t => bool; -/** Check if the pvar is a global var */ +/** Check if the pvar is a global var or a static local var */ let is_global: t => bool; -/** Check if the pvar is a local var */ +/** Check if the pvar is a static variable declared inside a function */ +let is_static_local: t => bool; + + +/** Check if the pvar is a (non-static) local var */ let is_local: t => bool; @@ -104,7 +108,13 @@ let mk_callee: Mangled.t => Procname.t => t; /** create a global variable with the given name */ -let mk_global: is_constexpr::bool? => is_pod::bool? => Mangled.t => DB.source_file => t; +let mk_global: + is_constexpr::bool? => + is_pod::bool? => + is_static_local::bool? => + Mangled.t => + DB.source_file => + t; /** create a fresh temporary variable local to procedure [pname]. for use in the frontends only! */ diff --git a/infer/src/checkers/Siof.ml b/infer/src/checkers/Siof.ml index 03173a5c8..a3adba8c4 100644 --- a/infer/src/checkers/Siof.ml +++ b/infer/src/checkers/Siof.ml @@ -30,6 +30,7 @@ module TransferFunctions (CFG : ProcCfg.S) = struct let get_globals astate loc e = let is_dangerous_global pv = Pvar.is_global pv + && not (Pvar.is_static_local pv) && not (Pvar.is_pod pv) && not (Pvar.is_compile_constant pv) in let globals = Exp.get_vars e |> snd |> IList.filter is_dangerous_global in diff --git a/infer/src/clang/cFrontend_utils.ml b/infer/src/clang/cFrontend_utils.ml index 9615be5eb..fb939a48a 100644 --- a/infer/src/clang/cFrontend_utils.ml +++ b/infer/src/clang/cFrontend_utils.ml @@ -761,7 +761,9 @@ struct | Clang_ast_t.ClassTemplateSpecializationDecl(_, _, _, _, _, _, _, {xrdi_is_pod}, _) -> xrdi_is_pod | _ -> true) true in - Pvar.mk_global ~is_constexpr ~is_pod (mk_name name_string simple_name) translation_unit + Pvar.mk_global ~is_constexpr ~is_pod + ~is_static_local:(var_decl_info.Clang_ast_t.vdi_is_static_local) + (mk_name name_string simple_name) translation_unit let mk_sil_var trans_unit_ctx named_decl_info decl_info_type_ptr_opt procname outer_procname = match decl_info_type_ptr_opt with diff --git a/infer/tests/codetoanalyze/cpp/checkers/issues.exp b/infer/tests/codetoanalyze/cpp/checkers/issues.exp index feaf6966a..fc5c5f10e 100644 --- a/infer/tests/codetoanalyze/cpp/checkers/issues.exp +++ b/infer/tests/codetoanalyze/cpp/checkers/issues.exp @@ -3,7 +3,6 @@ codetoanalyze/cpp/checkers/siof/siof.cpp, __infer_globals_initializer_another_gl codetoanalyze/cpp/checkers/siof/siof.cpp, __infer_globals_initializer_another_global_object2, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_global_object2,call to access_to_non_pod,access to global_object2] codetoanalyze/cpp/checkers/siof/siof.cpp, __infer_globals_initializer_another_global_object3, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_global_object3,call to access_to_templated_non_pod,access to global_object3] codetoanalyze/cpp/checkers/siof/siof.cpp, __infer_globals_initializer_initWithGlobal, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of initWithGlobal,call to getGlobalNonPOD,access to global_object2] -codetoanalyze/cpp/checkers/siof/siof.cpp, __infer_globals_initializer_initWithStatic, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of initWithStatic,call to getFunctionStaticNonPOD,access to getFunctionStaticNonPOD_instance] codetoanalyze/cpp/checkers/siof/siof.cpp, __infer_globals_initializer_pod_accesses_non_pod, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of pod_accesses_non_pod,call to access_to_non_pod,access to global_object2] codetoanalyze/cpp/checkers/siof/siof_templated.cpp, __infer_globals_initializer_another_templated_global_object, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_templated_global_object,call to SomeOtherTemplatedNonPODObject<_Bool>_SomeOtherTemplatedNonPODObject,access to extern_global_object] codetoanalyze/cpp/checkers/siof/siof_templated.cpp, __infer_globals_initializer_another_templated_global_object2, 0, STATIC_INITIALIZATION_ORDER_FIASCO, [initialization of another_templated_global_object2,call to access_to_non_pod,access to global_object2]