https://github.com/steakhal created 
https://github.com/llvm/llvm-project/pull/209227

Part §6 of rdar://179151023
Depends on #209225.
Approved in #205351.

From 56e713c6d610a3b7d6821c51022ffd27bc4d0a0c Mon Sep 17 00:00:00 2001
From: Jan Korous <[email protected]>
Date: Tue, 12 May 2026 18:39:13 -0700
Subject: [PATCH] [clang][ssaf][NFC] Add unittests for PointerFlow and
 UnsafeBufferUsage about local entities
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Part §6 of rdar://179151023

Co-Authored-By: Jan Korous <[email protected]>
Co-Authored-By: Claude Opus 4.7 <[email protected]>
---
 .../Analyses/PointerFlow/PointerFlowTest.cpp  | 47 ++++++++++++++++++-
 .../UnsafeBufferUsageTest.cpp                 | 47 ++++++++++++++++++-
 2 files changed, 92 insertions(+), 2 deletions(-)

diff --git 
a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp
 
b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp
index b6d2b8b1af3cf..a56a9072be097 100644
--- 
a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp
+++ 
b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp
@@ -161,7 +161,8 @@ class PointerFlowTest : public TestFixture {
   template <typename ContributorDecl = NamedDecl,
             typename =
                 std::enable_if_t<std::is_base_of_v<NamedDecl, 
ContributorDecl>>>
-  bool setUpTest(StringRef Code) {
+  bool setUpTest(StringRef Code, const SSAFOptions &Opts = {}) {
+    this->Opts = Opts; // Override the options.
     AST = tooling::buildASTFromCodeWithArgs(
         Code, {"-Wno-unused-value", "-Wno-int-to-pointer-cast"});
 
@@ -1573,4 +1574,48 @@ TEST_F(PointerFlowTest, RefBindFunctionCallInitializer) {
   EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"r", 1U}, {"g", 1U, true}}}));
 }
 
+//////////////////////////////////////////////////////////////
+//          Local-entity inclusion option tests             //
+//////////////////////////////////////////////////////////////
+
+TEST_F(PointerFlowTest, LocalPointerSkippedByDefault) {
+  StringRef Code = R"cpp(
+    void foo(int *param) {
+      int *local_ptr = param;
+      local_ptr = param;
+    }
+  )cpp";
+
+  ASSERT_TRUE(setUpTest(Code));
+
+  // Without IncludeLocalEntities, the local pointer is not registered as a
+  // contributor and therefore has no entity summary of its own.
+  EXPECT_FALSE(getEntitySummary<VarDecl>("local_ptr"));
+  // The enclosing function still has its summary describing the assignment
+  // edge from `local_ptr` to `param` (via the initializer).
+  EXPECT_TRUE(getEntitySummary("foo"));
+}
+
+TEST_F(PointerFlowTest, LocalPointerReportedWhenIncluded) {
+  SSAFOptions Opts;
+  Opts.IncludeLocalEntities = true;
+  StringRef Code = R"cpp(
+    void foo(int *param) {
+      int *local_ptr = param;
+      local_ptr = param;
+    }
+  )cpp";
+
+  ASSERT_TRUE(setUpTest(Code, Opts));
+
+  // With the option enabled, the local pointer becomes a contributor and gets
+  // its own entity summary describing the same edge that was previously only
+  // observable through `foo`.
+  const auto *LocalSum = getEntitySummary<VarDecl>("local_ptr");
+  ASSERT_TRUE(LocalSum);
+  EXPECT_EQ(*LocalSum,
+            makeEdges(__LINE__, {{{"local_ptr", 1U}, {"param", 1U}}}));
+
+  EXPECT_TRUE(getEntitySummary("foo"));
+}
 } // namespace
diff --git 
a/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
 
b/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
index c2f4cb97c0fae..6d47bff85a059 100644
--- 
a/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
+++ 
b/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
@@ -47,7 +47,8 @@ class UnsafeBufferUsageTest : public TestFixture {
               BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")),
         Builder(TUSum, Opts) {}
 
-  bool setUpTest(StringRef Code) {
+  bool setUpTest(StringRef Code, const SSAFOptions &Opts = {}) {
+    this->Opts = Opts; // Override the options.
     AST = tooling::buildASTFromCodeWithArgs(
         Code, {"-Wno-unused-value", "-Wno-int-to-pointer-cast"});
 
@@ -779,5 +780,49 @@ TEST_F(UnsafeBufferUsageTest, StmtExprArrayAccess) {
           .contains("attempt to translate StmtExpr to EntityPointerLevels"));
 }
 #endif
+//////////////////////////////////////////////////////////////
+//          Local-entity inclusion option tests             //
+//////////////////////////////////////////////////////////////
+
+TEST_F(UnsafeBufferUsageTest, LocalVarSkippedByDefault) {
+  // The unsafe subscript p[5] sits inside a local-variable initializer.
+  // Without IncludeLocalEntities, only `use` (the enclosing function) is a
+  // contributor. The initializer is still walked as part of `use`'s body, so
+  // `use` gets a summary attributing the unsafe usage to its parameter.
+  ASSERT_TRUE(setUpTest(R"cpp(
+    int use(int *param) {
+      int x = param[5];
+      return x;
+    }
+  )cpp"));
+
+  EXPECT_TRUE(getEntitySummary("use"));
+  // `x` is not a contributor and therefore has no entity summary of its own.
+  EXPECT_FALSE(getEntitySummary<VarDecl>("x"));
+}
+
+TEST_F(UnsafeBufferUsageTest, LocalVarReportedWhenIncluded) {
+  // With IncludeLocalEntities, the local var `x` becomes its own contributor.
+  // The matcher then walks `x`'s scope (the initializer) and reports the
+  // unsafe subscript on `param` against `x` as well.
+  SSAFOptions Opts;
+  Opts.IncludeLocalEntities = true;
+  ASSERT_TRUE(setUpTest(R"cpp(
+    int use(int *param) {
+      int x = param[5];
+      return x;
+    }
+  )cpp",
+                        Opts));
+
+  // Pre-existing per-function summary is still produced.
+  EXPECT_TRUE(getEntitySummary("use"));
+
+  // The new local-entity summary describes the same unsafe-pointer usage,
+  // but is attributed to the local variable's own scope.
+  const auto *LocalSum = getEntitySummary<VarDecl>("x");
+  ASSERT_TRUE(LocalSum);
+  EXPECT_EQ(*LocalSum, makeSet(__LINE__, {{"param", 1U}}));
+}
 
 } // namespace

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to