[clang] [llvm] [clang][ssaf] Rework TUSummaryBuilder::addEntity to take NamedDecl (PR #194448)
Balázs Benics via cfe-commits
cfe-commits at lists.llvm.org
Fri May 1 04:19:16 PDT 2026
https://github.com/steakhal updated https://github.com/llvm/llvm-project/pull/194448
>From 79b9d4151dd209b8a71f505790a293b919e52cf2 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Tue, 28 Apr 2026 16:21:21 +0100
Subject: [PATCH 1/5] [clang][ssaf] Rework addEntity to populate linkage as
well
---
.../EntityPointerLevel/EntityPointerLevel.h | 12 ++-
.../Core/TUSummary/TUSummaryBuilder.h | 16 +++-
.../Analyses/CallGraph/CallGraphExtractor.cpp | 17 ++--
.../EntityPointerLevel/EntityPointerLevel.cpp | 86 +++++++++++--------
.../UnsafeBufferUsageExtractor.cpp | 13 +--
.../Core/TUSummary/TUSummaryBuilder.cpp | 51 ++++++++++-
.../UnsafeBufferUsageTest.cpp | 28 +++---
.../TUSummaryBuilderTest.cpp | 80 +++++++++++++----
8 files changed, 204 insertions(+), 99 deletions(-)
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
index 429bb74fb417e..b46f0573177b3 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
@@ -11,11 +11,10 @@
#include "clang/AST/Expr.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "llvm/ADT/STLFunctionalExtras.h"
#include <set>
namespace clang::ssaf {
+class TUSummaryBuilder;
/// An EntityPointerLevel is associated with a level of the declared
/// pointer/array type of an entity. In the fully-expanded spelling of the
@@ -93,9 +92,9 @@ using EntityPointerLevelSet =
/// \param Ctx the AST context of `E`
/// \param AddEntity the callback provided by the caller to convert EntityNames
/// to EntityIds.
-llvm::Expected<EntityPointerLevelSet> translateEntityPointerLevel(
- const Expr *E, ASTContext &Ctx,
- llvm::function_ref<EntityId(EntityName EN)> AddEntity);
+llvm::Expected<EntityPointerLevelSet>
+translateEntityPointerLevel(const Expr *E, ASTContext &Ctx,
+ TUSummaryBuilder &Builder);
/// Creates a `EntityPointerLevel` from a pair of an EntityId and a pointer
/// level:
@@ -109,8 +108,7 @@ EntityPointerLevel buildEntityPointerLevel(EntityId, unsigned);
/// \param IsFunRet true iff the created EPL is associated with the return type
/// of a function entity.
llvm::Expected<EntityPointerLevel>
-createEntityPointerLevel(const NamedDecl *ND,
- llvm::function_ref<EntityId(EntityName EN)> AddEntity,
+createEntityPointerLevel(const NamedDecl *ND, TUSummaryBuilder &Builder,
bool IsFunRet = false);
/// Creates a new EntityPointerLevel (EPL) from `E` by incrementing `E`'s
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
index fd07abfab8c87..da6839ce97e00 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
@@ -9,9 +9,11 @@
#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
+#include "clang/AST/DeclBase.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include <memory>
+#include <optional>
#include <utility>
namespace clang::ssaf {
@@ -23,9 +25,15 @@ class TUSummaryBuilder {
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);
+ /// Creates EntityName from the Decl, registers the entity, and sets its
+ /// linkage atomically.
+ /// \returns the EntityId, or std::nullopt if EntityName creation fails.
+ std::optional<EntityId> addEntity(const NamedDecl *D);
+
+ /// Creates EntityName for the return value of \p FD, registers the entity,
+ /// and sets its linkage atomically.
+ /// \returns the EntityId, or std::nullopt if EntityName creation fails.
+ std::optional<EntityId> addEntityForReturn(const FunctionDecl *FD);
/// Associate the \p Data \c EntitySummary with the \p Entity.
/// This consumes the \p Data only if \p Entity wasn't associated yet with the
@@ -39,6 +47,8 @@ class TUSummaryBuilder {
private:
TUSummary &Summary;
+ EntityId addEntityImpl(const EntityName &Name, const Decl *D);
+
std::pair<EntitySummary *, bool>
addSummaryImpl(EntityId Entity, std::unique_ptr<EntitySummary> &&Data);
};
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
index 1dbed7e0b0d8a..22038e915a32b 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
@@ -14,7 +14,6 @@
#include "clang/Analysis/CallGraph.h"
#include "clang/Basic/SourceManager.h"
#include "clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
#include "llvm/ADT/STLExtras.h"
@@ -53,8 +52,8 @@ void CallGraphExtractor::handleCallGraphNode(const ASTContext &Ctx,
// FIXME: `clang::CallGraph` does not create entries for primary templates.
assert(!Definition->isTemplated());
- auto CallerName = getEntityName(Definition);
- if (!CallerName)
+ auto CallerId = SummaryBuilder.addEntity(Definition);
+ if (!CallerId)
return;
auto FnSummary = std::make_unique<CallGraphSummary>();
@@ -80,21 +79,19 @@ void CallGraphExtractor::handleCallGraphNode(const ASTContext &Ctx,
// FIXME: `clang::CallGraph` does not create entries for primary templates.
assert(!CalleeDecl->isTemplated());
- auto CalleeName = getEntityName(CalleeDecl);
- if (!CalleeName)
+ auto CalleeId = SummaryBuilder.addEntity(cast<NamedDecl>(CalleeDecl));
+ if (!CalleeId)
continue;
- EntityId CalleeId = SummaryBuilder.addEntity(*CalleeName);
if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(CalleeDecl);
MD && MD->isVirtual()) {
- FnSummary->VirtualCallees.insert(CalleeId);
+ FnSummary->VirtualCallees.insert(*CalleeId);
continue;
}
- FnSummary->DirectCallees.insert(CalleeId);
+ FnSummary->DirectCallees.insert(*CalleeId);
}
- EntityId CallerId = SummaryBuilder.addEntity(*CallerName);
- SummaryBuilder.addSummary(CallerId, std::move(FnSummary));
+ SummaryBuilder.addSummary(*CallerId, std::move(FnSummary));
}
static TUSummaryExtractorRegistry::Add<CallGraphExtractor>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
index 52e6705ec43af..7a760b72c9d11 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
@@ -12,8 +12,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
#include <optional>
using namespace clang;
@@ -51,8 +50,23 @@ class EntityPointerLevelTranslator
E->getStmtClassName());
}
- EntityPointerLevel createEntityPointerLevelFor(const EntityName &Name) {
- return EntityPointerLevel({AddEntity(Name), 1});
+ Expected<EntityPointerLevel>
+ createEntityPointerLevelFor(const NamedDecl *ND) {
+ std::optional<EntityId> Id = Builder.addEntity(ND);
+ if (!Id)
+ return makeErrAtNode(Ctx, ND, "failed to create EntityId for %s",
+ ND->getDeclKindName());
+ return EntityPointerLevel{buildEntityPointerLevel(*Id, 1)};
+ }
+
+ Expected<EntityPointerLevel>
+ createEntityPointerLevelForReturn(const FunctionDecl *FD) {
+ std::optional<EntityId> Id = Builder.addEntityForReturn(FD);
+ if (!Id) {
+ return makeErrAtNode(Ctx, FD, "failed to create EntityId for function %s",
+ cast<NamedDecl>(FD)->getNameAsString().c_str());
+ }
+ return EntityPointerLevel{buildEntityPointerLevel(*Id, 1)};
}
// The common helper function for Translate(*base):
@@ -68,28 +82,25 @@ class EntityPointerLevelTranslator
return EntityPointerLevelSet{Incremented.begin(), Incremented.end()};
}
- std::function<EntityId(EntityName EN)> AddEntity;
+ TUSummaryBuilder &Builder;
ASTContext &Ctx;
public:
- EntityPointerLevelTranslator(std::function<EntityId(EntityName EN)> AddEntity,
- ASTContext &Ctx)
- : AddEntity(AddEntity), Ctx(Ctx) {}
+ EntityPointerLevelTranslator(TUSummaryBuilder &Builder, ASTContext &Ctx)
+ : Builder(Builder), Ctx(Ctx) {}
Expected<EntityPointerLevelSet> translate(const Expr *E) { return Visit(E); }
Expected<EntityPointerLevel> translate(const NamedDecl *D, bool IsRet) {
- if (IsRet && !isa<FunctionDecl>(D))
- return makeErrAtNode(
- Ctx, D,
- "attempt to call getEntityNameForReturn on a NamedDecl of %s kind",
- D->getDeclKindName());
-
- std::optional<EntityName> EN =
- IsRet ? getEntityNameForReturn(cast<FunctionDecl>(D))
- : getEntityName(D);
- if (EN)
- return createEntityPointerLevelFor(*EN);
- return makeEntityNameErr(Ctx, D);
+ if (!IsRet)
+ return createEntityPointerLevelFor(D);
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ return createEntityPointerLevelForReturn(FD);
+
+ return makeErrAtNode(
+ Ctx, D,
+ "attempt to call getEntityNameForReturn on a NamedDecl of %s kind",
+ D->getDeclKindName());
}
static EntityPointerLevel incrementPointerLevel(const EntityPointerLevel &E) {
@@ -167,10 +178,10 @@ class EntityPointerLevelTranslator
// Translate(f(...)) -> {} if it is an indirect call
// -> {(f_return, 1)}, otherwise
Expected<EntityPointerLevelSet> VisitCallExpr(const CallExpr *E) {
- if (auto *FD = E->getDirectCallee())
- if (auto FDEntityName = getEntityNameForReturn(FD))
- return EntityPointerLevelSet{
- createEntityPointerLevelFor(*FDEntityName)};
+ if (auto *FD = E->getDirectCallee()) {
+ if (auto ReturnId = Builder.addEntityForReturn(FD))
+ return EntityPointerLevelSet{buildEntityPointerLevel(*ReturnId, 1)};
+ }
return EntityPointerLevelSet{};
}
@@ -210,16 +221,18 @@ class EntityPointerLevelTranslator
// Translate(DRE) -> {(Decl, 1)}
Expected<EntityPointerLevelSet> VisitDeclRefExpr(const DeclRefExpr *E) {
- if (auto EntityName = getEntityName(E->getDecl()))
- return EntityPointerLevelSet{createEntityPointerLevelFor(*EntityName)};
- return makeEntityNameErr(Ctx, E->getDecl());
+ auto Res = createEntityPointerLevelFor(E->getDecl());
+ if (!Res)
+ return Res.takeError();
+ return EntityPointerLevelSet{*Res};
}
// Translate({., ->}f) -> {(MemberDecl, 1)}
Expected<EntityPointerLevelSet> VisitMemberExpr(const MemberExpr *E) {
- if (auto EntityName = getEntityName(E->getMemberDecl()))
- return EntityPointerLevelSet{createEntityPointerLevelFor(*EntityName)};
- return makeEntityNameErr(Ctx, E->getMemberDecl());
+ auto Res = createEntityPointerLevelFor(E->getMemberDecl());
+ if (!Res)
+ return Res.takeError();
+ return EntityPointerLevelSet{*Res};
}
Expected<EntityPointerLevelSet>
@@ -229,19 +242,18 @@ class EntityPointerLevelTranslator
};
} // namespace clang::ssaf
-Expected<EntityPointerLevelSet> clang::ssaf::translateEntityPointerLevel(
- const Expr *E, ASTContext &Ctx,
- llvm::function_ref<EntityId(EntityName EN)> AddEntity) {
- EntityPointerLevelTranslator Translator(AddEntity, Ctx);
+Expected<EntityPointerLevelSet>
+clang::ssaf::translateEntityPointerLevel(const Expr *E, ASTContext &Ctx,
+ TUSummaryBuilder &Builder) {
+ EntityPointerLevelTranslator Translator(Builder, Ctx);
return Translator.translate(E);
}
/// Create an EntityPointerLevel from a ValueDecl of a pointer type.
Expected<EntityPointerLevel> clang::ssaf::createEntityPointerLevel(
- const NamedDecl *ND, llvm::function_ref<EntityId(EntityName EN)> AddEntity,
- bool IsFunRet) {
- EntityPointerLevelTranslator Translator(AddEntity, ND->getASTContext());
+ const NamedDecl *ND, TUSummaryBuilder &Builder, bool IsFunRet) {
+ EntityPointerLevelTranslator Translator(Builder, ND->getASTContext());
return Translator.translate(ND, IsFunRet);
}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index 550416c353fb7..dda2fb6131b8f 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -13,8 +13,6 @@
#include "clang/Analysis/Analyses/UnsafeBufferUsage.h"
#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
@@ -51,9 +49,7 @@ clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::extractEntitySummary(
for (const Expr *Ptr : UnsafePointers) {
Expected<EntityPointerLevelSet> Translation =
- translateEntityPointerLevel(Ptr, Ctx, [this](const EntityName &EN) {
- return SummaryBuilder.addEntity(EN);
- });
+ translateEntityPointerLevel(Ptr, Ctx, SummaryBuilder);
if (Translation) {
// Filter out those temporary invalid EntityPointerLevels associated
@@ -86,14 +82,13 @@ void clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
if ((*EntitySummary)->empty())
continue;
- auto ContributorName = getEntityName(CD);
+ auto ContributorId = SummaryBuilder.addEntity(CD);
- if (!ContributorName)
+ if (!ContributorId)
llvm::reportFatalInternalError(makeEntityNameErr(Ctx, CD));
[[maybe_unused]] auto [Ignored, InsertionSucceeded] =
- SummaryBuilder.addSummary(SummaryBuilder.addEntity(*ContributorName),
- std::move(*EntitySummary));
+ SummaryBuilder.addSummary(*ContributorId, std::move(*EntitySummary));
assert(InsertionSucceeded && "duplicated contributor extraction");
}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
index 180a78cae33a9..12920b69e2e29 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
@@ -7,17 +7,64 @@
//===----------------------------------------------------------------------===//
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/AST/Decl.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
#include <memory>
+#include <optional>
#include <utility>
using namespace clang;
using namespace ssaf;
-EntityId TUSummaryBuilder::addEntity(const EntityName &E) {
- return Summary.IdTable.getId(E);
+static EntityLinkageType getLinkageForDecl(const Decl *D) {
+ const auto *ND = dyn_cast<NamedDecl>(D);
+ if (!ND)
+ return EntityLinkageType::None;
+
+ switch (ND->getFormalLinkage()) {
+ case Linkage::Invalid: {
+ llvm_unreachable("Shouldn't be invalid");
+ }
+ case Linkage::None:
+ return EntityLinkageType::None;
+ case Linkage::Internal:
+ return EntityLinkageType::Internal;
+ case Linkage::UniqueExternal:
+ return EntityLinkageType::Internal;
+ case Linkage::VisibleNone:
+ return EntityLinkageType::Internal;
+ case Linkage::Module:
+ return EntityLinkageType::External;
+ case Linkage::External:
+ return EntityLinkageType::External;
+ }
+ llvm_unreachable("Unhandled clang::Linkage kind");
+}
+
+EntityId TUSummaryBuilder::addEntityImpl(const EntityName &Name,
+ const Decl *D) {
+ EntityId Id = Summary.IdTable.getId(Name);
+ Summary.LinkageTable.try_emplace(Id, getLinkageForDecl(D));
+ return Id;
+}
+
+std::optional<EntityId> TUSummaryBuilder::addEntity(const NamedDecl *D) {
+ auto Name = getEntityName(D);
+ if (!Name)
+ return std::nullopt;
+ return addEntityImpl(*Name, D);
+}
+
+std::optional<EntityId>
+TUSummaryBuilder::addEntityForReturn(const FunctionDecl *FD) {
+ auto Name = getEntityNameForReturn(FD);
+ if (!Name)
+ return std::nullopt;
+ return addEntityImpl(*Name, FD);
}
std::pair<EntitySummary *, bool>
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
index 465488357e20e..2490d43992bfa 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
@@ -13,7 +13,6 @@
#include "clang/Frontend/ASTUnit.h"
#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
@@ -74,15 +73,14 @@ class UnsafeBufferUsageTest : public TestFixture {
return nullptr;
}
- std::optional<EntityName> EN = getEntityName(ContributorDefn);
-
- if (!EN) {
+ std::optional<EntityId> ContributorEntityId =
+ Builder.addEntity(ContributorDefn);
+ if (!ContributorEntityId) {
ADD_FAILURE() << "failed to get EntityName for contributor \""
<< ContributorEntityName << "\"";
return nullptr;
}
- EntityId ContributorEntityId = Builder.addEntity(*EN);
auto &TUSumData = getData(TUSum);
auto EntitiesSumIter =
TUSumData.find(UnsafeBufferUsageEntitySummary::summaryName());
@@ -92,7 +90,7 @@ class UnsafeBufferUsageTest : public TestFixture {
if (EntitiesSumIter == TUSumData.end())
return nullptr;
- auto EntitySumIter = EntitiesSumIter->second.find(ContributorEntityId);
+ auto EntitySumIter = EntitiesSumIter->second.find(*ContributorEntityId);
// If entity summary is empty, it may not exist:
if (EntitySumIter == EntitiesSumIter->second.end())
@@ -103,15 +101,13 @@ class UnsafeBufferUsageTest : public TestFixture {
std::optional<EntityId> getEntityId(StringRef Name) {
if (const auto *D = findDeclByName(Name, AST->getASTContext()))
- if (auto EntityName = getEntityName(D))
- return Builder.addEntity(*EntityName);
+ return Builder.addEntity(D);
return std::nullopt;
}
std::optional<EntityId> getEntityIdForReturn(StringRef FunName) {
if (const auto *D = findFnByName(FunName, AST->getASTContext()))
- if (auto EntityName = getEntityNameForReturn(D))
- return Builder.addEntity(*EntityName);
+ return Builder.addEntityForReturn(D);
return std::nullopt;
}
@@ -151,8 +147,9 @@ getSubsetOf(const EntityPointerLevelSet &Set, EntityId Entity) {
}
TEST_F(UnsafeBufferUsageTest, EntityPointerLevelComparison) {
- EntityId E1 = Builder.addEntity({"c:@F at foo", "", {}});
- EntityId E2 = Builder.addEntity({"c:@F at bar", "", {}});
+ EntityIdTable Table;
+ EntityId E1 = Table.getId({"c:@F at foo", "", {}});
+ EntityId E2 = Table.getId({"c:@F at bar", "", {}});
auto P1 = buildEntityPointerLevel(E1, 2);
auto P2 = buildEntityPointerLevel(E1, 2);
@@ -170,9 +167,10 @@ TEST_F(UnsafeBufferUsageTest, EntityPointerLevelComparison) {
}
TEST_F(UnsafeBufferUsageTest, UnsafeBufferUsageEntityPointerLevelSetTest) {
- EntityId E1 = Builder.addEntity({"c:@F at foo", "", {}});
- EntityId E2 = Builder.addEntity({"c:@F at bar", "", {}});
- EntityId E3 = Builder.addEntity({"c:@F at baz", "", {}});
+ EntityIdTable Table;
+ EntityId E1 = Table.getId({"c:@F at foo", "", {}});
+ EntityId E2 = Table.getId({"c:@F at bar", "", {}});
+ EntityId E3 = Table.getId({"c:@F at baz", "", {}});
auto P1 = buildEntityPointerLevel(E1, 1);
auto P2 = buildEntityPointerLevel(E1, 2);
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
index ece39e2164df7..0eae3a3a0fe32 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
@@ -7,14 +7,16 @@
//===----------------------------------------------------------------------===//
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "FindDecl.h"
#include "TestFixture.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
@@ -32,11 +34,6 @@ using testing::Field;
using testing::Optional;
using testing::UnorderedElementsAre;
-[[nodiscard]]
-static EntityId addTestEntity(TUSummaryBuilder &Builder, llvm::StringRef USR) {
- return Builder.addEntity(EntityName(USR, /*Suffix=*/"", /*Namespace=*/{}));
-}
-
struct SummaryResult {
EntitySummary *Summary;
bool Inserted;
@@ -95,6 +92,11 @@ struct TUSummaryBuilderTest : ssaf::TestFixture {
BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")};
TUSummaryBuilder Builder = TUSummaryBuilder(this->Summary);
+ [[nodiscard]] EntityId addTestEntity(llvm::StringRef USR) {
+ return getIdTable(Summary).getId(
+ EntityName(USR, /*Suffix=*/"", /*Namespace=*/{}));
+ }
+
[[nodiscard]] static SmallVector<SummaryName>
summaryNames(const TUSummary &Summary) {
return llvm::to_vector(llvm::make_first_range(getData(Summary)));
@@ -128,22 +130,23 @@ TEST_F(TUSummaryBuilderTest, AddEntity) {
EntityName EN1("c:@F at foo", "", /*Namespace=*/{});
EntityName EN2("c:@F at bar", "", /*Namespace=*/{});
- EntityId ID = Builder.addEntity(EN1);
- EntityId IDAlias = Builder.addEntity(EN1);
+ EntityIdTable &IdTable = getIdTable(Summary);
+
+ EntityId ID = IdTable.getId(EN1);
+ EntityId IDAlias = IdTable.getId(EN1);
EXPECT_EQ(ID, IDAlias); // Idenpotency
- EntityId ID2 = Builder.addEntity(EN2);
+ EntityId ID2 = IdTable.getId(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, TUSummaryBuilderAddSingleSummary) {
- EntityId ID = addTestEntity(Builder, "c:@F at foo");
+ EntityId ID = addTestEntity("c:@F at foo");
auto [Name, Res] = addSummaryTo(Builder, ID, MockSummaryData1(10));
ASSERT_TRUE(Res.Inserted);
ASSERT_TRUE(Res.Summary);
@@ -157,7 +160,7 @@ TEST_F(TUSummaryBuilderTest, TUSummaryBuilderAddSingleSummary) {
}
TEST_F(TUSummaryBuilderTest, AddMultipleSummariesToSameEntity) {
- EntityId ID = addTestEntity(Builder, "c:@F at foo");
+ EntityId ID = addTestEntity("c:@F at foo");
// Add different summary types to the same entity.
auto [Name1, Res1] = addSummaryTo(Builder, ID, MockSummaryData1(42));
@@ -188,9 +191,9 @@ TEST_F(TUSummaryBuilderTest, AddMultipleSummariesToSameEntity) {
}
TEST_F(TUSummaryBuilderTest, AddSameSummaryTypeToMultipleEntities) {
- EntityId ID1 = addTestEntity(Builder, "c:@F at foo");
- EntityId ID2 = addTestEntity(Builder, "c:@F at bar");
- EntityId ID3 = addTestEntity(Builder, "c:@F at baz");
+ EntityId ID1 = addTestEntity("c:@F at foo");
+ EntityId ID2 = addTestEntity("c:@F at bar");
+ EntityId ID3 = addTestEntity("c:@F at baz");
// Add the same summary type to different entities.
auto [Name1, Res1] = addSummaryTo(Builder, ID1, MockSummaryData1(1));
@@ -220,7 +223,7 @@ TEST_F(TUSummaryBuilderTest, AddSameSummaryTypeToMultipleEntities) {
}
TEST_F(TUSummaryBuilderTest, AddConflictingSummaryToSameEntity) {
- EntityId ID = addTestEntity(Builder, "c:@F at foo");
+ EntityId ID = addTestEntity("c:@F at foo");
auto [Name, Res] = addSummaryTo(Builder, ID, MockSummaryData1(10));
ASSERT_TRUE(Res.Inserted);
@@ -266,4 +269,49 @@ TEST_F(TUSummaryBuilderTest, AddConflictingSummaryToSameEntity) {
Optional(Field(&MockSummaryData1::Value, 30)));
}
+struct TUSummaryBuilderLinkageTest : TUSummaryBuilderTest {
+ std::unique_ptr<ASTUnit> AST;
+
+ const FunctionDecl *findFnByName(StringRef Name) {
+ return ssaf::findFnByName(Name, AST->getASTContext());
+ }
+
+ std::optional<EntityLinkageType> getLinkageFor(std::optional<EntityId> ID) {
+ if (!ID)
+ return std::nullopt;
+ if (auto It = getLinkageTable(Summary).find(*ID);
+ It != getLinkageTable(Summary).end())
+ return It->second.getLinkage();
+ return std::nullopt;
+ }
+};
+
+TEST_F(TUSummaryBuilderLinkageTest, HasInternalLinkage) {
+ AST = tooling::buildASTFromCode("static void target() {}");
+ const FunctionDecl *Fn = findFnByName("target");
+ ASSERT_TRUE(Fn);
+ EXPECT_EQ(getLinkageFor(Builder.addEntity(Fn)), EntityLinkageType::Internal);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, HasExternalLinkage) {
+ AST = tooling::buildASTFromCode("void target() {}");
+ const FunctionDecl *Fn = findFnByName("target");
+ ASSERT_TRUE(Fn);
+ EXPECT_EQ(getLinkageFor(Builder.addEntity(Fn)), EntityLinkageType::External);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, HasExternalLinkageWithInline) {
+ AST = tooling::buildASTFromCode("inline void target() {}");
+ const FunctionDecl *Fn = findFnByName("target");
+ ASSERT_TRUE(Fn);
+ EXPECT_EQ(getLinkageFor(Builder.addEntity(Fn)), EntityLinkageType::External);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, HasInternalLinkageWithStaticInline) {
+ AST = tooling::buildASTFromCode("static inline void target() {}");
+ const FunctionDecl *Fn = findFnByName("target");
+ ASSERT_TRUE(Fn);
+ EXPECT_EQ(getLinkageFor(Builder.addEntity(Fn)), EntityLinkageType::Internal);
+}
+
} // namespace
>From 85b84be71620fdac6a29079ad43075fa64fd2239 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Wed, 29 Apr 2026 10:46:21 +0100
Subject: [PATCH 2/5] Add more tests
---
.../TUSummaryBuilderTest.cpp | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
index 0eae3a3a0fe32..151f07b92207d 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
@@ -314,4 +314,22 @@ TEST_F(TUSummaryBuilderLinkageTest, HasInternalLinkageWithStaticInline) {
EXPECT_EQ(getLinkageFor(Builder.addEntity(Fn)), EntityLinkageType::Internal);
}
+TEST_F(TUSummaryBuilderLinkageTest, ConstVolatileGlobalHasExternalLinkage) {
+ AST = tooling::buildASTFromCode("namespace ns {\n"
+ " const volatile int glob = 0;\n"
+ "}");
+ const auto *VD = findDeclByName<VarDecl>("glob", AST->getASTContext());
+ ASSERT_TRUE(VD);
+ EXPECT_EQ(getLinkageFor(Builder.addEntity(VD)), EntityLinkageType::External);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, ConstGlobalHasInternalLinkage) {
+ AST = tooling::buildASTFromCode("namespace ns {\n"
+ " const int glob = 0;\n"
+ "}");
+ const auto *VD = findDeclByName<VarDecl>("glob", AST->getASTContext());
+ ASSERT_TRUE(VD);
+ EXPECT_EQ(getLinkageFor(Builder.addEntity(VD)), EntityLinkageType::Internal);
+}
+
} // namespace
>From 09f0370eb60c82111378b5632fdc992d644cf363 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Thu, 30 Apr 2026 11:32:03 +0100
Subject: [PATCH 3/5] Accept proposed error wording
Fixes https://github.com/llvm/llvm-project/pull/194448/changes#r3164542992
---
.../Analyses/EntityPointerLevel/EntityPointerLevel.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
index 7a760b72c9d11..7703d97a8e684 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
@@ -97,10 +97,8 @@ class EntityPointerLevelTranslator
if (const auto *FD = dyn_cast<FunctionDecl>(D))
return createEntityPointerLevelForReturn(FD);
- return makeErrAtNode(
- Ctx, D,
- "attempt to call getEntityNameForReturn on a NamedDecl of %s kind",
- D->getDeclKindName());
+ return makeErrAtNode(Ctx, D, "attempt to get entity for return of %s",
+ D->getDeclKindName());
}
static EntityPointerLevel incrementPointerLevel(const EntityPointerLevel &E) {
>From ed265ed7c6b9906889a4b0e7374faac094dd1515 Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Fri, 1 May 2026 12:15:54 +0100
Subject: [PATCH 4/5] Move addEntity helper methods to TUSummaryExtractor
---
.../EntityPointerLevel/EntityPointerLevel.h | 6 +-
.../Core/TUSummary/ExtractorRegistry.h | 4 +-
.../Core/TUSummary/TUSummaryBuilder.h | 15 +----
.../Core/TUSummary/TUSummaryExtractor.h | 13 +++++
.../Analyses/CallGraph/CallGraphExtractor.cpp | 4 +-
.../EntityPointerLevel/EntityPointerLevel.cpp | 21 +++----
.../UnsafeBufferUsageExtractor.cpp | 4 +-
.../Core/CMakeLists.txt | 1 +
.../Core/TUSummary/ExtractorRegistry.cpp | 3 +-
.../Core/TUSummary/TUSummaryBuilder.cpp | 54 +++--------------
.../Core/TUSummary/TUSummaryExtractor.cpp | 58 +++++++++++++++++++
.../UnsafeBufferUsageTest.cpp | 8 +--
.../TUSummaryBuilderTest.cpp | 22 ++++---
.../Core/BUILD.gn | 1 +
14 files changed, 123 insertions(+), 91 deletions(-)
create mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
index b46f0573177b3..e6c9e808c26a6 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
@@ -14,7 +14,7 @@
#include <set>
namespace clang::ssaf {
-class TUSummaryBuilder;
+class TUSummaryExtractor;
/// An EntityPointerLevel is associated with a level of the declared
/// pointer/array type of an entity. In the fully-expanded spelling of the
@@ -94,7 +94,7 @@ using EntityPointerLevelSet =
/// to EntityIds.
llvm::Expected<EntityPointerLevelSet>
translateEntityPointerLevel(const Expr *E, ASTContext &Ctx,
- TUSummaryBuilder &Builder);
+ TUSummaryExtractor &Extractor);
/// Creates a `EntityPointerLevel` from a pair of an EntityId and a pointer
/// level:
@@ -108,7 +108,7 @@ EntityPointerLevel buildEntityPointerLevel(EntityId, unsigned);
/// \param IsFunRet true iff the created EPL is associated with the return type
/// of a function entity.
llvm::Expected<EntityPointerLevel>
-createEntityPointerLevel(const NamedDecl *ND, TUSummaryBuilder &Builder,
+createEntityPointerLevel(const NamedDecl *ND, TUSummaryExtractor &Extractor,
bool IsFunRet = false);
/// Creates a new EntityPointerLevel (EPL) from `E` by incrementing `E`'s
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
index da57838c64b2f..8639439dc1616 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
@@ -41,8 +41,8 @@ bool isTUSummaryExtractorRegistered(llvm::StringRef SummaryName);
/// This might return null if the construction of the desired TUSummaryExtractor
/// failed.
/// It's a fatal error if there is no extractor registered with the name.
-std::unique_ptr<ASTConsumer> makeTUSummaryExtractor(llvm::StringRef SummaryName,
- TUSummaryBuilder &Builder);
+std::unique_ptr<TUSummaryExtractor>
+makeTUSummaryExtractor(llvm::StringRef SummaryName, TUSummaryBuilder &Builder);
/// Print the list of available TUSummaryExtractors.
void printAvailableTUSummaryExtractors(llvm::raw_ostream &OS);
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
index da6839ce97e00..f9ebe5358b585 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
@@ -9,11 +9,10 @@
#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
-#include "clang/AST/DeclBase.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include <memory>
-#include <optional>
#include <utility>
namespace clang::ssaf {
@@ -25,15 +24,7 @@ class TUSummaryBuilder {
public:
explicit TUSummaryBuilder(TUSummary &Summary) : Summary(Summary) {}
- /// Creates EntityName from the Decl, registers the entity, and sets its
- /// linkage atomically.
- /// \returns the EntityId, or std::nullopt if EntityName creation fails.
- std::optional<EntityId> addEntity(const NamedDecl *D);
-
- /// Creates EntityName for the return value of \p FD, registers the entity,
- /// and sets its linkage atomically.
- /// \returns the EntityId, or std::nullopt if EntityName creation fails.
- std::optional<EntityId> addEntityForReturn(const FunctionDecl *FD);
+ EntityId addEntity(const EntityName &EN, EntityLinkageType Linkage);
/// Associate the \p Data \c EntitySummary with the \p Entity.
/// This consumes the \p Data only if \p Entity wasn't associated yet with the
@@ -47,8 +38,6 @@ class TUSummaryBuilder {
private:
TUSummary &Summary;
- EntityId addEntityImpl(const EntityName &Name, const Decl *D);
-
std::pair<EntitySummary *, bool>
addSummaryImpl(EntityId Entity, std::unique_ptr<EntitySummary> &&Data);
};
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
index 629a8d0e35ae4..46b0ae835d729 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
@@ -10,6 +10,9 @@
#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/Decl.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include <optional>
namespace clang::ssaf {
class TUSummaryBuilder;
@@ -19,6 +22,16 @@ class TUSummaryExtractor : public ASTConsumer {
explicit TUSummaryExtractor(TUSummaryBuilder &Builder)
: SummaryBuilder(Builder) {}
+ /// Creates EntityName from the Decl, registers the entity, and sets its
+ /// linkage atomically.
+ /// \returns the EntityId, or std::nullopt if EntityName creation fails.
+ std::optional<EntityId> addEntity(const NamedDecl *D);
+
+ /// Creates EntityName for the return value of \p FD, registers the entity,
+ /// and sets its linkage atomically.
+ /// \returns the EntityId, or std::nullopt if EntityName creation fails.
+ std::optional<EntityId> addEntityForReturn(const FunctionDecl *FD);
+
protected:
TUSummaryBuilder &SummaryBuilder;
};
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
index 22038e915a32b..3436da7c2244b 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
@@ -52,7 +52,7 @@ void CallGraphExtractor::handleCallGraphNode(const ASTContext &Ctx,
// FIXME: `clang::CallGraph` does not create entries for primary templates.
assert(!Definition->isTemplated());
- auto CallerId = SummaryBuilder.addEntity(Definition);
+ auto CallerId = addEntity(Definition);
if (!CallerId)
return;
@@ -79,7 +79,7 @@ void CallGraphExtractor::handleCallGraphNode(const ASTContext &Ctx,
// FIXME: `clang::CallGraph` does not create entries for primary templates.
assert(!CalleeDecl->isTemplated());
- auto CalleeId = SummaryBuilder.addEntity(cast<NamedDecl>(CalleeDecl));
+ auto CalleeId = addEntity(cast<NamedDecl>(CalleeDecl));
if (!CalleeId)
continue;
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
index 7703d97a8e684..15fedbd83de92 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
@@ -13,6 +13,7 @@
#include "clang/AST/StmtVisitor.h"
#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
#include <optional>
using namespace clang;
@@ -52,7 +53,7 @@ class EntityPointerLevelTranslator
Expected<EntityPointerLevel>
createEntityPointerLevelFor(const NamedDecl *ND) {
- std::optional<EntityId> Id = Builder.addEntity(ND);
+ std::optional<EntityId> Id = Extractor.addEntity(ND);
if (!Id)
return makeErrAtNode(Ctx, ND, "failed to create EntityId for %s",
ND->getDeclKindName());
@@ -61,7 +62,7 @@ class EntityPointerLevelTranslator
Expected<EntityPointerLevel>
createEntityPointerLevelForReturn(const FunctionDecl *FD) {
- std::optional<EntityId> Id = Builder.addEntityForReturn(FD);
+ std::optional<EntityId> Id = Extractor.addEntityForReturn(FD);
if (!Id) {
return makeErrAtNode(Ctx, FD, "failed to create EntityId for function %s",
cast<NamedDecl>(FD)->getNameAsString().c_str());
@@ -82,12 +83,12 @@ class EntityPointerLevelTranslator
return EntityPointerLevelSet{Incremented.begin(), Incremented.end()};
}
- TUSummaryBuilder &Builder;
+ TUSummaryExtractor &Extractor;
ASTContext &Ctx;
public:
- EntityPointerLevelTranslator(TUSummaryBuilder &Builder, ASTContext &Ctx)
- : Builder(Builder), Ctx(Ctx) {}
+ EntityPointerLevelTranslator(TUSummaryExtractor &Extractor, ASTContext &Ctx)
+ : Extractor(Extractor), Ctx(Ctx) {}
Expected<EntityPointerLevelSet> translate(const Expr *E) { return Visit(E); }
Expected<EntityPointerLevel> translate(const NamedDecl *D, bool IsRet) {
@@ -177,7 +178,7 @@ class EntityPointerLevelTranslator
// -> {(f_return, 1)}, otherwise
Expected<EntityPointerLevelSet> VisitCallExpr(const CallExpr *E) {
if (auto *FD = E->getDirectCallee()) {
- if (auto ReturnId = Builder.addEntityForReturn(FD))
+ if (auto ReturnId = Extractor.addEntityForReturn(FD))
return EntityPointerLevelSet{buildEntityPointerLevel(*ReturnId, 1)};
}
return EntityPointerLevelSet{};
@@ -242,16 +243,16 @@ class EntityPointerLevelTranslator
Expected<EntityPointerLevelSet>
clang::ssaf::translateEntityPointerLevel(const Expr *E, ASTContext &Ctx,
- TUSummaryBuilder &Builder) {
- EntityPointerLevelTranslator Translator(Builder, Ctx);
+ TUSummaryExtractor &Extractor) {
+ EntityPointerLevelTranslator Translator(Extractor, Ctx);
return Translator.translate(E);
}
/// Create an EntityPointerLevel from a ValueDecl of a pointer type.
Expected<EntityPointerLevel> clang::ssaf::createEntityPointerLevel(
- const NamedDecl *ND, TUSummaryBuilder &Builder, bool IsFunRet) {
- EntityPointerLevelTranslator Translator(Builder, ND->getASTContext());
+ const NamedDecl *ND, TUSummaryExtractor &Extractor, bool IsFunRet) {
+ EntityPointerLevelTranslator Translator(Extractor, ND->getASTContext());
return Translator.translate(ND, IsFunRet);
}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index dda2fb6131b8f..4032b48880eab 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -49,7 +49,7 @@ clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::extractEntitySummary(
for (const Expr *Ptr : UnsafePointers) {
Expected<EntityPointerLevelSet> Translation =
- translateEntityPointerLevel(Ptr, Ctx, SummaryBuilder);
+ translateEntityPointerLevel(Ptr, Ctx, *this);
if (Translation) {
// Filter out those temporary invalid EntityPointerLevels associated
@@ -82,7 +82,7 @@ void clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
if ((*EntitySummary)->empty())
continue;
- auto ContributorId = SummaryBuilder.addEntity(CD);
+ auto ContributorId = addEntity(CD);
if (!ContributorId)
llvm::reportFatalInternalError(makeEntityNameErr(Ctx, CD));
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
index 83772ceff58bf..2c43d645f7e74 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
@@ -24,6 +24,7 @@ add_clang_library(clangScalableStaticAnalysisFrameworkCore
Support/ErrorBuilder.cpp
TUSummary/ExtractorRegistry.cpp
TUSummary/TUSummaryBuilder.cpp
+ TUSummary/TUSummaryExtractor.cpp
WholeProgramAnalysis/AnalysisDriver.cpp
WholeProgramAnalysis/AnalysisName.cpp
WholeProgramAnalysis/AnalysisRegistry.cpp
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
index 01acc64f6f26c..b59d190dde519 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
#include <memory>
using namespace clang;
@@ -21,7 +22,7 @@ bool ssaf::isTUSummaryExtractorRegistered(llvm::StringRef SummaryName) {
return false;
}
-std::unique_ptr<ASTConsumer>
+std::unique_ptr<TUSummaryExtractor>
ssaf::makeTUSummaryExtractor(llvm::StringRef SummaryName,
TUSummaryBuilder &Builder) {
for (const auto &Entry : TUSummaryExtractorRegistry::entries())
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
index 12920b69e2e29..daea76f7001cb 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
@@ -7,66 +7,26 @@
//===----------------------------------------------------------------------===//
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/AST/Decl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
#include <memory>
-#include <optional>
#include <utility>
using namespace clang;
using namespace ssaf;
-static EntityLinkageType getLinkageForDecl(const Decl *D) {
- const auto *ND = dyn_cast<NamedDecl>(D);
- if (!ND)
- return EntityLinkageType::None;
-
- switch (ND->getFormalLinkage()) {
- case Linkage::Invalid: {
- llvm_unreachable("Shouldn't be invalid");
- }
- case Linkage::None:
- return EntityLinkageType::None;
- case Linkage::Internal:
- return EntityLinkageType::Internal;
- case Linkage::UniqueExternal:
- return EntityLinkageType::Internal;
- case Linkage::VisibleNone:
- return EntityLinkageType::Internal;
- case Linkage::Module:
- return EntityLinkageType::External;
- case Linkage::External:
- return EntityLinkageType::External;
- }
- llvm_unreachable("Unhandled clang::Linkage kind");
-}
-
-EntityId TUSummaryBuilder::addEntityImpl(const EntityName &Name,
- const Decl *D) {
- EntityId Id = Summary.IdTable.getId(Name);
- Summary.LinkageTable.try_emplace(Id, getLinkageForDecl(D));
+EntityId TUSummaryBuilder::addEntity(const EntityName &EN,
+ EntityLinkageType Linkage) {
+ EntityId Id = Summary.IdTable.getId(EN);
+ [[maybe_unused]] EntityLinkageType Link =
+ Summary.LinkageTable.try_emplace(Id, Linkage).first->second.getLinkage();
+ // Even if we had in the past a linkage, that must bee the same as we set now.
+ assert(Link == Linkage);
return Id;
}
-std::optional<EntityId> TUSummaryBuilder::addEntity(const NamedDecl *D) {
- auto Name = getEntityName(D);
- if (!Name)
- return std::nullopt;
- return addEntityImpl(*Name, D);
-}
-
-std::optional<EntityId>
-TUSummaryBuilder::addEntityForReturn(const FunctionDecl *FD) {
- auto Name = getEntityNameForReturn(FD);
- if (!Name)
- return std::nullopt;
- return addEntityImpl(*Name, FD);
-}
-
std::pair<EntitySummary *, bool>
TUSummaryBuilder::addSummaryImpl(EntityId Entity,
std::unique_ptr<EntitySummary> &&Data) {
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp
new file mode 100644
index 0000000000000..3476fadd54b57
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp
@@ -0,0 +1,58 @@
+//===- TUSummaryExtractor.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/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/AST/Decl.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include <optional>
+
+using namespace clang;
+using namespace ssaf;
+
+static EntityLinkageType getLinkageForDecl(const Decl *D) {
+ const auto *ND = dyn_cast<NamedDecl>(D);
+ if (!ND)
+ return EntityLinkageType::None;
+
+ switch (ND->getFormalLinkage()) {
+ case Linkage::Invalid: {
+ llvm_unreachable("Shouldn't be invalid");
+ }
+ case Linkage::None:
+ return EntityLinkageType::None;
+ case Linkage::Internal:
+ return EntityLinkageType::Internal;
+ case Linkage::UniqueExternal:
+ return EntityLinkageType::Internal;
+ case Linkage::VisibleNone:
+ return EntityLinkageType::Internal;
+ case Linkage::Module:
+ return EntityLinkageType::External;
+ case Linkage::External:
+ return EntityLinkageType::External;
+ }
+ llvm_unreachable("Unhandled clang::Linkage kind");
+}
+
+std::optional<EntityId> TUSummaryExtractor::addEntity(const NamedDecl *D) {
+ auto Name = getEntityName(D);
+ if (!Name)
+ return std::nullopt;
+ return SummaryBuilder.addEntity(*Name, getLinkageForDecl(D));
+}
+
+std::optional<EntityId>
+TUSummaryExtractor::addEntityForReturn(const FunctionDecl *FD) {
+ auto Name = getEntityNameForReturn(FD);
+ if (!Name)
+ return std::nullopt;
+ return SummaryBuilder.addEntity(*Name, getLinkageForDecl(FD));
+}
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
index 2490d43992bfa..7dc13a890cad4 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
@@ -39,7 +39,7 @@ class UnsafeBufferUsageTest : public TestFixture {
protected:
TUSummary TUSum;
TUSummaryBuilder Builder;
- std::unique_ptr<ASTConsumer> Extractor;
+ std::unique_ptr<TUSummaryExtractor> Extractor;
std::unique_ptr<ASTUnit> AST;
UnsafeBufferUsageTest()
@@ -74,7 +74,7 @@ class UnsafeBufferUsageTest : public TestFixture {
}
std::optional<EntityId> ContributorEntityId =
- Builder.addEntity(ContributorDefn);
+ Extractor->addEntity(ContributorDefn);
if (!ContributorEntityId) {
ADD_FAILURE() << "failed to get EntityName for contributor \""
<< ContributorEntityName << "\"";
@@ -101,13 +101,13 @@ class UnsafeBufferUsageTest : public TestFixture {
std::optional<EntityId> getEntityId(StringRef Name) {
if (const auto *D = findDeclByName(Name, AST->getASTContext()))
- return Builder.addEntity(D);
+ return Extractor->addEntity(D);
return std::nullopt;
}
std::optional<EntityId> getEntityIdForReturn(StringRef FunName) {
if (const auto *D = findFnByName(FunName, AST->getASTContext()))
- return Builder.addEntityForReturn(D);
+ return Extractor->addEntityForReturn(D);
return std::nullopt;
}
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
index 151f07b92207d..0c7846d784d7c 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
@@ -16,6 +16,7 @@
#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
@@ -90,7 +91,8 @@ void PrintTo(const MockSummaryData3 &S, std::ostream *OS) {
struct TUSummaryBuilderTest : ssaf::TestFixture {
TUSummary Summary{
BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")};
- TUSummaryBuilder Builder = TUSummaryBuilder(this->Summary);
+ TUSummaryBuilder Builder{Summary};
+ TUSummaryExtractor Extractor{Builder};
[[nodiscard]] EntityId addTestEntity(llvm::StringRef USR) {
return getIdTable(Summary).getId(
@@ -290,28 +292,32 @@ TEST_F(TUSummaryBuilderLinkageTest, HasInternalLinkage) {
AST = tooling::buildASTFromCode("static void target() {}");
const FunctionDecl *Fn = findFnByName("target");
ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Builder.addEntity(Fn)), EntityLinkageType::Internal);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)),
+ EntityLinkageType::Internal);
}
TEST_F(TUSummaryBuilderLinkageTest, HasExternalLinkage) {
AST = tooling::buildASTFromCode("void target() {}");
const FunctionDecl *Fn = findFnByName("target");
ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Builder.addEntity(Fn)), EntityLinkageType::External);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)),
+ EntityLinkageType::External);
}
TEST_F(TUSummaryBuilderLinkageTest, HasExternalLinkageWithInline) {
AST = tooling::buildASTFromCode("inline void target() {}");
const FunctionDecl *Fn = findFnByName("target");
ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Builder.addEntity(Fn)), EntityLinkageType::External);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)),
+ EntityLinkageType::External);
}
TEST_F(TUSummaryBuilderLinkageTest, HasInternalLinkageWithStaticInline) {
AST = tooling::buildASTFromCode("static inline void target() {}");
const FunctionDecl *Fn = findFnByName("target");
ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Builder.addEntity(Fn)), EntityLinkageType::Internal);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)),
+ EntityLinkageType::Internal);
}
TEST_F(TUSummaryBuilderLinkageTest, ConstVolatileGlobalHasExternalLinkage) {
@@ -320,7 +326,8 @@ TEST_F(TUSummaryBuilderLinkageTest, ConstVolatileGlobalHasExternalLinkage) {
"}");
const auto *VD = findDeclByName<VarDecl>("glob", AST->getASTContext());
ASSERT_TRUE(VD);
- EXPECT_EQ(getLinkageFor(Builder.addEntity(VD)), EntityLinkageType::External);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(VD)),
+ EntityLinkageType::External);
}
TEST_F(TUSummaryBuilderLinkageTest, ConstGlobalHasInternalLinkage) {
@@ -329,7 +336,8 @@ TEST_F(TUSummaryBuilderLinkageTest, ConstGlobalHasInternalLinkage) {
"}");
const auto *VD = findDeclByName<VarDecl>("glob", AST->getASTContext());
ASSERT_TRUE(VD);
- EXPECT_EQ(getLinkageFor(Builder.addEntity(VD)), EntityLinkageType::Internal);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(VD)),
+ EntityLinkageType::Internal);
}
} // namespace
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
index 70879d66e4700..e2da7fcd82e62 100644
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
@@ -28,6 +28,7 @@ static_library("Core") {
"Support/ErrorBuilder.cpp",
"TUSummary/ExtractorRegistry.cpp",
"TUSummary/TUSummaryBuilder.cpp",
+ "TUSummary/TUSummaryExtractor.cpp",
"WholeProgramAnalysis/AnalysisDriver.cpp",
"WholeProgramAnalysis/AnalysisName.cpp",
"WholeProgramAnalysis/AnalysisRegistry.cpp",
>From d9af2ebb6f94070913c5ec35ce7cddad1d8b34fb Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Fri, 1 May 2026 12:18:24 +0100
Subject: [PATCH 5/5] NFC Make EXPECT_EQ lines fit nicely
---
.../TUSummaryBuilderTest.cpp | 20 ++++++++-----------
1 file changed, 8 insertions(+), 12 deletions(-)
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
index 0c7846d784d7c..3fff10f08d38a 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
@@ -273,6 +273,8 @@ TEST_F(TUSummaryBuilderTest, AddConflictingSummaryToSameEntity) {
struct TUSummaryBuilderLinkageTest : TUSummaryBuilderTest {
std::unique_ptr<ASTUnit> AST;
+ static constexpr auto Internal = EntityLinkageType::Internal;
+ static constexpr auto External = EntityLinkageType::External;
const FunctionDecl *findFnByName(StringRef Name) {
return ssaf::findFnByName(Name, AST->getASTContext());
@@ -292,32 +294,28 @@ TEST_F(TUSummaryBuilderLinkageTest, HasInternalLinkage) {
AST = tooling::buildASTFromCode("static void target() {}");
const FunctionDecl *Fn = findFnByName("target");
ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)),
- EntityLinkageType::Internal);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), Internal);
}
TEST_F(TUSummaryBuilderLinkageTest, HasExternalLinkage) {
AST = tooling::buildASTFromCode("void target() {}");
const FunctionDecl *Fn = findFnByName("target");
ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)),
- EntityLinkageType::External);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), External);
}
TEST_F(TUSummaryBuilderLinkageTest, HasExternalLinkageWithInline) {
AST = tooling::buildASTFromCode("inline void target() {}");
const FunctionDecl *Fn = findFnByName("target");
ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)),
- EntityLinkageType::External);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), External);
}
TEST_F(TUSummaryBuilderLinkageTest, HasInternalLinkageWithStaticInline) {
AST = tooling::buildASTFromCode("static inline void target() {}");
const FunctionDecl *Fn = findFnByName("target");
ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)),
- EntityLinkageType::Internal);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), Internal);
}
TEST_F(TUSummaryBuilderLinkageTest, ConstVolatileGlobalHasExternalLinkage) {
@@ -326,8 +324,7 @@ TEST_F(TUSummaryBuilderLinkageTest, ConstVolatileGlobalHasExternalLinkage) {
"}");
const auto *VD = findDeclByName<VarDecl>("glob", AST->getASTContext());
ASSERT_TRUE(VD);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(VD)),
- EntityLinkageType::External);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(VD)), External);
}
TEST_F(TUSummaryBuilderLinkageTest, ConstGlobalHasInternalLinkage) {
@@ -336,8 +333,7 @@ TEST_F(TUSummaryBuilderLinkageTest, ConstGlobalHasInternalLinkage) {
"}");
const auto *VD = findDeclByName<VarDecl>("glob", AST->getASTContext());
ASSERT_TRUE(VD);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(VD)),
- EntityLinkageType::Internal);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(VD)), Internal);
}
} // namespace
More information about the cfe-commits
mailing list