]> granicus.if.org Git - clang/commitdiff
[analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger
authorKristof Umann <dkszelethus@gmail.com>
Fri, 14 Sep 2018 10:18:26 +0000 (10:18 +0000)
committerKristof Umann <dkszelethus@gmail.com>
Fri, 14 Sep 2018 10:18:26 +0000 (10:18 +0000)
Differential Revision: https://reviews.llvm.org/D49437

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@342221 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp
lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp
test/Analysis/cxx-uninitialized-object-ptr-ref.cpp

index b6322293212c9ff648d82a6e3dae8e1dfd8b8747..711b43f3b58fd917cce095707ea30c0a06c62505 100644 (file)
@@ -274,15 +274,15 @@ bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R,
       continue;
     }
 
-    if (isDereferencableType(T)) {
+    SVal V = State->getSVal(FieldVal);
+
+    if (isDereferencableType(T) || V.getAs<nonloc::LocAsInteger>()) {
       if (isDereferencableUninit(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 fa7cf1888bd45423c165f339a3feff4e0de7ea2a..f60fc0dfe0fc9d1c0b72018e617a2d1a5d45694a 100644 (file)
@@ -57,9 +57,9 @@ public:
   }
 };
 
-/// Represents a void* field that needs to be casted back to its dynamic type
-/// for a correct note message.
-class NeedsCastLocField final : public FieldNode {
+/// 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 : public FieldNode {
   QualType CastBackType;
 
 public:
@@ -71,7 +71,13 @@ public:
   }
 
   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 {
@@ -106,11 +112,12 @@ static llvm::Optional<DereferenceInfo> dereference(ProgramStateRef State,
 bool FindUninitializedFields::isDereferencableUninit(
     const FieldRegion *FR, FieldChainInfo LocalChain) {
 
-  assert(isDereferencableType(FR->getDecl()->getType()) &&
-         "This method only checks dereferencable objects!");
-
   SVal V = State->getSVal(FR);
 
+  assert((isDereferencableType(FR->getDecl()->getType()) ||
+          V.getAs<nonloc::LocAsInteger>()) &&
+         "This method only checks dereferencable objects!");
+
   if (V.isUnknown() || V.getAs<loc::ConcreteInt>()) {
     IsAnyFieldInitialized = true;
     return false;
@@ -196,13 +203,15 @@ static llvm::Optional<DereferenceInfo> dereference(ProgramStateRef State,
 
   llvm::SmallSet<const TypedValueRegion *, 5> VisitedRegions;
 
-  // If the static type of the field is a void pointer, we need to cast it back
-  // to the dynamic type before dereferencing.
-  bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType());
-
   SVal V = State->getSVal(FR);
   assert(V.getAsRegion() && "V must have an underlying region!");
 
+  // If the static type of the field is a void pointer, or it is a
+  // nonloc::LocAsInteger, we need to cast it back to the dynamic type before
+  // dereferencing.
+  bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()) ||
+                       V.getAs<nonloc::LocAsInteger>();
+
   // The region we'd like to acquire.
   const auto *R = V.getAsRegion()->getAs<TypedValueRegion>();
   if (!R)
index 4ee113c9e8f4c8be581ad78803d645be1435e968..7669ac510f19e62d1094a9e68e2e5013daeb067a 100644 (file)
@@ -21,6 +21,24 @@ void fConcreteIntLocTest() {
   ConcreteIntLocTest();
 }
 
+//===----------------------------------------------------------------------===//
+// nonloc::LocAsInteger tests.
+//===----------------------------------------------------------------------===//
+
+using intptr_t = long;
+
+struct LocAsIntegerTest {
+  intptr_t ptr; // expected-note{{uninitialized pointee 'reinterpret_cast<char *>(this->ptr)'}}
+  int dontGetFilteredByNonPedanticMode = 0;
+
+  LocAsIntegerTest(void *ptr) : ptr(reinterpret_cast<intptr_t>(ptr)) {} // expected-warning{{1 uninitialized field}}
+};
+
+void fLocAsIntegerTest() {
+  char c;
+  LocAsIntegerTest t(&c);
+}
+
 //===----------------------------------------------------------------------===//
 // Null pointer tests.
 //===----------------------------------------------------------------------===//