@@ -41,10 +41,14 @@ enum LifetimeKind {
4141 // / a default member initializer), the program is ill-formed.
4242 LK_MemInitializer,
4343
44- // / The lifetime of a temporary bound to this entity probably ends too soon,
44+ // / The lifetime of a temporary bound to this entity may end too soon,
4545 // / because the entity is a pointer and we assign the address of a temporary
4646 // / object to it.
4747 LK_Assignment,
48+
49+ // / The lifetime of a temporary bound to this entity probably ends too soon,
50+ // / because the entity may capture the reference to a temporary object.
51+ LK_LifetimeCapture,
4852};
4953using LifetimeResult =
5054 llvm::PointerIntPair<const InitializedEntity *, 3 , LifetimeKind>;
@@ -189,6 +193,7 @@ struct IndirectLocalPathEntry {
189193 VarInit,
190194 LValToRVal,
191195 LifetimeBoundCall,
196+ LifetimeCapture,
192197 TemporaryCopy,
193198 LambdaCaptureInit,
194199 GslReferenceInit,
@@ -898,6 +903,7 @@ static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I,
898903 case IndirectLocalPathEntry::AddressOf:
899904 case IndirectLocalPathEntry::LValToRVal:
900905 case IndirectLocalPathEntry::LifetimeBoundCall:
906+ case IndirectLocalPathEntry::LifetimeCapture:
901907 case IndirectLocalPathEntry::TemporaryCopy:
902908 case IndirectLocalPathEntry::GslReferenceInit:
903909 case IndirectLocalPathEntry::GslPointerInit:
@@ -928,6 +934,7 @@ static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path) {
928934 case IndirectLocalPathEntry::VarInit:
929935 case IndirectLocalPathEntry::AddressOf:
930936 case IndirectLocalPathEntry::LifetimeBoundCall:
937+ case IndirectLocalPathEntry::LifetimeCapture:
931938 continue ;
932939 case IndirectLocalPathEntry::GslPointerInit:
933940 case IndirectLocalPathEntry::GslReferenceInit:
@@ -948,21 +955,22 @@ static bool isAssignmentOperatorLifetimeBound(CXXMethodDecl *CMD) {
948955}
949956
950957static bool shouldRunGSLAssignmentAnalysis (const Sema &SemaRef,
951- const AssignedEntity &Entity) {
958+ const CapturingEntity &Entity) {
952959 bool EnableGSLAssignmentWarnings = !SemaRef.getDiagnostics ().isIgnored (
953960 diag::warn_dangling_lifetime_pointer_assignment, SourceLocation ());
954961 return (EnableGSLAssignmentWarnings &&
955- (isRecordWithAttr<PointerAttr>(Entity.LHS ->getType ()) ||
962+ (isRecordWithAttr<PointerAttr>(Entity.Expression ->getType ()) ||
956963 isAssignmentOperatorLifetimeBound (Entity.AssignmentOperator )));
957964}
958965
959966static void checkExprLifetimeImpl (Sema &SemaRef,
960967 const InitializedEntity *InitEntity,
961968 const InitializedEntity *ExtendingEntity,
962969 LifetimeKind LK,
963- const AssignedEntity *AEntity, Expr *Init) {
964- assert ((AEntity && LK == LK_Assignment) ||
965- (InitEntity && LK != LK_Assignment));
970+ const CapturingEntity *CEntity, Expr *Init) {
971+ assert (InitEntity || CEntity);
972+ assert (!CEntity || LK == LK_Assignment || LK == LK_LifetimeCapture);
973+ assert (!InitEntity || LK != LK_Assignment);
966974 // If this entity doesn't have an interesting lifetime, don't bother looking
967975 // for temporaries within its initializer.
968976 if (LK == LK_FullExpression)
@@ -1046,6 +1054,17 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
10461054 break ;
10471055 }
10481056
1057+ case LK_LifetimeCapture: {
1058+ if (!MTE)
1059+ return false ;
1060+ assert (shouldLifetimeExtendThroughPath (Path) ==
1061+ PathLifetimeKind::NoExtend &&
1062+ " No lifetime extension for in function calls" );
1063+ SemaRef.Diag (DiagLoc, diag::warn_dangling_reference_captured)
1064+ << CEntity->Expression << DiagRange;
1065+ return false ;
1066+ }
1067+
10491068 case LK_Assignment: {
10501069 if (!MTE || pathContainsInit (Path))
10511070 return false ;
@@ -1056,7 +1075,7 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
10561075 IsGslPtrValueFromGslTempOwner
10571076 ? diag::warn_dangling_lifetime_pointer_assignment
10581077 : diag::warn_dangling_pointer_assignment)
1059- << AEntity-> LHS << DiagRange;
1078+ << CEntity-> Expression << DiagRange;
10601079 return false ;
10611080 }
10621081 case LK_MemInitializer: {
@@ -1199,6 +1218,7 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
11991218 break ;
12001219
12011220 case IndirectLocalPathEntry::LifetimeBoundCall:
1221+ case IndirectLocalPathEntry::LifetimeCapture:
12021222 case IndirectLocalPathEntry::TemporaryCopy:
12031223 case IndirectLocalPathEntry::GslPointerInit:
12041224 case IndirectLocalPathEntry::GslReferenceInit:
@@ -1243,8 +1263,10 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
12431263 };
12441264
12451265 llvm::SmallVector<IndirectLocalPathEntry, 8 > Path;
1246- if (LK == LK_Assignment && shouldRunGSLAssignmentAnalysis (SemaRef, *AEntity ))
1266+ if (LK == LK_Assignment && shouldRunGSLAssignmentAnalysis (SemaRef, *CEntity ))
12471267 Path.push_back ({IndirectLocalPathEntry::GslPointerAssignment, Init});
1268+ else if (LK == LK_LifetimeCapture)
1269+ Path.push_back ({IndirectLocalPathEntry::LifetimeCapture, Init});
12481270
12491271 if (Init->isGLValue ())
12501272 visitLocalsRetainedByReferenceBinding (Path, Init, RK_ReferenceBinding,
@@ -1256,7 +1278,7 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
12561278 /* RevisitSubinits=*/ !InitEntity);
12571279}
12581280
1259- void checkExprLifetime (Sema &SemaRef, const InitializedEntity &Entity,
1281+ void checkInitLifetime (Sema &SemaRef, const InitializedEntity &Entity,
12601282 Expr *Init) {
12611283 auto LTResult = getEntityLifetime (&Entity);
12621284 LifetimeKind LK = LTResult.getInt ();
@@ -1265,20 +1287,26 @@ void checkExprLifetime(Sema &SemaRef, const InitializedEntity &Entity,
12651287 /* AEntity*/ nullptr , Init);
12661288}
12671289
1268- void checkExprLifetime (Sema &SemaRef, const AssignedEntity &Entity,
1269- Expr *Init ) {
1290+ void checkAssignmentLifetime (Sema &SemaRef, const CapturingEntity &Entity,
1291+ Expr *RHS ) {
12701292 bool EnableDanglingPointerAssignment = !SemaRef.getDiagnostics ().isIgnored (
12711293 diag::warn_dangling_pointer_assignment, SourceLocation ());
12721294 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1273- Entity.LHS ->getType ()->isPointerType ()) ||
1295+ Entity.Expression ->getType ()->isPointerType ()) ||
12741296 shouldRunGSLAssignmentAnalysis (SemaRef, Entity);
12751297
12761298 if (!RunAnalysis)
12771299 return ;
12781300
12791301 checkExprLifetimeImpl (SemaRef, /* InitEntity=*/ nullptr ,
12801302 /* ExtendingEntity=*/ nullptr , LK_Assignment, &Entity,
1281- Init );
1303+ RHS );
12821304}
12831305
1306+ void checkCaptureLifetime (Sema &SemaRef, const CapturingEntity &Entity,
1307+ Expr *Captured) {
1308+ checkExprLifetimeImpl (SemaRef, /* InitEntity=*/ nullptr ,
1309+ /* ExtendingEntity=*/ nullptr , LK_LifetimeCapture,
1310+ &Entity, Captured);
1311+ }
12841312} // namespace clang::sema
0 commit comments