https://github.com/StepfenShawn updated https://github.com/llvm/llvm-project/pull/191812
From 628a2b5afedf9b24008d09b61c05315e079f8f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=8D=8CShawn?= <[email protected]> Date: Mon, 13 Apr 2026 21:02:51 +0800 Subject: [PATCH 1/4] Add support for uninitialized union fields check Implement support for checking uninitialized union fields in FindUninitializedFields. --- .../UninitializedObjectChecker.cpp | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp index 6d4389fda8753..a98b2d7f5f0ec 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -374,8 +374,30 @@ bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R, bool FindUninitializedFields::isUnionUninit(const TypedValueRegion *R) { assert(R->getValueType()->isUnionType() && "This method only checks union objects!"); - // TODO: Implement support for union fields. - return false; + + const RecordDecl *RD = R->getValueType()->getAsRecordDecl()->getDefinition(); + + if (!RD) + return false; + + // A union is considered initialized if at least one of its fields has a + // non-undefined value. If every field is undefined (or the union has no + // fields), we treat it as uninitialized. + for (const FieldDecl *FD : RD->fields()) { + if (FD->isUnnamedBitField()) + continue; + + const auto FieldVal = State->getLValue(FD, loc::MemRegionVal(R)).castAs<loc::MemRegionVal>(); + SVal V = State->getSVal(FieldVal); + + // If any field has a defined value, the union is initialized. + if (!V.isUndef()) { + IsAnyFieldInitialized = true; + return false; + } + } + + return true; } bool FindUninitializedFields::isPrimitiveUninit(SVal V) { From 883142b8d8ac6f94cceab3e7a4570eeb7b43c48f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=8D=8CShawn?= <[email protected]> Date: Mon, 13 Apr 2026 21:06:27 +0800 Subject: [PATCH 2/4] Implement tests for union field initialization warnings Add tests for uninitialized union fields in structs/classes. --- .../cxx-uninitialized-object-union-field.cpp | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 clang/test/Analysis/cxx-uninitialized-object-union-field.cpp diff --git a/clang/test/Analysis/cxx-uninitialized-object-union-field.cpp b/clang/test/Analysis/cxx-uninitialized-object-union-field.cpp new file mode 100644 index 0000000000000..8f5f777111109 --- /dev/null +++ b/clang/test/Analysis/cxx-uninitialized-object-union-field.cpp @@ -0,0 +1,57 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,optin.cplusplus.UninitializedObject \ +// RUN: -analyzer-config optin.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \ +// RUN: -std=c++11 -verify %s + +//===----------------------------------------------------------------------===// +// Tests for union fields inside structs/classes. +//===----------------------------------------------------------------------===// + +// A struct with an uninitialized union field -- should warn. +struct WithUninitUnion { + union { + int i; + float f; + } u; // expected-note{{uninitialized field 'this->u'}} + int x; + + WithUninitUnion(int val) : x(val) { // expected-warning{{1 uninitialized field at the end of the constructor call}} + // u is never initialized + } +}; + +void fWithUninitUnion() { + WithUninitUnion w(42); +} + +// A struct where the union field IS initialized -- should not warn. +struct WithInitUnion { + union { + int i; + float f; + } u; + int x; + + WithInitUnion(int val) : x(val) { + u.i = val; // union is initialized via one of its members + } +}; + +void fWithInitUnion() { + WithInitUnion w(42); // no-warning +} + +// A struct with only a union field, left uninitialized (pedantic mode). +struct OnlyUninitUnion { + union { + int i; + char c; + } u; // expected-note{{uninitialized field 'this->u'}} + + OnlyUninitUnion() { // expected-warning{{1 uninitialized field at the end of the constructor call}} + // u is never initialized + } +}; + +void fOnlyUninitUnion() { + OnlyUninitUnion o; +} From e6cbe707576e20329a645ec8f41b14c9bf7cf980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=8D=8CShawn?= <[email protected]> Date: Mon, 13 Apr 2026 22:40:42 +0800 Subject: [PATCH 3/4] Fix uninitialized field warnings in union tests --- clang/test/Analysis/cxx-uninitialized-object.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/clang/test/Analysis/cxx-uninitialized-object.cpp b/clang/test/Analysis/cxx-uninitialized-object.cpp index daaf6f418c7d1..8ce90b555b791 100644 --- a/clang/test/Analysis/cxx-uninitialized-object.cpp +++ b/clang/test/Analysis/cxx-uninitialized-object.cpp @@ -435,16 +435,14 @@ class ContainsSimpleUnionTest2 { float uf; int ui; char uc; - // TODO: we'd expect the note: {{uninitialized field 'this->u'}} - } u; // no-note + } u; // expected-note{{uninitialized field 'this->u'}} public: - ContainsSimpleUnionTest2() {} + ContainsSimpleUnionTest2() {} // expected-warning{{1 uninitialized field at the end of the constructor call}} }; void fContainsSimpleUnionTest2() { - // TODO: we'd expect the warning: {{1 uninitialized field}} - ContainsSimpleUnionTest2(); // no-warning + ContainsSimpleUnionTest2(); } class UnionPointerTest1 { @@ -479,17 +477,15 @@ class UnionPointerTest2 { }; private: - // TODO: we'd expect the note: {{uninitialized field 'this->uptr'}} - SimpleUnion *uptr; // no-note + SimpleUnion *uptr; // expected-note{{uninitialized pointee 'this->uptr'}} public: - UnionPointerTest2(SimpleUnion *uptr, char) : uptr(uptr) {} + UnionPointerTest2(SimpleUnion *uptr, char) : uptr(uptr) {} // expected-warning{{1 uninitialized field at the end of the constructor call}} }; void fUnionPointerTest2() { UnionPointerTest2::SimpleUnion u; - // TODO: we'd expect the warning: {{1 uninitialized field}} - UnionPointerTest2(&u, int()); // no-warning + UnionPointerTest2(&u, int()); } class ContainsUnionWithRecordTest1 { From ea966c251ccec9d91125120da5b99dc537bebdf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=8D=8CShawn?= <[email protected]> Date: Mon, 13 Apr 2026 23:12:17 +0800 Subject: [PATCH 4/4] Update cxx-uninitialized-object.cpp --- .../Analysis/cxx-uninitialized-object.cpp | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/clang/test/Analysis/cxx-uninitialized-object.cpp b/clang/test/Analysis/cxx-uninitialized-object.cpp index 8ce90b555b791..d727d59821f0b 100644 --- a/clang/test/Analysis/cxx-uninitialized-object.cpp +++ b/clang/test/Analysis/cxx-uninitialized-object.cpp @@ -435,10 +435,16 @@ class ContainsSimpleUnionTest2 { float uf; int ui; char uc; - } u; // expected-note{{uninitialized field 'this->u'}} + } u; +#ifdef PEDANTIC + // expected-note@-1{{uninitialized field 'this->u'}} +#endif public: - ContainsSimpleUnionTest2() {} // expected-warning{{1 uninitialized field at the end of the constructor call}} + ContainsSimpleUnionTest2() {} +#ifdef PEDANTIC + // expected-warning@-1{{1 uninitialized field at the end of the constructor call}} +#endif }; void fContainsSimpleUnionTest2() { @@ -477,10 +483,16 @@ class UnionPointerTest2 { }; private: - SimpleUnion *uptr; // expected-note{{uninitialized pointee 'this->uptr'}} + SimpleUnion *uptr; +#ifdef PEDANTIC + // expected-note@-1{{uninitialized pointee 'this->uptr'}} +#endif public: - UnionPointerTest2(SimpleUnion *uptr, char) : uptr(uptr) {} // expected-warning{{1 uninitialized field at the end of the constructor call}} + UnionPointerTest2(SimpleUnion *uptr, char) : uptr(uptr) {} +#ifdef PEDANTIC + // expected-warning@-1{{1 uninitialized field at the end of the constructor call}} +#endif }; void fUnionPointerTest2() { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
