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 <[email protected]>

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@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 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


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to