Skip to content

Commit 919b723

Browse files
committed
Fix a newly-found false positive.
1 parent b01656a commit 919b723

File tree

3 files changed

+31
-0
lines changed

3 files changed

+31
-0
lines changed

clang/lib/Sema/CheckExprLifetime.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,8 @@ static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
367367
if (Callee->getReturnType()->isReferenceType()) {
368368
if (!Callee->getIdentifier()) {
369369
auto OO = Callee->getOverloadedOperator();
370+
if (!Callee->getParent()->hasAttr<OwnerAttr>())
371+
return false;
370372
return OO == OverloadedOperatorKind::OO_Subscript ||
371373
OO == OverloadedOperatorKind::OO_Star;
372374
}

clang/test/Sema/Inputs/lifetime-analysis.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ struct reference_wrapper {
128128
template<typename T>
129129
reference_wrapper<T> ref(T& t) noexcept;
130130

131+
template <typename T>
132+
struct [[gsl::Pointer]] iterator {
133+
T& operator*() const;
134+
};
135+
131136
struct false_type {
132137
static constexpr bool value = false;
133138
constexpr operator bool() const noexcept { return value; }

clang/test/Sema/warn-lifetime-analysis-nocfg.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,4 +752,28 @@ Pointer test3(Bar bar) {
752752
return bar; // expected-warning {{address of stack}}
753753
}
754754

755+
template<typename T>
756+
struct MySpan {
757+
MySpan(const std::vector<T>& v);
758+
using iterator = std::iterator<T>;
759+
iterator begin() const [[clang::lifetimebound]];
760+
};
761+
template <typename T>
762+
typename MySpan<T>::iterator ReturnFirstIt(const MySpan<T>& v [[clang::lifetimebound]]);
763+
764+
void test4() {
765+
std::vector<int> v{1};
766+
// MySpan<T> doesn't own any underlying T objects, the pointee object of
767+
// the MySpan iterator is still alive when the whole span is destroyed, thus
768+
// no diagnostic.
769+
const int& t1 = *MySpan<int>(v).begin();
770+
const int& t2 = *ReturnFirstIt(MySpan<int>(v));
771+
// Ideally, we would diagnose the following case, but due to implementation
772+
// constraints, we do not.
773+
const int& t4 = *MySpan<int>(std::vector<int>{}).begin();
774+
775+
auto it1 = MySpan<int>(v).begin(); // expected-warning {{temporary whose address is use}}
776+
auto it2 = ReturnFirstIt(MySpan<int>(v)); // expected-warning {{temporary whose address is used}}
777+
}
778+
755779
} // namespace LifetimeboundInterleave

0 commit comments

Comments
 (0)