@@ -481,6 +481,9 @@ namespace {
481
481
bool isInitializedAtUse (const DIMemoryUse &Use,
482
482
bool *SuperInitDone = nullptr ,
483
483
bool *FailedSelfUse = nullptr );
484
+
485
+ bool hasUninitializedMemberAtInst (SILInstruction *Inst, unsigned FirstElt,
486
+ unsigned NumElts);
484
487
485
488
void handleStoreUse (unsigned UseID);
486
489
void handleInOutUse (const DIMemoryUse &Use);
@@ -1329,13 +1332,23 @@ void LifetimeChecker::handleLoadUseFailure(const DIMemoryUse &Use,
1329
1332
return ;
1330
1333
}
1331
1334
1335
+ SILLocation Loc = Inst->getLoc ();
1336
+
1337
+ // Try to find the return location
1338
+ auto TermLoc = Inst->getParent ()->getTerminator ()->getLoc ();
1339
+ if (TermLoc.getKind () == SILLocation::ReturnKind) {
1340
+ Loc = TermLoc;
1341
+ }
1342
+
1332
1343
// If this is a load with a single user that is a return (and optionally a
1333
1344
// retain_value for non-trivial structs/enums), then this is a return in the
1334
1345
// enum/struct init case, and we haven't stored to self. Emit a specific
1335
1346
// diagnostic.
1336
1347
if (auto *LI = dyn_cast<LoadInst>(Inst)) {
1337
1348
bool hasReturnUse = false , hasUnknownUses = false ;
1338
1349
1350
+ auto *LoadBB = LI->getParent ();
1351
+
1339
1352
for (auto LoadUse : LI->getUses ()) {
1340
1353
auto *User = LoadUse->getUser ();
1341
1354
@@ -1349,6 +1362,18 @@ void LifetimeChecker::handleLoadUseFailure(const DIMemoryUse &Use,
1349
1362
1350
1363
if (auto *EI = dyn_cast<EnumInst>(User))
1351
1364
if (isFailableInitReturnUseOfEnum (EI)) {
1365
+ // Try to find the return location
1366
+ for (auto Pred : LoadBB->getPreds ()) {
1367
+ auto *TI = Pred->getTerminator ();
1368
+ auto TermLoc = TI->getLoc ();
1369
+
1370
+ // Check if this is an early return with uninitialized members
1371
+ if (TermLoc.getKind () == SILLocation::ReturnKind &&
1372
+ hasUninitializedMemberAtInst (TI, Use.FirstElement ,
1373
+ Use.NumElements ))
1374
+ Loc = TermLoc;
1375
+ }
1376
+
1352
1377
hasReturnUse = true ;
1353
1378
continue ;
1354
1379
}
@@ -1360,13 +1385,13 @@ void LifetimeChecker::handleLoadUseFailure(const DIMemoryUse &Use,
1360
1385
if (hasReturnUse && !hasUnknownUses) {
1361
1386
if (TheMemory.isEnumInitSelf ()) {
1362
1387
if (!shouldEmitError (Inst)) return ;
1363
- diagnose (Module, Inst-> getLoc () ,
1388
+ diagnose (Module, Loc ,
1364
1389
diag::return_from_init_without_initing_self);
1365
1390
return ;
1366
1391
} else if (TheMemory.isAnyInitSelf () && !TheMemory.isClassInitSelf () &&
1367
1392
!TheMemory.isDelegatingInit ()) {
1368
1393
if (!shouldEmitError (Inst)) return ;
1369
- diagnose (Module, Inst-> getLoc () ,
1394
+ diagnose (Module, Loc ,
1370
1395
diag::return_from_init_without_initing_stored_properties);
1371
1396
noteUninitializedMembers (Use);
1372
1397
return ;
@@ -2446,6 +2471,21 @@ bool LifetimeChecker::isInitializedAtUse(const DIMemoryUse &Use,
2446
2471
return true ;
2447
2472
}
2448
2473
2474
+ bool LifetimeChecker::hasUninitializedMemberAtInst (SILInstruction *Inst,
2475
+ unsigned FirstElt,
2476
+ unsigned NumElts) {
2477
+ // Determine the liveness states of the elements that we care about.
2478
+ AvailabilitySet Liveness =
2479
+ getLivenessAtInst (Inst, FirstElt, NumElts);
2480
+
2481
+ // Find unintialized member
2482
+ for (unsigned i = FirstElt, e = i+NumElts;
2483
+ i != e; ++i)
2484
+ if (Liveness.get (i) != DIKind::Yes)
2485
+ return true ;
2486
+
2487
+ return false ;
2488
+ }
2449
2489
2450
2490
2451
2491
0 commit comments