[clang] 6bcc877 - [clang][ssaf] Rework addEntity to take NamedDecl (#194448)
via cfe-commits
cfe-commits at lists.llvm.org
Wed May 6 08:03:38 PDT 2026
Author: Balázs Benics
Date: 2026-05-06T15:03:32Z
New Revision: 6bcc877da20e6701e01e536d78062ba58f266b5b
URL: https://github.com/llvm/llvm-project/commit/6bcc877da20e6701e01e536d78062ba58f266b5b
DIFF: https://github.com/llvm/llvm-project/commit/6bcc877da20e6701e01e536d78062ba58f266b5b.diff
LOG: [clang][ssaf] Rework addEntity to take NamedDecl (#194448)
This patch changes `addEntity` to take a `NamedDecl` to be able to
calculate the linkage for the entity.
It will try to get an `EntityName` and then try to get a Linkage for it.
Bundling the EntityName creation and then setting the linkage makes this
API safer as nobody can forget to set the linkage this way.
Assisted-By: claude
Added:
clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp
Modified:
clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
Removed:
################################################################################
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
index 98812e0ea04e3..35eae269105f7 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 TUSummaryExtractor;
/// 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,
+ TUSummaryExtractor &Extractor);
/// 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, 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 fd07abfab8c87..f9ebe5358b585 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
@@ -10,6 +10,7 @@
#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_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 <utility>
@@ -23,9 +24,7 @@ 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);
+ 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
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 1dbed7e0b0d8a..3436da7c2244b 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 = 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 = 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 ce301f7cc1b10..da6084f4d41a8 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
@@ -11,9 +11,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include <map>
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
#include <optional>
using namespace clang;
@@ -51,8 +49,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 = Extractor.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 = Extractor.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 +81,23 @@ class EntityPointerLevelTranslator
return EntityPointerLevelSet{Incremented.begin(), Incremented.end()};
}
- std::function<EntityId(EntityName EN)> AddEntity;
+ TUSummaryExtractor &Extractor;
ASTContext &Ctx;
public:
- EntityPointerLevelTranslator(std::function<EntityId(EntityName EN)> AddEntity,
- ASTContext &Ctx)
- : AddEntity(AddEntity), 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) {
- 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 get entity for return of %s",
+ D->getDeclKindName());
}
static EntityPointerLevel incrementPointerLevel(const EntityPointerLevel &E) {
@@ -167,10 +175,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 = Extractor.addEntityForReturn(FD))
+ return EntityPointerLevelSet{buildEntityPointerLevel(*ReturnId, 1)};
+ }
return EntityPointerLevelSet{};
}
@@ -210,16 +218,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};
}
// Translate(`DefaultArg`) -> Translate(`DefaultArg->getExpr()`)
@@ -235,19 +245,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,
+ 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, llvm::function_ref<EntityId(EntityName EN)> AddEntity,
- bool IsFunRet) {
- EntityPointerLevelTranslator Translator(AddEntity, 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/PointerFlow/PointerFlowExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
index 473ce5b11ae5b..8f79c987cc290 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
@@ -42,10 +42,10 @@ class PointerFlowMatcher {
public:
EdgeSet Results;
ASTContext &Ctx;
+ TUSummaryExtractor &Extractor;
- PointerFlowMatcher(ASTContext &Ctx,
- std::function<EntityId(const EntityName &)> AddEntity)
- : Ctx(Ctx), AddEntity(std::move(AddEntity)) {}
+ PointerFlowMatcher(ASTContext &Ctx, TUSummaryExtractor &Extractor)
+ : Ctx(Ctx), Extractor(Extractor) {}
llvm::Error matches(const DynTypedNode &DynNode, const NamedDecl *RootDecl);
@@ -88,7 +88,7 @@ class PointerFlowMatcher {
Expected<EntityPointerLevelSet> PointerFlowMatcher::toEPL(const NamedDecl *N,
bool IsRet) const {
- auto Ret = createEntityPointerLevel(N, AddEntity, IsRet);
+ auto Ret = createEntityPointerLevel(N, Extractor, IsRet);
if (Ret)
return EntityPointerLevelSet{*Ret};
@@ -96,7 +96,7 @@ Expected<EntityPointerLevelSet> PointerFlowMatcher::toEPL(const NamedDecl *N,
}
Expected<EntityPointerLevelSet> PointerFlowMatcher::toEPL(const Expr *N) const {
- return translateEntityPointerLevel(N, Ctx, AddEntity);
+ return translateEntityPointerLevel(N, Ctx, Extractor);
}
llvm::Error
@@ -309,14 +309,10 @@ class PointerFlowTUSummaryExtractor : public TUSummaryExtractor {
PointerFlowTUSummaryExtractor(TUSummaryBuilder &Builder)
: TUSummaryExtractor(Builder) {}
- EntityId addEntity(const EntityName &EN) {
- return SummaryBuilder.addEntity(EN);
- }
-
Expected<std::unique_ptr<PointerFlowEntitySummary>>
- extractEntitySummary(const NamedDecl *Contributor, ASTContext &Ctx) {
- PointerFlowMatcher Matcher(
- Ctx, [this](const EntityName &EN) { return addEntity(EN); });
+ extractEntitySummary(const NamedDecl *Contributor, ASTContext &Ctx,
+ TUSummaryExtractor &Extractor) {
+ PointerFlowMatcher Matcher(Ctx, Extractor);
auto MatchAction = [&Matcher, &Contributor](const DynTypedNode &Node) {
auto Err = Matcher.matches(Node, Contributor);
@@ -334,7 +330,7 @@ class PointerFlowTUSummaryExtractor : public TUSummaryExtractor {
findContributors(Ctx, Contributors);
for (auto *CD : Contributors) {
- auto EntitySummary = extractEntitySummary(CD, Ctx);
+ auto EntitySummary = extractEntitySummary(CD, Ctx, *this);
if (!EntitySummary)
llvm::reportFatalInternalError(EntitySummary.takeError());
@@ -342,13 +338,12 @@ class PointerFlowTUSummaryExtractor : public TUSummaryExtractor {
if ((*EntitySummary)->empty())
continue;
- auto ContributorName = getEntityName(CD);
-
- if (!ContributorName)
+ std::optional<EntityId> ContributorId = addEntity(CD);
+ if (!ContributorId)
llvm::reportFatalInternalError(makeEntityNameErr(Ctx, CD));
- [[maybe_unused]] auto [_, InsertionSucceeded] = SummaryBuilder.addSummary(
- addEntity(*ContributorName), std::move(*EntitySummary));
+ [[maybe_unused]] auto [_, InsertionSucceeded] =
+ SummaryBuilder.addSummary(*ContributorId, std::move(*EntitySummary));
assert(InsertionSucceeded && "duplicated contributor extraction");
}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index 5e202d8a443c7..9103778d585fb 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, *this);
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 = 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/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 180a78cae33a9..daea76f7001cb 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
@@ -8,6 +8,7 @@
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.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>
@@ -16,8 +17,14 @@
using namespace clang;
using namespace ssaf;
-EntityId TUSummaryBuilder::addEntity(const EntityName &E) {
- return Summary.IdTable.getId(E);
+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::pair<EntitySummary *, bool>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp
new file mode 100644
index 0000000000000..9594a6b179db5
--- /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/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/TUSummaryBuilder.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/PointerFlow/PointerFlowTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
index 2d6a958ce4eac..9f7a508ea35fd 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
@@ -183,15 +183,15 @@ class PointerFlowTest : public TestFixture {
return nullptr;
}
- std::optional<EntityName> EN = getEntityName(ContributorDefn);
+ std::optional<EntityId> ContributorEntityId =
+ Extractor->addEntity(ContributorDefn);
- if (!EN) {
+ if (!ContributorEntityId) {
ADD_FAILURE() << "failed to get EntityName for contributor \""
<< toStringRef(Name) << "\"";
return nullptr;
}
- EntityId ContributorEntityId = Builder.addEntity(*EN);
auto &TUSumData = getData(TUSum);
auto EntitiesSumIter =
TUSumData.find(PointerFlowEntitySummary::summaryName());
@@ -201,7 +201,7 @@ class PointerFlowTest : 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())
@@ -213,16 +213,14 @@ class PointerFlowTest : public TestFixture {
public:
std::optional<EntityId> getEntityId(FindEntityByName Name) {
if (const auto *D = findEntityByName(Name, AST->getASTContext())) {
- if (auto EntityName = getEntityName(D))
- return Builder.addEntity(*EntityName);
+ return Extractor->addEntity(D);
}
return std::nullopt;
}
std::optional<EntityId> getEntityIdForReturn(FindEntityByName FunName) {
if (const auto *D = findFnByName(FunName, AST->getASTContext())) {
- if (auto EntityName = getEntityNameForReturn(D))
- return Builder.addEntity(*EntityName);
+ return Extractor->addEntityForReturn(D);
}
return std::nullopt;
}
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
index 465488357e20e..7dc13a890cad4 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"
@@ -40,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,15 +73,14 @@ class UnsafeBufferUsageTest : public TestFixture {
return nullptr;
}
- std::optional<EntityName> EN = getEntityName(ContributorDefn);
-
- if (!EN) {
+ std::optional<EntityId> ContributorEntityId =
+ Extractor->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 Extractor->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 Extractor->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..3fff10f08d38a 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
@@ -7,14 +7,17 @@
//===----------------------------------------------------------------------===//
#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/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
@@ -32,11 +35,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;
@@ -93,7 +91,13 @@ 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(
+ EntityName(USR, /*Suffix=*/"", /*Namespace=*/{}));
+ }
[[nodiscard]] static SmallVector<SummaryName>
summaryNames(const TUSummary &Summary) {
@@ -128,22 +132,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 +162,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
diff erent summary types to the same entity.
auto [Name1, Res1] = addSummaryTo(Builder, ID, MockSummaryData1(42));
@@ -188,9 +193,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
diff erent entities.
auto [Name1, Res1] = addSummaryTo(Builder, ID1, MockSummaryData1(1));
@@ -220,7 +225,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 +271,69 @@ TEST_F(TUSummaryBuilderTest, AddConflictingSummaryToSameEntity) {
Optional(Field(&MockSummaryData1::Value, 30)));
}
+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());
+ }
+
+ 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(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)), 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)), 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)), 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(Extractor.addEntity(VD)), 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(Extractor.addEntity(VD)), 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",
More information about the cfe-commits
mailing list