https://github.com/usx95 created https://github.com/llvm/llvm-project/pull/191632
None >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 1/5] 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 2/5] 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 3/5] 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 4/5] 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 5/5] 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
