@@ -2294,56 +2294,6 @@ namespace {
22942294 }
22952295
22962296 if (auto MD = dyn_cast<FuncDecl>(member)) {
2297- if (auto cxxMethod = dyn_cast<clang::CXXMethodDecl>(m)) {
2298- ImportedName methodImportedName =
2299- Impl.importFullName (cxxMethod, getActiveSwiftVersion ());
2300- auto cxxOperatorKind = cxxMethod->getOverloadedOperator ();
2301-
2302- if (cxxOperatorKind == clang::OverloadedOperatorKind::OO_PlusPlus) {
2303- // Make sure the type is not a foreign reference type.
2304- // We cannot handle `operator++` for those types, since the
2305- // current implementation creates a new instance of the type.
2306- if (cxxMethod->param_empty () && !isa<ClassDecl>(result)) {
2307- // This is a pre-increment operator. We synthesize a
2308- // non-mutating function called `successor() -> Self`.
2309- FuncDecl *successorFunc = synthesizer.makeSuccessorFunc (MD);
2310- result->addMember (successorFunc);
2311-
2312- Impl.markUnavailable (MD, " use .successor()" );
2313- } else {
2314- Impl.markUnavailable (MD, " unable to create .successor() func" );
2315- }
2316- MD->overwriteAccess (AccessLevel::Private);
2317- }
2318- // Check if this method _is_ an overloaded operator but is not a
2319- // call / subscript / dereference / increment. Those
2320- // operators do not need static versions.
2321- else if (cxxOperatorKind !=
2322- clang::OverloadedOperatorKind::OO_None &&
2323- cxxOperatorKind !=
2324- clang::OverloadedOperatorKind::OO_PlusPlus &&
2325- cxxOperatorKind !=
2326- clang::OverloadedOperatorKind::OO_Call &&
2327- !methodImportedName.isSubscriptAccessor () &&
2328- !methodImportedName.isDereferenceAccessor ()) {
2329-
2330- auto opFuncDecl = synthesizer.makeOperator (MD, cxxMethod);
2331-
2332- Impl.addAlternateDecl (MD, opFuncDecl);
2333-
2334- auto msg = " use " + std::string{clang::getOperatorSpelling (cxxOperatorKind)} + " instead" ;
2335- Impl.markUnavailable (MD,msg);
2336-
2337- // Make the actual member operator private.
2338- MD->overwriteAccess (AccessLevel::Private);
2339-
2340- // Make sure the synthesized decl can be found by lookupDirect.
2341- result->addMemberToLookupTable (opFuncDecl);
2342-
2343- addEntryToLookupTable (*Impl.findLookupTable (decl), cxxMethod,
2344- Impl.getNameImporter ());
2345- }
2346- }
23472297 methods.push_back (MD);
23482298 continue ;
23492299 }
@@ -3005,6 +2955,21 @@ namespace {
30052955 if (isSpecializationDepthGreaterThan (def, 8 ))
30062956 return nullptr ;
30072957
2958+ // For class template instantiations, we need to add their member
2959+ // operators to the lookup table to make them discoverable with
2960+ // unqualified lookup. This makes it possible to implement a Swift
2961+ // protocol requirement with an instantiation of a C++ member operator.
2962+ // This cannot be done when building the lookup table,
2963+ // because templates are instantiated lazily.
2964+ for (auto member : def->decls ()) {
2965+ if (auto method = dyn_cast<clang::CXXMethodDecl>(member)) {
2966+ if (method->isOverloadedOperator ()) {
2967+ addEntryToLookupTable (*Impl.findLookupTable (decl), method,
2968+ Impl.getNameImporter ());
2969+ }
2970+ }
2971+ }
2972+
30082973 return VisitCXXRecordDecl (def);
30092974 }
30102975
@@ -3263,12 +3228,19 @@ namespace {
32633228 }
32643229
32653230 // / Handles special functions such as subscripts and dereference operators.
3266- bool processSpecialImportedFunc (FuncDecl *func, ImportedName importedName) {
3231+ bool
3232+ processSpecialImportedFunc (FuncDecl *func, ImportedName importedName,
3233+ clang::OverloadedOperatorKind cxxOperatorKind) {
3234+ if (cxxOperatorKind == clang::OverloadedOperatorKind::OO_None)
3235+ return true ;
3236+
32673237 auto dc = func->getDeclContext ();
3238+ auto typeDecl = dc->getSelfNominalTypeDecl ();
3239+ if (!typeDecl)
3240+ return true ;
32683241
32693242 if (importedName.isSubscriptAccessor ()) {
32703243 assert (func->getParameters ()->size () == 1 );
3271- auto typeDecl = dc->getSelfNominalTypeDecl ();
32723244 auto parameter = func->getParameters ()->get (0 );
32733245 auto parameterType = parameter->getTypeInContext ();
32743246 if (!typeDecl || !parameterType)
@@ -3298,10 +3270,10 @@ namespace {
32983270 }
32993271
33003272 Impl.markUnavailable (func, " use subscript" );
3273+ return true ;
33013274 }
33023275
33033276 if (importedName.isDereferenceAccessor ()) {
3304- auto typeDecl = dc->getSelfNominalTypeDecl ();
33053277 auto &getterAndSetter = Impl.cxxDereferenceOperators [typeDecl];
33063278
33073279 switch (importedName.getAccessorKind ()) {
@@ -3316,6 +3288,42 @@ namespace {
33163288 }
33173289
33183290 Impl.markUnavailable (func, " use .pointee property" );
3291+ return true ;
3292+ }
3293+
3294+ if (cxxOperatorKind == clang::OverloadedOperatorKind::OO_PlusPlus) {
3295+ // Make sure the type is not a foreign reference type.
3296+ // We cannot handle `operator++` for those types, since the
3297+ // current implementation creates a new instance of the type.
3298+ if (func->getParameters ()->size () == 0 && !isa<ClassDecl>(typeDecl)) {
3299+ // This is a pre-increment operator. We synthesize a
3300+ // non-mutating function called `successor() -> Self`.
3301+ FuncDecl *successorFunc = synthesizer.makeSuccessorFunc (func);
3302+ typeDecl->addMember (successorFunc);
3303+
3304+ Impl.markUnavailable (func, " use .successor()" );
3305+ } else {
3306+ Impl.markUnavailable (func, " unable to create .successor() func" );
3307+ }
3308+ func->overwriteAccess (AccessLevel::Private);
3309+ return true ;
3310+ }
3311+
3312+ // Check if this method _is_ an overloaded operator but is not a
3313+ // call / subscript / dereference / increment. Those
3314+ // operators do not need static versions.
3315+ if (cxxOperatorKind != clang::OverloadedOperatorKind::OO_Call) {
3316+ auto opFuncDecl = synthesizer.makeOperator (func, cxxOperatorKind);
3317+ Impl.addAlternateDecl (func, opFuncDecl);
3318+
3319+ Impl.markUnavailable (
3320+ func, (Twine (" use " ) + clang::getOperatorSpelling (cxxOperatorKind) +
3321+ " instead" )
3322+ .str ());
3323+
3324+ // Make sure the synthesized decl can be found by lookupDirect.
3325+ typeDecl->addMemberToLookupTable (opFuncDecl);
3326+ return true ;
33193327 }
33203328
33213329 return true ;
@@ -3644,7 +3652,8 @@ namespace {
36443652 func->setAccess (AccessLevel::Public);
36453653
36463654 if (!importFuncWithoutSignature) {
3647- bool success = processSpecialImportedFunc (func, importedName);
3655+ bool success = processSpecialImportedFunc (
3656+ func, importedName, decl->getOverloadedOperator ());
36483657 if (!success)
36493658 return nullptr ;
36503659 }
@@ -4024,6 +4033,12 @@ namespace {
40244033 if (!importedDC)
40254034 return nullptr ;
40264035
4036+ // While importing the DeclContext, we might have imported the decl
4037+ // itself.
4038+ auto known = Impl.importDeclCached (decl, getVersion ());
4039+ if (known.has_value ())
4040+ return known.value ();
4041+
40274042 if (isa<clang::TypeDecl>(decl->getTargetDecl ())) {
40284043 Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
40294044 if (!SwiftDecl)
@@ -4072,7 +4087,8 @@ namespace {
40724087 if (!clonedMethod)
40734088 return nullptr ;
40744089
4075- bool success = processSpecialImportedFunc (clonedMethod, importedName);
4090+ bool success = processSpecialImportedFunc (
4091+ clonedMethod, importedName, targetMethod->getOverloadedOperator ());
40764092 if (!success)
40774093 return nullptr ;
40784094
0 commit comments