================
@@ -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

Reply via email to