[clang] [clang][ssaf] Add LUSummary consumer APIs (PR #185803)
Balázs Benics via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 12 07:46:34 PDT 2026
================
@@ -0,0 +1,390 @@
+//===- SummaryDataTest.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 "../TestFixture.h"
+#include "clang/Analysis/Scalable/EntityLinker/LUSummary.h"
+#include "clang/Analysis/Scalable/Model/BuildNamespace.h"
+#include "clang/Analysis/Scalable/Model/EntityId.h"
+#include "clang/Analysis/Scalable/Model/EntityIdTable.h"
+#include "clang/Analysis/Scalable/Model/EntityLinkage.h"
+#include "clang/Analysis/Scalable/Model/EntityName.h"
+#include "clang/Analysis/Scalable/Model/SummaryName.h"
+#include "clang/Analysis/Scalable/SummaryData/LUSummaryConsumer.h"
+#include "clang/Analysis/Scalable/SummaryData/SummaryDataBuilderRegistry.h"
+#include "clang/Analysis/Scalable/TUSummary/EntitySummary.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+#include <algorithm>
+#include <memory>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+
+// ---------------------------------------------------------------------------
+// Instance counter
+// ---------------------------------------------------------------------------
+
+static int NextSummaryInstanceId = 0;
+
+// ---------------------------------------------------------------------------
+// Entity summaries
+// ---------------------------------------------------------------------------
+
+class Analysis1EntitySummary : public EntitySummary {
+public:
+ int InstanceId = NextSummaryInstanceId++;
+ SummaryName getSummaryName() const override {
+ return SummaryName("Analysis1");
+ }
+};
+
+class Analysis2EntitySummary : public EntitySummary {
+public:
+ int InstanceId = NextSummaryInstanceId++;
+ SummaryName getSummaryName() const override {
+ return SummaryName("Analysis2");
+ }
+};
+
+class Analysis4EntitySummary : public EntitySummary {
+public:
+ int InstanceId = NextSummaryInstanceId++;
+ SummaryName getSummaryName() const override {
+ return SummaryName("Analysis4");
+ }
+};
+
+// ---------------------------------------------------------------------------
+// Data
+// ---------------------------------------------------------------------------
+
+class Analysis1Data : public SummaryData {
+public:
+ static SummaryName summaryName() { return SummaryName("Analysis1"); }
+ std::vector<std::pair<EntityId, int>> Entries;
+ bool WasFinalized = false;
+};
+
+class Analysis2Data : public SummaryData {
+public:
+ static SummaryName summaryName() { return SummaryName("Analysis2"); }
+ std::vector<std::pair<EntityId, int>> Entries;
+ bool WasFinalized = false;
+};
+
+// No builder or registration for Analysis3. Data for Analysis3 is inserted
+// into the LUSummary to verify the consumer silently skips it.
+class Analysis3Data : public SummaryData {
+public:
+ static SummaryName summaryName() { return SummaryName("Analysis3"); }
+};
+
+// Analysis4 has a registered builder but no data is inserted into the
+// LUSummary, so the builder is never invoked and getData returns nullptr.
+class Analysis4Data : public SummaryData {
+public:
+ static SummaryName summaryName() { return SummaryName("Analysis4"); }
+ std::vector<std::pair<EntityId, int>> Entries;
+ bool WasFinalized = false;
+};
+
+// ---------------------------------------------------------------------------
+// Builder destruction flags (reset in SetUp)
+// ---------------------------------------------------------------------------
+
+static bool Analysis1BuilderWasDestroyed = false;
+static bool Analysis2BuilderWasDestroyed = false;
+static bool Analysis4BuilderWasDestroyed = false;
+
+// ---------------------------------------------------------------------------
+// Builders
+// ---------------------------------------------------------------------------
+
+class Analysis1Builder
+ : public SummaryDataBuilder<Analysis1Data, Analysis1EntitySummary> {
+public:
+ ~Analysis1Builder() { Analysis1BuilderWasDestroyed = true; }
+
+ void addSummary(EntityId Id,
+ std::unique_ptr<Analysis1EntitySummary> S) override {
+ getData().Entries.push_back({Id, S->InstanceId});
+ }
+
+ void finalize() override { getData().WasFinalized = true; }
+};
+
+static SummaryDataBuilderRegistry::Add<Analysis1Builder>
+ RegAnalysis1("Builder for Analysis1");
+
+class Analysis2Builder
+ : public SummaryDataBuilder<Analysis2Data, Analysis2EntitySummary> {
+public:
+ ~Analysis2Builder() { Analysis2BuilderWasDestroyed = true; }
+
+ void addSummary(EntityId Id,
+ std::unique_ptr<Analysis2EntitySummary> S) override {
+ getData().Entries.push_back({Id, S->InstanceId});
+ }
+
+ void finalize() override { getData().WasFinalized = true; }
+};
+
+static SummaryDataBuilderRegistry::Add<Analysis2Builder>
+ RegAnalysis2("Builder for Analysis2");
+
+class Analysis4Builder
+ : public SummaryDataBuilder<Analysis4Data, Analysis4EntitySummary> {
+public:
+ ~Analysis4Builder() { Analysis4BuilderWasDestroyed = true; }
+
+ void addSummary(EntityId Id,
+ std::unique_ptr<Analysis4EntitySummary> S) override {
+ getData().Entries.push_back({Id, S->InstanceId});
+ }
+
+ void finalize() override { getData().WasFinalized = true; }
+};
+
+static SummaryDataBuilderRegistry::Add<Analysis4Builder>
+ RegAnalysis4("Builder for Analysis4");
+
+// ---------------------------------------------------------------------------
+// Fixture
+// ---------------------------------------------------------------------------
+
+class LUSummaryConsumerTest : public TestFixture {
+protected:
+ static constexpr EntityLinkage ExternalLinkage =
+ EntityLinkage(EntityLinkageType::External);
+
+ void SetUp() override {
+ NextSummaryInstanceId = 0;
+ Analysis1BuilderWasDestroyed = false;
+ Analysis2BuilderWasDestroyed = false;
+ Analysis4BuilderWasDestroyed = false;
+ }
+
+ std::unique_ptr<LUSummary> makeLUSummary() {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ return std::make_unique<LUSummary>(std::move(NS));
+ }
+
+ EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ EntityName Name(USR.str(), "", NS);
+ EntityId Id = getIdTable(LU).getId(Name);
+ getLinkageTable(LU).insert({Id, ExternalLinkage});
+ return Id;
+ }
+
+ static bool hasEntry(const std::vector<std::pair<EntityId, int>> &Entries,
+ EntityId Id, int InstanceId) {
+ return std::find(Entries.begin(), Entries.end(),
+ std::make_pair(Id, InstanceId)) != Entries.end();
----------------
steakhal wrote:
I think you probably wanted to use `llvm::is_contained`.
https://github.com/llvm/llvm-project/pull/185803
More information about the cfe-commits
mailing list