Index: lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -265,16 +265,16 @@ continue; } + SVal V = State->getSVal(FieldVal); + if (T->isAnyPointerType() || T->isReferenceType() || - T->isBlockPointerType()) { + T->isBlockPointerType() || V.getAs()) { if (isPointerOrReferenceUninit(FR, LocalChain)) ContainsUninitField = true; continue; } if (isPrimitiveType(T)) { - SVal V = State->getSVal(FieldVal); - if (isPrimitiveUninit(V)) { if (addFieldToUninits(LocalChain.add(RegularField(FR)))) ContainsUninitField = true; Index: lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp +++ lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp @@ -60,8 +60,8 @@ } }; -/// Represents a void* field that needs to be casted back to its dynamic type -/// for a correct note message. +/// Represents a nonloc::LocAsInteger or void* field, that point to objects, but +/// needs to be casted back to its dynamic type for a correct note message. class NeedsCastLocField final : public FieldNode { QualType CastBackType; @@ -74,7 +74,13 @@ } virtual void printPrefix(llvm::raw_ostream &Out) const override { - Out << "static_cast" << '<' << CastBackType.getAsString() << ">("; + // If this object is a nonloc::LocAsInteger. + if (getDecl()->getType()->isIntegerType()) + Out << "reinterpret_cast"; + // If this pointer's dynamic type is different then it's static type. + else + Out << "static_cast"; + Out << '<' << CastBackType.getAsString() << ">("; } virtual void printNode(llvm::raw_ostream &Out) const override { @@ -105,17 +111,16 @@ // Methods for FindUninitializedFields. //===----------------------------------------------------------------------===// -// Note that pointers/references don't contain fields themselves, so in this -// function we won't add anything to LocalChain. bool FindUninitializedFields::isPointerOrReferenceUninit( const FieldRegion *FR, FieldChainInfo LocalChain) { + SVal V = State->getSVal(FR); + assert((FR->getDecl()->getType()->isAnyPointerType() || FR->getDecl()->getType()->isReferenceType() || - FR->getDecl()->getType()->isBlockPointerType()) && - "This method only checks pointer/reference objects!"); - - SVal V = State->getSVal(FR); + FR->getDecl()->getType()->isBlockPointerType() || + V.getAs()) && + "This method only checks pointer/reference or LocAsInteger objects!"); if (V.isUnknown() || V.getAs()) { IsAnyFieldInitialized = true; @@ -216,6 +221,11 @@ bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()); SVal V = State->getSVal(FR); + if (auto LocAsInt = V.getAs()) { + NeedsCastBack = true; + V = LocAsInt->getLoc(); + } + assert(V.getAs() && "V must be loc::MemRegionVal!"); // If V is multiple pointer value, we'll dereference it again (e.g.: int** -> @@ -242,6 +252,9 @@ } V = State->getSVal(*Tmp, DynT); + // TODO: Handle the case where V is nonloc::LocAsInteger, while avoiding + // infinite loops in the following sinister case: + // int *ptr = reinterpret_cast(ptr); } return std::make_tuple(V, DynT, NeedsCastBack); Index: test/Analysis/cxx-uninitialized-object-ptr-ref.cpp =================================================================== --- test/Analysis/cxx-uninitialized-object-ptr-ref.cpp +++ test/Analysis/cxx-uninitialized-object-ptr-ref.cpp @@ -22,6 +22,24 @@ } //===----------------------------------------------------------------------===// +// nonloc::LocAsInteger tests. +//===----------------------------------------------------------------------===// + +using intptr_t = long; + +struct LocAsIntegerTest { + intptr_t ptr; // expected-note{{uninitialized pointee 'reinterpret_cast(this->ptr)'}} + int dontGetFilteredByNonPedanticMode = 0; + + LocAsIntegerTest(void *ptr) : ptr(reinterpret_cast(ptr)) {} // expected-warning{{1 uninitialized field}} +}; + +void fLocAsIntegerTest() { + char c; + LocAsIntegerTest t(&c); +} + +//===----------------------------------------------------------------------===// // Null pointer tests. //===----------------------------------------------------------------------===//