================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits