[clang] 2205a23 - [LifetimeSafety] Fix false negative for GSL Owner type with arrow operator (#184725)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 6 02:38:26 PST 2026
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
More information about the cfe-commits
mailing list