diff --git a/infer/src/IR/Typ.ml b/infer/src/IR/Typ.ml index 44a9c8068..68bb8c5df 100644 --- a/infer/src/IR/Typ.ml +++ b/infer/src/IR/Typ.ml @@ -364,6 +364,8 @@ module Name = struct let is_class = function CppClass _ | JavaClass _ | ObjcClass _ -> true | _ -> false + let is_union = function CUnion _ -> true | _ -> false + let is_objc_protocol name = match name with ObjcProtocol _ -> true | _ -> false let is_same_type t1 t2 = diff --git a/infer/src/IR/Typ.mli b/infer/src/IR/Typ.mli index a076b6aaa..e99e61f7e 100644 --- a/infer/src/IR/Typ.mli +++ b/infer/src/IR/Typ.mli @@ -134,6 +134,9 @@ module Name : sig val is_class : t -> bool (** [is_class name] holds if [name] names CPP/Objc/Java class *) + val is_union : t -> bool + (** [is_union name] holds if [name] names C/CPP union *) + val is_same_type : t -> t -> bool (** [is_class name1 name2] holds if [name1] and [name2] name same kind of type *) diff --git a/infer/src/checkers/uninit.ml b/infer/src/checkers/uninit.ml index e1649d838..486ea5572 100644 --- a/infer/src/checkers/uninit.ml +++ b/infer/src/checkers/uninit.ml @@ -360,7 +360,9 @@ let get_locals cfg tenv pdesc = let pvar = Pvar.mk var_data.name (Procdesc.get_proc_name pdesc) in let base_access_expr = AccessExpression.Base (Var.of_pvar pvar, var_data.typ) in match var_data.typ.Typ.desc with - | Typ.Tstruct qual_name -> ( + | Typ.Tstruct qual_name + (* T30105165 remove filtering after we improve union translation *) + when not (Typ.Name.is_union qual_name) -> ( match Tenv.lookup tenv qual_name with | Some {fields} -> let flist = diff --git a/infer/src/clang/CType_decl.ml b/infer/src/clang/CType_decl.ml index 938e10e2c..8e07177da 100644 --- a/infer/src/clang/CType_decl.ml +++ b/infer/src/clang/CType_decl.ml @@ -425,6 +425,8 @@ and get_record_typename ?tenv decl = let args = get_template_args tenv spec_info in let mangled = if String.equal "" mangling then None else Some mangling in Typ.Name.Cpp.from_qual_name (Typ.Template {mangled; args}) tname + | CXXRecordDecl (_, name_info, _, _, _, `TTK_Union, _, _), _ -> + Typ.CUnion (CAst_utils.get_qualified_name ~linters_mode name_info) | CXXRecordDecl (_, name_info, _, _, _, _, _, _), _ | ClassTemplateSpecializationDecl (_, name_info, _, _, _, _, _, _, _, _), _ -> (* we use Typ.CppClass for C++ because we expect Typ.CppClass from *) diff --git a/infer/tests/codetoanalyze/cpp/uninit/issues.exp b/infer/tests/codetoanalyze/cpp/uninit/issues.exp index 87ee2eeff..5846f3b38 100644 --- a/infer/tests/codetoanalyze/cpp/uninit/issues.exp +++ b/infer/tests/codetoanalyze/cpp/uninit/issues.exp @@ -10,7 +10,6 @@ codetoanalyze/cpp/uninit/struct.cpp, pass_basic_type_field_bad, 3, UNINITIALIZED codetoanalyze/cpp/uninit/struct.cpp, struct_uninit_bad, 3, UNINITIALIZED_VALUE, no_bucket, ERROR, [] codetoanalyze/cpp/uninit/uninit.cpp, FP_no_warning_noreturn_callee_ok, 7, UNINITIALIZED_VALUE, no_bucket, ERROR, [] codetoanalyze/cpp/uninit/uninit.cpp, FP_pointer_param_void_star_ok, 4, UNINITIALIZED_VALUE, no_bucket, ERROR, [] -codetoanalyze/cpp/uninit/uninit.cpp, FP_union_ok, 6, UNINITIALIZED_VALUE, no_bucket, ERROR, [] codetoanalyze/cpp/uninit/uninit.cpp, bad1, 2, UNINITIALIZED_VALUE, no_bucket, ERROR, [] codetoanalyze/cpp/uninit/uninit.cpp, bad2, 2, UNINITIALIZED_VALUE, no_bucket, ERROR, [] codetoanalyze/cpp/uninit/uninit.cpp, branch1_FP, 11, UNINITIALIZED_VALUE, no_bucket, ERROR, [] diff --git a/infer/tests/codetoanalyze/cpp/uninit/uninit.cpp b/infer/tests/codetoanalyze/cpp/uninit/uninit.cpp index 6f0f649b7..046fc9eb0 100644 --- a/infer/tests/codetoanalyze/cpp/uninit/uninit.cpp +++ b/infer/tests/codetoanalyze/cpp/uninit/uninit.cpp @@ -269,12 +269,12 @@ int* FP_pointer_param_void_star_ok() { return a.ptr; // false positive } -short FP_union_ok() { +short union_ok() { union { int* a; short* b; } u; init(u.a); - short* p = u.b; // false positive + short* p = u.b; return *p; }