[llvm-branch-commits] [clang] [SSAF][TypeConstrainedPointers] Add pointer parameters of 'main' as constrained pointers (PR #208578)
Ziqing Luo via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Jul 13 13:49:59 PDT 2026
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 <ziqing_luo at apple.com>
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 at 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 at operator delete#*v#S0_#"
// CHECK-DAG: "id": [[DEL_PLACE_PARAM_ID:[0-9]+]],{{([^]]|[[:space:]])+\],[[:space:]]+"suffix": "2",[[:space:]]+"usr": }}"c:@F at 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 at 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 <ziqing_luo at apple.com>
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 <benicsbalazs at gmail.com>
---
.../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 <ziqing_luo at apple.com>
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();
More information about the llvm-branch-commits
mailing list