https://github.com/ziqingluo-90 updated https://github.com/llvm/llvm-project/pull/208578
>From f57ae8235332136c37c9a2267d2c4e9925c1b19c Mon Sep 17 00:00:00 2001 From: Ziqing Luo <[email protected]> Date: Thu, 9 Jul 2026 14:57:22 -0700 Subject: [PATCH 1/3] [SSAF][PinnedPointers] Add pointer parameters of 'main' as pinned pointers Similar to some pointer entities of operator new/delete overload functions, pointer type parameters of the main function shall also retain its type during clang-reforge transformation. rdar://179151882 --- .../TypeConstrainedPointers.h | 3 +++ .../TypeConstrainedPointers.cpp | 11 ++++++++ .../type-constrained-pointers.cpp | 8 ++++++ .../TypeConstrainedPointersExtractorTest.cpp | 27 +++++++++++++++++++ 4 files changed, 49 insertions(+) diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.h index e785782c001fa..26920606ef615 100644 --- a/clang/include/clang/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.h +++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.h @@ -35,6 +35,9 @@ namespace clang::ssaf { /// pointer to the memory block to deallocate (or a null pointer). /// -# The second parameter of `operator delete(void*, void*)` representing /// the placement pointer matching the corresponding placement `new`. +/// +/// From the `main` function: +/// -# Pointer-typed parameters of `main`. struct TypeConstrainedPointersEntitySummary final : public EntitySummary { static constexpr llvm::StringLiteral Name = "TypeConstrainedPointers"; diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.cpp index 21bd75055e034..452a2eba2c974 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.cpp @@ -55,6 +55,9 @@ namespace { // pointer to the memory block to deallocate (or a null pointer); // 4 the second parameter of `operator delete(void*, void*)` representing // the placement pointer matching the corresponding placement `new`. +// +// From the `main` function: +// 5 pointer-typed parameters of `main`. class TypeConstrainedPointersExtractor final : public TUSummaryExtractor { public: using TUSummaryExtractor::TUSummaryExtractor; @@ -103,6 +106,14 @@ TypeConstrainedPointersExtractor::extractEntitySummary( Summary->Entities.insert(*Id); break; default: + // Extract case 5: pointer-typed parameters of main. + if (FD->isMain()) + for (unsigned I = 0; I < FD->getNumParams(); ++I) { + if (!hasPtrOrArrType(FD->getParamDecl(I))) + continue; + if (auto Id = addEntity(FD->getParamDecl(I))) + Summary->Entities.insert(*Id); + } return; }; // Extract case 2 & 4: only `operator new(size_t, void*)` and diff --git a/clang/test/Analysis/Scalable/TypeConstrainedPointers/type-constrained-pointers.cpp b/clang/test/Analysis/Scalable/TypeConstrainedPointers/type-constrained-pointers.cpp index 2d2e39824e016..648ac94bb0dea 100644 --- a/clang/test/Analysis/Scalable/TypeConstrainedPointers/type-constrained-pointers.cpp +++ b/clang/test/Analysis/Scalable/TypeConstrainedPointers/type-constrained-pointers.cpp @@ -32,6 +32,10 @@ void operator delete(void *ptr) noexcept {} void operator delete(void *ptr, void *placement) noexcept; void operator delete(void *ptr, void *placement) noexcept {} +// main: argv (suffix "2") is extracted; argc (suffix "1") is not a pointer. +int main(int argc, char **argv); +int main(int argc, char **argv) { return 0; } + // Plain new: return entity (suffix "0"). // CHECK-DAG: "id": [[NEW_RET_ID:[0-9]+]],{{([^]]|[[:space:]])+\],[[:space:]]+"suffix": "0",[[:space:]]+"usr": }}"c:@F@operator new#{{.*}}#" @@ -46,6 +50,9 @@ void operator delete(void *ptr, void *placement) noexcept {} // CHECK-DAG: "id": [[DEL_PLACE_PTR_ID:[0-9]+]],{{([^]]|[[:space:]])+\],[[:space:]]+"suffix": "1",[[:space:]]+"usr": }}"c:@F@operator delete#*v#S0_#" // CHECK-DAG: "id": [[DEL_PLACE_PARAM_ID:[0-9]+]],{{([^]]|[[:space:]])+\],[[:space:]]+"suffix": "2",[[:space:]]+"usr": }}"c:@F@operator delete#*v#S0_#" +// main: argv (suffix "2", 0-based param index 1). +// CHECK-DAG: "id": [[MAIN_ARGV_ID:[0-9]+]],{{([^]]|[[:space:]])+\],[[:space:]]+"suffix": "2",[[:space:]]+"usr": }}"c:@F@main{{.*}}" + // CHECK: "analysis_name": "TypeConstrainedPointersAnalysisResult" // CHECK-DAG: "@": [[NEW_RET_ID]] @@ -54,5 +61,6 @@ void operator delete(void *ptr, void *placement) noexcept {} // CHECK-DAG: "@": [[DEL_PTR_ID]] // CHECK-DAG: "@": [[DEL_PLACE_PTR_ID]] // CHECK-DAG: "@": [[DEL_PLACE_PARAM_ID]] +// CHECK-DAG: "@": [[MAIN_ARGV_ID]] // CHECK: "type": "WPASuite" diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp index 8c7c5ff6a0ebc..c1eb3b13950a5 100644 --- a/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp +++ b/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp @@ -257,4 +257,31 @@ TEST_F(TypeConstrainedPointersExtractorTest, NoOperatorNewOrDeleteSummary) { ASSERT_EQ(TUSummariesIter, TUData.end()); } +TEST_F(TypeConstrainedPointersExtractorTest, MainPointerParams) { + ASSERT_TRUE(setUpTest(R"cpp( + int main(int argc, char **argv) { return 0; } + )cpp")); + + const auto *S = getEntitySummary("main"); + + ASSERT_TRUE(S); + + auto ArgvId = getEntityId("argv"); + + ASSERT_TRUE(ArgvId); + // argc is not a pointer — only argv and envp are extracted. + EXPECT_EQ(*S, (std::set{*ArgvId})); +} + +TEST_F(TypeConstrainedPointersExtractorTest, MainNoPointerParams) { + ASSERT_TRUE(setUpTest(R"cpp( + int main(); + int main() { return 0; } + )cpp")); + + const auto *S = getEntitySummary("main"); + + EXPECT_FALSE(S); +} + } // namespace >From 93e46f6780475ade54fd7fd06258e7ab80fc7ee4 Mon Sep 17 00:00:00 2001 From: Ziqing Luo <[email protected]> Date: Mon, 13 Jul 2026 13:06:41 -0700 Subject: [PATCH 2/3] Update clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Balázs Benics <[email protected]> --- .../TypeConstrainedPointersExtractorTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp index c1eb3b13950a5..47e85dd536600 100644 --- a/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp +++ b/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp @@ -270,7 +270,7 @@ TEST_F(TypeConstrainedPointersExtractorTest, MainPointerParams) { ASSERT_TRUE(ArgvId); // argc is not a pointer — only argv and envp are extracted. - EXPECT_EQ(*S, (std::set{*ArgvId})); + EXPECT_EQ(*S, (std::set<EntityId>{*ArgvId})); } TEST_F(TypeConstrainedPointersExtractorTest, MainNoPointerParams) { >From bec96fb59482bfa4a3bff2b8b556a0e09947019e Mon Sep 17 00:00:00 2001 From: Ziqing Luo <[email protected]> Date: Mon, 13 Jul 2026 13:46:29 -0700 Subject: [PATCH 3/3] address comments --- .../TypeConstrainedPointers.cpp | 9 +++--- .../TypeConstrainedPointersExtractorTest.cpp | 32 +++++++++++++++---- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.cpp index 452a2eba2c974..8e6d1c4507e26 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.cpp @@ -108,11 +108,10 @@ TypeConstrainedPointersExtractor::extractEntitySummary( default: // Extract case 5: pointer-typed parameters of main. if (FD->isMain()) - for (unsigned I = 0; I < FD->getNumParams(); ++I) { - if (!hasPtrOrArrType(FD->getParamDecl(I))) - continue; - if (auto Id = addEntity(FD->getParamDecl(I))) - Summary->Entities.insert(*Id); + for (const ParmVarDecl *PVD : FD->parameters()) { + if (hasPtrOrArrType(PVD)) + if (auto Id = addEntity(PVD)) + Summary->Entities.insert(*Id); } return; }; diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp index 47e85dd536600..037d062b65b93 100644 --- a/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp +++ b/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp @@ -150,7 +150,7 @@ TEST_F(TypeConstrainedPointersExtractorTest, FreeOperatorDelete) { ASSERT_TRUE(PtrId); - EXPECT_EQ(*S, std::set{*PtrId}); + EXPECT_EQ(*S, std::set<EntityId>{*PtrId}); } TEST_F(TypeConstrainedPointersExtractorTest, MemberOperatorDelete) { @@ -168,7 +168,7 @@ TEST_F(TypeConstrainedPointersExtractorTest, MemberOperatorDelete) { auto PId = getEntityId("p"); ASSERT_TRUE(PId); - EXPECT_EQ(*S, std::set{*PId}); + EXPECT_EQ(*S, std::set<EntityId>{*PId}); } TEST_F(TypeConstrainedPointersExtractorTest, OperatorDeleteArray) { @@ -184,7 +184,7 @@ TEST_F(TypeConstrainedPointersExtractorTest, OperatorDeleteArray) { auto PId = getEntityId("p"); ASSERT_TRUE(PId); - EXPECT_EQ(*S, std::set{*PId}); + EXPECT_EQ(*S, std::set<EntityId>{*PId}); } TEST_F(TypeConstrainedPointersExtractorTest, OperatorNew) { @@ -201,7 +201,7 @@ TEST_F(TypeConstrainedPointersExtractorTest, OperatorNew) { auto RetId = getEntityIdForReturn("operator new"); ASSERT_TRUE(RetId); - EXPECT_EQ(*S, std::set{*RetId}); + EXPECT_EQ(*S, std::set<EntityId>{*RetId}); } TEST_F(TypeConstrainedPointersExtractorTest, PlacementNew) { @@ -222,7 +222,7 @@ TEST_F(TypeConstrainedPointersExtractorTest, PlacementNew) { ASSERT_TRUE(PlacementId); ASSERT_TRUE(RetId); - EXPECT_EQ(*S, (std::set{*PlacementId, *RetId})); + EXPECT_EQ(*S, (std::set<EntityId>{*PlacementId, *RetId})); } TEST_F(TypeConstrainedPointersExtractorTest, PlacementDelete) { @@ -242,7 +242,7 @@ TEST_F(TypeConstrainedPointersExtractorTest, PlacementDelete) { ASSERT_TRUE(PtrId); ASSERT_TRUE(PlacementId); - EXPECT_EQ(*S, (std::set{*PtrId, *PlacementId})); + EXPECT_EQ(*S, (std::set<EntityId>{*PtrId, *PlacementId})); } TEST_F(TypeConstrainedPointersExtractorTest, NoOperatorNewOrDeleteSummary) { @@ -269,10 +269,28 @@ TEST_F(TypeConstrainedPointersExtractorTest, MainPointerParams) { auto ArgvId = getEntityId("argv"); ASSERT_TRUE(ArgvId); - // argc is not a pointer — only argv and envp are extracted. + // argc is not a pointer — only argv is extracted. EXPECT_EQ(*S, (std::set<EntityId>{*ArgvId})); } +TEST_F(TypeConstrainedPointersExtractorTest, MainThreePointerParams) { + ASSERT_TRUE(setUpTest(R"cpp( + int main(int argc, char **argv, char **envp) { return 0; } + )cpp")); + + const auto *S = getEntitySummary("main"); + + ASSERT_TRUE(S); + + auto ArgvId = getEntityId("argv"); + auto EnvpId = getEntityId("envp"); + + ASSERT_TRUE(ArgvId); + ASSERT_TRUE(EnvpId); + // argc is not a pointer — argv and envp are both extracted. + EXPECT_EQ(*S, (std::set<EntityId>{*ArgvId, *EnvpId})); +} + TEST_F(TypeConstrainedPointersExtractorTest, MainNoPointerParams) { ASSERT_TRUE(setUpTest(R"cpp( int main(); _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
