Skip to content

Commit 0ee0f46

Browse files
committed
[clang] Don't emit bogus dangling diagnostics when [[gsl::Owner]] and [[clang::lifetimebound]] are used together.
1 parent e50131a commit 0ee0f46

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ Improvements to Clang's diagnostics
300300

301301
- Clang now diagnoses cases where a dangling ``GSLOwner<GSLPointer>`` object is constructed, e.g. ``std::vector<string_view> v = {std::string()};`` (#GH100526).
302302

303+
- Don't emit bogus dangling diagnostics when ``[[gsl::Owner]]`` and `[[clang::lifetimebound]]` are used together (#GH108272).
304+
303305
Improvements to Clang's time-trace
304306
----------------------------------
305307

clang/lib/Sema/CheckExprLifetime.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,8 @@ static bool isGSLOwner(QualType T) {
289289

290290
static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
291291
if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
292-
if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))
292+
if (isRecordWithAttr<PointerAttr>(Conv->getConversionType())
293+
&& Callee->getParent()->hasAttr<OwnerAttr>())
293294
return true;
294295
if (!isInStlNamespace(Callee->getParent()))
295296
return false;

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,3 +630,37 @@ std::optional<std::string_view> test3(int i) {
630630
}
631631

632632
} // namespace GH100526
633+
634+
namespace GH108272 {
635+
template <typename T>
636+
struct [[gsl::Owner]] StatusOr {
637+
const T &value() [[clang::lifetimebound]];
638+
};
639+
640+
template <typename V>
641+
class Wrapper1 {
642+
public:
643+
operator V() const;
644+
V value;
645+
};
646+
std::string_view test1() {
647+
StatusOr<Wrapper1<std::string_view>> k;
648+
// Be conservative in this case, as there is not enough information available
649+
// to infer the lifetime relationship for the Wrapper1 type.
650+
std::string_view good = StatusOr<Wrapper1<std::string_view>>().value();
651+
return k.value();
652+
}
653+
654+
template <typename V>
655+
class Wrapper2 {
656+
public:
657+
operator V() const [[clang::lifetimebound]];
658+
V value;
659+
};
660+
std::string_view test2() {
661+
StatusOr<Wrapper2<std::string_view>> k;
662+
// We expect dangling issues as the conversion operator is lifetimebound。
663+
std::string_view bad = StatusOr<Wrapper2<std::string_view>>().value(); // expected-warning {{temporary whose address is used as value of}}
664+
return k.value(); // expected-warning {{address of stack memory associated}}
665+
}
666+
} // namespace GH108272

0 commit comments

Comments
 (0)