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 <[email protected]> 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
