[llvm-branch-commits] [clang] [SSAF][UnsafeBufferUsage] Remove UnsafeBufferUsageExtractor.h (PR #191931)

Ziqing Luo via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Apr 15 11:06:48 PDT 2026


https://github.com/ziqingluo-90 updated https://github.com/llvm/llvm-project/pull/191931

>From 65abbbd4e682d67ee4fe642f8898cb5bb52ed6f6 Mon Sep 17 00:00:00 2001
From: Ziqing Luo <ziqing_luo at apple.com>
Date: Mon, 13 Apr 2026 17:26:04 -0700
Subject: [PATCH 1/2] [SSAF][UnsafeBufferUsage] Remove
 UnsafeBufferUsageExtractor.h

- Removed UnsafeBufferUsageExtractor.h
- Registered UnsafeBufferUsageExtractor
- Changed unit tests to enable the extractor with `HandleTranslationUnit`
- Fixed bugs in `UnsafeBufferUsageExtractor::HandleTranslationUnit`
---
 .../UnsafeBufferUsageExtractor.h              |  35 --
 .../SSAFBuiltinForceLinker.h                  |   5 +
 .../UnsafeBufferUsageExtractor.cpp            | 142 ++++----
 .../UnsafeBufferUsageTest.cpp                 | 313 ++++++++++--------
 4 files changed, 258 insertions(+), 237 deletions(-)
 delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h

diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h
deleted file mode 100644
index 13d4e18b4e81f..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- UnsafeBufferUsageExtractor.h -----------------------------*- C++ -*-===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
-#include "llvm/Support/Error.h"
-#include <memory>
-
-namespace clang::ssaf {
-class UnsafeBufferUsageTUSummaryExtractor : public TUSummaryExtractor {
-public:
-  UnsafeBufferUsageTUSummaryExtractor(TUSummaryBuilder &Builder)
-      : TUSummaryExtractor(Builder) {}
-
-  EntityId addEntity(EntityName EN) { return SummaryBuilder.addEntity(EN); }
-
-  std::unique_ptr<UnsafeBufferUsageEntitySummary>
-  extractEntitySummary(const Decl *Contributor, ASTContext &Ctx,
-                       llvm::Error &Error);
-
-  void HandleTranslationUnit(ASTContext &Ctx) override;
-};
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
index 2030dc8a12030..916ef1ce783c4 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
@@ -36,6 +36,11 @@ extern volatile int UnsafeBufferUsageSSAFJSONFormatAnchorSource;
 [[maybe_unused]] static int UnsafeBufferUsageSSAFJSONFormatAnchorDestination =
     UnsafeBufferUsageSSAFJSONFormatAnchorSource;
 
+extern volatile int UnsafeBufferUsageTUSummaryExtractorAnchorSource;
+[[maybe_unused]] static int
+    UnsafeBufferUsageTUSummaryExtractorAnchorDestination =
+        UnsafeBufferUsageTUSummaryExtractorAnchorSource;
+
 // This anchor is used to force the linker to link the CallGraphExtractor.
 extern volatile int CallGraphExtractorAnchorSource;
 [[maybe_unused]] static int CallGraphExtractorAnchorDestination =
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index c412855028efb..72944bd0be323 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -6,7 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DynamicRecursiveASTVisitor.h"
@@ -16,6 +15,9 @@
 #include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.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"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Error.h"
 #include <memory>
@@ -24,8 +26,8 @@ namespace {
 using namespace clang;
 using namespace ssaf;
 
-static llvm::Error makeCreateEntityNameError(const NamedDecl *FailedDecl,
-                                             ASTContext &Ctx) {
+llvm::Error makeCreateEntityNameError(const NamedDecl *FailedDecl,
+                                      ASTContext &Ctx) {
   std::string LocStr = FailedDecl->getSourceRange().getBegin().printToString(
       Ctx.getSourceManager());
   return llvm::createStringError(
@@ -33,19 +35,8 @@ static llvm::Error makeCreateEntityNameError(const NamedDecl *FailedDecl,
       FailedDecl->getNameAsString().c_str(), LocStr.c_str());
 }
 
-static llvm::Error makeAddEntitySummaryError(const NamedDecl *FailedContributor,
-                                             ASTContext &Ctx) {
-  std::string LocStr =
-      FailedContributor->getSourceRange().getBegin().printToString(
-          Ctx.getSourceManager());
-  return llvm::createStringError(
-      "failed to add entity summary for contributor %s declared at %s",
-      FailedContributor->getNameAsString().c_str(), LocStr.c_str());
-}
-
 Expected<EntityPointerLevelSet>
 buildEntityPointerLevels(std::set<const Expr *> &&UnsafePointers,
-                         UnsafeBufferUsageTUSummaryExtractor &Extractor,
                          ASTContext &Ctx,
                          std::function<EntityId(EntityName)> AddEntity) {
   EntityPointerLevelSet Result{};
@@ -71,7 +62,6 @@ buildEntityPointerLevels(std::set<const Expr *> &&UnsafePointers,
     return AllErrors;
   return Result;
 }
-} // namespace
 
 static std::set<const Expr *> findUnsafePointersInContributor(const Decl *D) {
   if (isa<FunctionDecl>(D) || isa<VarDecl>(D))
@@ -86,78 +76,84 @@ static std::set<const Expr *> findUnsafePointersInContributor(const Decl *D) {
   }
   return {};
 }
+} // namespace
 
-std::unique_ptr<UnsafeBufferUsageEntitySummary>
-UnsafeBufferUsageTUSummaryExtractor::extractEntitySummary(
-    const Decl *Contributor, ASTContext &Ctx, llvm::Error &Error) {
-  auto AddEntity = [this](EntityName EN) { return addEntity(EN); };
-  Expected<EntityPointerLevelSet> EPLs = buildEntityPointerLevels(
-      findUnsafePointersInContributor(Contributor), *this, Ctx, AddEntity);
-
-  if (EPLs)
-    return std::make_unique<UnsafeBufferUsageEntitySummary>(
-        UnsafeBufferUsageEntitySummary(std::move(*EPLs)));
-  Error = EPLs.takeError();
-  return nullptr;
-}
+class clang::ssaf::UnsafeBufferUsageTUSummaryExtractor
+    : public TUSummaryExtractor {
+public:
+  UnsafeBufferUsageTUSummaryExtractor(TUSummaryBuilder &Builder)
+      : TUSummaryExtractor(Builder) {}
 
-void UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
-    ASTContext &Ctx) {
+  EntityId addEntity(EntityName EN) { return SummaryBuilder.addEntity(EN); }
 
-  // FIXME: I suppose finding contributor Decls is commonly needed by all/many
-  // extractors
-  class ContributorFinder : public DynamicRecursiveASTVisitor {
-  public:
-    std::vector<const NamedDecl *> Contributors;
+  Expected<std::unique_ptr<UnsafeBufferUsageEntitySummary>>
+  extractEntitySummary(const Decl *Contributor, ASTContext &Ctx) {
+    auto AddEntity = [this](EntityName EN) { return addEntity(EN); };
+    Expected<EntityPointerLevelSet> EPLs = buildEntityPointerLevels(
+        findUnsafePointersInContributor(Contributor), Ctx, AddEntity);
 
-    bool VisitFunctionDecl(FunctionDecl *D) override {
-      Contributors.push_back(D);
-      return true;
-    }
+    if (EPLs)
+      return std::make_unique<UnsafeBufferUsageEntitySummary>(
+          UnsafeBufferUsageEntitySummary(std::move(*EPLs)));
+    return EPLs.takeError();
+  }
 
-    bool VisitRecordDecl(RecordDecl *D) override {
-      Contributors.push_back(D);
-      return true;
-    }
+  void HandleTranslationUnit(ASTContext &Ctx) override {
 
-    bool VisitVarDecl(VarDecl *D) override {
-      DeclContext *DC = D->getDeclContext();
+    // FIXME: I suppose finding contributor Decls is commonly needed by all/many
+    // extractors
+    class ContributorFinder : public DynamicRecursiveASTVisitor {
+    public:
+      std::vector<const NamedDecl *> Contributors;
 
-      if (DC->isFileContext() || DC->isNamespace())
+      bool VisitFunctionDecl(FunctionDecl *D) override {
         Contributors.push_back(D);
-      return false;
-    }
-  } ContributorFinder;
+        return true;
+      }
 
-  ContributorFinder.VisitTranslationUnitDecl(Ctx.getTranslationUnitDecl());
+      bool VisitRecordDecl(RecordDecl *D) override {
+        Contributors.push_back(D);
+        return true;
+      }
 
-  llvm::Error Errors = llvm::ErrorSuccess();
-  auto addError = [&Errors](llvm::Error Err) {
-    Errors = llvm::joinErrors(std::move(Errors), std::move(Err));
-  };
+      bool VisitVarDecl(VarDecl *D) override {
+        DeclContext *DC = D->getDeclContext();
 
-  for (auto *CD : ContributorFinder.Contributors) {
-    llvm::Error Error = llvm::ErrorSuccess();
-    auto EntitySummary = extractEntitySummary(CD, Ctx, Error);
+        if (DC->isFileContext() || DC->isNamespace())
+          Contributors.push_back(D);
+        return true;
+      }
+    } ContributorFinder;
 
-    if (Error)
-      addError(std::move(Error));
-    if (EntitySummary->empty())
-      continue;
+    ContributorFinder.VisitTranslationUnitDecl(Ctx.getTranslationUnitDecl());
 
-    auto ContributorName = getEntityName(CD);
+    ContributorFinder.TraverseAST(Ctx);
+    for (auto *CD : ContributorFinder.Contributors) {
+      auto EntitySummary = extractEntitySummary(CD, Ctx);
 
-    if (!ContributorName) {
-      addError(makeCreateEntityNameError(CD, Ctx));
-      continue;
-    }
+      if (!EntitySummary)
+        llvm::reportFatalInternalError(EntitySummary.takeError());
+      assert(*EntitySummary);
+      if ((*EntitySummary)->empty())
+        continue;
+
+      auto ContributorName = getEntityName(CD);
 
-    auto [EntitySummaryPtr, Success] = SummaryBuilder.addSummary(
-        addEntity(*ContributorName), std::move(EntitySummary));
+      if (!ContributorName)
+        llvm::reportFatalInternalError(makeCreateEntityNameError(CD, Ctx));
 
-    if (!Success)
-      addError(makeAddEntitySummaryError(CD, Ctx));
+      auto [Ignored, InsertionSucceeded] = SummaryBuilder.addSummary(
+          addEntity(*ContributorName), std::move(*EntitySummary));
+
+      assert(InsertionSucceeded && "duplicated contributor extraction");
+    }
   }
-  // FIXME: handle errors!
-  llvm::consumeError(std::move(Errors));
-}
+};
+
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int UnsafeBufferUsageTUSummaryExtractorAnchorSource = 0;
+
+static clang::ssaf::TUSummaryExtractorRegistry::Add<
+    ssaf::UnsafeBufferUsageTUSummaryExtractor>
+    RegisterExtractor(UnsafeBufferUsageEntitySummary::Name,
+                      "The TUSummaryExtractor for unsafe buffer pointers");
\ No newline at end of file
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
index d2c513b7c70a2..59c2cd38ffacf 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
@@ -11,20 +11,23 @@
 #include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.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"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Testing/Support/Error.h"
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
+#include <initializer_list>
 #include <memory>
 #include <optional>
 
@@ -33,7 +36,6 @@ using namespace ssaf;
 using testing::UnorderedElementsAre;
 
 namespace {
-
 template <typename SomeDecl = NamedDecl>
 const SomeDecl *findDeclByName(StringRef Name, ASTContext &Ctx) {
   class NamedDeclFinder : public DynamicRecursiveASTVisitor {
@@ -68,52 +70,82 @@ class UnsafeBufferUsageTest : public TestFixture {
 protected:
   TUSummary TUSum;
   TUSummaryBuilder Builder;
-  UnsafeBufferUsageTUSummaryExtractor Extractor;
+  std::unique_ptr<TUSummaryExtractor> Extractor;
   std::unique_ptr<ASTUnit> AST;
 
   UnsafeBufferUsageTest()
       : TUSum(BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")),
-        Builder(TUSum), Extractor(Builder) {}
+        Builder(TUSum), Extractor(nullptr) {}
 
-  template <typename ContributorDecl = NamedDecl>
-  std::unique_ptr<UnsafeBufferUsageEntitySummary>
-  setUpTest(StringRef Code, StringRef ContributorName) {
+  bool setUpTest(StringRef Code) {
     AST = tooling::buildASTFromCodeWithArgs(
         Code, {"-Wno-unused-value", "-Wno-int-to-pointer-cast"});
 
-    const auto *ContributorDefn =
-        findDeclByName<ContributorDecl>(ContributorName, AST->getASTContext());
+    for (auto &E : clang::ssaf::TUSummaryExtractorRegistry::entries()) {
+      if (E.getName() == UnsafeBufferUsageEntitySummary::Name) {
+        Extractor = E.instantiate(Builder);
+        break;
+      }
+    }
+
+    if (!Extractor) {
+      ADD_FAILURE() << "failed to find UnsafeBufferUsageTUSummaryExtractor";
+      return false;
+    }
+    Extractor->HandleTranslationUnit(AST->getASTContext());
+    return true;
+  }
 
-    if (!ContributorDefn)
+  template <typename ContributorDecl = NamedDecl>
+  const UnsafeBufferUsageEntitySummary *
+  getEntitySummary(StringRef ContributorEntityName) {
+    auto *ContributorDefn = findDeclByName<ContributorDecl>(
+        ContributorEntityName, AST->getASTContext());
+
+    if (!ContributorDefn) {
+      ADD_FAILURE() << "failed to find Decl of \"" << ContributorEntityName
+                    << "\"";
       return nullptr;
+    }
 
     std::optional<EntityName> EN = getEntityName(ContributorDefn);
 
-    if (!EN)
+    if (!EN) {
+      ADD_FAILURE() << "failed to get EntityName for contributor \""
+                    << ContributorEntityName << "\"";
       return nullptr;
+    }
 
-    llvm::Error Error = llvm::ErrorSuccess();
-    auto Sum = Extractor.extractEntitySummary(ContributorDefn,
-                                              AST->getASTContext(), Error);
+    EntityId ContributorEntityId = Builder.addEntity(*EN);
+    auto &TUSumData = getData(TUSum);
+    auto EntitiesSumIter =
+        TUSumData.find(UnsafeBufferUsageEntitySummary::summaryName());
 
-    if (Error) {
-      llvm::consumeError(std::move(Error));
+    // If none entity summary was collected, it may not be an entry in
+    // `TUSumData`:
+    if (EntitiesSumIter == TUSumData.end())
       return nullptr;
-    }
-    return Sum;
+
+    auto EntitySumIter = EntitiesSumIter->second.find(ContributorEntityId);
+
+    // If entity summary is empty, it may not exist:
+    if (EntitySumIter == EntitiesSumIter->second.end())
+      return nullptr;
+    return static_cast<const UnsafeBufferUsageEntitySummary *>(
+        EntitySumIter->second.get());
   }
 
   std::optional<EntityId> getEntityId(StringRef Name) {
     if (const auto *D = findDeclByName(Name, AST->getASTContext()))
       if (auto EntityName = getEntityName(D))
-        return Extractor.addEntity(*EntityName);
+        return Builder.addEntity(*EntityName);
     return std::nullopt;
   }
 
   std::optional<EntityId> getEntityIdForReturn(StringRef FunName) {
     if (const auto *D = findFnByName(FunName, AST->getASTContext()))
       if (auto EntityName = getEntityNameForReturn(D))
-        return Extractor.addEntity(*EntityName);
+        return Builder.addEntity(*EntityName);
     return std::nullopt;
   }
 
@@ -153,8 +185,8 @@ getSubsetOf(const EntityPointerLevelSet &Set, EntityId Entity) {
 }
 
 TEST_F(UnsafeBufferUsageTest, EntityPointerLevelComparison) {
-  EntityId E1 = Extractor.addEntity({"c:@F at foo", "", {}});
-  EntityId E2 = Extractor.addEntity({"c:@F at bar", "", {}});
+  EntityId E1 = Builder.addEntity({"c:@F at foo", "", {}});
+  EntityId E2 = Builder.addEntity({"c:@F at bar", "", {}});
 
   auto P1 = buildEntityPointerLevel(E1, 2);
   auto P2 = buildEntityPointerLevel(E1, 2);
@@ -172,9 +204,9 @@ TEST_F(UnsafeBufferUsageTest, EntityPointerLevelComparison) {
 }
 
 TEST_F(UnsafeBufferUsageTest, UnsafeBufferUsageEntityPointerLevelSetTest) {
-  EntityId E1 = Extractor.addEntity({"c:@F at foo", "", {}});
-  EntityId E2 = Extractor.addEntity({"c:@F at bar", "", {}});
-  EntityId E3 = Extractor.addEntity({"c:@F at baz", "", {}});
+  EntityId E1 = Builder.addEntity({"c:@F at foo", "", {}});
+  EntityId E2 = Builder.addEntity({"c:@F at bar", "", {}});
+  EntityId E3 = Builder.addEntity({"c:@F at baz", "", {}});
 
   auto P1 = buildEntityPointerLevel(E1, 1);
   auto P2 = buildEntityPointerLevel(E1, 2);
@@ -195,13 +227,14 @@ TEST_F(UnsafeBufferUsageTest, UnsafeBufferUsageEntityPointerLevelSetTest) {
 //////////////////////////////////////////////////////////////
 
 TEST_F(UnsafeBufferUsageTest, UnsafeBufferUsageSerializeTest) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int ***p, int ****q, int x) {
       p[5][5][5];
       q[5][5][5][5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
   ASSERT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U},
                                      {"p", 2U},
@@ -241,40 +274,43 @@ TEST_F(UnsafeBufferUsageTest, UnsafeBufferUsageSerializeTest) {
 //////////////////////////////////////////////////////////////
 
 TEST_F(UnsafeBufferUsageTest, SimpleFunctionWithUnsafePointer) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int *p) {
       p[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, PointerArithmetic) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int *p, int *q) {
       *(p + 5);
       *(q - 3);
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, PointerIncrementDecrement) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int *p, int *q, int *r, int *s) {
       (++p)[5];
       (q++)[5];
       (--r)[5];
       (s--)[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum,
@@ -282,40 +318,43 @@ TEST_F(UnsafeBufferUsageTest, PointerIncrementDecrement) {
 }
 
 TEST_F(UnsafeBufferUsageTest, PointerAssignment) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int *p, int *q) {
       (p = q + 5)[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, CompoundAssignment) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int *p, int *q) {
       (p += 5)[5];
       (q -= 3)[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, MultiLevelPointer) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int **p, int **q, int **r) {
       (*p)[5];
       *(*q);
       *(q[5]);
       r[5][5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum,
@@ -323,13 +362,14 @@ TEST_F(UnsafeBufferUsageTest, MultiLevelPointer) {
 }
 
 TEST_F(UnsafeBufferUsageTest, ConditionalOperator) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int **p, int **q, int cond) {
       (cond ? *p : *q)[5];
       cond ? p[5] : q[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum,
@@ -337,78 +377,84 @@ TEST_F(UnsafeBufferUsageTest, ConditionalOperator) {
 }
 
 TEST_F(UnsafeBufferUsageTest, CastExpression) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(void *p, int q) {
       ((int*)p)[5];
       ((int*)q)[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, CommaOperator) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int *p, int x) {
       (x++, p)[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, CommaOperator2) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int **p, int **q, int x) {
       (p[x] = 0, q[x] = 0)[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}, {"q", 2U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, ParenthesizedExpression) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int *p) {
       (((p)))[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, ArrayParameter) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int arr[], int arr2[][10]) {
       int n = 5;
       arr[100];
       arr2[5][n];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"arr", 1U}, {"arr2", 1U}, {"arr2", 2U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, FunctionCall) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     int ** (*fp)();
     int ** foo() {
       fp = &foo;
       foo()[5];
       (*fp())[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   // No (foo, 2) becasue indirect calls are ignored.
@@ -416,7 +462,7 @@ TEST_F(UnsafeBufferUsageTest, FunctionCall) {
 }
 
 TEST_F(UnsafeBufferUsageTest, StructMemberAccess) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     struct S {
       int *ptr;
       int (*ptr_to_arr)[10];
@@ -426,206 +472,215 @@ TEST_F(UnsafeBufferUsageTest, StructMemberAccess) {
       obj.ptr[5];
       (*obj.ptr_to_arr)[n];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"ptr", 1U}, {"ptr_to_arr", 2U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, StringLiteralSubscript) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo() {
       "hello"[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
-  EXPECT_NE(Sum, nullptr);
   // String literals should not generate pointer kind variables
-  EXPECT_EQ(*Sum, makeSet(__LINE__, {}));
+  EXPECT_EQ(Sum, nullptr);
 }
 
 TEST_F(UnsafeBufferUsageTest, OpaqueValueExpr) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int *p, int *q) {
        (p ?: q)[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, AddressOfOperator) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int x) {
       (&x)[5];
     }
-  )cpp",
-                       "foo");
-
-  EXPECT_NE(Sum, nullptr);
-  // Address-of should not generate pointer kind variables for 'x'
-  EXPECT_EQ(*Sum, makeSet(__LINE__, {}));
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
+  // Address-of should not generate pointer kind variables for 'x':
+  EXPECT_EQ(Sum, nullptr);
 }
 
 TEST_F(UnsafeBufferUsageTest, AddressOfThenDereference) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo(int *p, int *q) {
       (*(&p))[5];
       (&(*q))[5];
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1}, {"q", 1}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, PointerToArrayOfPointers) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     void foo() {
       int * arr[10];
-      int * (*p)[10] = arr;
+      int * (*p)[10] = &arr;
 
-      (*p)[5][5]; // '(*p)[5]' is unsafe 
+      (*p)[5][5]; // '(*p)[5]' is unsafe
                   // '(*p)' is fine because 5 < 10
     }
-  )cpp",
-                       "foo");
+  )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 3}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, UnsafePointerInGlobalVariableInitializer) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
       int *gp;
       int x = gp[5];
-    )cpp",
-                       {"x"});
+    )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("x");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, UnsafePointerInFieldInitializer) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
       int *gp;
       struct Foo {
         int field = gp[5];
       };
-    )cpp",
-                       {"Foo"});
+    )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("Foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, UnsafePointerInFieldInitializer2) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
       int *gp;
       union Foo {
         int field = gp[5];
         int x;
       };
-    )cpp",
-                       {"Foo"});
+    )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("Foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, InitializerList) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
       int *gp;
       struct Foo {
         int field;
         int x;
       };
       Foo FooObj{gp[5], 0};
-    )cpp",
-                       {"FooObj"});
+    )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("FooObj");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, UnsafePointerInCXXCtorInitializer) {
-  auto Sum = setUpTest<CXXConstructorDecl>(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
       struct Foo {
         int member;
         Foo(int *p) : member(p[5]) {}
       };
-    )cpp",
-                                           {"Foo"});
+    )cpp"),
+            true);
+  const auto *Sum = getEntitySummary<CXXConstructorDecl>("Foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, UnsafePointerInDefaultArg) {
-  auto Sum = setUpTest(R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     int * gp;
     void foo(int x = gp[5]);
-    )cpp",
-                       {"foo"});
+    )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
 }
 
 TEST_F(UnsafeBufferUsageTest, NestedDefinitions) {
-  StringRef Code = R"cpp(
+  ASSERT_EQ(setUpTest(R"cpp(
     int * a = [](){
       struct Foo {
         void bar(int * ptr) { ptr[3] = 0; }
       };
       return nullptr;
     }();
-    )cpp";
-  auto Sum = setUpTest(Code, {"bar"});
+    )cpp"),
+            true);
+  const auto *Sum = getEntitySummary("bar");
 
   EXPECT_NE(Sum, nullptr);
   // The closest contributor owns the fact:
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"ptr", 1U}}));
 
-  Sum = setUpTest(Code, {"Foo"});
+  Sum = getEntitySummary("Foo");
 
-  EXPECT_NE(Sum, nullptr);
-  EXPECT_TRUE(Sum->empty());
+  EXPECT_EQ(Sum, nullptr);
 
-  Sum = setUpTest(Code, {"a"});
+  Sum = getEntitySummary("a");
 
-  EXPECT_NE(Sum, nullptr);
-  EXPECT_TRUE(Sum->empty());
+  EXPECT_EQ(Sum, nullptr);
 }
 
 TEST_F(UnsafeBufferUsageTest, NestedDefinitions2) {
-  StringRef Code = R"cpp(
+  bool SetupSuccess = setUpTest(R"cpp(
     int main(void) {
        struct Foo {
           void bar(int * ptr) { ptr[3] = 0; }
        };
     }
-    )cpp";
-  auto Sum = setUpTest(Code, {"bar"});
+    )cpp");
+
+  ASSERT_EQ(SetupSuccess, true);
+
+  const auto *Sum = getEntitySummary("bar");
 
   EXPECT_NE(Sum, nullptr);
   // The closest contributor owns the fact:
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"ptr", 1U}}));
 
-  Sum = setUpTest(Code, {"Foo"});
+  Sum = getEntitySummary("Foo");
 
-  EXPECT_NE(Sum, nullptr);
-  EXPECT_TRUE(Sum->empty());
+  EXPECT_EQ(Sum, nullptr);
 
-  Sum = setUpTest(Code, {"main"});
+  Sum = getEntitySummary("main");
 
-  EXPECT_NE(Sum, nullptr);
-  EXPECT_TRUE(Sum->empty());
+  EXPECT_EQ(Sum, nullptr);
 }
 
 } // namespace

>From f4ab5e00ea532531a9b3fc3bc3b71966bd6533e5 Mon Sep 17 00:00:00 2001
From: Ziqing Luo <ziqing_luo at apple.com>
Date: Wed, 15 Apr 2026 11:06:18 -0700
Subject: [PATCH 2/2] clean up code

---
 .../EntityPointerLevel/EntityPointerLevel.h   |   2 +-
 .../SSAFBuiltinForceLinker.h                  |   4 +
 .../EntityPointerLevel/EntityPointerLevel.cpp |   2 +-
 .../UnsafeBufferUsageExtractor.cpp            | 106 +++++++++---------
 .../UnsafeBufferUsageTest.cpp                 |   3 +-
 5 files changed, 63 insertions(+), 54 deletions(-)

diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
index ed8400f65e310..506b81170f757 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
@@ -107,7 +107,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>
-creatEntityPointerLevel(const NamedDecl *ND,
+createEntityPointerLevel(const NamedDecl *ND,
                         llvm::function_ref<EntityId(EntityName EN)> AddEntity,
                         bool IsFunRet = false);
 
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
index 916ef1ce783c4..5616976e10f77 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
@@ -32,10 +32,14 @@ extern volatile int SSAFAnalysisRegistryAnchorSource;
 [[maybe_unused]] static int SSAFAnalysisRegistryAnchorDestination =
     SSAFAnalysisRegistryAnchorSource;
 
+// This anchor is used to force the linker to link the UnsafeBufferUsage
+// JSON format.
 extern volatile int UnsafeBufferUsageSSAFJSONFormatAnchorSource;
 [[maybe_unused]] static int UnsafeBufferUsageSSAFJSONFormatAnchorDestination =
     UnsafeBufferUsageSSAFJSONFormatAnchorSource;
 
+// This anchor is used to force the linker to link the
+// UnsafeBufferUsageTUSummaryExtractor.
 extern volatile int UnsafeBufferUsageTUSummaryExtractorAnchorSource;
 [[maybe_unused]] static int
     UnsafeBufferUsageTUSummaryExtractorAnchorDestination =
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
index 7e4200467ce9e..dee8cf3465c1e 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
@@ -256,7 +256,7 @@ Expected<EntityPointerLevelSet> clang::ssaf::translateEntityPointerLevel(
 }
 
 /// Create an EntityPointerLevel from a ValueDecl of a pointer type.
-Expected<EntityPointerLevel> clang::ssaf::creatEntityPointerLevel(
+Expected<EntityPointerLevel> clang::ssaf::createEntityPointerLevel(
     const NamedDecl *ND, llvm::function_ref<EntityId(EntityName EN)> AddEntity,
     bool IsFunRet) {
   EntityPointerLevelTranslator Translator(AddEntity, ND->getASTContext());
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index 72944bd0be323..712c2d39e3695 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -78,8 +78,8 @@ static std::set<const Expr *> findUnsafePointersInContributor(const Decl *D) {
 }
 } // namespace
 
-class clang::ssaf::UnsafeBufferUsageTUSummaryExtractor
-    : public TUSummaryExtractor {
+namespace clang::ssaf {
+class UnsafeBufferUsageTUSummaryExtractor : public TUSummaryExtractor {
 public:
   UnsafeBufferUsageTUSummaryExtractor(TUSummaryBuilder &Builder)
       : TUSummaryExtractor(Builder) {}
@@ -87,68 +87,74 @@ class clang::ssaf::UnsafeBufferUsageTUSummaryExtractor
   EntityId addEntity(EntityName EN) { return SummaryBuilder.addEntity(EN); }
 
   Expected<std::unique_ptr<UnsafeBufferUsageEntitySummary>>
-  extractEntitySummary(const Decl *Contributor, ASTContext &Ctx) {
-    auto AddEntity = [this](EntityName EN) { return addEntity(EN); };
-    Expected<EntityPointerLevelSet> EPLs = buildEntityPointerLevels(
-        findUnsafePointersInContributor(Contributor), Ctx, AddEntity);
-
-    if (EPLs)
-      return std::make_unique<UnsafeBufferUsageEntitySummary>(
-          UnsafeBufferUsageEntitySummary(std::move(*EPLs)));
-    return EPLs.takeError();
-  }
+  extractEntitySummary(const Decl *Contributor, ASTContext &Ctx);
 
-  void HandleTranslationUnit(ASTContext &Ctx) override {
+  void HandleTranslationUnit(ASTContext &Ctx) override;
+};
+} // namespace clang::ssaf
+
+Expected<std::unique_ptr<UnsafeBufferUsageEntitySummary>>
+clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::extractEntitySummary(
+    const Decl *Contributor, ASTContext &Ctx) {
+  auto AddEntity = [this](EntityName EN) { return addEntity(EN); };
+  Expected<EntityPointerLevelSet> EPLs = buildEntityPointerLevels(
+      findUnsafePointersInContributor(Contributor), Ctx, AddEntity);
+
+  if (EPLs)
+    return std::make_unique<UnsafeBufferUsageEntitySummary>(
+        UnsafeBufferUsageEntitySummary(std::move(*EPLs)));
+  return EPLs.takeError();
+}
 
-    // FIXME: I suppose finding contributor Decls is commonly needed by all/many
-    // extractors
-    class ContributorFinder : public DynamicRecursiveASTVisitor {
-    public:
-      std::vector<const NamedDecl *> Contributors;
+void clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
+    ASTContext &Ctx) {
 
-      bool VisitFunctionDecl(FunctionDecl *D) override {
-        Contributors.push_back(D);
-        return true;
-      }
+  // FIXME: I suppose finding contributor Decls is commonly needed by all/many
+  // extractors
+  class ContributorFinder : public DynamicRecursiveASTVisitor {
+  public:
+    std::vector<const NamedDecl *> Contributors;
 
-      bool VisitRecordDecl(RecordDecl *D) override {
-        Contributors.push_back(D);
-        return true;
-      }
+    bool VisitFunctionDecl(FunctionDecl *D) override {
+      Contributors.push_back(D);
+      return true;
+    }
 
-      bool VisitVarDecl(VarDecl *D) override {
-        DeclContext *DC = D->getDeclContext();
+    bool VisitRecordDecl(RecordDecl *D) override {
+      Contributors.push_back(D);
+      return true;
+    }
 
-        if (DC->isFileContext() || DC->isNamespace())
-          Contributors.push_back(D);
-        return true;
-      }
-    } ContributorFinder;
+    bool VisitVarDecl(VarDecl *D) override {
+      DeclContext *DC = D->getDeclContext();
 
-    ContributorFinder.VisitTranslationUnitDecl(Ctx.getTranslationUnitDecl());
+      if (DC->isFileContext() || DC->isNamespace())
+        Contributors.push_back(D);
+      return true;
+    }
+  } ContributorFinder;
 
-    ContributorFinder.TraverseAST(Ctx);
-    for (auto *CD : ContributorFinder.Contributors) {
-      auto EntitySummary = extractEntitySummary(CD, Ctx);
+  ContributorFinder.TraverseAST(Ctx);
+  for (auto *CD : ContributorFinder.Contributors) {
+    auto EntitySummary = extractEntitySummary(CD, Ctx);
 
-      if (!EntitySummary)
-        llvm::reportFatalInternalError(EntitySummary.takeError());
-      assert(*EntitySummary);
-      if ((*EntitySummary)->empty())
-        continue;
+    if (!EntitySummary)
+      llvm::reportFatalInternalError(EntitySummary.takeError());
+    assert(*EntitySummary);
+    if ((*EntitySummary)->empty())
+      continue;
 
-      auto ContributorName = getEntityName(CD);
+    auto ContributorName = getEntityName(CD);
 
-      if (!ContributorName)
-        llvm::reportFatalInternalError(makeCreateEntityNameError(CD, Ctx));
+    if (!ContributorName)
+      llvm::reportFatalInternalError(makeCreateEntityNameError(CD, Ctx));
 
-      auto [Ignored, InsertionSucceeded] = SummaryBuilder.addSummary(
-          addEntity(*ContributorName), std::move(*EntitySummary));
+    auto [Ignored, InsertionSucceeded] = SummaryBuilder.addSummary(
+        addEntity(*ContributorName), std::move(*EntitySummary));
 
-      assert(InsertionSucceeded && "duplicated contributor extraction");
-    }
+    assert(InsertionSucceeded && "duplicated contributor extraction");
   }
-};
+}
 
 // NOLINTNEXTLINE(misc-use-internal-linkage)
 volatile int UnsafeBufferUsageTUSummaryExtractorAnchorSource = 0;
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
index 59c2cd38ffacf..11c3e4e01c5bc 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
@@ -11,7 +11,6 @@
 #include "clang/AST/DynamicRecursiveASTVisitor.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
 #include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
 #include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
@@ -457,7 +456,7 @@ TEST_F(UnsafeBufferUsageTest, FunctionCall) {
   const auto *Sum = getEntitySummary("foo");
 
   EXPECT_NE(Sum, nullptr);
-  // No (foo, 2) becasue indirect calls are ignored.
+  // No (foo, 2) because indirect calls are ignored.
   EXPECT_EQ(*Sum, makeSet(__LINE__, {{"foo", 1U, true}}));
 }
 



More information about the llvm-branch-commits mailing list