[clang] [SSAF] Let UnsafeBufferUsageExtractor & PointerFlowExtractor ignore templates (PR #198927)
Ziqing Luo via cfe-commits
cfe-commits at lists.llvm.org
Wed May 20 15:57:40 PDT 2026
https://github.com/ziqingluo-90 created https://github.com/llvm/llvm-project/pull/198927
Templates are ignored for two reasons:
- Template instantiations are still handled. Template facts can be inferred from their instantiations.
- Templates are inherently difficult to reason about. Their ASTs can contain dependent expression types (such as ParenListExpr) that complicate analysis.
>From d9917961296f0ed7b47be771eaebe7fbeaa6a955 Mon Sep 17 00:00:00 2001
From: Ziqing Luo <ziqing_luo at apple.com>
Date: Tue, 12 May 2026 15:24:52 -0700
Subject: [PATCH] [SSAF] Let UnsafeBufferUsageExtractor & PointerFlowExtractor
ignore templates
Templates are ignored for two reasons:
- Template instantiations are still handled. Template facts can be
inferred from their instantiations.
- Templates are inherently difficult to reason about. Their ASTs can
contain dependent expression types (such as ParenListExpr) that
complicate analysis.
---
.../PointerFlow/PointerFlowExtractor.cpp | 6 ++++
.../UnsafeBufferUsageExtractor.cpp | 6 ++++
.../Analyses/PointerFlow/PointerFlowTest.cpp | 33 +++++++++++++++++++
.../UnsafeBufferUsageTest.cpp | 32 ++++++++++++++++++
4 files changed, 77 insertions(+)
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
index e1130a2c52e4c..8ccfb676ca98d 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
@@ -329,6 +329,12 @@ class PointerFlowTUSummaryExtractor : public TUSummaryExtractor {
findContributors(Ctx, Contributors);
for (auto *CD : Contributors) {
+ // Templates are skipped, but their instantiations are handled. The idea
+ // is that we can conclude facts about a template through all of its
+ // instantiations.
+ if (CD->isTemplated() || CD->getDeclContext()->isDependentContext())
+ continue;
+
auto EntitySummary = extractEntitySummary(CD, Ctx, *this);
if (!EntitySummary)
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index 9103778d585fb..00aa0f571d22a 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -74,6 +74,12 @@ void clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
findContributors(Ctx, Contributors);
for (auto *CD : Contributors) {
+ // Templates are skipped, but their instantiations are handled. The idea
+ // is that we can conclude facts about a template through all of its
+ // instantiations.
+ if (CD->isTemplated() || CD->getDeclContext()->isDependentContext())
+ continue;
+
auto EntitySummary = extractEntitySummary(CD, Ctx);
if (!EntitySummary)
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
index 9f7a508ea35fd..97a2215982a79 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
@@ -1126,4 +1126,37 @@ TEST_F(PointerFlowTest, NestedLambdaAssign) {
ASSERT_NE(Sum, nullptr);
EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"y", 1U}, {"x", 1U}}}));
}
+
+//////////////////////////////////////////////////////////////
+// Template is ignored. //
+//////////////////////////////////////////////////////////////
+TEST_F(PointerFlowTest, FunctionTemplate) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ template <typename T>
+ T* f(T *p) {
+ int *q = p
+ return q;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary<FunctionDecl>("f");
+
+ ASSERT_EQ(Sum, nullptr);
+}
+
+TEST_F(PointerFlowTest, MethodInClassTemplate) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ template <typename T>
+ struct Wrapper {
+ T *ptr;
+ void set(T *p) { ptr = p; }
+ };
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary<FunctionDecl>("set");
+
+ ASSERT_EQ(Sum, nullptr);
+}
} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
index 6b75ed3f1a1fe..39f880dc5396d 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
@@ -570,4 +570,36 @@ TEST_F(UnsafeBufferUsageTest, NestedDefinitions2) {
EXPECT_EQ(Sum, nullptr);
}
+//////////////////////////////////////////////////////////////
+// Template is ignored. //
+//////////////////////////////////////////////////////////////
+
+TEST_F(UnsafeBufferUsageTest, FunctionTemplate) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ template <typename T>
+ T* f(T *p) {
+ return &p[5];
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary<FunctionDecl>("f");
+
+ ASSERT_EQ(Sum, nullptr);
+}
+
+TEST_F(UnsafeBufferUsageTest, MethodInClassTemplate) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ template <typename T>
+ struct Wrapper {
+ T *ptr;
+ void set(T *p) { ptr = p[5]; }
+ };
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary<FunctionDecl>("set");
+
+ ASSERT_EQ(Sum, nullptr);
+}
} // namespace
More information about the cfe-commits
mailing list