[clang] [clang][analyzer] Fix the false positive ArgInitializedness warning on unnamed bit-field (PR #145066)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jun 28 03:07:09 PDT 2025
================
@@ -2122,8 +2122,21 @@ SVal RegionStoreManager::getBindingForField(RegionBindingsConstRef B,
if (const std::optional<SVal> &V = B.getDirectBinding(R))
return *V;
- // If the containing record was initialized, try to get its constant value.
+ // UnnamedBitField is always Undefined unless using memory operation such
+ // as 'memset'.
+ // For example, for code
+ // typedef struct {
+ // int i :2;
+ // int :30; // unnamed bit-field
+ // } A;
+ // A a = {1};
+ // The bits of the unnamed bit-field in local variable a can be anything.
const FieldDecl *FD = R->getDecl();
+ if (FD->isUnnamedBitField()) {
+ return UndefinedVal();
+ }
+
+ // If the containing record was initialized, try to get its constant value.
----------------
Tedlion wrote:
I can provide some evidence where the `UndefinedVal`(in c) and the `SymbolVal`(in c++) are from.
After **reverting all my changes** in CallAndMessageChecker.cpp and RegionStore.cpp, I use watchpoints to find where the return values of the invoking `StoreMgr.getBinding(store, loc::MemRegionVal(FR))` from:
Following is the test code:
```c
// unnamed.c
struct B {
int i : 2;
int : 30; // unnamed bit-field
};
extern void consume_B(struct B);
void bitfield_B_init(void) {
struct B b1;
b1.i = 1; // b1 is initialized
consume_B(b1);
}
```
When analyzing the test code as c, via `clang -cc1 -x c -analyze -analyzer-checker=core unnamed.c`, I get the stackframes:
```
1# RegionStoreManager::getBindingForFieldOrElementCommon(const RegionBindingsRef &, const clang::ento::TypedValueRegion *, QualType) RegionStore.cpp:2312
2# RegionStoreManager::getBindingForField(const RegionBindingsRef &, const clang::ento::FieldRegion *) RegionStore.cpp:2170
3# RegionStoreManager::getBinding(const RegionBindingsRef &, Loc, QualType) RegionStore.cpp:1617
4# RegionStoreManager::getBinding(const void *, Loc, QualType) RegionStore.cpp:711
5# FindUninitializedField::Find(const clang::ento::TypedValueRegion *) CallAndMessageChecker.cpp:263
......
```
```cpp
// in FindUninitializedField::Find
for (const auto *I : RD->fields()) {
const FieldRegion *FR = MrMgr.getFieldRegion(I, R);
FieldChain.push_back(I);
T = I->getType();
if (T->getAsStructureType()) {
if (Find(FR))
return true;
} else {
SVal V = StoreMgr.getBinding(store, loc::MemRegionVal(FR));
if (V.isUndef())
return true;
}
FieldChain.pop_back();
}
```
When I switching to frame 5 and print the `FR->getRawMemorySpace()`, I get the type `clang::ento::StackLocalsSpaceRegion *`
While analyzing the test code as c++, via `clang -cc1 -x c ++-analyze -analyzer-checker=core unnamed.c`, I get the stackframes:
```
RegionStoreManager::getBindingForFieldOrElementCommon(const RegionBindingsRef &, const clang::ento::TypedValueRegion *, QualType) RegionStore.cpp:2317
RegionStoreManager::getBindingForField(const RegionBindingsRef &, const clang::ento::FieldRegion *) RegionStore.cpp:2170
RegionStoreManager::getBinding(const RegionBindingsRef &, Loc, QualType) RegionStore.cpp:1617
RegionStoreManager::getBinding(const void *, Loc, QualType) RegionStore.cpp:711
FindUninitializedField::Find(const clang::ento::TypedValueRegion *) CallAndMessageChecker.cpp:263
```
When I switching to frame 5 and print the `FR->getRawMemorySpace()`, I get the type `clang::ento::StackArgumentsSpaceRegion *`
The raw memory space of `b1` is different in c and c++, I wonder it due to the implicit copy constructor in c++?
And the difference on `FR->getRawMemorySpace()` finally reaches the if check in `RegionStoreManager::getBindingForFieldOrElementCommon` and returns a different result.
```cpp
// line 2288 in RegionStore.cpp
if (isa<StackLocalsSpaceRegion>(R->getRawMemorySpace())) {
if (isa<ElementRegion>(R)) {
```
The last statement in `getBindingForFieldOrElementCommon` seems a default handle, where the c++ unnamed bit-field gets its binding.
```cpp
// All other values are symbolic.
return svalBuilder.getRegionValueSymbolVal(R);
```
https://github.com/llvm/llvm-project/pull/145066
More information about the cfe-commits
mailing list