@@ -434,38 +434,53 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
434
434
<< " \n has unexpected copying instruction: " << *inst);
435
435
436
436
// Try to come up with a useful diagnostic.
437
+
438
+ // First, identify what is being copied.
439
+ SILValue copied;
437
440
if (auto svi = dyn_cast<SingleValueInstruction>(inst)) {
438
- if (auto name = VariableNameInferrer::inferName (svi)) {
439
- // Simplistic check for whether this is a closure capture.
440
- for (auto user : svi->getUsers ()) {
441
- if (isa<PartialApplyInst>(user)) {
442
- LLVM_DEBUG (llvm::dbgs () << " captured by " << *user);
443
- diagnose (loc, diag::manualownership_copy_captured, *name);
444
- return false ;
445
- }
446
- }
441
+ copied = svi;
442
+ } else if (auto cai = dyn_cast<CopyAddrInst>(inst)) {
443
+ copied = cai->getSrc ();
444
+ }
447
445
448
- // There's no hope of borrowing access if there's a consuming use .
449
- for ( auto op : svi-> getUses ()) {
450
- auto useKind = op-> getOperandOwnership ();
451
-
452
- // Only some DestroyingConsume's, like 'store', are interesting.
453
- if (useKind == OperandOwnership::ForwardingConsume
454
- || isa<StoreInst>(op-> getUser ())) {
455
- LLVM_DEBUG ( llvm::dbgs () << " demanded by " << *(op-> getUser ()) );
456
- diagnose (loc, diag::manualownership_copy_demanded, *name) ;
457
- return false ;
458
- }
459
- }
446
+ // Find a name for that copied thing .
447
+ std::optional<Identifier> name;
448
+ if (copied)
449
+ name = VariableNameInferrer::inferName (copied);
450
+
451
+ if (!name) {
452
+ // Emit a rudimentary diagnostic.
453
+ diagnose (loc, diag::manualownership_copy );
454
+ return false ;
455
+ }
456
+
457
+ // Try to tailor the diagnostic based on usages.
460
458
461
- diagnose (loc, diag::manualownership_copy_happened, *name);
459
+ // Simplistic check for whether this is a closure capture.
460
+ for (auto user : copied->getUsers ()) {
461
+ if (isa<PartialApplyInst>(user)) {
462
+ LLVM_DEBUG (llvm::dbgs () << " captured by " << *user);
463
+ diagnose (loc, diag::manualownership_copy_captured, *name);
462
464
return false ;
463
465
}
464
466
}
465
467
466
- // Back-up diagnostic, when all-else fails.
467
- diagnose (loc, diag::manualownership_copy);
468
- return false ; // Don't bail-out early; diagnose more issues in the func.
468
+ // There's no hope of borrowing access if there's a consuming use.
469
+ for (auto op : copied->getUses ()) {
470
+ auto useKind = op->getOperandOwnership ();
471
+
472
+ // Only some DestroyingConsume's, like 'store', are interesting.
473
+ if (useKind == OperandOwnership::ForwardingConsume
474
+ || isa<StoreInst>(op->getUser ())) {
475
+ LLVM_DEBUG (llvm::dbgs () << " demanded by " << *(op->getUser ()));
476
+ diagnose (loc, diag::manualownership_copy_demanded, *name);
477
+ return false ;
478
+ }
479
+ }
480
+
481
+ // Catch-all diagnostic for when we at least have the name.
482
+ diagnose (loc, diag::manualownership_copy_happened, *name);
483
+ return false ;
469
484
}
470
485
}
471
486
return false ;
0 commit comments