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
