Szelethus added inline comments.

================
Comment at: lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp:392
 
-    if (T->isMemberPointerType()) {
-      if (isMemberPointerUninit(FR, LocalChain))
+    if (T->isPointerType() || T->isReferenceType()) {
+      if (isPointerOrReferenceUninit(FR, LocalChain))
----------------
NoQ wrote:
> george.karpenkov wrote:
> > I am confused here, how can references be uninitialized?
> Hmm, that's actually a good question. I guess we technically initialize a 
> reference with an undefined pointer, but that should be caught by another 
> checker early because it's an immediate UB.
> 
> In any case, there don't seem to be tests for this.
I guess you could say that naming could be improved upon. I didn't mean that 
the reference object itself, but rather it's pointee is uninitialized.

```
int a; // say that this isn't zero initialized
int &c = a;
```

There are numerous tests for this both for left value and right value 
references in `cxx-uninitialized-object-ptr-ref.cpp`.


================
Comment at: lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp:488-491
   // TODO: Dereferencing should be done according to the dynamic type.
   while (Optional<Loc> L = DerefdV.getAs<Loc>()) {
     DerefdV = State->getSVal(*L);
   }
----------------
NoQ wrote:
> Ok, this isn't related to that review, but i still don't understand why this 
> loop terminates. We might skip `void *` above, but we don't skip `void 
> *****`, right? And if we go on dereferencing that, we'll eventually get to a 
> `void *` that can point to anything.
> 
> A bit more of an intuition dump: I strongly believe that in `getSVal(Loc, T)` 
> the optional argument `T` should be mandatory. Omitting it almost always 
> leads to errors, because there are no types in machine memory, and our 
> `RegionStore` tries to work exactly like machine memory, and `getSVal(Loc)` 
> makes a best-effort guess on what the type of the region is, which in some 
> cases may work reliably (these are exactly the cases where you don't mind 
> passing the type directly), but is usually error-prone in other cases. So 
> whenever i see a `getSVal(Loc)` without a type, i imagine that the code 
> essentially reads raw bytes from the symbolic memory and makes random guesses 
> on what they mean.
> 
> So the point is "oh we can do better with dynamic type info", it's "we're 
> doing something completely unreliable here". It's not just about void 
> pointers, it's about the fact that the underlying storage simply has no types 
> at all.
From the code a couple lines back:

  if (isVoidPointer(FD)) {
    IsAnyFieldInitialized = true;
    return false;
  }

Note that isn't `Type::isVoidPointer`, I'm calling a statically defined 
function to filter out all void pointer cases.
```
/// Returns whether FD can be (transitively) dereferenced to a void pointer type
/// (void*, void**, ...). The type of the region behind a void pointer isn't
/// known, and thus FD can not be analyzed.
bool isVoidPointer(const FieldDecl *FD);
```

I see your point, this is a bit dodgy. I'm already working on a fix, and hope 
to upload it along with other important fixes during the next week. It's high 
on my priority list :)


https://reviews.llvm.org/D48325



_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to