@@ -2294,56 +2294,6 @@ namespace {
2294
2294
}
2295
2295
2296
2296
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
- }
2347
2297
methods.push_back (MD);
2348
2298
continue ;
2349
2299
}
@@ -3005,6 +2955,21 @@ namespace {
3005
2955
if (isSpecializationDepthGreaterThan (def, 8 ))
3006
2956
return nullptr ;
3007
2957
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
+
3008
2973
return VisitCXXRecordDecl (def);
3009
2974
}
3010
2975
@@ -3263,12 +3228,19 @@ namespace {
3263
3228
}
3264
3229
3265
3230
// / 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
+
3267
3237
auto dc = func->getDeclContext ();
3238
+ auto typeDecl = dc->getSelfNominalTypeDecl ();
3239
+ if (!typeDecl)
3240
+ return true ;
3268
3241
3269
3242
if (importedName.isSubscriptAccessor ()) {
3270
3243
assert (func->getParameters ()->size () == 1 );
3271
- auto typeDecl = dc->getSelfNominalTypeDecl ();
3272
3244
auto parameter = func->getParameters ()->get (0 );
3273
3245
auto parameterType = parameter->getTypeInContext ();
3274
3246
if (!typeDecl || !parameterType)
@@ -3298,10 +3270,10 @@ namespace {
3298
3270
}
3299
3271
3300
3272
Impl.markUnavailable (func, " use subscript" );
3273
+ return true ;
3301
3274
}
3302
3275
3303
3276
if (importedName.isDereferenceAccessor ()) {
3304
- auto typeDecl = dc->getSelfNominalTypeDecl ();
3305
3277
auto &getterAndSetter = Impl.cxxDereferenceOperators [typeDecl];
3306
3278
3307
3279
switch (importedName.getAccessorKind ()) {
@@ -3316,6 +3288,42 @@ namespace {
3316
3288
}
3317
3289
3318
3290
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 ;
3319
3327
}
3320
3328
3321
3329
return true ;
@@ -3644,7 +3652,8 @@ namespace {
3644
3652
func->setAccess (AccessLevel::Public);
3645
3653
3646
3654
if (!importFuncWithoutSignature) {
3647
- bool success = processSpecialImportedFunc (func, importedName);
3655
+ bool success = processSpecialImportedFunc (
3656
+ func, importedName, decl->getOverloadedOperator ());
3648
3657
if (!success)
3649
3658
return nullptr ;
3650
3659
}
@@ -4024,6 +4033,12 @@ namespace {
4024
4033
if (!importedDC)
4025
4034
return nullptr ;
4026
4035
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
+
4027
4042
if (isa<clang::TypeDecl>(decl->getTargetDecl ())) {
4028
4043
Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
4029
4044
if (!SwiftDecl)
@@ -4072,7 +4087,8 @@ namespace {
4072
4087
if (!clonedMethod)
4073
4088
return nullptr ;
4074
4089
4075
- bool success = processSpecialImportedFunc (clonedMethod, importedName);
4090
+ bool success = processSpecialImportedFunc (
4091
+ clonedMethod, importedName, targetMethod->getOverloadedOperator ());
4076
4092
if (!success)
4077
4093
return nullptr ;
4078
4094
0 commit comments