=?utf-8?b?8J+NjFNoYXdu?= <[email protected]>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/[email protected]>


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: 🍌Shawn (StepfenShawn)

<details>
<summary>Changes</summary>

Implement `isUnionUninit()` in `UninitializedObjectChecker` to detect
uninitialized union fields.  Also adds a new test file to verify the behavior 
with union fields
inside structs and classes.

---
Full diff: https://github.com/llvm/llvm-project/pull/191812.diff


2 Files Affected:

- (modified) 
clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
 (+24-2) 
- (added) clang/test/Analysis/cxx-uninitialized-object-union-field.cpp (+57) 


``````````diff
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) {
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;
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/191812
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to