@@ -434,38 +434,53 @@ bool PerformanceDiagnostics::visitInst(SILInstruction *inst,
434434 << " \n has unexpected copying instruction: " << *inst);
435435
436436 // Try to come up with a useful diagnostic.
437+
438+ // First, identify what is being copied.
439+ SILValue copied;
437440 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+ }
447445
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.
460458
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);
462464 return false ;
463465 }
464466 }
465467
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 ;
469484 }
470485 }
471486 return false ;
0 commit comments