@@ -3873,62 +3873,106 @@ findSimilarFunction(DeclNameRef replacedFunctionName,
3873
3873
// Note: we might pass a constant attribute when typechecker is nullptr.
3874
3874
// Any modification to attr must be guarded by a null check on TC.
3875
3875
//
3876
- SmallVector<ValueDecl *, 4> results ;
3877
- lookupReplacedDecl(replacedFunctionName, attr, base, results );
3876
+ SmallVector<ValueDecl *, 4> lookupResults ;
3877
+ lookupReplacedDecl(replacedFunctionName, attr, base, lookupResults );
3878
3878
3879
- for (auto *result : results) {
3879
+ SmallVector<AbstractFunctionDecl *, 4> candidates;
3880
+ for (auto *result : lookupResults) {
3880
3881
// Protocol requirements are not replaceable.
3881
3882
if (isa<ProtocolDecl>(result->getDeclContext()))
3882
3883
continue;
3883
3884
// Check for static/instance mismatch.
3884
3885
if (result->isStatic() != base->isStatic())
3885
3886
continue;
3886
3887
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();
3900
3948
}
3901
- return cast<AbstractFunctionDecl>(result) ;
3949
+ return nullptr ;
3902
3950
}
3951
+
3952
+ return result;
3903
3953
}
3904
3954
3955
+ attr->setInvalid();
3956
+
3905
3957
if (!Diags)
3906
3958
return nullptr;
3907
3959
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());
3921
3966
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());
3930
3974
}
3931
- attr->setInvalid();
3975
+
3932
3976
return nullptr;
3933
3977
}
3934
3978
0 commit comments