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

Reply via email to