[llvm-branch-commits] [clang] [clang][ssaf][NFC] Add unittests for PointerFlow and UnsafeBufferUsage about local entities (PR #209227)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jul 13 08:47:06 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Balázs Benics (steakhal)
<details>
<summary>Changes</summary>
Part §6 of rdar://179151023
Depends on #<!-- -->209225.
Approved in #<!-- -->205351.
---
Full diff: https://github.com/llvm/llvm-project/pull/209227.diff
2 Files Affected:
- (modified) clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp (+46-1)
- (modified) clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp (+46-1)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/209227
More information about the llvm-branch-commits
mailing list