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 d2e85df3290052c9e6b9bbcf854353c83117d54c 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 | 10 +++++- .../Sema/LifetimeSafety/lifetimebound.cpp | 35 ------------------- 3 files changed, 13 insertions(+), 41 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..c6e8db029da95 100644 --- a/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp +++ b/clang/test/Sema/LifetimeSafety/annotation-suggestions-fixits.cpp @@ -8,7 +8,8 @@ // RUN: -Wlifetime-safety-suggestions -Wno-dangling -fixit %t.cpp // RUN: %clang_cc1 -fsyntax-only -std=c++17 -flifetime-safety-inference \ // RUN: -fexperimental-lifetime-safety-tu-analysis \ -// RUN: -Werror=lifetime-safety-suggestions -Wno-dangling %t.cpp +// RUN: -Werror=lifetime-safety-suggestions -Wno-dangling \ +// RUN: -Werror=lifetime-safety-lifetimebound-violation %t.cpp struct View; @@ -174,3 +175,10 @@ struct TrailingReturn { return data; } }; + +struct ViewWithMember { + ViewWithMember(const char *data) : mData(data) {} + // CHECK: :[[@LINE-1]]:18: warning: parameter in intra-TU function should be marked + // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:34-[[@LINE-2]]:34}:" {{\[\[}}clang::lifetimebound]]" + const char *mData; +}; 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
