diff --git a/infer/src/checkers/uninit.ml b/infer/src/checkers/uninit.ml index 8fa4e74d5..ca2a91605 100644 --- a/infer/src/checkers/uninit.ml +++ b/infer/src/checkers/uninit.ml @@ -100,10 +100,6 @@ module TransferFunctions (CFG : ProcCfg.S) = struct uninit_vars - let remove_array_element base uninit_vars = - D.remove (base, [AccessPath.ArrayAccess (snd base, [])]) uninit_vars - - let get_formals call = match Ondemand.get_proc_desc call with | Some proc_desc -> @@ -175,19 +171,15 @@ module TransferFunctions (CFG : ProcCfg.S) = struct | HilExp.AccessPath (((_, {Typ.desc= Tarray _}) as base), al) when is_blacklisted_function call -> D.remove (base, al) acc - | HilExp.AccessPath ap when Typ.Procname.is_constructor call -> - remove_fields tenv (fst ap) (D.remove ap acc) - | HilExp.AccessPath (((_, {Typ.desc= Tptr _}) as base), al) - when not (Typ.Procname.is_constructor call) -> - let acc' = D.remove (base, al) acc in - remove_fields tenv base acc' - | HilExp.AccessPath (((_, {Typ.desc= Tptr (t', _)}) as base), al) -> - let acc' = D.remove (base, al) acc in - remove_array_element (fst base, t') acc' | HilExp.AccessPath (((_, t) as base), al) when is_struct t && List.length al > 0 && function_expect_a_pointer call idx -> (* Access to a field of a struct by reference *) D.remove (base, al) acc + | HilExp.AccessPath ap when Typ.Procname.is_constructor call -> + remove_fields tenv (fst ap) (D.remove ap acc) + | HilExp.AccessPath (((_, {Typ.desc= Tptr _}) as base), al) -> + let acc' = D.remove (base, al) acc in + remove_fields tenv base acc' | HilExp.Closure (_, apl) -> (* remove the captured variables of a block/lambda *) List.fold ~f:(fun acc' (base, _) -> D.remove (base, []) acc') ~init:acc apl diff --git a/infer/tests/codetoanalyze/cpp/uninit/members.cpp b/infer/tests/codetoanalyze/cpp/uninit/members.cpp new file mode 100644 index 000000000..8742faf06 --- /dev/null +++ b/infer/tests/codetoanalyze/cpp/uninit/members.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017 - 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 + +class A { + + public: + std::string a_name; + int i; + + A() {} // user defined default constructor. + // Does not initialize i so, it gets random value +}; + +class B { + + public: + std::string a_name; + int i; + + // No user defined default constructor. + // If default constructor is called i is initialized. +}; + +int access_members_bad() { + A a; + + std::string n = a.a_name; + int i = a.i; // error + + return 0; +}; + +int access_members_bad2() { + A a{}; + + std::string n = a.a_name; + int i = a.i; // error + + return 0; +}; + +int access_members_ok() { + + B b{}; // call default implicit constructor which initialize i. + std::string n = b.a_name; + int i = b.i; + + return 0; +}; + +int access_members_bad3() { + + B b; // no constructor is called + std::string n = b.a_name; + int i = b.i; + + return 0; +};