[clang] d90f305 - [SSAF][TypeConstrainedPointers] Add pointer parameters of 'main' as constrained pointers (#208578)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 13 14:49:47 PDT 2026
Author: Ziqing Luo
Date: 2026-07-13T21:49:42Z
New Revision: d90f3050c354b264c7156b8180b9ec1ab09c14c7
URL: https://github.com/llvm/llvm-project/commit/d90f3050c354b264c7156b8180b9ec1ab09c14c7
DIFF: https://github.com/llvm/llvm-project/commit/d90f3050c354b264c7156b8180b9ec1ab09c14c7.diff
LOG: [SSAF][TypeConstrainedPointers] Add pointer parameters of 'main' as constrained pointers (#208578)
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
---------
Co-authored-by: Balázs Benics <benicsbalazs at gmail.com>
Added:
Modified:
clang/include/clang/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.h
clang/lib/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointers.cpp
clang/test/Analysis/Scalable/TypeConstrainedPointers/type-constrained-pointers.cpp
clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp
Removed:
################################################################################
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..8e6d1c4507e26 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,13 @@ TypeConstrainedPointersExtractor::extractEntitySummary(
Summary->Entities.insert(*Id);
break;
default:
+ // Extract case 5: pointer-typed parameters of main.
+ if (FD->isMain())
+ for (const ParmVarDecl *PVD : FD->parameters()) {
+ if (hasPtrOrArrType(PVD))
+ if (auto Id = addEntity(PVD))
+ 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 68ce35aa2a695..037d062b65b93 100644
--- a/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Analyses/TypeConstrainedPointers/TypeConstrainedPointersExtractorTest.cpp
@@ -257,4 +257,49 @@ 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 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();
+ int main() { return 0; }
+ )cpp"));
+
+ const auto *S = getEntitySummary("main");
+
+ EXPECT_FALSE(S);
+}
+
} // namespace
More information about the cfe-commits
mailing list