@@ -190,9 +190,8 @@ void FactsGenerator::VisitCXXConstructExpr(const CXXConstructExpr *CCE) {
190190 return ;
191191 }
192192 // For defaulted (implicit or `= default`) copy/move constructors, propagate
193- // origins directly. User-defined copy/move constructors have opaque semantics
194- // and fall through to `handleFunctionCall`, where [[clang::lifetimebound]] is
195- // needed to propagate origins.
193+ // origins directly. User-defined copy/move constructors are not handled here
194+ // as they have opaque semantics.
196195 if (CCE->getConstructor ()->isCopyOrMoveConstructor () &&
197196 CCE->getConstructor ()->isDefaulted () && CCE->getNumArgs () == 1 &&
198197 hasOrigins (CCE->getType ())) {
@@ -202,6 +201,16 @@ void FactsGenerator::VisitCXXConstructExpr(const CXXConstructExpr *CCE) {
202201 return ;
203202 }
204203 }
204+ // Standard library callable wrappers (e.g., std::function) propagate the
205+ // stored lambda's origins.
206+ if (const auto *RD = CCE->getType ()->getAsCXXRecordDecl ();
207+ RD && isStdCallableWrapperType (RD) && CCE->getNumArgs () == 1 ) {
208+ const Expr *Arg = CCE->getArg (0 );
209+ if (OriginList *ArgList = getRValueOrigins (Arg, getOriginsList (*Arg))) {
210+ flow (getOriginsList (*CCE), ArgList, /* Kill=*/ true );
211+ return ;
212+ }
213+ }
205214 handleFunctionCall (CCE, CCE->getConstructor (),
206215 {CCE->getArgs (), CCE->getNumArgs ()},
207216 /* IsGslConstruction=*/ false );
@@ -400,6 +409,15 @@ void FactsGenerator::handleAssignment(const Expr *LHSExpr,
400409 } else
401410 markUseAsWrite (DRE_LHS);
402411 }
412+ if (!RHSList) {
413+ // RHS has no tracked origins (e.g., assigning a callable without origins
414+ // to std::function). Clear loans of the destination.
415+ for (OriginList *LHSInner = LHSList->peelOuterOrigin (); LHSInner;
416+ LHSInner = LHSInner->peelOuterOrigin ())
417+ CurrentBlockFacts.push_back (
418+ FactMgr.createFact <KillOriginFact>(LHSInner->getOuterOriginID ()));
419+ return ;
420+ }
403421 // Kill the old loans of the destination origin and flow the new loans
404422 // from the source origin.
405423 flow (LHSList->peelOuterOrigin (), RHSList, /* Kill=*/ true );
@@ -493,6 +511,13 @@ void FactsGenerator::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE) {
493511 handleAssignment (OCE->getArg (0 ), OCE->getArg (1 ));
494512 return ;
495513 }
514+ // Standard library callable wrappers (e.g., std::function) can propagate
515+ // the stored lambda's origins.
516+ if (const auto *RD = LHSTy->getAsCXXRecordDecl ();
517+ RD && isStdCallableWrapperType (RD)) {
518+ handleAssignment (OCE->getArg (0 ), OCE->getArg (1 ));
519+ return ;
520+ }
496521 // Other tracked types: only defaulted operator= propagates origins.
497522 // User-defined operator= has opaque semantics, so don't handle them now.
498523 if (const auto *MD =
0 commit comments