https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/174741
>From ce2cb8555280945312f4afaca6b72331c3b1477c Mon Sep 17 00:00:00 2001 From: Utkarsh Saxena <[email protected]> Date: Tue, 16 Dec 2025 12:13:42 +0000 Subject: [PATCH] only-for-owners --- .../LifetimeSafety/FactsGenerator.cpp | 16 ++++++ .../unittests/Analysis/LifetimeSafetyTest.cpp | 52 +++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp index fe5fabc6d6405..b10c61f1cb6b7 100644 --- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp +++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp @@ -485,6 +485,14 @@ void FactsGenerator::handleFunctionCall(const Expr *Call, } return PVD ? PVD->hasAttr<clang::LifetimeBoundAttr>() : false; }; + auto shouldTrackPointerImplicitObjectArg = [FD](unsigned I) -> bool { + const auto *Method = dyn_cast<CXXMethodDecl>(FD); + if (!Method || !Method->isInstance()) + return false; + return I == 0 && + isGslPointerType(Method->getFunctionObjectParameterType()) && + shouldTrackImplicitObjectArg(Method); + }; if (Args.empty()) return; bool KillSrc = true; @@ -505,6 +513,14 @@ void FactsGenerator::handleFunctionCall(const Expr *Call, flow(CallList, ArgList, KillSrc); KillSrc = false; } + } else if (shouldTrackPointerImplicitObjectArg(I)) { + assert(ArgList->getLength() >= 2 && + "Object arg of pointer type should have atleast two origins"); + // See through the GSLPointer reference to see the pointer's value. + CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>( + CallList->getOuterOriginID(), + ArgList->peelOuterOrigin()->getOuterOriginID(), KillSrc)); + KillSrc = false; } else if (IsArgLifetimeBound(I)) { // Lifetimebound on a non-GSL-ctor function means the returned // pointer/reference itself must not outlive the arguments. This diff --git a/clang/unittests/Analysis/LifetimeSafetyTest.cpp b/clang/unittests/Analysis/LifetimeSafetyTest.cpp index 3afb44656d78a..f4eb5b22610e4 100644 --- a/clang/unittests/Analysis/LifetimeSafetyTest.cpp +++ b/clang/unittests/Analysis/LifetimeSafetyTest.cpp @@ -1751,6 +1751,58 @@ TEST_F(LifetimeAnalysisTest, TrackImplicitObjectArg_MapFind) { EXPECT_THAT(Origin("it"), HasLoansTo({"m"}, "p1")); } + +TEST_F(LifetimeAnalysisTest, TrackImplicitObjectArg_GSLPointerArg) { + SetupTest(R"( + namespace std { + + template<typename T> + struct basic_string_view { + basic_string_view(); + basic_string_view(const T *); + const T *begin() const; + const T *data() const; + }; + using string_view = basic_string_view<char>; + + template<typename T> + struct basic_string { + basic_string(); + basic_string(const T *); + const T *c_str() const; + operator basic_string_view<T> () const; + const T *data() const; + }; + using string = basic_string<char>; + } + + void target() { + std::string s1; + std::string_view sv1 = s1; + + std::string s2; + const char* sv2 = std::string_view(s2).begin(); + + std::string s3; + const char* sv3 = std::string_view(s3).data(); + + std::string s4; + std::string_view sv4 = std::string_view{std::string_view(s4).data()}; + + std::string s5; + const char* data5 = std::string_view(s5).data(); + std::string_view sv5 = data5; + POINT(end); + } + )"); + EXPECT_THAT(Origin("sv1"), HasLoansTo({"s1"}, "end")); + EXPECT_THAT(Origin("sv2"), HasLoansTo({"s2"}, "end")); + EXPECT_THAT(Origin("sv3"), HasLoansTo({"s3"}, "end")); + // FIXME: Handle GSL pointer construction from raw pointers. + EXPECT_THAT(Origin("sv4"), HasLoansTo({}, "end")); + EXPECT_THAT(Origin("sv5"), HasLoansTo({}, "end")); +} + // ========================================================================= // // Tests for shouldTrackFirstArgument // ========================================================================= // _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
