https://github.com/usx95 updated 
https://github.com/llvm/llvm-project/pull/191699

>From f859fd8e79999b5c650cb8a745d74f0b80c4d96e Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sat, 11 Apr 2026 13:11:00 +0000
Subject: [PATCH 01/11] Make Unique inference

---
 a.o                                           | Bin 0 -> 3448 bytes
 .../LifetimeSafety/FactsGenerator.cpp         |   3 +-
 clang/lib/Analysis/LifetimeSafety/Origins.cpp |   1 +
 clang/lib/Sema/SemaAttr.cpp                   |  55 ++++++++++++++
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |   2 +
 clang/test/Sema/Inputs/lifetime-analysis.h    |   3 +
 .../Sema/warn-lifetime-analysis-nocfg.cpp     |  11 +++
 clang/test/Sema/warn-lifetime-safety.cpp      |  70 +++++++++++++++++-
 8 files changed, 141 insertions(+), 4 deletions(-)
 create mode 100644 a.o

diff --git a/a.o b/a.o
new file mode 100644
index 
0000000000000000000000000000000000000000..62582c83f3bfdb00d8640bee02912561d1d29b77
GIT binary patch
literal 3448
zcmb_eO>7%Q6dv16V$viHAqP+qq^J@_qMLP$9D-1B<ZQdpG(`C!qN3Vt)@#SqKa0I~
z+#;)$A|WhODToV*100aZp$Ei;8w9lojyV*mNE|Bhqe$i89*}YXnfG?*+2gg%1)enf
zX1;mzzVFS>j(ts;KkN7T7@3cqVXYCNjFp3}e$?qk**HY5s@31r?LTDoMx}9pxLQ^A
z?=!Wg>_e{(@LlyrvF=O(3_~}n8NPj6zI02iep`k33kOx@*H)%l<-iGUG<?C}$+PU)
z=Na)u)oNu=tsVl$56}f)tbc>LxrXoExqZ-4S8FKhK&=(sbf~TfGnG9zxCSY<Z%08z
ztpXxkCHJbz&tJC^)++a$U<O)-V2jw9zBgFxMXrYn0J1~1cA>6TgO_eOdn7!Jw4O~)
zl+1h~mCH^{g(X>%lPP=R)TV7)g%>6#VX#@;kc?brGMz5DkJDB@_oivs5=Mq*!trT6
zq8sK+Vp<MGOgU`K$VMa_nTjOh8`Ft+VrFK;ke@-;aZc^Ky2O0tQQz^Qf#43*^Elwx
z&>q9b?8xXl{@8H;3IxEA=6qKd=be=UA7j*UT7MD-*wEt8j$ns!_-7%>>`?!x8#9k{
zVAr6v$E`KvaEtq)4M0PF91n6o1b!IWzu5;cd4xS^bc+cve>a!~Ts3WT!%nE9vJJ;U
zz){!%1CEN@?G6^u1xGaCREE8lJptV@K_~7h+SAZr8#^os`JWQ>;NGIW4y{|f+5`Wt
z2mVnH9LwsK|4T;?zA@LFGX>pGpmmFX0P!dM_-0+B9XtfQTRgpgd^5=MSHrbad_Cev
z1w1U^$U^b(sXB)7n3M1|7j{mBh_4Iyh!B55z>f*|O9GB{Q2qr0e^|it0zM|-Zwt7{
z%VFpHpl=(o2|j_xm-Z5&^8)?|@1tAieT)~sj+B50cpu%n0^TR!?+ZA7zhr~sM~{t-
zFzw<(WJS*>O*<A+mhDieVCPfWq*h9qTQK>YZ5HejMx9@_Bkr70^28}lKy!XBL_kO`
zW>aq!P0h0NFLN5jnU?ZqT9<6IY%{z_GiDY#$$YM8F<mk&3mCIo8F<Fii=_;cvN_w7
z&MmB-F4($pnMru@YI-~lmvoY8tJ$qoHm)t1g<{5JZf<i^OXPJNCJjR~%Z6#$nyqi7
z0f9Q82mVUN@l7$3b`fjK=$B2+l}@r>S@IT*yCv4QqA7FMt1GhB$@o8|#qEMr3m#(H
z*w~b^xD52?VzIV*LwrZ#x~)rdYp^{DNz;<$vSz`LTrR7pQ}z|DBzG*7>8$)0|0gUK
z&ne}4jUUD*#lsDgaJ{ryg=6B`#egV2z~~-!N1b<587A;9iBbUfpCSmh<2r`l9!jBa
z^HGlf0v<JaWU|lreCvjE0iKr6GWH(y@ILX{b)Jy!Qsl?`k=BzR1ajo>_XzlcC#2sM
zKJ2)g`(Uw?%d=kQmjvz)8uH^Fd+T52{C@9x6a_~5-BC+FjeFI<!}Adz^5Z^H-Q;g_
zesBFz&QHH%#OKx1i~mE;Pwx-;u@Nu%`<y@EsehgGlYZj&j(>+ZCzogaF5iDTXUL6O
zXg%TEfFYF(O|(tUpAkXmbGYe07cepOM+y|dF0ntknB|er?(+4!p7o@k;5*R4`lAGJ
zzsKv};bW{H-yN-|`o97!FyF|5yAG{si~K^MdjZ#@dCU46Ft2uu+vOnspFu<S5Hv6U
EKZPRj`v3p{

literal 0
HcmV?d00001

diff --git a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp 
b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
index 82b890b57817e..69a64d08e0385 100644
--- a/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/FactsGenerator.cpp
@@ -484,7 +484,8 @@ void FactsGenerator::VisitCXXOperatorCallExpr(const 
CXXOperatorCallExpr *OCE) {
       hasOrigins(OCE->getArg(0)->getType())) {
     // Pointer-like types: assignment inherently propagates origins.
     QualType LHSTy = OCE->getArg(0)->getType();
-    if (LHSTy->isPointerOrReferenceType() || isGslPointerType(LHSTy)) {
+    if (LHSTy->isPointerOrReferenceType() || isGslPointerType(LHSTy) ||
+        isGslOwnerType(LHSTy)) {
       handleAssignment(OCE->getArg(0), OCE->getArg(1));
       return;
     }
diff --git a/clang/lib/Analysis/LifetimeSafety/Origins.cpp 
b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
index abf9890b08522..c0f98dffe8354 100644
--- a/clang/lib/Analysis/LifetimeSafety/Origins.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Origins.cpp
@@ -68,6 +68,7 @@ class LifetimeAnnotatedOriginTypeCollector
   }
 
   bool shouldVisitLambdaBody() const { return false; }
+  bool shouldVisitTemplateInstantiations() const { return true; }
 
   const llvm::SmallVector<QualType> &getCollectedTypes() const {
     return CollectedTypes;
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp
index 7c79f954e6743..d173b1ba58d8e 100644
--- a/clang/lib/Sema/SemaAttr.cpp
+++ b/clang/lib/Sema/SemaAttr.cpp
@@ -250,6 +250,61 @@ void Sema::inferLifetimeBoundAttribute(FunctionDecl *FD) {
     }
     return;
   }
+
+  // Handle std::make_unique to propagate lifetimebound attributes from the
+  // constructed type's constructor to make_unique's parameters.
+  if (FD->isInStdNamespace() && FD->getDeclName().isIdentifier() &&
+      FD->getName() == "make_unique") {
+    if (!FD->isFunctionTemplateSpecialization())
+      return;
+
+    const TemplateArgumentList *TAL = FD->getTemplateSpecializationArgs();
+    if (!TAL || TAL->size() < 1)
+      return;
+
+    // make_unique's first template argument is the type being constructed.
+    TemplateArgument TA = TAL->get(0);
+    if (TA.getKind() != TemplateArgument::Type)
+      return;
+
+    QualType T = TA.getAsType();
+    const auto *RD = T->getAsCXXRecordDecl();
+    if (!RD)
+      return;
+
+    // Find the constructor that matches make_unique's arguments.
+    for (const auto *Ctor : RD->ctors()) {
+      if (Ctor->getNumParams() != FD->getNumParams())
+        continue;
+
+      bool Compatible = true;
+      for (unsigned i = 0; i < Ctor->getNumParams(); ++i) {
+        QualType CtorParamType = Ctor->getParamDecl(i)->getType();
+        QualType FDParamType = FD->getParamDecl(i)->getType();
+        // Compare types ignoring references.
+        if (!Context.hasSameUnqualifiedType(
+                CtorParamType.getNonReferenceType(),
+                FDParamType.getNonReferenceType())) {
+          Compatible = false;
+          break;
+        }
+      }
+
+      if (!Compatible)
+        continue;
+      // Propagate lifetimebound attributes only if the constructor parameter 
is
+      // a reference. This avoids incorrect loan tracking when a by-value view
+      // (like string_view) is passed by reference to make_unique.
+      for (unsigned i = 0; i < Ctor->getNumParams(); ++i)
+        if (Ctor->getParamDecl(i)->hasAttr<LifetimeBoundAttr>() &&
+            Ctor->getParamDecl(i)->getType()->isReferenceType())
+          FD->getParamDecl(i)->addAttr(
+              LifetimeBoundAttr::CreateImplicit(Context, FD->getLocation()));
+      break; // Found matching constructor, done.
+    }
+    return;
+  }
+
   if (auto *CMD = dyn_cast<CXXMethodDecl>(FD)) {
     const auto *CRD = CMD->getParent();
     if (!CRD->isInStdNamespace() || !CRD->getIdentifier())
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp 
b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 09c2482168ab7..954160d4112a5 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5473,6 +5473,8 @@ 
TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New,
   SemaRef.InstantiateAttrs(TemplateArgs, Definition, New,
                            LateAttrs, StartingScope);
 
+  SemaRef.inferLifetimeBoundAttribute(New);
+
   return false;
 }
 
diff --git a/clang/test/Sema/Inputs/lifetime-analysis.h 
b/clang/test/Sema/Inputs/lifetime-analysis.h
index d1e847d20cc50..67e6c0f18de5c 100644
--- a/clang/test/Sema/Inputs/lifetime-analysis.h
+++ b/clang/test/Sema/Inputs/lifetime-analysis.h
@@ -205,6 +205,9 @@ struct unique_ptr {
   T *get() const;
 };
 
+template<typename T, typename... Args>
+unique_ptr<T> make_unique(Args&&... args);
+
 template<typename T>
 struct optional {
   optional();
diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp 
b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
index 0ed151b9db136..c352cca2023a6 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -176,6 +176,17 @@ void initLocalGslPtrWithTempOwner() {
   use(global2, p2);                       // cfg-note 2 {{later used here}}
 }
 
+struct LifetimeBoundCtor {
+  LifetimeBoundCtor(const MyIntOwner& obj1 [[clang::lifetimebound]]);
+  LifetimeBoundCtor(std::string_view sv [[clang::lifetimebound]]);
+};
+
+auto lifetimebound_make_unique_single_param() {
+  return std::make_unique<LifetimeBoundCtor>(MyIntOwner{}); // 
expected-warning {{returning address of local temporary object}} \
+                                                            // cfg-warning 
{{address of stack memory is returned later}} cfg-note {{returned here}}
+}
+
+
 
 struct Unannotated {
   typedef std::vector<int>::iterator iterator;
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp 
b/clang/test/Sema/warn-lifetime-safety.cpp
index 77d8e3370676d..190b93193e352 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -936,6 +936,70 @@ void lifetimebound_ctor() {
   (void)v;   // expected-note {{later used here}}
 }
 
+void lifetimebound_make_unique() {
+  std::unique_ptr<LifetimeBoundCtor> ptr;
+  {
+    MyObj obj;
+    ptr = std::make_unique<LifetimeBoundCtor>(obj); // expected-warning 
{{object whose reference is captured does not live long enough}}
+  } // expected-note {{destroyed here}}
+  (void)ptr; // expected-note {{later used here}}
+}
+
+void lifetimebound_make_unique_temp() {
+  std::unique_ptr<LifetimeBoundCtor> ptr = 
std::make_unique<LifetimeBoundCtor>(MyObj()); // expected-warning {{object 
whose reference is captured does not live long enough}} \
+                                                                               
          // expected-note {{destroyed here}}
+  (void)ptr; // expected-note {{later used here}}
+}
+
+struct MultiLifetimeBoundCtor {
+  MultiLifetimeBoundCtor(const MyObj& obj1 [[clang::lifetimebound]], const 
MyObj& obj2);
+  MultiLifetimeBoundCtor(const MyObj& obj1, const MyObj& obj2 
[[clang::lifetimebound]], int);
+  MultiLifetimeBoundCtor(const MyObj& obj1 [[clang::lifetimebound]], const 
MyObj& obj2 [[clang::lifetimebound]], double);
+  MultiLifetimeBoundCtor(std::string_view sv [[clang::lifetimebound]]);
+};
+
+void lifetimebound_make_unique_multi_params() {
+  std::unique_ptr<MultiLifetimeBoundCtor> ptr;
+  MyObj obj_long;
+  {
+    MyObj obj_short;
+    ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_short, obj_long); // 
expected-warning {{object whose reference is captured does not live long 
enough}}
+  } // expected-note {{destroyed here}}
+  (void)ptr; // expected-note {{later used here}}
+}
+
+void lifetimebound_make_unique_multi_params2() {
+  std::unique_ptr<MultiLifetimeBoundCtor> ptr;
+  MyObj obj_long;
+  {
+    MyObj obj_short;
+    ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_long, obj_short, 1); // 
expected-warning {{object whose reference is captured does not live long 
enough}}
+  } // expected-note {{destroyed here}}
+  (void)ptr; // expected-note {{later used here}}
+}
+
+void lifetimebound_make_unique_multi_params3_1() {
+  std::unique_ptr<MultiLifetimeBoundCtor> ptr;
+  MyObj obj_long;
+  {
+    MyObj obj_short;
+    ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_short, obj_long, 1.0); 
// expected-warning {{object whose reference is captured does not live long 
enough}}
+  } // expected-note {{destroyed here}}
+  (void)ptr; // expected-note {{later used here}}
+}
+
+void lifetimebound_make_unique_multi_params3_2() {
+  std::unique_ptr<MultiLifetimeBoundCtor> ptr;
+  MyObj obj_long;
+  {
+    MyObj obj_short;
+    ptr = std::make_unique<MultiLifetimeBoundCtor>(obj_long, obj_short, 1.0); 
// expected-warning {{object whose reference is captured does not live long 
enough}}
+  } // expected-note {{destroyed here}}
+  (void)ptr; // expected-note {{later used here}}
+}
+
+
+
 View lifetimebound_return_of_local() {
   MyObj stack;
   return Identity(stack); // expected-warning {{address of stack memory is 
returned later}}
@@ -2425,9 +2489,9 @@ void owner_outlives_lifetimebound_source() {
   std::unique_ptr<S> ups;
   {
     std::string local;
-    ups = getUniqueS(local);
-  }
-  (void)ups; // Should warn.
+    ups = getUniqueS(local); // expected-warning {{object whose reference is 
captured does not live long enough}}
+  } // expected-note {{destroyed here}}
+  (void)ups; // expected-note {{later used here}}
 }
 
 } // namespace track_origins_for_lifetimebound_record_type

>From 537f87e51c6d5fed7406fbbb54f1ee19d8c45544 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sat, 11 Apr 2026 13:26:11 +0000
Subject: [PATCH 02/11] string_view and pointer parameters

---
 a.o                                      | Bin 3448 -> 2984 bytes
 clang/test/Sema/warn-lifetime-safety.cpp |  24 ++++++++++++++++++++++-
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/a.o b/a.o
index 
62582c83f3bfdb00d8640bee02912561d1d29b77..6a53ddbada9cbc2494763f0d57e07746d0d02737
 100644
GIT binary patch
literal 2984
zcmbVO&2Jl35P!DYBrQoWg#)M@T*Ltm-Po<;IDE;Gv&~Yat(7LCs#GoO_1bacFYLAB
z7DYsgRLQa;aX~_GK?o!c95`^{0z$3S9DD2^08%74gcCVLGV^=;rgk<qhmQ1iW`1uz
z-_Ab!Gky6=Fc1(-0r7$8Ym5r9Kh~F1QcQ`L$#Tu;{Auj`9eJ!D0X25@Bcr1q7`t2h
z#%}Xq-vhVyJz?ij<jzCs%@5_DGCEs(M(2=xpO8qrdGH(R@ccTDy}hSKmtuFL68%dU
z-6kPhd!A93Tz4L&?mQ&usnPkpLy@lScl1Ag?FZ_rN<^<0m=p;i5~o+iyYF!|!s|yB
zK*<h`?zID>GvTY6?Cp|ODMVUMy-}=IB9|^}Q7u|1x{<fmUANYFXJ&?!^=4MHtL2$e
zspUN`*6P)}j_qo&%qM5(^SPumH&2wEwG*>ZJDarT;<LHAcs`m<M(ucRKH<EL>RwSL
z2JWwjKsy{bKRG_}Ira5A;aH%{cq~kZ9|Y4=V-+$W6?@#?YlHi%{e8fJ`<Z1KdHidr
z=Q;kHq+o$IX`O<=If6GR$in1UnEVMoO$%c(P7C@O#a|#kN$dY;kv30>e|p1gLLxW}
z79pAO<W@*la2zk9pdmQWkgOC^pJ0A&Ag?@I!p_jf8v}W9CZMyl=on7W)e-pm2z*J#
z$H{pl-x-M+TEpT$7==@u3qhQ`N0<fBF5$!CMC7jbeqnpm^GFUK>3Hv`it!61gMg!V
z#^(SM0Y`SmuK*+hj#*&*E<hsSQ?wXw03-rFO^b10AZp`S9}$2=n3Tb3NdY7RHgJWB
z4T*aAi%JIDRx<2EN(SpF88~WUnm8Mtnil5mxa&0B775pHy0K`pQv9Upm^HWlVPe&)
z7aUh#jOi_*)t!>1xlY>^xERV#g@i)A+N=pnvuic-uWXj-nJZ;lWuaB7uA?noU%S|F
zEqepeRk(Ca&lH7*i^a5ZIl6=j!d$Ct7ArY(#c4Flj>_e%oB6s0wc*xXD@*)dS@LJ4
zXy$FIIaand9MdbDi@v&&DeAhfp;c2~tle0RnpC-Mn@-zyYOYBkOV0C0!jX{osKZNN
z(la+H<5D_(EMZJ_nX_C=Tl|QQH?Nsyq1`rXbTL;eR;lRTGh0!9ThGtGBiF%s;7B?y
zJ)&<hkOSmXg+_b824@iFDLjbye(|*9vkeU2A?7YcYmg??Fmj9MXcIHa-}|e|_<iCp
zDS40?Fec(V0sipi8E5_rVX}T@PpYJC#rYmo>a%#P|4f36<?~Of1Z`!A{5Vp7{r?h%
z{6U}pAz>h{-_!c_vp%Z-TPhysLw?*(+&A+DN<OUrFhC-{r#<atJ)`n}tn%~kBl6=u
z;=IhaRsN8#|ES8(^>co|{wdkXSU&%sR05t8<j1|u{*1>7Ln@v#5+x;7{xSoKD_Hsf
zx<!jIWg^-4!@wc7UwK%~SHAc``F|s$^&eb6BVUk!R#OZpzNh+cE1l1u{kebahn9O)
kV%y48vXuJ%6{G(Q9{Jn)kzjxAu;hlmR1RSH|K!jAACLKYRR910

literal 3448
zcmb_eO>7%Q6dv16V$viHAqP+qq^J@_qMLP$9D-1B<ZQdpG(`C!qN3Vt)@#SqKa0I~
z+#;)$A|WhODToV*100aZp$Ei;8w9lojyV*mNE|Bhqe$i89*}YXnfG?*+2gg%1)enf
zX1;mzzVFS>j(ts;KkN7T7@3cqVXYCNjFp3}e$?qk**HY5s@31r?LTDoMx}9pxLQ^A
z?=!Wg>_e{(@LlyrvF=O(3_~}n8NPj6zI02iep`k33kOx@*H)%l<-iGUG<?C}$+PU)
z=Na)u)oNu=tsVl$56}f)tbc>LxrXoExqZ-4S8FKhK&=(sbf~TfGnG9zxCSY<Z%08z
ztpXxkCHJbz&tJC^)++a$U<O)-V2jw9zBgFxMXrYn0J1~1cA>6TgO_eOdn7!Jw4O~)
zl+1h~mCH^{g(X>%lPP=R)TV7)g%>6#VX#@;kc?brGMz5DkJDB@_oivs5=Mq*!trT6
zq8sK+Vp<MGOgU`K$VMa_nTjOh8`Ft+VrFK;ke@-;aZc^Ky2O0tQQz^Qf#43*^Elwx
z&>q9b?8xXl{@8H;3IxEA=6qKd=be=UA7j*UT7MD-*wEt8j$ns!_-7%>>`?!x8#9k{
zVAr6v$E`KvaEtq)4M0PF91n6o1b!IWzu5;cd4xS^bc+cve>a!~Ts3WT!%nE9vJJ;U
zz){!%1CEN@?G6^u1xGaCREE8lJptV@K_~7h+SAZr8#^os`JWQ>;NGIW4y{|f+5`Wt
z2mVnH9LwsK|4T;?zA@LFGX>pGpmmFX0P!dM_-0+B9XtfQTRgpgd^5=MSHrbad_Cev
z1w1U^$U^b(sXB)7n3M1|7j{mBh_4Iyh!B55z>f*|O9GB{Q2qr0e^|it0zM|-Zwt7{
z%VFpHpl=(o2|j_xm-Z5&^8)?|@1tAieT)~sj+B50cpu%n0^TR!?+ZA7zhr~sM~{t-
zFzw<(WJS*>O*<A+mhDieVCPfWq*h9qTQK>YZ5HejMx9@_Bkr70^28}lKy!XBL_kO`
zW>aq!P0h0NFLN5jnU?ZqT9<6IY%{z_GiDY#$$YM8F<mk&3mCIo8F<Fii=_;cvN_w7
z&MmB-F4($pnMru@YI-~lmvoY8tJ$qoHm)t1g<{5JZf<i^OXPJNCJjR~%Z6#$nyqi7
z0f9Q82mVUN@l7$3b`fjK=$B2+l}@r>S@IT*yCv4QqA7FMt1GhB$@o8|#qEMr3m#(H
z*w~b^xD52?VzIV*LwrZ#x~)rdYp^{DNz;<$vSz`LTrR7pQ}z|DBzG*7>8$)0|0gUK
z&ne}4jUUD*#lsDgaJ{ryg=6B`#egV2z~~-!N1b<587A;9iBbUfpCSmh<2r`l9!jBa
z^HGlf0v<JaWU|lreCvjE0iKr6GWH(y@ILX{b)Jy!Qsl?`k=BzR1ajo>_XzlcC#2sM
zKJ2)g`(Uw?%d=kQmjvz)8uH^Fd+T52{C@9x6a_~5-BC+FjeFI<!}Adz^5Z^H-Q;g_
zesBFz&QHH%#OKx1i~mE;Pwx-;u@Nu%`<y@EsehgGlYZj&j(>+ZCzogaF5iDTXUL6O
zXg%TEfFYF(O|(tUpAkXmbGYe07cepOM+y|dF0ntknB|er?(+4!p7o@k;5*R4`lAGJ
zzsKv};bW{H-yN-|`o97!FyF|5yAG{si~K^MdjZ#@dCU46Ft2uu+vOnspFu<S5Hv6U
EKZPRj`v3p{

diff --git a/clang/test/Sema/warn-lifetime-safety.cpp 
b/clang/test/Sema/warn-lifetime-safety.cpp
index 190b93193e352..667b0c4004483 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -925,6 +925,7 @@ void lifetimebound_return_reference() {
 struct LifetimeBoundCtor {
   LifetimeBoundCtor();
   LifetimeBoundCtor(const MyObj& obj [[clang::lifetimebound]]);
+  LifetimeBoundCtor(int* p [[clang::lifetimebound]]);
 };
 
 void lifetimebound_ctor() {
@@ -951,11 +952,32 @@ void lifetimebound_make_unique_temp() {
   (void)ptr; // expected-note {{later used here}}
 }
 
+void lifetimebound_make_unique_raw_ptr() {
+  std::unique_ptr<LifetimeBoundCtor> ptr;
+  int x = 0;
+  {
+    int* p = &x;
+    // FIXME: No warning expected with current implementation
+    ptr = std::make_unique<LifetimeBoundCtor>(p);
+  }
+  (void)ptr;
+}
+
+void lifetimebound_make_unique_string_view_local() {
+  std::unique_ptr<LifetimeBoundCtor> ptr;
+  {
+    std::string s;
+    std::string_view sv(s);
+    // FIXME: No warning expected with current implementation because of 
reference mismatch
+    ptr = std::make_unique<LifetimeBoundCtor>(sv);
+  }
+  (void)ptr;
+}
+
 struct MultiLifetimeBoundCtor {
   MultiLifetimeBoundCtor(const MyObj& obj1 [[clang::lifetimebound]], const 
MyObj& obj2);
   MultiLifetimeBoundCtor(const MyObj& obj1, const MyObj& obj2 
[[clang::lifetimebound]], int);
   MultiLifetimeBoundCtor(const MyObj& obj1 [[clang::lifetimebound]], const 
MyObj& obj2 [[clang::lifetimebound]], double);
-  MultiLifetimeBoundCtor(std::string_view sv [[clang::lifetimebound]]);
 };
 
 void lifetimebound_make_unique_multi_params() {

>From edc2eff95b831c5216b0d74ec066e9daeed44be2 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sat, 11 Apr 2026 13:27:10 +0000
Subject: [PATCH 03/11] remove a.o

---
 a.o | Bin 2984 -> 0 bytes
 1 file changed, 0 insertions(+), 0 deletions(-)
 delete mode 100644 a.o

diff --git a/a.o b/a.o
deleted file mode 100644
index 
6a53ddbada9cbc2494763f0d57e07746d0d02737..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2984
zcmbVO&2Jl35P!DYBrQoWg#)M@T*Ltm-Po<;IDE;Gv&~Yat(7LCs#GoO_1bacFYLAB
z7DYsgRLQa;aX~_GK?o!c95`^{0z$3S9DD2^08%74gcCVLGV^=;rgk<qhmQ1iW`1uz
z-_Ab!Gky6=Fc1(-0r7$8Ym5r9Kh~F1QcQ`L$#Tu;{Auj`9eJ!D0X25@Bcr1q7`t2h
z#%}Xq-vhVyJz?ij<jzCs%@5_DGCEs(M(2=xpO8qrdGH(R@ccTDy}hSKmtuFL68%dU
z-6kPhd!A93Tz4L&?mQ&usnPkpLy@lScl1Ag?FZ_rN<^<0m=p;i5~o+iyYF!|!s|yB
zK*<h`?zID>GvTY6?Cp|ODMVUMy-}=IB9|^}Q7u|1x{<fmUANYFXJ&?!^=4MHtL2$e
zspUN`*6P)}j_qo&%qM5(^SPumH&2wEwG*>ZJDarT;<LHAcs`m<M(ucRKH<EL>RwSL
z2JWwjKsy{bKRG_}Ira5A;aH%{cq~kZ9|Y4=V-+$W6?@#?YlHi%{e8fJ`<Z1KdHidr
z=Q;kHq+o$IX`O<=If6GR$in1UnEVMoO$%c(P7C@O#a|#kN$dY;kv30>e|p1gLLxW}
z79pAO<W@*la2zk9pdmQWkgOC^pJ0A&Ag?@I!p_jf8v}W9CZMyl=on7W)e-pm2z*J#
z$H{pl-x-M+TEpT$7==@u3qhQ`N0<fBF5$!CMC7jbeqnpm^GFUK>3Hv`it!61gMg!V
z#^(SM0Y`SmuK*+hj#*&*E<hsSQ?wXw03-rFO^b10AZp`S9}$2=n3Tb3NdY7RHgJWB
z4T*aAi%JIDRx<2EN(SpF88~WUnm8Mtnil5mxa&0B775pHy0K`pQv9Upm^HWlVPe&)
z7aUh#jOi_*)t!>1xlY>^xERV#g@i)A+N=pnvuic-uWXj-nJZ;lWuaB7uA?noU%S|F
zEqepeRk(Ca&lH7*i^a5ZIl6=j!d$Ct7ArY(#c4Flj>_e%oB6s0wc*xXD@*)dS@LJ4
zXy$FIIaand9MdbDi@v&&DeAhfp;c2~tle0RnpC-Mn@-zyYOYBkOV0C0!jX{osKZNN
z(la+H<5D_(EMZJ_nX_C=Tl|QQH?Nsyq1`rXbTL;eR;lRTGh0!9ThGtGBiF%s;7B?y
zJ)&<hkOSmXg+_b824@iFDLjbye(|*9vkeU2A?7YcYmg??Fmj9MXcIHa-}|e|_<iCp
zDS40?Fec(V0sipi8E5_rVX}T@PpYJC#rYmo>a%#P|4f36<?~Of1Z`!A{5Vp7{r?h%
z{6U}pAz>h{-_!c_vp%Z-TPhysLw?*(+&A+DN<OUrFhC-{r#<atJ)`n}tn%~kBl6=u
z;=IhaRsN8#|ES8(^>co|{wdkXSU&%sR05t8<j1|u{*1>7Ln@v#5+x;7{xSoKD_Hsf
zx<!jIWg^-4!@wc7UwK%~SHAc``F|s$^&eb6BVUk!R#OZpzNh+cE1l1u{kebahn9O)
kV%y48vXuJ%6{G(Q9{Jn)kzjxAu;hlmR1RSH|K!jAACLKYRR910


>From d50a426d6f5f7800551fe19d8dea7afd9f208d7e Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sat, 11 Apr 2026 13:36:43 +0000
Subject: [PATCH 04/11] dangling field

---
 .../Sema/warn-lifetime-safety-dangling-field.cpp | 16 ++++++++++++++++
 clang/test/Sema/warn-lifetime-safety.cpp         |  2 ++
 2 files changed, 18 insertions(+)

diff --git a/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp 
b/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp
index fa45458371012..e35a68ceae961 100644
--- a/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-dangling-field.cpp
@@ -184,3 +184,19 @@ struct IndirectEscape2 {
     p = s.data();
   }
 };
+
+namespace MakeUnique {
+struct MyObj {};
+
+struct LifetimeBoundCtor {
+  LifetimeBoundCtor(const MyObj& obj [[clang::lifetimebound]]);
+};
+
+struct HasUniquePtrField {
+  std::unique_ptr<LifetimeBoundCtor> field; // expected-note {{this field 
dangles}}
+
+  void setWithParam(MyObj obj) {
+    field = std::make_unique<LifetimeBoundCtor>(obj); // expected-warning 
{{address of stack memory escapes to a field}}
+  }
+};
+} // namespace MakeUnique
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp 
b/clang/test/Sema/warn-lifetime-safety.cpp
index 667b0c4004483..b48a380e7b5ea 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -974,6 +974,8 @@ void lifetimebound_make_unique_string_view_local() {
   (void)ptr;
 }
 
+
+
 struct MultiLifetimeBoundCtor {
   MultiLifetimeBoundCtor(const MyObj& obj1 [[clang::lifetimebound]], const 
MyObj& obj2);
   MultiLifetimeBoundCtor(const MyObj& obj1, const MyObj& obj2 
[[clang::lifetimebound]], int);

>From 2411c1e5f90da1f4d9c0503f58df3859f2822f08 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sat, 11 Apr 2026 13:47:55 +0000
Subject: [PATCH 05/11] lifetime suggestion

---
 .../Sema/warn-lifetime-safety-suggestions.cpp | 21 +++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp 
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 19c3251b9c296..401f02b3bb788 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -67,6 +67,7 @@ struct ReturnThisPointer {
 //--- test_source.cpp
 
 #include "test_header.h"
+#include "Inputs/lifetime-analysis.h"
 
 View definition_before_header(View a) {
   return a;                               // expected-note {{param returned 
here}}
@@ -456,3 +457,23 @@ S forward(const MyObj &obj) { // expected-warning 
{{parameter in intra-TU functi
 }
 
 } // namespace track_origins_for_lifetimebound_record_type
+
+namespace make_unique_suggestion {
+
+struct LifetimeBoundCtor {
+  LifetimeBoundCtor(const MyObj& obj [[clang::lifetimebound]]);
+};
+
+std::unique_ptr<LifetimeBoundCtor> create_target(const MyObj& obj) { // 
expected-warning {{parameter in intra-TU function should be marked 
[[clang::lifetimebound]]}}
+  return std::make_unique<LifetimeBoundCtor>(obj); // expected-note {{param 
returned here}}
+}
+
+void test_inference() {
+  std::unique_ptr<LifetimeBoundCtor> ptr;
+  {
+    MyObj obj;
+    ptr = create_target(obj); // expected-warning {{object whose reference is 
captured does not live long enough}}
+  } // expected-note {{destroyed here}}
+  (void)ptr; // expected-note {{later used here}}
+}
+} // namespace make_unique_suggestion

>From d194a7a5f2f362667ce03e4b98bee957d9fd12b6 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sat, 11 Apr 2026 14:47:51 +0000
Subject: [PATCH 06/11] fix suggestions test

---
 clang/test/Sema/warn-lifetime-safety-suggestions.cpp | 9 +++++----
 clang/test/Sema/warn-lifetime-safety.cpp             | 4 ----
 2 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp 
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 401f02b3bb788..5906170b0d146 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -1,8 +1,8 @@
 // RUN: rm -rf %t
 // RUN: split-file %s %t
-// RUN: %clang_cc1 -fsyntax-only -flifetime-safety-inference 
-fexperimental-lifetime-safety-tu-analysis -Wlifetime-safety-suggestions 
-Wlifetime-safety -Wno-dangling -I%t -verify %t/test_source.cpp
-// RUN: %clang_cc1 -flifetime-safety-inference 
-fexperimental-lifetime-safety-tu-analysis -Wlifetime-safety-suggestions 
-Wlifetime-safety -Wno-dangling -I%t -fixit %t/test_source.cpp
-// RUN: %clang_cc1 -fsyntax-only -flifetime-safety-inference 
-fexperimental-lifetime-safety-tu-analysis -Wlifetime-safety-suggestions 
-Wno-dangling -I%t -Werror=lifetime-safety-suggestions %t/test_source.cpp
+// RUN: %clang_cc1 -fsyntax-only -flifetime-safety-inference 
-fexperimental-lifetime-safety-tu-analysis -Wlifetime-safety-suggestions 
-Wlifetime-safety -Wno-dangling -I%S -I%t -verify %t/test_source.cpp
+// RUN: %clang_cc1 -flifetime-safety-inference 
-fexperimental-lifetime-safety-tu-analysis -Wlifetime-safety-suggestions 
-Wlifetime-safety -Wno-dangling -I%S -I%t -fixit %t/test_source.cpp
+// RUN: %clang_cc1 -fsyntax-only -flifetime-safety-inference 
-fexperimental-lifetime-safety-tu-analysis -Wlifetime-safety-suggestions 
-Wno-dangling -I%S -I%t -Werror=lifetime-safety-suggestions %t/test_source.cpp
 
 View definition_before_header(View a);
 
@@ -10,6 +10,8 @@ View definition_before_header(View a);
 #ifndef TEST_HEADER_H
 #define TEST_HEADER_H
 
+#include "Inputs/lifetime-analysis.h"
+
 struct View;
 
 struct [[gsl::Owner]] MyObj {
@@ -67,7 +69,6 @@ struct ReturnThisPointer {
 //--- test_source.cpp
 
 #include "test_header.h"
-#include "Inputs/lifetime-analysis.h"
 
 View definition_before_header(View a) {
   return a;                               // expected-note {{param returned 
here}}
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp 
b/clang/test/Sema/warn-lifetime-safety.cpp
index b48a380e7b5ea..e0147d69459f5 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -974,8 +974,6 @@ void lifetimebound_make_unique_string_view_local() {
   (void)ptr;
 }
 
-
-
 struct MultiLifetimeBoundCtor {
   MultiLifetimeBoundCtor(const MyObj& obj1 [[clang::lifetimebound]], const 
MyObj& obj2);
   MultiLifetimeBoundCtor(const MyObj& obj1, const MyObj& obj2 
[[clang::lifetimebound]], int);
@@ -2507,8 +2505,6 @@ std::string_view return_dangling_view_through_owner() {
   return sv; // expected-note {{returned here}}
 }
 
-// FIXME: False negative. Move assignment of unique_ptr is not defaulted,
-// so origins from `local` don't propagate to `ups`.
 void owner_outlives_lifetimebound_source() {
   std::unique_ptr<S> ups;
   {

>From 36cc5af4d82c6a71281976cbbff16c9672d641e1 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sun, 12 Apr 2026 10:11:30 +0000
Subject: [PATCH 07/11] Annotation inference on constructor

---
 .../Analyses/LifetimeSafety/LifetimeSafety.h  |  9 ++--
 clang/lib/Analysis/LifetimeSafety/Checker.cpp | 39 +++++++++++++-----
 clang/lib/Sema/AnalysisBasedWarnings.cpp      |  4 ++
 clang/lib/Sema/SemaLifetimeSafety.h           | 18 +++++---
 .../Sema/warn-lifetime-analysis-nocfg.cpp     | 40 +++++++++---------
 .../Sema/warn-lifetime-safety-suggestions.cpp | 41 ++++++++++++++++++-
 clang/test/Sema/warn-lifetime-safety.cpp      | 12 +++---
 7 files changed, 114 insertions(+), 49 deletions(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 08038dd096685..412c28c6587eb 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -28,6 +28,7 @@
 #include "clang/Analysis/Analyses/LifetimeSafety/MovedLoans.h"
 #include "clang/Analysis/Analyses/LifetimeSafety/Origins.h"
 #include "clang/Analysis/AnalysisDeclContext.h"
+#include "llvm/ADT/PointerUnion.h"
 #include <cstddef>
 #include <memory>
 
@@ -88,10 +89,10 @@ class LifetimeSafetySemaHelper {
                                           const Expr *UseExpr,
                                           const Expr *InvalidationExpr) {}
 
-  // Suggests lifetime bound annotations for function paramters.
-  virtual void suggestLifetimeboundToParmVar(SuggestionScope Scope,
-                                             const ParmVarDecl *ParmToAnnotate,
-                                             const Expr *EscapeExpr) {}
+  // Suggests lifetime bound annotations for function parameters.
+  virtual void suggestLifetimeboundToParmVar(
+      SuggestionScope Scope, const ParmVarDecl *ParmToAnnotate,
+      llvm::PointerUnion<const Expr *, const FieldDecl *> Target) {}
 
   // Reports misuse of [[clang::noescape]] when parameter escapes through 
return
   virtual void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape,
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 36477c6f67b52..3181caff4a5e8 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -59,7 +59,7 @@ using EscapingTarget =
 class LifetimeChecker {
 private:
   llvm::DenseMap<LoanID, PendingWarning> FinalWarningsMap;
-  llvm::DenseMap<AnnotationTarget, const Expr *> AnnotationWarningsMap;
+  llvm::DenseMap<AnnotationTarget, EscapingTarget> AnnotationWarningsMap;
   llvm::DenseMap<const ParmVarDecl *, EscapingTarget> NoescapeWarningsMap;
   const LoanPropagationAnalysis &LoanPropagation;
   const MovedLoansAnalysis &MovedLoans;
@@ -67,6 +67,7 @@ class LifetimeChecker {
   FactManager &FactMgr;
   LifetimeSafetySemaHelper *SemaHelper;
   ASTContext &AST;
+  const Decl *D;
 
   static SourceLocation
   GetFactLoc(llvm::PointerUnion<const UseFact *, const OriginEscapesFact *> F) 
{
@@ -89,7 +90,7 @@ class LifetimeChecker {
                   LifetimeSafetySemaHelper *SemaHelper)
       : LoanPropagation(LoanPropagation), MovedLoans(MovedLoans),
         LiveOrigins(LiveOrigins), FactMgr(FM), SemaHelper(SemaHelper),
-        AST(ADC.getASTContext()) {
+        AST(ADC.getASTContext()), D(ADC.getDecl()) {
     for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>())
       for (const Fact *F : FactMgr.getFacts(B))
         if (const auto *EF = F->getAs<ExpireFact>())
@@ -126,9 +127,13 @@ class LifetimeChecker {
         return;
       }
       // Suggest lifetimebound for parameter escaping through return.
-      if (!PVD->hasAttr<LifetimeBoundAttr>())
+      if (!PVD->hasAttr<LifetimeBoundAttr>()) {
         if (auto *ReturnEsc = dyn_cast<ReturnEscapeFact>(OEF))
           AnnotationWarningsMap.try_emplace(PVD, ReturnEsc->getReturnExpr());
+        else if (auto *FieldEsc = dyn_cast<FieldEscapeFact>(OEF))
+          if (isa<CXXConstructorDecl>(D))
+            AnnotationWarningsMap.try_emplace(PVD, FieldEsc->getFieldDecl());
+      }
       // TODO: Suggest lifetime_capture_by(this) for parameter escaping to a
       // field!
     };
@@ -292,14 +297,22 @@ class LifetimeChecker {
   static void suggestWithScopeForParmVar(LifetimeSafetySemaHelper *SemaHelper,
                                          const ParmVarDecl *PVD,
                                          SourceManager &SM,
-                                         const Expr *EscapeExpr) {
+                                         EscapingTarget EscapeTarget) {
+    llvm::PointerUnion<const Expr *, const FieldDecl *> Target;
+    if (const auto *E = EscapeTarget.dyn_cast<const Expr *>())
+      Target = E;
+    else if (const auto *F = EscapeTarget.dyn_cast<const FieldDecl *>())
+      Target = F;
+    else
+      return;
+
     if (const FunctionDecl *CrossTUDecl = getCrossTUDecl(*PVD, SM))
       SemaHelper->suggestLifetimeboundToParmVar(
           SuggestionScope::CrossTU,
-          CrossTUDecl->getParamDecl(PVD->getFunctionScopeIndex()), EscapeExpr);
+          CrossTUDecl->getParamDecl(PVD->getFunctionScopeIndex()), Target);
     else
       SemaHelper->suggestLifetimeboundToParmVar(SuggestionScope::IntraTU, PVD,
-                                                EscapeExpr);
+                                                Target);
   }
 
   static void
@@ -319,11 +332,15 @@ class LifetimeChecker {
     if (!SemaHelper)
       return;
     SourceManager &SM = AST.getSourceManager();
-    for (auto [Target, EscapeExpr] : AnnotationWarningsMap) {
+    for (auto [Target, EscapeTarget] : AnnotationWarningsMap) {
       if (const auto *PVD = Target.dyn_cast<const ParmVarDecl *>())
-        suggestWithScopeForParmVar(SemaHelper, PVD, SM, EscapeExpr);
-      else if (const auto *MD = Target.dyn_cast<const CXXMethodDecl *>())
-        suggestWithScopeForImplicitThis(SemaHelper, MD, SM, EscapeExpr);
+        suggestWithScopeForParmVar(SemaHelper, PVD, SM, EscapeTarget);
+      else if (const auto *MD = Target.dyn_cast<const CXXMethodDecl *>()) {
+        if (const auto *EscapeExpr = EscapeTarget.dyn_cast<const Expr *>())
+          suggestWithScopeForImplicitThis(SemaHelper, MD, SM, EscapeExpr);
+        else
+          llvm_unreachable("Implicit this can only escape via Expr (return)");
+      }
     }
   }
 
@@ -341,7 +358,7 @@ class LifetimeChecker {
   }
 
   void inferAnnotations() {
-    for (auto [Target, EscapeExpr] : AnnotationWarningsMap) {
+    for (auto [Target, EscapeTarget] : AnnotationWarningsMap) {
       if (const auto *MD = Target.dyn_cast<const CXXMethodDecl *>()) {
         if (!implicitObjectParamIsLifetimeBound(MD))
           SemaHelper->addLifetimeBoundToImplicitThis(cast<CXXMethodDecl>(MD));
diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp 
b/clang/lib/Sema/AnalysisBasedWarnings.cpp
index 48957caf61e5a..c538e7cb2211e 100644
--- a/clang/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp
@@ -2925,6 +2925,10 @@ LifetimeSafetyTUAnalysis(Sema &S, TranslationUnitDecl 
*TU,
     AC.getCFGBuildOptions().PruneTriviallyFalseEdges = true;
     AC.getCFGBuildOptions().AddLifetime = true;
     AC.getCFGBuildOptions().AddParameterLifetimes = true;
+    AC.getCFGBuildOptions().AddInitializers = true;
+    AC.getCFGBuildOptions().AddCXXDefaultInitExprInCtors = true;
+    AC.getCFGBuildOptions().AddImplicitDtors = true;
+    AC.getCFGBuildOptions().AddTemporaryDtors = true;
     AC.getCFGBuildOptions().setAllAlwaysAdd();
     if (AC.getCFG())
       runLifetimeSafetyAnalysis(AC, &SemaHelper, LSStats, S.CollectStats);
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h 
b/clang/lib/Sema/SemaLifetimeSafety.h
index e6f7e3d929f61..add2490be497e 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -131,9 +131,9 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
         << UseExpr->getSourceRange();
   }
 
-  void suggestLifetimeboundToParmVar(SuggestionScope Scope,
-                                     const ParmVarDecl *ParmToAnnotate,
-                                     const Expr *EscapeExpr) override {
+  void suggestLifetimeboundToParmVar(
+      SuggestionScope Scope, const ParmVarDecl *ParmToAnnotate,
+      llvm::PointerUnion<const Expr *, const FieldDecl *> Target) override {
     unsigned DiagID =
         (Scope == SuggestionScope::CrossTU)
             ? diag::warn_lifetime_safety_cross_tu_param_suggestion
@@ -150,9 +150,15 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
     S.Diag(ParmToAnnotate->getBeginLoc(), DiagID)
         << ParmToAnnotate->getSourceRange()
         << FixItHint::CreateInsertion(InsertionPoint, FixItText);
-    S.Diag(EscapeExpr->getBeginLoc(),
-           diag::note_lifetime_safety_suggestion_returned_here)
-        << EscapeExpr->getSourceRange();
+
+    if (const auto *EscapeExpr = Target.dyn_cast<const Expr *>())
+      S.Diag(EscapeExpr->getBeginLoc(),
+             diag::note_lifetime_safety_suggestion_returned_here)
+          << EscapeExpr->getSourceRange();
+    else if (const auto *EscapeField = Target.dyn_cast<const FieldDecl *>())
+      S.Diag(EscapeField->getLocation(),
+             diag::note_lifetime_safety_escapes_to_field_here)
+          << EscapeField->getSourceRange();
   }
 
   void suggestLifetimeboundToImplicitThis(SuggestionScope Scope,
diff --git a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp 
b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
index c352cca2023a6..e07c90f248764 100644
--- a/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ b/clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -1,7 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -Wdangling -Wdangling-field 
-Wreturn-stack-address -verify %s
-// RUN: %clang_cc1 -fsyntax-only -Wlifetime-safety -Wno-dangling 
-verify=cfg,cfg-field %s
-
-// FIXME: cfg-field should be detected in end-of-TU analysis but it doesn't 
work for constructors!
+// RUN: %clang_cc1 -fsyntax-only -Wlifetime-safety -Wno-dangling -verify=cfg %s
 // RUN: %clang_cc1 -fsyntax-only -flifetime-safety-inference 
-fexperimental-lifetime-safety-tu-analysis -Wlifetime-safety -Wno-dangling 
-verify=cfg %s
 
 #include "Inputs/lifetime-analysis.h"
@@ -84,17 +82,17 @@ void dangligGslPtrFromTemporary() {
 
 struct DanglingGslPtrField {
   MyIntPointer p; // expected-note {{pointer member declared here}} \
-                  // cfg-field-note 3 {{this field dangles}}
+                  // cfg-note 3 {{this field dangles}}
   MyLongPointerFromConversion p2; // expected-note {{pointer member declared 
here}} \
-                                  // cfg-field-note 2 {{this field dangles}}
+                                  // cfg-note 2 {{this field dangles}}
 
-  DanglingGslPtrField(int i) : p(&i) {} // cfg-field-warning {{address of 
stack memory escapes to a field}}
+  DanglingGslPtrField(int i) : p(&i) {} // cfg-warning {{address of stack 
memory escapes to a field}}
   DanglingGslPtrField() : p2(MyLongOwnerWithConversion{}) {}  // 
expected-warning {{initializing pointer member 'p2' to point to a temporary 
object whose lifetime is shorter than the lifetime of the constructed object}} \
-                                                              // 
cfg-field-warning {{address of stack memory escapes to a field}}
+                                                              // cfg-warning 
{{address of stack memory escapes to a field}}
   DanglingGslPtrField(double) : p(MyIntOwner{}) {}  // expected-warning 
{{initializing pointer member 'p' to point to a temporary object whose lifetime 
is shorter than the lifetime of the constructed object}} \
-                                                    // cfg-field-warning 
{{address of stack memory escapes to a field}}
-  DanglingGslPtrField(MyIntOwner io) : p(io) {} // cfg-field-warning {{address 
of stack memory escapes to a field}}
-  DanglingGslPtrField(MyLongOwnerWithConversion lo) : p2(lo) {} // 
cfg-field-warning {{address of stack memory escapes to a field}}
+                                                    // cfg-warning {{address 
of stack memory escapes to a field}}
+  DanglingGslPtrField(MyIntOwner io) : p(io) {} // cfg-warning {{address of 
stack memory escapes to a field}}
+  DanglingGslPtrField(MyLongOwnerWithConversion lo) : p2(lo) {} // cfg-warning 
{{address of stack memory escapes to a field}}
 };
 
 MyIntPointer danglingGslPtrFromLocal() {
@@ -361,11 +359,11 @@ const char *trackThroughMultiplePointer() {
 
 struct X {
   X(std::unique_ptr<int> up) :
-    pointee(*up),             // cfg-field-warning {{may have been moved.}}
-    pointee2(up.get()),       // cfg-field-warning {{may have been moved.}}
-    pointer(std::move(up)) {} // cfg-field-note 2 {{potentially moved here}}
-  int &pointee;               // cfg-field-note {{this field dangles}}
-  int *pointee2;              // cfg-field-note {{this field dangles}}
+    pointee(*up),             // cfg-warning {{may have been moved.}}
+    pointee2(up.get()),       // cfg-warning {{may have been moved.}}
+    pointer(std::move(up)) {} // cfg-note 2 {{potentially moved here}}
+  int &pointee;               // cfg-note {{this field dangles}}
+  int *pointee2;              // cfg-note {{this field dangles}}
   std::unique_ptr<int> pointer;
 };
 
@@ -376,9 +374,9 @@ struct X2 {
   // A common usage that moves the passing owner to the class.
   // verify a strict warning on this case.
   X2(XOwner owner) :
-    pointee(owner.get()),       // cfg-field-warning {{may have been moved.}}
-    owner(std::move(owner)) {}  // cfg-field-note {{potentially moved here}}
-  int* pointee;                 // cfg-field-note {{this field dangles}}
+    pointee(owner.get()),       // cfg-warning {{may have been moved.}}
+    owner(std::move(owner)) {}  // cfg-note {{potentially moved here}}
+  int* pointee;                 // cfg-note {{this field dangles}}
   XOwner owner;
 };
 
@@ -1127,10 +1125,10 @@ struct Foo2 {
 };
 
 struct Test {
-  Test(Foo2 foo) : bar(foo.bar.get()),  // cfg-field-warning-re {{address of 
stack memory escapes to a field. {{.*}} may have been moved}}
-      storage(std::move(foo.bar)) {};   // cfg-field-note {{potentially moved 
here}}
+  Test(Foo2 foo) : bar(foo.bar.get()),  // cfg-warning-re {{address of stack 
memory escapes to a field. {{.*}} may have been moved}}
+      storage(std::move(foo.bar)) {};   // cfg-note {{potentially moved here}}
 
-  Bar* bar; // cfg-field-note {{this field dangles}}
+  Bar* bar; // cfg-note {{this field dangles}}
   std::unique_ptr<Bar> storage;
 };
 
diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp 
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 5906170b0d146..4f62dd608e814 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -462,7 +462,8 @@ S forward(const MyObj &obj) { // expected-warning 
{{parameter in intra-TU functi
 namespace make_unique_suggestion {
 
 struct LifetimeBoundCtor {
-  LifetimeBoundCtor(const MyObj& obj [[clang::lifetimebound]]);
+  const MyObj& obj;
+  LifetimeBoundCtor(const MyObj& obj [[clang::lifetimebound]]) : obj(obj) {}
 };
 
 std::unique_ptr<LifetimeBoundCtor> create_target(const MyObj& obj) { // 
expected-warning {{parameter in intra-TU function should be marked 
[[clang::lifetimebound]]}}
@@ -478,3 +479,41 @@ void test_inference() {
   (void)ptr; // expected-note {{later used here}}
 }
 } // namespace make_unique_suggestion
+
+namespace capturing_constructor {
+struct A {
+  View v; // expected-note {{escapes to this field}}
+  A(const MyObj& obj) : v(obj) {} // expected-warning {{parameter in intra-TU 
function should be marked [[clang::lifetimebound]]}}
+};
+
+struct B {
+  const int* p; // expected-note {{escapes to this field}}
+  B(const int& r) : p(&r) {} // expected-warning {{parameter in intra-TU 
function should be marked [[clang::lifetimebound]]}}
+};
+
+struct C {
+  View v; // expected-note {{escapes to this field}}
+  C(View v_param) : v(v_param) {} // expected-warning {{parameter in intra-TU 
function should be marked [[clang::lifetimebound]]}}
+};
+
+struct D {
+  const int* p; // expected-note {{escapes to this field}}
+  D(const int* p_param) : p(p_param) {} // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}
+};
+} // namespace capturing_constructor
+
+namespace capturing_constructor_inference {
+struct B {
+  const MyObj* p; // expected-note {{escapes to this field}}
+  B(const MyObj& obj) : p(&obj) {} // expected-warning {{parameter in intra-TU 
function should be marked [[clang::lifetimebound]]}}
+};
+
+void test(B& b_out) {
+  {
+    MyObj obj;
+    B b(obj); // expected-warning {{object whose reference is captured does 
not live long enough}}
+    b_out = b;
+  } // expected-note {{destroyed here}}
+  (void)b_out; // expected-note {{later used here}}
+}
+} // namespace capturing_constructor_inference
diff --git a/clang/test/Sema/warn-lifetime-safety.cpp 
b/clang/test/Sema/warn-lifetime-safety.cpp
index e0147d69459f5..07562c4b33f8e 100644
--- a/clang/test/Sema/warn-lifetime-safety.cpp
+++ b/clang/test/Sema/warn-lifetime-safety.cpp
@@ -2361,8 +2361,8 @@ void from_template_instantiation() {
 }
 
 struct FieldInitFromLifetimebound {
-  S value; // function-note {{this field dangles}}
-  FieldInitFromLifetimebound() : value(getS(std::string("temp"))) {} // 
function-warning {{address of stack memory escapes to a field}}
+  S value; // expected-note {{this field dangles}}
+  FieldInitFromLifetimebound() : value(getS(std::string("temp"))) {} // 
expected-warning {{address of stack memory escapes to a field}}
 };
 
 S S::return_self_after_registration() const {
@@ -2551,13 +2551,13 @@ void nested_local_pointer() {
 }
 
 struct PFieldFromParam {
-  Pointer<Bar> value;                      // function-note {{this field 
dangles}}
-  PFieldFromParam(Bar bar) : value(bar) {} // function-warning {{address of 
stack memory escapes to a field}}
+  Pointer<Bar> value;                      // expected-note {{this field 
dangles}}
+  PFieldFromParam(Bar bar) : value(bar) {} // expected-warning {{address of 
stack memory escapes to a field}}
 };
 
 struct PFieldFromTemp {
-  Pointer<Bar> value;                // function-note {{this field dangles}}
-  PFieldFromTemp() : value(Bar{}) {} // function-warning {{address of stack 
memory escapes to a field}}
+  Pointer<Bar> value;                // expected-note {{this field dangles}}
+  PFieldFromTemp() : value(Bar{}) {} // expected-warning {{address of stack 
memory escapes to a field}}
 };
 
 } // namespace gslpointer_construction_from_lifetimebound

>From 2dc6dd7f6a61a9e7af37025fbec84c8b3844143e Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sun, 12 Apr 2026 11:25:11 +0000
Subject: [PATCH 08/11] refactor

---
 clang/lib/Analysis/LifetimeSafety/Checker.cpp | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 3181caff4a5e8..2f92622da33ad 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -67,7 +67,7 @@ class LifetimeChecker {
   FactManager &FactMgr;
   LifetimeSafetySemaHelper *SemaHelper;
   ASTContext &AST;
-  const Decl *D;
+  const Decl *FD;
 
   static SourceLocation
   GetFactLoc(llvm::PointerUnion<const UseFact *, const OriginEscapesFact *> F) 
{
@@ -90,7 +90,7 @@ class LifetimeChecker {
                   LifetimeSafetySemaHelper *SemaHelper)
       : LoanPropagation(LoanPropagation), MovedLoans(MovedLoans),
         LiveOrigins(LiveOrigins), FactMgr(FM), SemaHelper(SemaHelper),
-        AST(ADC.getASTContext()), D(ADC.getDecl()) {
+        AST(ADC.getASTContext()), FD(ADC.getDecl()) {
     for (const CFGBlock *B : *ADC.getAnalysis<PostOrderCFGView>())
       for (const Fact *F : FactMgr.getFacts(B))
         if (const auto *EF = F->getAs<ExpireFact>())
@@ -130,9 +130,9 @@ class LifetimeChecker {
       if (!PVD->hasAttr<LifetimeBoundAttr>()) {
         if (auto *ReturnEsc = dyn_cast<ReturnEscapeFact>(OEF))
           AnnotationWarningsMap.try_emplace(PVD, ReturnEsc->getReturnExpr());
-        else if (auto *FieldEsc = dyn_cast<FieldEscapeFact>(OEF))
-          if (isa<CXXConstructorDecl>(D))
-            AnnotationWarningsMap.try_emplace(PVD, FieldEsc->getFieldDecl());
+        else if (auto *FieldEsc = dyn_cast<FieldEscapeFact>(OEF);
+                 FieldEsc && isa<CXXConstructorDecl>(FD))
+          AnnotationWarningsMap.try_emplace(PVD, FieldEsc->getFieldDecl());
       }
       // TODO: Suggest lifetime_capture_by(this) for parameter escaping to a
       // field!

>From 17d50549d173a4904bf9c08c82599ba09e4a7d5d Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sun, 12 Apr 2026 11:34:46 +0000
Subject: [PATCH 09/11] Refactor EscapingTarget

---
 .../Analyses/LifetimeSafety/LifetimeSafety.h      |  9 ++++++---
 clang/lib/Analysis/LifetimeSafety/Checker.cpp     | 15 +++++----------
 clang/lib/Sema/SemaLifetimeSafety.h               |  6 +++---
 3 files changed, 14 insertions(+), 16 deletions(-)

diff --git 
a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h 
b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
index 412c28c6587eb..83c3c455c4c81 100644
--- a/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
+++ b/clang/include/clang/Analysis/Analyses/LifetimeSafety/LifetimeSafety.h
@@ -89,10 +89,13 @@ class LifetimeSafetySemaHelper {
                                           const Expr *UseExpr,
                                           const Expr *InvalidationExpr) {}
 
+  using EscapingTarget =
+      llvm::PointerUnion<const Expr *, const FieldDecl *, const VarDecl *>;
+
   // Suggests lifetime bound annotations for function parameters.
-  virtual void suggestLifetimeboundToParmVar(
-      SuggestionScope Scope, const ParmVarDecl *ParmToAnnotate,
-      llvm::PointerUnion<const Expr *, const FieldDecl *> Target) {}
+  virtual void suggestLifetimeboundToParmVar(SuggestionScope Scope,
+                                             const ParmVarDecl *ParmToAnnotate,
+                                             EscapingTarget Target) {}
 
   // Reports misuse of [[clang::noescape]] when parameter escapes through 
return
   virtual void reportNoescapeViolation(const ParmVarDecl *ParmWithNoescape,
diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index 2f92622da33ad..f82caedcbe044 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -53,8 +53,7 @@ struct PendingWarning {
 
 using AnnotationTarget =
     llvm::PointerUnion<const ParmVarDecl *, const CXXMethodDecl *>;
-using EscapingTarget =
-    llvm::PointerUnion<const Expr *, const FieldDecl *, const VarDecl *>;
+using EscapingTarget = LifetimeSafetySemaHelper::EscapingTarget;
 
 class LifetimeChecker {
 private:
@@ -298,21 +297,17 @@ class LifetimeChecker {
                                          const ParmVarDecl *PVD,
                                          SourceManager &SM,
                                          EscapingTarget EscapeTarget) {
-    llvm::PointerUnion<const Expr *, const FieldDecl *> Target;
-    if (const auto *E = EscapeTarget.dyn_cast<const Expr *>())
-      Target = E;
-    else if (const auto *F = EscapeTarget.dyn_cast<const FieldDecl *>())
-      Target = F;
-    else
+    if (llvm::isa<const VarDecl *>(EscapeTarget))
       return;
 
     if (const FunctionDecl *CrossTUDecl = getCrossTUDecl(*PVD, SM))
       SemaHelper->suggestLifetimeboundToParmVar(
           SuggestionScope::CrossTU,
-          CrossTUDecl->getParamDecl(PVD->getFunctionScopeIndex()), Target);
+          CrossTUDecl->getParamDecl(PVD->getFunctionScopeIndex()),
+          EscapeTarget);
     else
       SemaHelper->suggestLifetimeboundToParmVar(SuggestionScope::IntraTU, PVD,
-                                                Target);
+                                                EscapeTarget);
   }
 
   static void
diff --git a/clang/lib/Sema/SemaLifetimeSafety.h 
b/clang/lib/Sema/SemaLifetimeSafety.h
index add2490be497e..c56a9692abe1a 100644
--- a/clang/lib/Sema/SemaLifetimeSafety.h
+++ b/clang/lib/Sema/SemaLifetimeSafety.h
@@ -131,9 +131,9 @@ class LifetimeSafetySemaHelperImpl : public 
LifetimeSafetySemaHelper {
         << UseExpr->getSourceRange();
   }
 
-  void suggestLifetimeboundToParmVar(
-      SuggestionScope Scope, const ParmVarDecl *ParmToAnnotate,
-      llvm::PointerUnion<const Expr *, const FieldDecl *> Target) override {
+  void suggestLifetimeboundToParmVar(SuggestionScope Scope,
+                                     const ParmVarDecl *ParmToAnnotate,
+                                     EscapingTarget Target) override {
     unsigned DiagID =
         (Scope == SuggestionScope::CrossTU)
             ? diag::warn_lifetime_safety_cross_tu_param_suggestion

>From c73e396dc8330e3aaa5a0540b28ac8ca51b0985e Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sun, 12 Apr 2026 11:38:15 +0000
Subject: [PATCH 10/11] doc update

---
 clang/lib/Analysis/LifetimeSafety/Checker.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Analysis/LifetimeSafety/Checker.cpp 
b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
index f82caedcbe044..fe103739dbcb0 100644
--- a/clang/lib/Analysis/LifetimeSafety/Checker.cpp
+++ b/clang/lib/Analysis/LifetimeSafety/Checker.cpp
@@ -125,7 +125,8 @@ class LifetimeChecker {
           NoescapeWarningsMap.try_emplace(PVD, GlobalEsc->getGlobal());
         return;
       }
-      // Suggest lifetimebound for parameter escaping through return.
+      // Suggest lifetimebound for parameter escaping through return or a field
+      // in constructor.
       if (!PVD->hasAttr<LifetimeBoundAttr>()) {
         if (auto *ReturnEsc = dyn_cast<ReturnEscapeFact>(OEF))
           AnnotationWarningsMap.try_emplace(PVD, ReturnEsc->getReturnExpr());

>From f2e9ba03a24e9bc58528e5ad0f753efdcb016d49 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena <[email protected]>
Date: Sun, 12 Apr 2026 11:48:52 +0000
Subject: [PATCH 11/11] more tests

---
 .../Sema/warn-lifetime-safety-suggestions.cpp | 66 ++++++++++++-------
 1 file changed, 43 insertions(+), 23 deletions(-)

diff --git a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp 
b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
index 4f62dd608e814..ee3ed7f385faf 100644
--- a/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
+++ b/clang/test/Sema/warn-lifetime-safety-suggestions.cpp
@@ -481,39 +481,59 @@ void test_inference() {
 } // namespace make_unique_suggestion
 
 namespace capturing_constructor {
-struct A {
+struct CaptureRefToView {
   View v; // expected-note {{escapes to this field}}
-  A(const MyObj& obj) : v(obj) {} // expected-warning {{parameter in intra-TU 
function should be marked [[clang::lifetimebound]]}}
+  CaptureRefToView(const MyObj& obj) : v(obj) {} // expected-warning 
{{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
 };
 
-struct B {
-  const int* p; // expected-note {{escapes to this field}}
-  B(const int& r) : p(&r) {} // expected-warning {{parameter in intra-TU 
function should be marked [[clang::lifetimebound]]}}
+CaptureRefToView test_ref_to_view() {
+  MyObj obj;
+  CaptureRefToView x(obj); // expected-warning {{address of stack memory is 
returned later}}
+  return x; // expected-note {{returned here}}
+}
+
+struct CaptureRefToPtr {
+  const MyObj* p; // expected-note {{escapes to this field}}
+  CaptureRefToPtr(const MyObj& obj) : p(&obj) {} // expected-warning 
{{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
 };
 
-struct C {
+CaptureRefToPtr test_ref_to_ptr() {
+  MyObj obj;
+  CaptureRefToPtr x(obj); // expected-warning {{address of stack memory is 
returned later}}
+  return x; // expected-note {{returned here}}
+}
+
+struct CaptureViewToView {
   View v; // expected-note {{escapes to this field}}
-  C(View v_param) : v(v_param) {} // expected-warning {{parameter in intra-TU 
function should be marked [[clang::lifetimebound]]}}
+  CaptureViewToView(View v_param) : v(v_param) {} // expected-warning 
{{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
 };
 
-struct D {
-  const int* p; // expected-note {{escapes to this field}}
-  D(const int* p_param) : p(p_param) {} // expected-warning {{parameter in 
intra-TU function should be marked [[clang::lifetimebound]]}}
-};
-} // namespace capturing_constructor
+CaptureViewToView test_view_to_view() {
+  MyObj obj;
+  View v(obj); // expected-warning {{address of stack memory is returned 
later}}
+  CaptureViewToView x(v);
+  return x; // expected-note {{returned here}}
+}
 
-namespace capturing_constructor_inference {
-struct B {
+struct CapturePtrToPtr {
   const MyObj* p; // expected-note {{escapes to this field}}
-  B(const MyObj& obj) : p(&obj) {} // expected-warning {{parameter in intra-TU 
function should be marked [[clang::lifetimebound]]}}
+  CapturePtrToPtr(const MyObj* p_param) : p(p_param) {} // expected-warning 
{{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
 };
 
-void test(B& b_out) {
-  {
-    MyObj obj;
-    B b(obj); // expected-warning {{object whose reference is captured does 
not live long enough}}
-    b_out = b;
-  } // expected-note {{destroyed here}}
-  (void)b_out; // expected-note {{later used here}}
+CapturePtrToPtr test_ptr_to_ptr() {
+  MyObj obj;
+  CapturePtrToPtr x(&obj); // expected-warning {{address of stack memory is 
returned later}}
+  return x; // expected-note {{returned here}}
+}
+
+struct CaptureRefToRef {
+  const MyObj& r; // expected-note {{escapes to this field}}
+  CaptureRefToRef(const MyObj& obj) : r(obj) {} // expected-warning 
{{parameter in intra-TU function should be marked [[clang::lifetimebound]]}}
+};
+
+CaptureRefToRef test_ref_to_ref() {
+  MyObj obj;
+  CaptureRefToRef x(obj); // expected-warning {{address of stack memory is 
returned later}}
+  return x; // expected-note {{returned here}}
 }
-} // namespace capturing_constructor_inference
+} // namespace capturing_constructor

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to