li.zhe.hua updated this revision to Diff 442291. li.zhe.hua marked 2 inline comments as done. li.zhe.hua added a comment.
Address comments. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D129097/new/ https://reviews.llvm.org/D129097 Files: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Index: clang/unittests/Analysis/FlowSensitive/TransferTest.cpp =================================================================== --- clang/unittests/Analysis/FlowSensitive/TransferTest.cpp +++ clang/unittests/Analysis/FlowSensitive/TransferTest.cpp @@ -2213,12 +2213,14 @@ TEST(TransferTest, NullToPointerCast) { std::string Code = R"( + using my_nullptr_t = decltype(nullptr); struct Baz {}; void target() { int *FooX = nullptr; int *FooY = nullptr; bool **Bar = nullptr; Baz *Baz = nullptr; + my_nullptr_t Null = 0; // [[p]] } )"; @@ -2242,6 +2244,9 @@ const ValueDecl *BazDecl = findValueDecl(ASTCtx, "Baz"); ASSERT_THAT(BazDecl, NotNull()); + const ValueDecl *NullDecl = findValueDecl(ASTCtx, "Null"); + ASSERT_THAT(NullDecl, NotNull()); + const auto *FooXVal = cast<PointerValue>(Env.getValue(*FooXDecl, SkipPast::None)); const auto *FooYVal = @@ -2250,6 +2255,8 @@ cast<PointerValue>(Env.getValue(*BarDecl, SkipPast::None)); const auto *BazVal = cast<PointerValue>(Env.getValue(*BazDecl, SkipPast::None)); + const auto *NullVal = + cast<PointerValue>(Env.getValue(*NullDecl, SkipPast::None)); EXPECT_EQ(FooXVal, FooYVal); EXPECT_NE(FooXVal, BarVal); @@ -2267,6 +2274,11 @@ const StorageLocation &BazPointeeLoc = BazVal->getPointeeLoc(); EXPECT_TRUE(isa<AggregateStorageLocation>(BazPointeeLoc)); EXPECT_THAT(Env.getValue(BazPointeeLoc), IsNull()); + + const StorageLocation &NullPointeeLoc = + NullVal->getPointeeLoc(); + EXPECT_TRUE(isa<ScalarStorageLocation>(NullPointeeLoc)); + EXPECT_THAT(Env.getValue(NullPointeeLoc), IsNull()); }); } Index: clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp =================================================================== --- clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp +++ clang/lib/Analysis/FlowSensitive/DataflowAnalysisContext.cpp @@ -24,8 +24,8 @@ StorageLocation & DataflowAnalysisContext::getStableStorageLocation(QualType Type) { - assert(!Type.isNull()); - if (Type->isStructureOrClassType() || Type->isUnionType()) { + if (!Type.isNull() && + (Type->isStructureOrClassType() || Type->isUnionType())) { // FIXME: Explore options to avoid eager initialization of fields as some of // them might not be needed for a particular analysis. llvm::DenseMap<const ValueDecl *, StorageLocation *> FieldLocs; @@ -57,8 +57,8 @@ PointerValue & DataflowAnalysisContext::getOrCreateNullPointerValue(QualType PointeeType) { - assert(!PointeeType.isNull()); - auto CanonicalPointeeType = PointeeType.getCanonicalType(); + auto CanonicalPointeeType = + PointeeType.isNull() ? PointeeType : PointeeType.getCanonicalType(); auto Res = NullPointerVals.try_emplace(CanonicalPointeeType, nullptr); if (Res.second) { auto &PointeeLoc = getStableStorageLocation(CanonicalPointeeType); Index: clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h =================================================================== --- clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h +++ clang/include/clang/Analysis/FlowSensitive/DataflowAnalysisContext.h @@ -155,6 +155,7 @@ /// Returns a pointer value that represents a null pointer. Calls with /// `PointeeType` that are canonically equivalent will return the same result. + /// A null `PointeeType` can be used for the pointee of `std::nullptr_t`. PointerValue &getOrCreateNullPointerValue(QualType PointeeType); /// Returns a symbolic boolean value that models a boolean literal equal to @@ -251,6 +252,17 @@ bool equivalentBoolValues(BoolValue &Val1, BoolValue &Val2); private: + struct NullableQualTypeDenseMapInfo : private llvm::DenseMapInfo<QualType> { + static QualType getEmptyKey() { + // Allow a NULL `QualType` by using a different value as the empty key. + return QualType::getFromOpaquePtr(reinterpret_cast<Type *>(1)); + } + + using DenseMapInfo::getHashValue; + using DenseMapInfo::getTombstoneKey; + using DenseMapInfo::isEqual; + }; + /// Adds all constraints of the flow condition identified by `Token` and all /// of its transitive dependencies to `Constraints`. `VisitedTokens` is used /// to track tokens of flow conditions that were already visited by recursive @@ -311,7 +323,8 @@ // required to initialize the `PointeeLoc` field in `PointerValue`. Consider // creating a type-independent `NullPointerValue` without a `PointeeLoc` // field. - llvm::DenseMap<QualType, PointerValue *> NullPointerVals; + llvm::DenseMap<QualType, PointerValue *, NullableQualTypeDenseMapInfo> + NullPointerVals; AtomicBoolValue &TrueVal; AtomicBoolValue &FalseVal;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits