[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