@@ -45,10 +45,14 @@ enum LifetimeKind {
45
45
// / a default member initializer), the program is ill-formed.
46
46
LK_MemInitializer,
47
47
48
- // / The lifetime of a temporary bound to this entity probably ends too soon,
48
+ // / The lifetime of a temporary bound to this entity may end too soon,
49
49
// / because the entity is a pointer and we assign the address of a temporary
50
50
// / object to it.
51
51
LK_Assignment,
52
+
53
+ // / The lifetime of a temporary bound to this entity may end too soon,
54
+ // / because the entity may capture the reference to a temporary object.
55
+ LK_LifetimeCapture,
52
56
};
53
57
using LifetimeResult =
54
58
llvm::PointerIntPair<const InitializedEntity *, 3 , LifetimeKind>;
@@ -1108,13 +1112,14 @@ static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef,
1108
1112
isAssignmentOperatorLifetimeBound (Entity.AssignmentOperator )));
1109
1113
}
1110
1114
1111
- static void checkExprLifetimeImpl (Sema &SemaRef,
1112
- const InitializedEntity *InitEntity,
1113
- const InitializedEntity *ExtendingEntity,
1114
- LifetimeKind LK,
1115
- const AssignedEntity *AEntity, Expr *Init) {
1116
- assert ((AEntity && LK == LK_Assignment) ||
1117
- (InitEntity && LK != LK_Assignment));
1115
+ static void
1116
+ checkExprLifetimeImpl (Sema &SemaRef, const InitializedEntity *InitEntity,
1117
+ const InitializedEntity *ExtendingEntity, LifetimeKind LK,
1118
+ const AssignedEntity *AEntity,
1119
+ const CapturingEntity *CapEntity, Expr *Init) {
1120
+ assert (!AEntity || LK == LK_Assignment);
1121
+ assert (!CapEntity || LK == LK_LifetimeCapture);
1122
+ assert (!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1118
1123
// If this entity doesn't have an interesting lifetime, don't bother looking
1119
1124
// for temporaries within its initializer.
1120
1125
if (LK == LK_FullExpression)
@@ -1197,12 +1202,23 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
1197
1202
break ;
1198
1203
}
1199
1204
1205
+ case LK_LifetimeCapture: {
1206
+ // The captured entity has lifetime beyond the full-expression,
1207
+ // and the capturing entity does too, so don't warn.
1208
+ if (!MTE)
1209
+ return false ;
1210
+ if (CapEntity->Entity )
1211
+ SemaRef.Diag (DiagLoc, diag::warn_dangling_reference_captured)
1212
+ << CapEntity->Entity << DiagRange;
1213
+ else
1214
+ SemaRef.Diag (DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1215
+ << DiagRange;
1216
+ return false ;
1217
+ }
1218
+
1200
1219
case LK_Assignment: {
1201
1220
if (!MTE || pathContainsInit (Path))
1202
1221
return false ;
1203
- assert (shouldLifetimeExtendThroughPath (Path) ==
1204
- PathLifetimeKind::NoExtend &&
1205
- " No lifetime extension for assignments" );
1206
1222
if (IsGslPtrValueFromGslTempOwner)
1207
1223
SemaRef.Diag (DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1208
1224
<< AEntity->LHS << DiagRange;
@@ -1411,13 +1427,23 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
1411
1427
};
1412
1428
1413
1429
llvm::SmallVector<IndirectLocalPathEntry, 8 > Path;
1414
- if (LK == LK_Assignment &&
1415
- shouldRunGSLAssignmentAnalysis (SemaRef, *AEntity)) {
1416
- Path.push_back (
1417
- {isAssignmentOperatorLifetimeBound (AEntity->AssignmentOperator )
1418
- ? IndirectLocalPathEntry::LifetimeBoundCall
1419
- : IndirectLocalPathEntry::GslPointerAssignment,
1420
- Init});
1430
+ switch (LK) {
1431
+ case LK_Assignment: {
1432
+ if (shouldRunGSLAssignmentAnalysis (SemaRef, *AEntity))
1433
+ Path.push_back (
1434
+ {isAssignmentOperatorLifetimeBound (AEntity->AssignmentOperator )
1435
+ ? IndirectLocalPathEntry::LifetimeBoundCall
1436
+ : IndirectLocalPathEntry::GslPointerAssignment,
1437
+ Init});
1438
+ break ;
1439
+ }
1440
+ case LK_LifetimeCapture: {
1441
+ if (isPointerLikeType (Init->getType ()))
1442
+ Path.push_back ({IndirectLocalPathEntry::GslPointerInit, Init});
1443
+ break ;
1444
+ }
1445
+ default :
1446
+ break ;
1421
1447
}
1422
1448
1423
1449
if (Init->isGLValue ())
@@ -1430,23 +1456,23 @@ static void checkExprLifetimeImpl(Sema &SemaRef,
1430
1456
/* RevisitSubinits=*/ !InitEntity);
1431
1457
}
1432
1458
1433
- void checkExprLifetime (Sema &SemaRef, const InitializedEntity &Entity,
1459
+ void checkInitLifetime (Sema &SemaRef, const InitializedEntity &Entity,
1434
1460
Expr *Init) {
1435
1461
auto LTResult = getEntityLifetime (&Entity);
1436
1462
LifetimeKind LK = LTResult.getInt ();
1437
1463
const InitializedEntity *ExtendingEntity = LTResult.getPointer ();
1438
1464
checkExprLifetimeImpl (SemaRef, &Entity, ExtendingEntity, LK,
1439
- /* AEntity*/ nullptr , Init);
1465
+ /* AEntity= */ nullptr , /* CapEntity= */ nullptr , Init);
1440
1466
}
1441
1467
1442
1468
void checkExprLifetimeMustTailArg (Sema &SemaRef,
1443
1469
const InitializedEntity &Entity, Expr *Init) {
1444
1470
checkExprLifetimeImpl (SemaRef, &Entity, nullptr , LK_MustTail,
1445
- /* AEntity*/ nullptr , Init);
1471
+ /* AEntity= */ nullptr , /* CapEntity= */ nullptr , Init);
1446
1472
}
1447
1473
1448
- void checkExprLifetime (Sema &SemaRef, const AssignedEntity &Entity,
1449
- Expr *Init) {
1474
+ void checkAssignmentLifetime (Sema &SemaRef, const AssignedEntity &Entity,
1475
+ Expr *Init) {
1450
1476
bool EnableDanglingPointerAssignment = !SemaRef.getDiagnostics ().isIgnored (
1451
1477
diag::warn_dangling_pointer_assignment, SourceLocation ());
1452
1478
bool RunAnalysis = (EnableDanglingPointerAssignment &&
@@ -1458,7 +1484,20 @@ void checkExprLifetime(Sema &SemaRef, const AssignedEntity &Entity,
1458
1484
1459
1485
checkExprLifetimeImpl (SemaRef, /* InitEntity=*/ nullptr ,
1460
1486
/* ExtendingEntity=*/ nullptr , LK_Assignment, &Entity,
1461
- Init);
1487
+ /* CapEntity=*/ nullptr , Init);
1488
+ }
1489
+
1490
+ void checkCaptureByLifetime (Sema &SemaRef, const CapturingEntity &Entity,
1491
+ Expr *Init) {
1492
+ if (SemaRef.getDiagnostics ().isIgnored (diag::warn_dangling_reference_captured,
1493
+ SourceLocation ()) &&
1494
+ SemaRef.getDiagnostics ().isIgnored (
1495
+ diag::warn_dangling_reference_captured_by_unknown, SourceLocation ()))
1496
+ return ;
1497
+ return checkExprLifetimeImpl (SemaRef, /* InitEntity=*/ nullptr ,
1498
+ /* ExtendingEntity=*/ nullptr , LK_LifetimeCapture,
1499
+ /* AEntity=*/ nullptr ,
1500
+ /* CapEntity=*/ &Entity, Init);
1462
1501
}
1463
1502
1464
1503
} // namespace clang::sema
0 commit comments