https://github.com/heturing updated https://github.com/llvm/llvm-project/pull/204797
>From a53fd784c5cc4e8e7808d547196f00b094889f0e Mon Sep 17 00:00:00 2001 From: Jiaqi He <[email protected]> Date: Fri, 19 Jun 2026 18:48:23 +0800 Subject: [PATCH 1/2] [LifetimeSafety] resolved lifetimeBound violation in constructor --- clang/lib/Analysis/LifetimeSafety/Checker.cpp | 5 ++- .../Sema/LifetimeSafety/lifetimebound.cpp | 35 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 clang/test/Sema/LifetimeSafety/lifetimebound.cpp diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp index d41d6f43f837b..595f9a1d32eba 100644 --- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp @@ -135,7 +135,10 @@ class LifetimeChecker { return; if (PVD->hasAttr<LifetimeBoundAttr>()) { // Track that this lifetimebound parameter correctly escapes. - if (isa<ReturnEscapeFact>(OEF)) + bool isVerifiedEscape = + isa<ReturnEscapeFact>(OEF) || + (isa<FieldEscapeFact>(OEF) && isa<CXXConstructorDecl>(FD)); + if (isVerifiedEscape) VerifiedLiftimeboundEscapes.insert(PVD); } else { // Otherwise, suggest lifetimebound for parameter escaping through diff --git a/clang/test/Sema/LifetimeSafety/lifetimebound.cpp b/clang/test/Sema/LifetimeSafety/lifetimebound.cpp new file mode 100644 index 0000000000000..a5e26b5bdadf2 --- /dev/null +++ b/clang/test/Sema/LifetimeSafety/lifetimebound.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -fsyntax-only -Wlifetime-safety-all -verify %s + + +using size_t = decltype(sizeof(0)); +extern "C" size_t strlen(const char *); + +#define LIFETIMEBOUND [[clang::lifetimebound]] + +struct View +{ + View(const char* data LIFETIMEBOUND) + : mData(data) + , mSize(strlen(data)) + {} + + const char* data() const { + return mData; + } + + size_t size() const { + return mSize; + } + +private: + const char* mData; + size_t mSize; +}; + +void test() { + char *c = new char[5]; //expected-warning {{allocated object does not live long enough}} + View v(c); + delete[] c; // expected-note {{freed here}} + const char *c1 = v.data(); // expected-note {{later used here}} + return; +} \ No newline at end of file >From 931917474c3128b9f74903d68d28fe0524560a29 Mon Sep 17 00:00:00 2001 From: Jiaqi He <[email protected]> Date: Mon, 22 Jun 2026 16:05:51 +0800 Subject: [PATCH 2/2] refactor code and test case --- clang/lib/Analysis/LifetimeSafety/Checker.cpp | 9 +++-- .../annotation-suggestions-fixits.cpp | 1 + .../Sema/LifetimeSafety/lifetimebound.cpp | 35 ------------------- .../misplaced-lifetimebound-intra-tu.cpp | 6 ++++ 4 files changed, 11 insertions(+), 40 deletions(-) delete mode 100644 clang/test/Sema/LifetimeSafety/lifetimebound.cpp diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp b/clang/lib/Analysis/LifetimeSafety/Checker.cpp index 595f9a1d32eba..c258a1dc3596c 100644 --- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp +++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp @@ -134,11 +134,10 @@ class LifetimeChecker { if (IsMoved) return; if (PVD->hasAttr<LifetimeBoundAttr>()) { - // Track that this lifetimebound parameter correctly escapes. - bool isVerifiedEscape = - isa<ReturnEscapeFact>(OEF) || - (isa<FieldEscapeFact>(OEF) && isa<CXXConstructorDecl>(FD)); - if (isVerifiedEscape) + // Track that this lifetimebound parameter correctly escapes + // (via return or via field assignment in a constructor). + if (isa<ReturnEscapeFact>(OEF) || + (isa<FieldEscapeFact>(OEF) && isa<CXXConstructorDecl>(FD))) VerifiedLiftimeboundEscapes.insert(PVD); } else { // Otherwise, suggest lifetimebound for parameter escaping through diff --git a/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp b/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp index 18be627211975..083601a5e616f 100644 --- a/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp +++ b/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp @@ -174,3 +174,4 @@ struct TrailingReturn { return data; } }; + diff --git a/clang/test/Sema/LifetimeSafety/lifetimebound.cpp b/clang/test/Sema/LifetimeSafety/lifetimebound.cpp deleted file mode 100644 index a5e26b5bdadf2..0000000000000 --- a/clang/test/Sema/LifetimeSafety/lifetimebound.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// RUN: %clang_cc1 -fsyntax-only -Wlifetime-safety-all -verify %s - - -using size_t = decltype(sizeof(0)); -extern "C" size_t strlen(const char *); - -#define LIFETIMEBOUND [[clang::lifetimebound]] - -struct View -{ - View(const char* data LIFETIMEBOUND) - : mData(data) - , mSize(strlen(data)) - {} - - const char* data() const { - return mData; - } - - size_t size() const { - return mSize; - } - -private: - const char* mData; - size_t mSize; -}; - -void test() { - char *c = new char[5]; //expected-warning {{allocated object does not live long enough}} - View v(c); - delete[] c; // expected-note {{freed here}} - const char *c1 = v.data(); // expected-note {{later used here}} - return; -} \ No newline at end of file diff --git a/clang/test/Sema/LifetimeSafety/misplaced-lifetimebound-intra-tu.cpp b/clang/test/Sema/LifetimeSafety/misplaced-lifetimebound-intra-tu.cpp index 7fa4cae100509..329d06fec80af 100644 --- a/clang/test/Sema/LifetimeSafety/misplaced-lifetimebound-intra-tu.cpp +++ b/clang/test/Sema/LifetimeSafety/misplaced-lifetimebound-intra-tu.cpp @@ -167,3 +167,9 @@ struct Derived : Base { auto Derived::virtual_get(const MyObj& obj [[clang::lifetimebound]]) const -> const MyObj& { // expected-note {{'lifetimebound' attribute appears here on the definition}} return obj; } + +struct ViewWithMember { + // No warning. A lifetimebound constructor parameter may escape into a field of the constructed object. + ViewWithMember(const char *data [[clang::lifetimebound]]) : mData(data) {} + const char *mData; +}; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
