@@ -3873,62 +3873,106 @@ findSimilarFunction(DeclNameRef replacedFunctionName,
38733873 // Note: we might pass a constant attribute when typechecker is nullptr.
38743874 // Any modification to attr must be guarded by a null check on TC.
38753875 //
3876- SmallVector<ValueDecl *, 4 > results ;
3877- lookupReplacedDecl (replacedFunctionName, attr, base, results );
3876+ SmallVector<ValueDecl *, 4 > lookupResults ;
3877+ lookupReplacedDecl (replacedFunctionName, attr, base, lookupResults );
38783878
3879- for (auto *result : results) {
3879+ SmallVector<AbstractFunctionDecl *, 4 > candidates;
3880+ for (auto *result : lookupResults) {
38803881 // Protocol requirements are not replaceable.
38813882 if (isa<ProtocolDecl>(result->getDeclContext ()))
38823883 continue ;
38833884 // Check for static/instance mismatch.
38843885 if (result->isStatic () != base->isStatic ())
38853886 continue ;
38863887
3887- auto resultTy = result->getInterfaceType ();
3888- auto replaceTy = base->getInterfaceType ();
3889- TypeMatchOptions matchMode = TypeMatchFlags::AllowABICompatible;
3890- matchMode |= TypeMatchFlags::AllowCompatibleOpaqueTypeArchetypes;
3891- if (resultTy->matches (replaceTy, matchMode)) {
3892- if (forDynamicReplacement && !result->isDynamic ()) {
3893- if (Diags) {
3894- Diags->diagnose (attr->getLocation (),
3895- diag::dynamic_replacement_function_not_dynamic,
3896- result->getName ());
3897- attr->setInvalid ();
3898- }
3899- return nullptr ;
3888+ if (auto *AFD = dyn_cast<AbstractFunctionDecl>(result))
3889+ candidates.push_back (AFD);
3890+ }
3891+
3892+ if (candidates.empty ()) {
3893+ if (Diags) {
3894+ Diags->diagnose (attr->getLocation (),
3895+ forDynamicReplacement
3896+ ? diag::dynamic_replacement_function_not_found
3897+ : diag::specialize_target_function_not_found,
3898+ replacedFunctionName);
3899+ }
3900+
3901+ attr->setInvalid ();
3902+ return nullptr ;
3903+ }
3904+
3905+ auto replaceTy = base->getInterfaceType ();
3906+
3907+ // Filter based on the exact type match first.
3908+ SmallVector<AbstractFunctionDecl *> matches;
3909+ llvm::copy_if (candidates, std::back_inserter (matches),
3910+ [&replaceTy](AbstractFunctionDecl *F) {
3911+ auto resultTy = F->getInterfaceType ();
3912+ TypeMatchOptions matchMode =
3913+ TypeMatchFlags::AllowABICompatible;
3914+ matchMode |=
3915+ TypeMatchFlags::AllowCompatibleOpaqueTypeArchetypes;
3916+ return resultTy->matches (replaceTy, matchMode);
3917+ });
3918+
3919+ // If there are no exact matches, strip sendability annotations
3920+ // from functions imported from Objective-C. This is a narrow
3921+ // fix for now but it could be extended to cover all `@preconcurrency`
3922+ // declarations.
3923+ if (matches.empty ()) {
3924+ llvm::copy_if (candidates, std::back_inserter (matches),
3925+ [&replaceTy](AbstractFunctionDecl *F) {
3926+ if (!F->hasClangNode ())
3927+ return false ;
3928+
3929+ auto resultTy = F->getInterfaceType ();
3930+ TypeMatchOptions matchMode =
3931+ TypeMatchFlags::AllowABICompatible;
3932+ matchMode |=
3933+ TypeMatchFlags::AllowCompatibleOpaqueTypeArchetypes;
3934+ matchMode |= TypeMatchFlags::IgnoreFunctionSendability;
3935+ matchMode |= TypeMatchFlags::IgnoreSendability;
3936+ return resultTy->matches (replaceTy, matchMode);
3937+ });
3938+ }
3939+
3940+ if (matches.size () == 1 ) {
3941+ auto result = matches.front ();
3942+ if (forDynamicReplacement && !result->isDynamic ()) {
3943+ if (Diags) {
3944+ Diags->diagnose (attr->getLocation (),
3945+ diag::dynamic_replacement_function_not_dynamic,
3946+ result->getName ());
3947+ attr->setInvalid ();
39003948 }
3901- return cast<AbstractFunctionDecl>(result) ;
3949+ return nullptr ;
39023950 }
3951+
3952+ return result;
39033953 }
39043954
3955+ attr->setInvalid ();
3956+
39053957 if (!Diags)
39063958 return nullptr ;
39073959
3908- if (results.empty ()) {
3909- Diags->diagnose (attr->getLocation (),
3910- forDynamicReplacement
3911- ? diag::dynamic_replacement_function_not_found
3912- : diag::specialize_target_function_not_found,
3913- replacedFunctionName);
3914- } else {
3915- Diags->diagnose (attr->getLocation (),
3916- forDynamicReplacement
3917- ? diag::dynamic_replacement_function_of_type_not_found
3918- : diag::specialize_target_function_of_type_not_found,
3919- replacedFunctionName,
3920- base->getInterfaceType ()->getCanonicalType ());
3960+ Diags->diagnose (attr->getLocation (),
3961+ forDynamicReplacement
3962+ ? diag::dynamic_replacement_function_of_type_not_found
3963+ : diag::specialize_target_function_of_type_not_found,
3964+ replacedFunctionName,
3965+ base->getInterfaceType ()->getCanonicalType ());
39213966
3922- for (auto *result : results) {
3923- Diags->diagnose (SourceLoc (),
3924- forDynamicReplacement
3925- ? diag::dynamic_replacement_found_function_of_type
3926- : diag::specialize_found_function_of_type,
3927- result->getName (),
3928- result->getInterfaceType ()->getCanonicalType ());
3929- }
3967+ for (auto *result : matches) {
3968+ Diags->diagnose (SourceLoc (),
3969+ forDynamicReplacement
3970+ ? diag::dynamic_replacement_found_function_of_type
3971+ : diag::specialize_found_function_of_type,
3972+ result->getName (),
3973+ result->getInterfaceType ()->getCanonicalType ());
39303974 }
3931- attr-> setInvalid ();
3975+
39323976 return nullptr ;
39333977}
39343978
0 commit comments