mboehme created this revision.
Herald added subscribers: martong, xazax.hun.
Herald added a reviewer: NoQ.
Herald added a project: All.
mboehme requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

DO NOT REVIEW

This is a WIP for discussion only.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D158628

Files:
  clang/include/clang/Analysis/FlowSensitive/Value.h
  clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
  clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
  clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
  clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
  clang/lib/Analysis/FlowSensitive/Transfer.cpp
  clang/lib/Analysis/FlowSensitive/Value.cpp
  clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
  clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
  clang/unittests/Analysis/FlowSensitive/ValueTest.cpp

Index: clang/unittests/Analysis/FlowSensitive/ValueTest.cpp
===================================================================
--- clang/unittests/Analysis/FlowSensitive/ValueTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/ValueTest.cpp
@@ -31,8 +31,8 @@
 
 TEST(ValueTest, AliasedPointersEquivalent) {
   auto L = ScalarStorageLocation(QualType());
-  PointerValue V1(L);
-  PointerValue V2(L);
+  PointerValue V1(&L);
+  PointerValue V2(&L);
   EXPECT_TRUE(areEquivalentValues(V1, V2));
   EXPECT_TRUE(areEquivalentValues(V2, V1));
 }
@@ -60,7 +60,7 @@
 TEST(ValueTest, DifferentKindsNotEquivalent) {
   Arena A;
   auto L = ScalarStorageLocation(QualType());
-  PointerValue V1(L);
+  PointerValue V1(&L);
   TopBoolValue V2(A.makeAtomRef(Atom(0)));
   EXPECT_FALSE(areEquivalentValues(V1, V2));
   EXPECT_FALSE(areEquivalentValues(V2, V1));
@@ -68,9 +68,9 @@
 
 TEST(ValueTest, NotAliasedPointersNotEquivalent) {
   auto L1 = ScalarStorageLocation(QualType());
-  PointerValue V1(L1);
+  PointerValue V1(&L1);
   auto L2 = ScalarStorageLocation(QualType());
-  PointerValue V2(L2);
+  PointerValue V2(&L2);
   EXPECT_FALSE(areEquivalentValues(V1, V2));
   EXPECT_FALSE(areEquivalentValues(V2, V1));
 }
Index: clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
===================================================================
--- clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TypeErasedDataflowAnalysisTest.cpp
@@ -768,7 +768,7 @@
         const auto *FooLoc =
             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
-        EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
+        EXPECT_EQ(BarVal->getPointeeLoc(), FooLoc);
       });
 }
 
Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
===================================================================
--- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -165,7 +165,7 @@
         ASSERT_THAT(FooValue, NotNull());
 
         EXPECT_TRUE(isa<RecordStorageLocation>(FooValue->getPointeeLoc()));
-        auto *FooPointeeValue = Env.getValue(FooValue->getPointeeLoc());
+        auto *FooPointeeValue = Env.getValue(*FooValue->getPointeeLoc());
         ASSERT_THAT(FooPointeeValue, NotNull());
         EXPECT_TRUE(isa<RecordValue>(FooPointeeValue));
       });
@@ -496,7 +496,7 @@
     const auto &FooPtrVal =
         *cast<PointerValue>(getFieldValue(&BarLoc, *FooPtrDecl, Env));
     const auto &FooPtrPointeeLoc =
-        cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
+        *cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
     EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), NotNull());
     EXPECT_THAT(getFieldValue(&FooPtrPointeeLoc, *BarDecl, Env), IsNull());
 
@@ -504,8 +504,9 @@
 
     const auto &BazPtrVal =
         *cast<PointerValue>(getFieldValue(&BarLoc, *BazPtrDecl, Env));
-    const StorageLocation &BazPtrPointeeLoc = BazPtrVal.getPointeeLoc();
-    EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
+    const StorageLocation *BazPtrPointeeLoc = BazPtrVal.getPointeeLoc();
+    ASSERT_THAT(BazPtrPointeeLoc, NotNull());
+    EXPECT_THAT(Env.getValue(*BazPtrPointeeLoc), NotNull());
   });
 }
 
@@ -534,8 +535,8 @@
         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
 
         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
-        const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
-        EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));
+        const auto &FooPointeeLoc =
+            *cast<RecordStorageLocation>(FooVal->getPointeeLoc());
 
         const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
         EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooPointeeVal));
@@ -637,28 +638,32 @@
         const auto &FooLoc =
             *cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
         const auto &FooVal = *cast<PointerValue>(Env.getValue(FooLoc));
+        ASSERT_THAT(FooVal.getPointeeLoc(), NotNull());
         const auto &FooPointeeVal =
-            *cast<RecordValue>(Env.getValue(FooVal.getPointeeLoc()));
+            *cast<RecordValue>(Env.getValue(*FooVal.getPointeeLoc()));
 
         const auto &BarVal =
             *cast<PointerValue>(getFieldValue(&FooPointeeVal, *BarDecl, Env));
+        ASSERT_THAT(BarVal.getPointeeLoc(), NotNull());
         const auto &BarPointeeVal =
-            *cast<RecordValue>(Env.getValue(BarVal.getPointeeLoc()));
+            *cast<RecordValue>(Env.getValue(*BarVal.getPointeeLoc()));
 
         EXPECT_THAT(getFieldValue(&BarPointeeVal, *FooRefDecl, Env), NotNull());
 
         const auto &FooPtrVal = *cast<PointerValue>(
             getFieldValue(&BarPointeeVal, *FooPtrDecl, Env));
+        ASSERT_THAT(FooPtrVal.getPointeeLoc(), NotNull());
         const auto &FooPtrPointeeLoc =
-            cast<RecordStorageLocation>(FooPtrVal.getPointeeLoc());
+            cast<RecordStorageLocation>(*FooPtrVal.getPointeeLoc());
         EXPECT_THAT(Env.getValue(FooPtrPointeeLoc), IsNull());
 
         EXPECT_THAT(getFieldValue(&BarPointeeVal, *BazRefDecl, Env), NotNull());
 
         const auto &BazPtrVal = *cast<PointerValue>(
             getFieldValue(&BarPointeeVal, *BazPtrDecl, Env));
-        const StorageLocation &BazPtrPointeeLoc = BazPtrVal.getPointeeLoc();
-        EXPECT_THAT(Env.getValue(BazPtrPointeeLoc), NotNull());
+        const StorageLocation *BazPtrPointeeLoc = BazPtrVal.getPointeeLoc();
+        ASSERT_THAT(BazPtrPointeeLoc, NotNull());
+        EXPECT_THAT(Env.getValue(*BazPtrPointeeLoc), NotNull());
       });
 }
 
@@ -915,7 +920,8 @@
         ASSERT_THAT(BarDecl, NotNull());
 
         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
-        EXPECT_EQ(Env.getValue(BarVal->getPointeeLoc()), FooVal);
+        ASSERT_THAT(BarVal->getPointeeLoc(), NotNull());
+        EXPECT_EQ(Env.getValue(*BarVal->getPointeeLoc()), FooVal);
 
         const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz");
         ASSERT_THAT(BazDecl, NotNull());
@@ -1099,10 +1105,10 @@
         ASSERT_TRUE(isa_and_nonnull<ScalarStorageLocation>(FooLoc));
 
         const PointerValue *FooVal = cast<PointerValue>(Env.getValue(*FooLoc));
-        const StorageLocation &FooPointeeLoc = FooVal->getPointeeLoc();
-        EXPECT_TRUE(isa<RecordStorageLocation>(&FooPointeeLoc));
+        const StorageLocation *FooPointeeLoc = FooVal->getPointeeLoc();
+        EXPECT_TRUE(isa<RecordStorageLocation>(FooPointeeLoc));
 
-        const Value *FooPointeeVal = Env.getValue(FooPointeeLoc);
+        const Value *FooPointeeVal = Env.getValue(*FooPointeeLoc);
         EXPECT_TRUE(isa_and_nonnull<RecordValue>(FooPointeeVal));
       });
 }
@@ -2521,21 +2527,21 @@
         EXPECT_NE(FooXVal, BazVal);
         EXPECT_NE(BarVal, BazVal);
 
-        const StorageLocation &FooPointeeLoc = FooXVal->getPointeeLoc();
+        const StorageLocation *FooPointeeLoc = FooXVal->getPointeeLoc();
         EXPECT_TRUE(isa<ScalarStorageLocation>(FooPointeeLoc));
-        EXPECT_THAT(Env.getValue(FooPointeeLoc), IsNull());
+        EXPECT_THAT(Env.getValue(*FooPointeeLoc), IsNull());
 
-        const StorageLocation &BarPointeeLoc = BarVal->getPointeeLoc();
+        const StorageLocation *BarPointeeLoc = BarVal->getPointeeLoc();
         EXPECT_TRUE(isa<ScalarStorageLocation>(BarPointeeLoc));
-        EXPECT_THAT(Env.getValue(BarPointeeLoc), IsNull());
+        EXPECT_THAT(Env.getValue(*BarPointeeLoc), IsNull());
 
-        const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc();
+        const StorageLocation *BazPointeeLoc = BazVal->getPointeeLoc();
         EXPECT_TRUE(isa<RecordStorageLocation>(BazPointeeLoc));
-        EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull());
+        EXPECT_THAT(Env.getValue(*BazPointeeLoc), IsNull());
 
-        const StorageLocation &NullPointeeLoc = NullVal->getPointeeLoc();
+        const StorageLocation *NullPointeeLoc = NullVal->getPointeeLoc();
         EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc));
-        EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull());
+        EXPECT_THAT(Env.getValue(*NullPointeeLoc), IsNull());
       });
 }
 
@@ -2631,7 +2637,7 @@
         const auto *FooLoc =
             cast<ScalarStorageLocation>(Env.getStorageLocation(*FooDecl));
         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
-        EXPECT_EQ(&BarVal->getPointeeLoc(), FooLoc);
+        EXPECT_EQ(BarVal->getPointeeLoc(), FooLoc);
       });
 }
 
@@ -2657,7 +2663,7 @@
 
         const auto *FooVal = cast<PointerValue>(Env.getValue(*FooDecl));
         const auto *BarVal = cast<PointerValue>(Env.getValue(*BarDecl));
-        EXPECT_EQ(&BarVal->getPointeeLoc(), &FooVal->getPointeeLoc());
+        EXPECT_EQ(BarVal->getPointeeLoc(), FooVal->getPointeeLoc());
       });
 }
 
@@ -2747,8 +2753,9 @@
 
         const auto *FooVal =
             cast<PointerValue>(EnvAfterLoop.getValue(*FooDecl));
+        ASSERT_THAT(FooVal->getPointeeLoc(), NotNull());
         const auto *FooPointeeVal =
-            cast<IntegerValue>(EnvAfterLoop.getValue(FooVal->getPointeeLoc()));
+            cast<IntegerValue>(EnvAfterLoop.getValue(*FooVal->getPointeeLoc()));
 
         const auto *BarVal = cast<IntegerValue>(EnvInLoop.getValue(*BarDecl));
         EXPECT_EQ(BarVal, FooPointeeVal);
@@ -3814,8 +3821,7 @@
         auto *LVal = dyn_cast<PointerValue>(InnerEnv.getValue(*LDecl));
         ASSERT_THAT(LVal, NotNull());
 
-        EXPECT_EQ(&LVal->getPointeeLoc(),
-                  InnerEnv.getStorageLocation(*ValDecl));
+        EXPECT_EQ(LVal->getPointeeLoc(), InnerEnv.getStorageLocation(*ValDecl));
 
         // Outer.
         LVal = dyn_cast<PointerValue>(OuterEnv.getValue(*LDecl));
@@ -3823,8 +3829,7 @@
 
         // The loop body may not have been executed, so we should not conclude
         // that `l` points to `val`.
-        EXPECT_NE(&LVal->getPointeeLoc(),
-                  OuterEnv.getStorageLocation(*ValDecl));
+        EXPECT_NE(LVal->getPointeeLoc(), OuterEnv.getStorageLocation(*ValDecl));
       });
 }
 
@@ -3843,10 +3848,7 @@
       }
     }
   )cc";
-  // FIXME: Implement pointer value widening to make analysis converge.
-  ASSERT_THAT_ERROR(
-      checkDataflowWithNoopAnalysis(Code),
-      llvm::FailedWithMessage("maximum number of iterations reached"));
+  ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
 }
 
 TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
@@ -3869,9 +3871,7 @@
     }
   )cc";
   // FIXME: Implement pointer value widening to make analysis converge.
-  ASSERT_THAT_ERROR(
-      checkDataflowWithNoopAnalysis(Code),
-      llvm::FailedWithMessage("maximum number of iterations reached"));
+  ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
 }
 
 TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {
@@ -5470,7 +5470,8 @@
 
         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
 
-        EXPECT_THAT(Env.getValue(P.getPointeeLoc()), NotNull());
+        ASSERT_THAT(P.getPointeeLoc(), NotNull());
+        EXPECT_THAT(Env.getValue(*P.getPointeeLoc()), NotNull());
       });
 }
 
@@ -5504,7 +5505,7 @@
 
         auto &P = getValueForDecl<PointerValue>(ASTCtx, Env, "p");
 
-        auto &OuterLoc = cast<RecordStorageLocation>(P.getPointeeLoc());
+        auto &OuterLoc = *cast<RecordStorageLocation>(P.getPointeeLoc());
         auto &OuterFieldLoc =
             *cast<RecordStorageLocation>(OuterLoc.getChild(*OuterField));
         auto &InnerFieldLoc = *OuterFieldLoc.getChild(*InnerField);
@@ -5545,13 +5546,13 @@
             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p1");
         auto &NonMemberP2 =
             getValueForDecl<PointerValue>(ASTCtx, Env, "non_member_p2");
-        EXPECT_EQ(&NonMemberP1.getPointeeLoc(), &NonMemberP2.getPointeeLoc());
+        EXPECT_EQ(NonMemberP1.getPointeeLoc(), NonMemberP2.getPointeeLoc());
 
         auto &MemberP1 =
             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p1");
         auto &MemberP2 =
             getValueForDecl<PointerValue>(ASTCtx, Env, "member_p2");
-        EXPECT_EQ(&MemberP1.getPointeeLoc(), &MemberP2.getPointeeLoc());
+        EXPECT_EQ(MemberP1.getPointeeLoc(), MemberP2.getPointeeLoc());
       });
 }
 
Index: clang/lib/Analysis/FlowSensitive/Value.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/Value.cpp
+++ clang/lib/Analysis/FlowSensitive/Value.cpp
@@ -21,7 +21,7 @@
                                            const Value &Val2) {
   if (auto *IndVal1 = dyn_cast<PointerValue>(&Val1)) {
     auto *IndVal2 = cast<PointerValue>(&Val2);
-    return &IndVal1->getPointeeLoc() == &IndVal2->getPointeeLoc();
+    return IndVal1->getPointeeLoc() == IndVal2->getPointeeLoc();
   }
   return false;
 }
@@ -36,7 +36,7 @@
   switch (Val.getKind()) {
   case Value::Kind::Pointer: {
     const auto *PV = dyn_cast<PointerValue>(&Val);
-    return OS << "Pointer(" << &PV->getPointeeLoc() << ")";
+    return OS << "Pointer(" << PV->getPointeeLoc() << ")";
   }
   // FIXME: support remaining cases.
   default:
Index: clang/lib/Analysis/FlowSensitive/Transfer.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -315,7 +315,7 @@
       if (PointeeLoc == nullptr)
         break;
 
-      Env.setValue(*S, Env.create<PointerValue>(*PointeeLoc));
+      Env.setValue(*S, Env.create<PointerValue>(PointeeLoc));
       break;
     }
     case CK_BuiltinFnToFnPtr:
@@ -340,7 +340,8 @@
       if (SubExprVal == nullptr)
         break;
 
-      Env.setStorageLocation(*S, SubExprVal->getPointeeLoc());
+      if (SubExprVal->getPointeeLoc() != nullptr)
+        Env.setStorageLocation(*S, *SubExprVal->getPointeeLoc());
       break;
     }
     case UO_AddrOf: {
@@ -349,7 +350,7 @@
         break;
 
       if (StorageLocation *PointeeLoc = Env.getStorageLocation(*SubExpr))
-        Env.setValue(*S, Env.create<PointerValue>(*PointeeLoc));
+        Env.setValue(*S, Env.create<PointerValue>(PointeeLoc));
       break;
     }
     case UO_LNot: {
@@ -372,7 +373,7 @@
       // `this` expression's pointee.
       return;
 
-    Env.setValue(*S, Env.create<PointerValue>(*ThisPointeeLoc));
+    Env.setValue(*S, Env.create<PointerValue>(ThisPointeeLoc));
   }
 
   void VisitCXXNewExpr(const CXXNewExpr *S) {
Index: clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
+++ clang/lib/Analysis/FlowSensitive/Models/UncheckedOptionalAccessModel.cpp
@@ -315,40 +315,43 @@
   // `Value` representing the optional (here, `OptionalVal`).
   if (auto *ValueProp = OptionalVal.getProperty("value")) {
     auto *ValuePtr = clang::cast<PointerValue>(ValueProp);
-    auto &ValueLoc = ValuePtr->getPointeeLoc();
-    if (Env.getValue(ValueLoc) != nullptr)
-      return &ValueLoc;
-
-    // The property was previously set, but the value has been lost. This can
-    // happen in various situations, for example:
-    // - Because of an environment merge (where the two environments mapped the
-    //   property to different values, which resulted in them both being
-    //   discarded).
-    // - When two blocks in the CFG, with neither a dominator of the other,
-    //   visit the same optional value. (FIXME: This is something we can and
-    //   should fix -- see also the lengthy FIXME below.)
-    // - Or even when a block is revisited during testing to collect
-    //   per-statement state.
-    // FIXME: This situation means that the optional contents are not shared
-    // between branches and the like. Practically, this lack of sharing
-    // reduces the precision of the model when the contents are relevant to
-    // the check, like another optional or a boolean that influences control
-    // flow.
-    if (ValueLoc.getType()->isRecordType()) {
-      refreshRecordValue(cast<RecordStorageLocation>(ValueLoc), Env);
-      return &ValueLoc;
-    } else {
-      auto *ValueVal = Env.createValue(ValueLoc.getType());
-      if (ValueVal == nullptr)
-        return nullptr;
-      Env.setValue(ValueLoc, *ValueVal);
-      return &ValueLoc;
+    auto *ValueLoc = ValuePtr->getPointeeLoc();
+    if (ValueLoc != nullptr) {
+      if (Env.getValue(*ValueLoc) != nullptr)
+        return ValueLoc;
+
+      // The property was previously set, but the value has been lost. This can
+      // happen in various situations, for example:
+      // - Because of an environment merge (where the two environments mapped
+      // the
+      //   property to different values, which resulted in them both being
+      //   discarded).
+      // - When two blocks in the CFG, with neither a dominator of the other,
+      //   visit the same optional value. (FIXME: This is something we can and
+      //   should fix -- see also the lengthy FIXME below.)
+      // - Or even when a block is revisited during testing to collect
+      //   per-statement state.
+      // FIXME: This situation means that the optional contents are not shared
+      // between branches and the like. Practically, this lack of sharing
+      // reduces the precision of the model when the contents are relevant to
+      // the check, like another optional or a boolean that influences control
+      // flow.
+      if (ValueLoc->getType()->isRecordType()) {
+        refreshStructValue(cast<RecordStorageLocation>(*ValueLoc), Env);
+        return ValueLoc;
+      } else {
+        auto *ValueVal = Env.createValue(ValueLoc->getType());
+        if (ValueVal == nullptr)
+          return nullptr;
+        Env.setValue(*ValueLoc, *ValueVal);
+        return ValueLoc;
+      }
     }
   }
 
   auto Ty = Q.getNonReferenceType();
   auto &ValueLoc = Env.createObject(Ty);
-  auto &ValuePtr = Env.create<PointerValue>(ValueLoc);
+  auto &ValuePtr = Env.create<PointerValue>(&ValueLoc);
   // FIXME:
   // The change we make to the `value` property below may become visible to
   // other blocks that aren't successors of the current block and therefore
@@ -429,7 +432,8 @@
 Value *getValueBehindPossiblePointer(const Expr &E, const Environment &Env) {
   Value *Val = Env.getValue(E);
   if (auto *PointerVal = dyn_cast_or_null<PointerValue>(Val))
-    return Env.getValue(PointerVal->getPointeeLoc());
+    if (PointerVal->getPointeeLoc() != nullptr)
+      return Env.getValue(*PointerVal->getPointeeLoc());
   return Val;
 }
 
@@ -450,7 +454,7 @@
           getValueBehindPossiblePointer(*ObjectExpr, State.Env)) {
     if (auto *Loc = maybeInitializeOptionalValueMember(
             UnwrapExpr->getType()->getPointeeType(), *OptionalVal, State.Env)) {
-      State.Env.setValue(*UnwrapExpr, State.Env.create<PointerValue>(*Loc));
+      State.Env.setValue(*UnwrapExpr, State.Env.create<PointerValue>(Loc));
     }
   }
 }
Index: clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
+++ clang/lib/Analysis/FlowSensitive/HTMLLogger.cpp
@@ -100,8 +100,8 @@
     case Value::Kind::FormulaBool:
       break;
     case Value::Kind::Pointer:
-      JOS.attributeObject(
-          "pointee", [&] { dump(cast<PointerValue>(V).getPointeeLoc()); });
+      if (StorageLocation *PointeeLoc = cast<PointerValue>(V).getPointeeLoc())
+        JOS.attributeObject("pointee", [&] { dump(*PointeeLoc); });
       break;
     case Value::Kind::Record:
       for (const auto &Child : cast<RecordValue>(V).getLoc().children())
Index: clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -161,6 +161,14 @@
     return CurrentEnv.makeTopBoolValue();
   }
 
+  if (auto *PrevPtr = dyn_cast<PointerValue>(&Prev)) {
+    auto &CurPtr = cast<PointerValue>(Current);
+
+    if (PrevPtr->getPointeeLoc() != CurPtr.getPointeeLoc())
+      // TODO: Preserve properties
+      return CurrentEnv.create<PointerValue>(nullptr);
+  }
+
   // FIXME: Add other built-in model widening.
 
   // Custom-model widening.
@@ -757,7 +765,7 @@
     StorageLocation &PointeeLoc =
         createLocAndMaybeValue(PointeeType, Visited, Depth, CreatedValuesCount);
 
-    return &arena().create<PointerValue>(PointeeLoc);
+    return &arena().create<PointerValue>(&PointeeLoc);
   }
 
   if (Type->isRecordType()) {
@@ -899,7 +907,7 @@
     return nullptr;
   if (ImplicitObject->getType()->isPointerType()) {
     if (auto *Val = cast_or_null<PointerValue>(Env.getValue(*ImplicitObject)))
-      return &cast<RecordStorageLocation>(Val->getPointeeLoc());
+      return cast_or_null<RecordStorageLocation>(Val->getPointeeLoc());
     return nullptr;
   }
   return cast_or_null<RecordStorageLocation>(
@@ -913,7 +921,7 @@
     return nullptr;
   if (ME.isArrow()) {
     if (auto *Val = cast_or_null<PointerValue>(Env.getValue(*Base)))
-      return &cast<RecordStorageLocation>(Val->getPointeeLoc());
+      return cast_or_null<RecordStorageLocation>(Val->getPointeeLoc());
     return nullptr;
   }
   return cast_or_null<RecordStorageLocation>(Env.getStorageLocation(*Base));
Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
===================================================================
--- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
+++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp
@@ -97,7 +97,7 @@
   auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr);
   if (Res.second) {
     auto &PointeeLoc = createStorageLocation(CanonicalPointeeType);
-    Res.first->second = &arena().create<PointerValue>(PointeeLoc);
+    Res.first->second = &arena().create<PointerValue>(&PointeeLoc);
   }
   return *Res.first->second;
 }
Index: clang/include/clang/Analysis/FlowSensitive/Value.h
===================================================================
--- clang/include/clang/Analysis/FlowSensitive/Value.h
+++ clang/include/clang/Analysis/FlowSensitive/Value.h
@@ -169,17 +169,17 @@
 /// Models a symbolic pointer. Specifically, any value of type `T*`.
 class PointerValue final : public Value {
 public:
-  explicit PointerValue(StorageLocation &PointeeLoc)
+  explicit PointerValue(StorageLocation *PointeeLoc)
       : Value(Kind::Pointer), PointeeLoc(PointeeLoc) {}
 
   static bool classof(const Value *Val) {
     return Val->getKind() == Kind::Pointer;
   }
 
-  StorageLocation &getPointeeLoc() const { return PointeeLoc; }
+  StorageLocation *getPointeeLoc() const { return PointeeLoc; }
 
 private:
-  StorageLocation &PointeeLoc;
+  StorageLocation *PointeeLoc;
 };
 
 /// Models a value of `struct` or `class` type.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to