Author: Zhijie Wang Date: 2026-03-06T11:38:21+01:00 New Revision: 2205a23801d4e0cca3cd28670b611a7f6adbeb06
URL: https://github.com/llvm/llvm-project/commit/2205a23801d4e0cca3cd28670b611a7f6adbeb06 DIFF: https://github.com/llvm/llvm-project/commit/2205a23801d4e0cca3cd28670b611a7f6adbeb06.diff LOG: [LifetimeSafety] Fix false negative for GSL Owner type with arrow operator (#184725) `shouldTrackImplicitObjectArg` tracks whether a method call's return value depends on the implicit object's lifetime. It already handles operator* on Owner types (return reference), but misses operator-> (return pointer). This fix adds `OO_Arrow` handling for Owner types. Only affects CFG (-Wlifetime-safety) analysis paths. Fixes #184361 Added: Modified: clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp clang/test/Sema/Inputs/lifetime-analysis.h clang/test/Sema/warn-lifetime-safety.cpp Removed: ################################################################################ diff --git a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp index 0d3da898137a6..4852f444a51b3 100644 --- a/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp +++ b/clang/lib/Analysis/LifetimeSafety/LifetimeAnnotations.cpp @@ -153,7 +153,12 @@ bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee, if (isPointerLikeType(Callee->getReturnType())) { if (!Callee->getIdentifier()) - return false; + // e.g., std::optional<T>::operator->() returns T*. + return RunningUnderLifetimeSafety + ? Callee->getParent()->hasAttr<OwnerAttr>() && + Callee->getOverloadedOperator() == + OverloadedOperatorKind::OO_Arrow + : false; return IteratorMembers.contains(Callee->getName()) || InnerPointerGetters.contains(Callee->getName()) || ContainerFindFns.contains(Callee->getName()); diff --git a/clang/test/Sema/Inputs/lifetime-analysis.h b/clang/test/Sema/Inputs/lifetime-analysis.h index 1b07f4f13467f..85b5a5fe5e07f 100644 --- a/clang/test/Sema/Inputs/lifetime-analysis.h +++ b/clang/test/Sema/Inputs/lifetime-analysis.h @@ -188,6 +188,7 @@ struct unique_ptr { ~unique_ptr(); T* release(); T &operator*(); + T *operator->(); T *get() const; }; @@ -204,6 +205,7 @@ struct optional { template<typename U> optional(optional<U>&& __t); + T *operator->(); T &operator*() &; T &&operator*() &&; T &value() &; diff --git a/clang/test/Sema/warn-lifetime-safety.cpp b/clang/test/Sema/warn-lifetime-safety.cpp index 097f3279d8e54..a75c70aa3674a 100644 --- a/clang/test/Sema/warn-lifetime-safety.cpp +++ b/clang/test/Sema/warn-lifetime-safety.cpp @@ -1746,3 +1746,41 @@ View test3(std::string a) { return b; // expected-note {{returned here}} } } // namespace non_trivial_views + +namespace OwnerArrowOperator { +void test_optional_arrow() { + const char* p; + { + std::optional<std::string> opt; + p = opt->data(); // expected-warning {{object whose reference is captured does not live long enough}} + } // expected-note {{destroyed here}} + (void)*p; // expected-note {{later used here}} +} + +void test_optional_arrow_lifetimebound() { + View v; + { + std::optional<MyObj> opt; + v = opt->getView(); // expected-warning {{object whose reference is captured does not live long enough}} + } // expected-note {{destroyed here}} + v.use(); // expected-note {{later used here}} +} + +void test_unique_ptr_arrow() { + const char* p; + { + std::unique_ptr<std::string> up; + p = up->data(); // expected-warning {{object whose reference is captured does not live long enough}} + } // expected-note {{destroyed here}} + (void)*p; // expected-note {{later used here}} +} + +void test_optional_view_arrow() { + const char* p; + { + std::optional<std::string_view> opt; + p = opt->data(); + } + (void)*p; +} +} // namespace OwnerArrowOperator _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
