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@foo", "", {}}); - EntityId E2 = Builder.addEntity({"c:@F@bar", "", {}}); + EntityIdTable Table; + EntityId E1 = Table.getId({"c:@F@foo", "", {}}); + EntityId E2 = Table.getId({"c:@F@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@foo", "", {}}); - EntityId E2 = Builder.addEntity({"c:@F@bar", "", {}}); - EntityId E3 = Builder.addEntity({"c:@F@baz", "", {}}); + EntityIdTable Table; + EntityId E1 = Table.getId({"c:@F@foo", "", {}}); + EntityId E2 = Table.getId({"c:@F@bar", "", {}}); + EntityId E3 = Table.getId({"c:@F@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@foo", "", /*Namespace=*/{}); EntityName EN2("c:@F@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@foo"); + EntityId ID = addTestEntity("c:@F@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@foo"); + EntityId ID = addTestEntity("c:@F@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@foo"); - EntityId ID2 = addTestEntity(Builder, "c:@F@bar"); - EntityId ID3 = addTestEntity(Builder, "c:@F@baz"); + EntityId ID1 = addTestEntity("c:@F@foo"); + EntityId ID2 = addTestEntity("c:@F@bar"); + EntityId ID3 = addTestEntity("c:@F@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@foo"); + EntityId ID = addTestEntity("c:@F@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", _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
