llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang @llvm/pr-subscribers-clang-ssaf Author: Balázs Benics (steakhal) <details> <summary>Changes</summary> Also adds a ssaf::TestFixture to provide access to the private fields of the SSAF object for introspection. Assisted-By: claude rdar://168773578 --- Patch is 24.14 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/181220.diff 14 Files Affected: - (modified) clang/include/clang/Analysis/Scalable/Model/BuildNamespace.h (+3-4) - (modified) clang/include/clang/Analysis/Scalable/Model/EntityId.h (+1) - (modified) clang/include/clang/Analysis/Scalable/Model/EntityName.h (+1-1) - (modified) clang/include/clang/Analysis/Scalable/Model/SummaryName.h (+1) - (modified) clang/include/clang/Analysis/Scalable/TUSummary/TUSummary.h (+2) - (modified) clang/include/clang/Analysis/Scalable/TUSummary/TUSummaryBuilder.h (+21-1) - (modified) clang/lib/Analysis/Scalable/CMakeLists.txt (+1) - (added) clang/lib/Analysis/Scalable/TUSummary/TUSummaryBuilder.cpp (+17) - (modified) clang/unittests/Analysis/Scalable/CMakeLists.txt (+2) - (modified) clang/unittests/Analysis/Scalable/Registries/MockTUSummaryBuilder.h (+1) - (modified) clang/unittests/Analysis/Scalable/Registries/SummaryExtractorRegistryTest.cpp (+12-3) - (added) clang/unittests/Analysis/Scalable/TUSummaryBuilderTest.cpp (+297) - (added) clang/unittests/Analysis/Scalable/TestFixture.cpp (+29) - (added) clang/unittests/Analysis/Scalable/TestFixture.h (+34) ``````````diff diff --git a/clang/include/clang/Analysis/Scalable/Model/BuildNamespace.h b/clang/include/clang/Analysis/Scalable/Model/BuildNamespace.h index 5ca26df1e9252..2cd8990708b8d 100644 --- a/clang/include/clang/Analysis/Scalable/Model/BuildNamespace.h +++ b/clang/include/clang/Analysis/Scalable/Model/BuildNamespace.h @@ -63,6 +63,7 @@ class BuildNamespace { bool operator<(const BuildNamespace &Other) const; friend class SerializationFormat; + friend class TestFixture; }; /// Represents a hierarchical sequence of build namespaces. @@ -75,8 +76,6 @@ class BuildNamespace { /// For example, an entity might be qualified by a compilation unit namespace /// followed by a shared library namespace. class NestedBuildNamespace { - friend class SerializationFormat; - std::vector<BuildNamespace> Namespaces; public: @@ -114,8 +113,8 @@ class NestedBuildNamespace { bool operator!=(const NestedBuildNamespace &Other) const; bool operator<(const NestedBuildNamespace &Other) const; - friend class JSONWriter; - friend class LinkUnitResolution; + friend class SerializationFormat; + friend class TestFixture; }; } // namespace clang::ssaf diff --git a/clang/include/clang/Analysis/Scalable/Model/EntityId.h b/clang/include/clang/Analysis/Scalable/Model/EntityId.h index 6fa059445d853..755a60e40cc68 100644 --- a/clang/include/clang/Analysis/Scalable/Model/EntityId.h +++ b/clang/include/clang/Analysis/Scalable/Model/EntityId.h @@ -29,6 +29,7 @@ class EntityIdTable; /// \see EntityIdTable class EntityId { friend class EntityIdTable; + friend class TestFixture; size_t Index; diff --git a/clang/include/clang/Analysis/Scalable/Model/EntityName.h b/clang/include/clang/Analysis/Scalable/Model/EntityName.h index 23890ab7bea43..72dd9ac803052 100644 --- a/clang/include/clang/Analysis/Scalable/Model/EntityName.h +++ b/clang/include/clang/Analysis/Scalable/Model/EntityName.h @@ -47,8 +47,8 @@ class EntityName { /// \param Namespace The namespace steps to append to this entity's namespace. EntityName makeQualified(NestedBuildNamespace Namespace) const; - friend class LinkUnitResolution; friend class SerializationFormat; + friend class TestFixture; }; } // namespace clang::ssaf diff --git a/clang/include/clang/Analysis/Scalable/Model/SummaryName.h b/clang/include/clang/Analysis/Scalable/Model/SummaryName.h index 785fe0eb10372..36a8cf5da78b1 100644 --- a/clang/include/clang/Analysis/Scalable/Model/SummaryName.h +++ b/clang/include/clang/Analysis/Scalable/Model/SummaryName.h @@ -31,6 +31,7 @@ class SummaryName { private: std::string Name; + friend class TestFixture; }; } // namespace clang::ssaf diff --git a/clang/include/clang/Analysis/Scalable/TUSummary/TUSummary.h b/clang/include/clang/Analysis/Scalable/TUSummary/TUSummary.h index 4af1c70e1a488..7d25234a7ca2c 100644 --- a/clang/include/clang/Analysis/Scalable/TUSummary/TUSummary.h +++ b/clang/include/clang/Analysis/Scalable/TUSummary/TUSummary.h @@ -32,6 +32,8 @@ class TUSummary { TUSummary(BuildNamespace TUNamespace) : TUNamespace(std::move(TUNamespace)) {} friend class SerializationFormat; + friend class TestFixture; + friend class TUSummaryBuilder; }; } // namespace clang::ssaf diff --git a/clang/include/clang/Analysis/Scalable/TUSummary/TUSummaryBuilder.h b/clang/include/clang/Analysis/Scalable/TUSummary/TUSummaryBuilder.h index fa679c145faa5..ad41bfb9450bc 100644 --- a/clang/include/clang/Analysis/Scalable/TUSummary/TUSummaryBuilder.h +++ b/clang/include/clang/Analysis/Scalable/TUSummary/TUSummaryBuilder.h @@ -9,10 +9,30 @@ #ifndef LLVM_CLANG_ANALYSIS_SCALABLE_TUSUMMARY_TUSUMMARYBUILDER_H #define LLVM_CLANG_ANALYSIS_SCALABLE_TUSUMMARY_TUSUMMARYBUILDER_H +#include <memory> + namespace clang::ssaf { +class EntityId; +class EntityName; +class EntitySummary; +class TUSummary; + class TUSummaryBuilder { - // Empty for now. +public: + explicit TUSummaryBuilder(TUSummary &Summary) : Summary(Summary) {} + + /// Add an entity to the summary and return its EntityId. + /// If the entity already exists, returns the existing ID (idempotent). + EntityId addEntity(const EntityName &E); + + /// Add analysis-specific fact data for an entity. + /// Precondition: The ContributingEntity must have been added via addEntity(). + void addFact(EntityId ContributingEntity, + std::unique_ptr<EntitySummary> NewData); + +private: + TUSummary &Summary; }; } // namespace clang::ssaf diff --git a/clang/lib/Analysis/Scalable/CMakeLists.txt b/clang/lib/Analysis/Scalable/CMakeLists.txt index 4145e7a521ba4..1d51a2fa1e67f 100644 --- a/clang/lib/Analysis/Scalable/CMakeLists.txt +++ b/clang/lib/Analysis/Scalable/CMakeLists.txt @@ -9,6 +9,7 @@ add_clang_library(clangAnalysisScalable Model/EntityName.cpp Serialization/SerializationFormatRegistry.cpp TUSummary/ExtractorRegistry.cpp + TUSummary/TUSummaryBuilder.cpp LINK_LIBS clangAST diff --git a/clang/lib/Analysis/Scalable/TUSummary/TUSummaryBuilder.cpp b/clang/lib/Analysis/Scalable/TUSummary/TUSummaryBuilder.cpp new file mode 100644 index 0000000000000..f5ed26b144522 --- /dev/null +++ b/clang/lib/Analysis/Scalable/TUSummary/TUSummaryBuilder.cpp @@ -0,0 +1,17 @@ +#include "clang/Analysis/Scalable/TUSummary/TUSummaryBuilder.h" +#include "clang/Analysis/Scalable/Model/EntityId.h" +#include "clang/Analysis/Scalable/TUSummary/TUSummary.h" +#include <memory> + +using namespace clang; +using namespace ssaf; + +EntityId TUSummaryBuilder::addEntity(const EntityName &E) { + return Summary.IdTable.getId(E); +} + +void TUSummaryBuilder::addFact(EntityId ContributingEntity, + std::unique_ptr<EntitySummary> NewData) { + Summary.Data[NewData->getSummaryName()][ContributingEntity] = + std::move(NewData); +} diff --git a/clang/unittests/Analysis/Scalable/CMakeLists.txt b/clang/unittests/Analysis/Scalable/CMakeLists.txt index 601845b4ab77a..ca3f67a005707 100644 --- a/clang/unittests/Analysis/Scalable/CMakeLists.txt +++ b/clang/unittests/Analysis/Scalable/CMakeLists.txt @@ -11,6 +11,8 @@ add_distinct_clang_unittest(ClangScalableAnalysisTests Registries/SerializationFormatRegistryTest.cpp Registries/SummaryExtractorRegistryTest.cpp SummaryNameTest.cpp + TestFixture.cpp + TUSummaryBuilderTest.cpp CLANG_LIBS clangAnalysisScalable diff --git a/clang/unittests/Analysis/Scalable/Registries/MockTUSummaryBuilder.h b/clang/unittests/Analysis/Scalable/Registries/MockTUSummaryBuilder.h index ccb79ae042625..755a47471a9f8 100644 --- a/clang/unittests/Analysis/Scalable/Registries/MockTUSummaryBuilder.h +++ b/clang/unittests/Analysis/Scalable/Registries/MockTUSummaryBuilder.h @@ -14,6 +14,7 @@ namespace clang::ssaf { class MockTUSummaryBuilder : public TUSummaryBuilder { public: + using TUSummaryBuilder::TUSummaryBuilder; void sendMessage(llvm::Twine Message) { Stream << Message << '\n'; } std::string consumeMessages() { return std::move(OutputBuffer); } diff --git a/clang/unittests/Analysis/Scalable/Registries/SummaryExtractorRegistryTest.cpp b/clang/unittests/Analysis/Scalable/Registries/SummaryExtractorRegistryTest.cpp index 2076fae0b5ab0..a17a4f145b038 100644 --- a/clang/unittests/Analysis/Scalable/Registries/SummaryExtractorRegistryTest.cpp +++ b/clang/unittests/Analysis/Scalable/Registries/SummaryExtractorRegistryTest.cpp @@ -8,6 +8,7 @@ #include "MockTUSummaryBuilder.h" #include "clang/Analysis/Scalable/TUSummary/ExtractorRegistry.h" +#include "clang/Analysis/Scalable/TUSummary/TUSummary.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Tooling/Tooling.h" #include "llvm/ADT/StringRef.h" @@ -17,6 +18,11 @@ using namespace clang; using namespace ssaf; +[[nodiscard]] +static TUSummary makeFakeSummary() { + return BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp"); +} + namespace { TEST(SummaryExtractorRegistryTest, isTUSummaryExtractorRegistered) { @@ -39,7 +45,8 @@ TEST(SummaryExtractorRegistryTest, EnumeratingRegistryEntries) { } TEST(SummaryExtractorRegistryTest, InstantiatingExtractor1) { - MockTUSummaryBuilder FakeBuilder; + TUSummary Summary = makeFakeSummary(); + MockTUSummaryBuilder FakeBuilder(Summary); { auto Consumer = makeTUSummaryExtractor("MockSummaryExtractor1", FakeBuilder); @@ -52,7 +59,8 @@ TEST(SummaryExtractorRegistryTest, InstantiatingExtractor1) { } TEST(SummaryExtractorRegistryTest, InstantiatingExtractor2) { - MockTUSummaryBuilder FakeBuilder; + TUSummary Summary = makeFakeSummary(); + MockTUSummaryBuilder FakeBuilder(Summary); { auto Consumer = makeTUSummaryExtractor("MockSummaryExtractor2", FakeBuilder); @@ -65,7 +73,8 @@ TEST(SummaryExtractorRegistryTest, InstantiatingExtractor2) { } TEST(SummaryExtractorRegistryTest, InvokingExtractors) { - MockTUSummaryBuilder FakeBuilder; + TUSummary Summary = makeFakeSummary(); + MockTUSummaryBuilder FakeBuilder(Summary); std::vector<std::unique_ptr<ASTConsumer>> Consumers; for (std::string Name : {"MockSummaryExtractor1", "MockSummaryExtractor2"}) { auto Consumer = makeTUSummaryExtractor(Name, FakeBuilder); diff --git a/clang/unittests/Analysis/Scalable/TUSummaryBuilderTest.cpp b/clang/unittests/Analysis/Scalable/TUSummaryBuilderTest.cpp new file mode 100644 index 0000000000000..2e40b5caf9ce5 --- /dev/null +++ b/clang/unittests/Analysis/Scalable/TUSummaryBuilderTest.cpp @@ -0,0 +1,297 @@ +//===- unittests/Analysis/Scalable/TUSummaryBuilderTest.cpp ---------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/Scalable/TUSummary/TUSummaryBuilder.h" +#include "TestFixture.h" +#include "clang/Analysis/Scalable/Model/BuildNamespace.h" +#include "clang/Analysis/Scalable/Model/EntityId.h" +#include "clang/Analysis/Scalable/Model/EntityName.h" +#include "clang/Analysis/Scalable/Model/SummaryName.h" +#include "clang/Analysis/Scalable/Serialization/SerializationFormat.h" +#include "clang/Analysis/Scalable/TUSummary/EntitySummary.h" +#include "clang/Analysis/Scalable/TUSummary/TUSummary.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include <type_traits> + +using namespace clang; +using namespace ssaf; + +using llvm::SmallVector; +using testing::Field; +using testing::Optional; +using testing::UnorderedElementsAre; + +[[nodiscard]] +static TUSummary makeFakeSummary() { + return BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp"); +} + +[[nodiscard]] +static EntityId addTestEntity(TUSummaryBuilder &Builder, llvm::StringRef USR) { + return Builder.addEntity(EntityName(USR, /*Suffix=*/"", /*Namespace=*/{})); +} + +template <class ConcreteEntitySummary> +[[nodiscard]] +static SummaryName addFactTo(TUSummaryBuilder &Builder, EntityId ID, + ConcreteEntitySummary Fact) { + static_assert(std::is_base_of_v<EntitySummary, ConcreteEntitySummary>); + auto NewFact = std::make_unique<ConcreteEntitySummary>(std::move(Fact)); + SummaryName Name = NewFact->getSummaryName(); + Builder.addFact(ID, std::move(NewFact)); + return Name; +} + +namespace { + +// Mock EntitySummary classes for testing +struct MockSummaryData1 final : public EntitySummary { + explicit MockSummaryData1(int Value) : Value(Value) {} + SummaryName getSummaryName() const override { + return SummaryName("MockSummary1"); + } + int Value; +}; + +struct MockSummaryData2 final : public EntitySummary { + explicit MockSummaryData2(std::string Text) : Text(std::move(Text)) {} + SummaryName getSummaryName() const override { + return SummaryName("MockSummary2"); + } + std::string Text; +}; + +struct MockSummaryData3 final : public EntitySummary { + explicit MockSummaryData3(bool Flag) : Flag(Flag) {} + SummaryName getSummaryName() const override { + return SummaryName("MockSummary3"); + } + bool Flag; +}; + +void PrintTo(const MockSummaryData1 &S, std::ostream *OS) { + *OS << "MockSummaryData1(" << S.getSummaryName().str().str() << ")"; +} +void PrintTo(const MockSummaryData2 &S, std::ostream *OS) { + *OS << "MockSummaryData2(" << S.getSummaryName().str().str() << ")"; +} +void PrintTo(const MockSummaryData3 &S, std::ostream *OS) { + *OS << "MockSummaryData3(" << S.getSummaryName().str().str() << ")"; +} + +struct TUSummaryBuilderTest : ssaf::TestFixture { + [[nodiscard]] static SmallVector<SummaryName> + summaryNames(const TUSummary &Summary) { + return llvm::to_vector(llvm::make_first_range(getData(Summary))); + } + + [[nodiscard]] static SmallVector<EntityId> + entitiesOfSummary(const TUSummary &Summary, const SummaryName &Name) { + const auto &MappingIt = getData(Summary).find(Name); + if (MappingIt == getData(Summary).end()) + return {}; + return llvm::to_vector(llvm::make_first_range(MappingIt->second)); + } + + template <class ConcreteSummaryData> + [[nodiscard]] static std::optional<ConcreteSummaryData> + getAsEntitySummary(const TUSummary &Summary, const SummaryName &Name, + EntityId E) { + static_assert(std::is_base_of_v<EntitySummary, ConcreteSummaryData>); + const auto &MappingIt = getData(Summary).find(Name); + if (MappingIt == getData(Summary).end()) + return std::nullopt; + auto SummaryIt = MappingIt->second.find(E); + if (SummaryIt == MappingIt->second.end()) + return std::nullopt; + assert(Name == SummaryIt->second->getSummaryName()); + return static_cast<const ConcreteSummaryData &>(*SummaryIt->second); + } +}; + +TEST_F(TUSummaryBuilderTest, AddEntity) { + TUSummary Summary = makeFakeSummary(); + TUSummaryBuilder Builder(Summary); + + EntityName EN1("c:@F@foo", "", /*Namespace=*/{}); + EntityName EN2("c:@F@bar", "", /*Namespace=*/{}); + + EntityId ID = Builder.addEntity(EN1); + EntityId IDAlias = Builder.addEntity(EN1); + EXPECT_EQ(ID, IDAlias); // Idenpotency + + EntityId ID2 = Builder.addEntity(EN2); + EXPECT_NE(ID, ID2); + EXPECT_NE(IDAlias, ID2); + + const EntityIdTable &IdTable = getIdTable(Summary); + EXPECT_EQ(IdTable.count(), 2U); + EXPECT_TRUE(IdTable.contains(EN1)); + EXPECT_TRUE(IdTable.contains(EN2)); +} + +TEST_F(TUSummaryBuilderTest, TUSummaryBuilderAddSingleFact) { + TUSummary Summary = makeFakeSummary(); + TUSummaryBuilder Builder(Summary); + + EntityId ID = addTestEntity(Builder, "c:@F@foo"); + SummaryName Name = addFactTo(Builder, ID, MockSummaryData1(10)); + + // Should have a summary type with an entity. + EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name)); + EXPECT_THAT(entitiesOfSummary(Summary, Name), UnorderedElementsAre(ID)); + + EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name, ID), + Optional(Field(&MockSummaryData1::Value, 10))); +} + +TEST_F(TUSummaryBuilderTest, AddMultipleFactsToSameEntity) { + TUSummary Summary = makeFakeSummary(); + TUSummaryBuilder Builder(Summary); + EntityId ID = addTestEntity(Builder, "c:@F@foo"); + + // Add different summary types to the same entity. + SummaryName Name1 = addFactTo(Builder, ID, MockSummaryData1(42)); + SummaryName Name2 = addFactTo(Builder, ID, MockSummaryData2("test data")); + SummaryName Name3 = addFactTo(Builder, ID, MockSummaryData3(true)); + + // All Names must be unique + EXPECT_EQ((std::set<SummaryName>{Name1, Name2, Name3}.size()), 3U); + + // Should have 3 summary type with the same entity. + EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name1, Name2, Name3)); + EXPECT_THAT(entitiesOfSummary(Summary, Name1), UnorderedElementsAre(ID)); + EXPECT_THAT(entitiesOfSummary(Summary, Name2), UnorderedElementsAre(ID)); + EXPECT_THAT(entitiesOfSummary(Summary, Name3), UnorderedElementsAre(ID)); + + EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name1, ID), + Optional(Field(&MockSummaryData1::Value, 42))); + EXPECT_THAT(getAsEntitySummary<MockSummaryData2>(Summary, Name2, ID), + Optional(Field(&MockSummaryData2::Text, "test data"))); + EXPECT_THAT(getAsEntitySummary<MockSummaryData3>(Summary, Name3, ID), + Optional(Field(&MockSummaryData3::Flag, true))); +} + +TEST_F(TUSummaryBuilderTest, AddSameFactTypeToMultipleEntities) { + TUSummary Summary = makeFakeSummary(); + TUSummaryBuilder Builder(Summary); + + EntityId ID1 = addTestEntity(Builder, "c:@F@foo"); + EntityId ID2 = addTestEntity(Builder, "c:@F@bar"); + EntityId ID3 = addTestEntity(Builder, "c:@F@baz"); + + // Add the same summary type to different entities. + SummaryName Name1 = addFactTo(Builder, ID1, MockSummaryData1(1)); + SummaryName Name2 = addFactTo(Builder, ID2, MockSummaryData1(2)); + SummaryName Name3 = addFactTo(Builder, ID3, MockSummaryData1(3)); + + // All 3 should be the same summary type. + EXPECT_THAT((llvm::ArrayRef{Name1, Name2, Name3}), testing::Each(Name1)); + + // Should have only 1 summary type with 3 entities. + EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name1)); + EXPECT_THAT(entitiesOfSummary(Summary, Name1), + UnorderedElementsAre(ID1, ID2, ID3)); + + EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name1, ID1), + Optional(Field(&MockSummaryData1::Value, 1))); + EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name2, ID2), + Optional(Field(&MockSummaryData1::Value, 2))); + EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name3, ID3), + Optional(Field(&MockSummaryData1::Value, 3))); +} + +TEST_F(TUSummaryBuilderTest, AddFactReplacesExistingFact) { + TUSummary Summary = makeFakeSummary(); + TUSummaryBuilder Builder(Summary); + EntityId ID = addTestEntity(Builder, "c:@F@foo"); + + SummaryName Name = addFactTo(Builder, ID, MockSummaryData1(10)); + + // Check the initial value. + EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name)); + EXPECT_THAT(entitiesOfSummary(Summary, Name), UnorderedElementsAre(ID)); + EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name, ID), + Optional(Field(&MockSummaryData1::Value, 10))); + + // Add another fact with the same SummaryName. + // This should replace the previous fact. + SummaryName ReplacementName = addFactTo(Builder, ID, MockSummaryData1(20)); + ASSERT_EQ(ReplacementName, Name); + + // Check that the value was replaced. + EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name)); + EXPECT_THAT(entitiesOfSummary(Summary, Name), UnorderedElementsAre(ID)); + EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name, ID), + Optional(Field(&MockSummaryData1::Value, 20))); +} + +TEST_F(TUSummaryBuilderTest, AddFactsComplexScenario) { + TUSummary Summary = makeFakeSummary(); + TUSummaryBuilder Builder(Summary); + + EntityId ID1 = addTestEntity(Builder, "c:@F@foo"); + EntityId ID2 = addTestEntity(Builder, "c:@F@bar"); + + SummaryName Name1 = addFactTo(Builder, ID1, MockSummaryData1(10)); + SummaryName Name2 = addFactTo(Builder, ID1, MockSummaryData2("twenty")); + + SummaryName Name3 = addFactTo(Builder, ID2, MockSummaryData1(30)); + SummaryName Name4 = addFactTo(Builder, ID2, MockSummaryData3(true)); + + // Check that we have only 3 distinct summary names. + EXPECT_EQ(Name1, Name3); + EXPECT_THAT((std::set{Name1, Name2, Name3, Name4}), + UnorderedElementsAre(Name1, Name2, Name4)); + + // Check that we have two facts for the two summaries each. + EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name1, Name2, Name4)); + EXPECT_THAT(entitiesOfSummary(Summary, Name1), + UnorderedElementsAre(ID1, ID2)); + EXPECT_THAT(entitiesOfSummary(Summary, Name2), UnorderedElementsAre(ID1)); + EXPECT_THAT(entitiesOfSummary(Summary, Name4), UnorderedElementsAre(ID2)); + + EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name1, ID1), + Optional(Field(&MockSummaryData1::Value, 10))); + EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name1, ID2), + Optional(Field(&MockSummaryData1::Value, 30))); + EXPECT_THAT(getAsEntitySummary<MockSummaryData2>(Summary, Name2, ID1), + Optional(Field(&MockSummaryData2::Text, "twenty")));... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/181220 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
