@@ -3237,6 +3237,58 @@ namespace {
3237
3237
llvm::None);
3238
3238
}
3239
3239
3240
+ // / Handles special functions such as subscripts and dereference operators.
3241
+ bool processSpecialImportedFunc (FuncDecl *func, ImportedName importedName) {
3242
+ auto dc = func->getDeclContext ();
3243
+
3244
+ if (importedName.isSubscriptAccessor ()) {
3245
+ assert (func->getParameters ()->size () == 1 );
3246
+ auto typeDecl = dc->getSelfNominalTypeDecl ();
3247
+ auto parameter = func->getParameters ()->get (0 );
3248
+ auto parameterType = parameter->getTypeInContext ();
3249
+ if (!typeDecl || !parameterType)
3250
+ return false ;
3251
+ if (parameter->isInOut ())
3252
+ // Subscripts with inout parameters are not allowed in Swift.
3253
+ return false ;
3254
+
3255
+ auto &getterAndSetter = Impl.cxxSubscripts [{typeDecl, parameterType}];
3256
+
3257
+ switch (importedName.getAccessorKind ()) {
3258
+ case ImportedAccessorKind::SubscriptGetter:
3259
+ getterAndSetter.first = func;
3260
+ break ;
3261
+ case ImportedAccessorKind::SubscriptSetter:
3262
+ getterAndSetter.second = func;
3263
+ break ;
3264
+ default :
3265
+ llvm_unreachable (" invalid subscript kind" );
3266
+ }
3267
+
3268
+ Impl.markUnavailable (func, " use subscript" );
3269
+ }
3270
+
3271
+ if (importedName.isDereferenceAccessor ()) {
3272
+ auto typeDecl = dc->getSelfNominalTypeDecl ();
3273
+ auto &getterAndSetter = Impl.cxxDereferenceOperators [typeDecl];
3274
+
3275
+ switch (importedName.getAccessorKind ()) {
3276
+ case ImportedAccessorKind::DereferenceGetter:
3277
+ getterAndSetter.first = func;
3278
+ break ;
3279
+ case ImportedAccessorKind::DereferenceSetter:
3280
+ getterAndSetter.second = func;
3281
+ break ;
3282
+ default :
3283
+ llvm_unreachable (" invalid dereference operator kind" );
3284
+ }
3285
+
3286
+ Impl.markUnavailable (func, " use .pointee property" );
3287
+ }
3288
+
3289
+ return true ;
3290
+ }
3291
+
3240
3292
Decl *importFunctionDecl (
3241
3293
const clang::FunctionDecl *decl, ImportedName importedName,
3242
3294
llvm::Optional<ImportedName> correctSwiftName,
@@ -3556,62 +3608,14 @@ namespace {
3556
3608
func->setImportAsStaticMember ();
3557
3609
}
3558
3610
}
3611
+ // Someday, maybe this will need to be 'open' for C++ virtual methods.
3612
+ func->setAccess (AccessLevel::Public);
3559
3613
3560
- bool makePrivate = false ;
3561
-
3562
- if (importedName.isSubscriptAccessor () && !importFuncWithoutSignature) {
3563
- assert (func->getParameters ()->size () == 1 );
3564
- auto typeDecl = dc->getSelfNominalTypeDecl ();
3565
- auto parameter = func->getParameters ()->get (0 );
3566
- auto parameterType = parameter->getTypeInContext ();
3567
- if (!typeDecl || !parameterType)
3614
+ if (!importFuncWithoutSignature) {
3615
+ bool success = processSpecialImportedFunc (func, importedName);
3616
+ if (!success)
3568
3617
return nullptr ;
3569
- if (parameter->isInOut ())
3570
- // Subscripts with inout parameters are not allowed in Swift.
3571
- return nullptr ;
3572
-
3573
- auto &getterAndSetter = Impl.cxxSubscripts [{ typeDecl,
3574
- parameterType }];
3575
-
3576
- switch (importedName.getAccessorKind ()) {
3577
- case ImportedAccessorKind::SubscriptGetter:
3578
- getterAndSetter.first = func;
3579
- break ;
3580
- case ImportedAccessorKind::SubscriptSetter:
3581
- getterAndSetter.second = func;
3582
- break ;
3583
- default :
3584
- llvm_unreachable (" invalid subscript kind" );
3585
- }
3586
-
3587
- Impl.markUnavailable (func, " use subscript" );
3588
- }
3589
-
3590
- if (importedName.isDereferenceAccessor () &&
3591
- !importFuncWithoutSignature) {
3592
- auto typeDecl = dc->getSelfNominalTypeDecl ();
3593
- auto &getterAndSetter = Impl.cxxDereferenceOperators [typeDecl];
3594
-
3595
- switch (importedName.getAccessorKind ()) {
3596
- case ImportedAccessorKind::DereferenceGetter:
3597
- getterAndSetter.first = func;
3598
- break ;
3599
- case ImportedAccessorKind::DereferenceSetter:
3600
- getterAndSetter.second = func;
3601
- break ;
3602
- default :
3603
- llvm_unreachable (" invalid dereference operator kind" );
3604
- }
3605
-
3606
- Impl.markUnavailable (func, " use .pointee property" );
3607
- makePrivate = true ;
3608
3618
}
3609
-
3610
- if (makePrivate)
3611
- func->setAccess (AccessLevel::Private);
3612
- else
3613
- // Someday, maybe this will need to be 'open' for C++ virtual methods.
3614
- func->setAccess (AccessLevel::Public);
3615
3619
}
3616
3620
3617
3621
result->setIsObjC (false );
@@ -3924,18 +3928,27 @@ namespace {
3924
3928
}
3925
3929
3926
3930
Decl *VisitUsingDecl (const clang::UsingDecl *decl) {
3927
- // Using declarations are not imported .
3931
+ // See VisitUsingShadowDecl below .
3928
3932
return nullptr ;
3929
3933
}
3930
3934
3931
3935
Decl *VisitUsingShadowDecl (const clang::UsingShadowDecl *decl) {
3932
- // Only import types for now.
3933
- if (!isa<clang::TypeDecl>(decl->getUnderlyingDecl ()))
3936
+ // Only import:
3937
+ // 1. Types
3938
+ // 2. C++ methods from privately inherited base classes
3939
+ if (!isa<clang::TypeDecl>(decl->getTargetDecl ()) &&
3940
+ !isa<clang::CXXMethodDecl>(decl->getTargetDecl ()))
3941
+ return nullptr ;
3942
+ // We don't import `using BaseClass::BaseClass` for now.
3943
+ if (isa<clang::CXXConstructorDecl>(decl->getTargetDecl ()))
3934
3944
return nullptr ;
3935
3945
3936
3946
ImportedName importedName;
3937
3947
llvm::Optional<ImportedName> correctSwiftName;
3938
3948
std::tie (importedName, correctSwiftName) = importFullName (decl);
3949
+ // Don't import something that doesn't have a name.
3950
+ if (importedName.getDeclName ().isSpecial ())
3951
+ return nullptr ;
3939
3952
auto Name = importedName.getDeclName ().getBaseIdentifier ();
3940
3953
if (Name.empty ())
3941
3954
return nullptr ;
@@ -3946,30 +3959,66 @@ namespace {
3946
3959
return importCompatibilityTypeAlias (decl, importedName,
3947
3960
*correctSwiftName);
3948
3961
3949
- auto DC =
3962
+ auto importedDC =
3950
3963
Impl.importDeclContextOf (decl, importedName.getEffectiveContext ());
3951
- if (!DC )
3964
+ if (!importedDC )
3952
3965
return nullptr ;
3953
3966
3954
- Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
3955
- if (!SwiftDecl)
3956
- return nullptr ;
3967
+ if (isa<clang::TypeDecl>(decl->getTargetDecl ())) {
3968
+ Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
3969
+ if (!SwiftDecl)
3970
+ return nullptr ;
3957
3971
3958
- const TypeDecl *SwiftTypeDecl = dyn_cast<TypeDecl>(SwiftDecl);
3959
- if (!SwiftTypeDecl)
3960
- return nullptr ;
3972
+ const TypeDecl *SwiftTypeDecl = dyn_cast<TypeDecl>(SwiftDecl);
3973
+ if (!SwiftTypeDecl)
3974
+ return nullptr ;
3961
3975
3962
- auto Loc = Impl.importSourceLoc (decl->getLocation ());
3963
- auto Result = Impl.createDeclWithClangNode <TypeAliasDecl>(
3964
- decl,
3965
- AccessLevel::Public,
3966
- Impl.importSourceLoc (decl->getBeginLoc ()),
3967
- SourceLoc (), Name,
3968
- Loc,
3969
- /* genericparams*/ nullptr , DC);
3970
- Result->setUnderlyingType (SwiftTypeDecl->getDeclaredInterfaceType ());
3976
+ auto Loc = Impl.importSourceLoc (decl->getLocation ());
3977
+ auto Result = Impl.createDeclWithClangNode <TypeAliasDecl>(
3978
+ decl,
3979
+ AccessLevel::Public,
3980
+ Impl.importSourceLoc (decl->getBeginLoc ()),
3981
+ SourceLoc (), Name,
3982
+ Loc,
3983
+ /* genericparams*/ nullptr , importedDC);
3984
+ Result->setUnderlyingType (SwiftTypeDecl->getDeclaredInterfaceType ());
3985
+
3986
+ return Result;
3987
+ }
3988
+ if (auto targetMethod =
3989
+ dyn_cast<clang::CXXMethodDecl>(decl->getTargetDecl ())) {
3990
+ auto dc = dyn_cast<clang::CXXRecordDecl>(decl->getDeclContext ());
3991
+
3992
+ auto targetDC = targetMethod->getDeclContext ();
3993
+ auto targetRecord = dyn_cast<clang::CXXRecordDecl>(targetDC);
3994
+ if (!targetRecord)
3995
+ return nullptr ;
3971
3996
3972
- return Result;
3997
+ // If this struct is not inherited from the struct where the method is
3998
+ // defined, bail.
3999
+ if (!dc->isDerivedFrom (targetRecord))
4000
+ return nullptr ;
4001
+
4002
+ auto importedBaseMethod = dyn_cast_or_null<FuncDecl>(
4003
+ Impl.importDecl (targetMethod, getActiveSwiftVersion ()));
4004
+ // This will be nullptr for a protected method of base class that is
4005
+ // made public with a using declaration in a derived class. This is
4006
+ // valid in C++ but we do not import such using declarations now.
4007
+ // TODO: make this work for protected base methods.
4008
+ if (!importedBaseMethod)
4009
+ return nullptr ;
4010
+ auto clonedMethod = dyn_cast_or_null<FuncDecl>(
4011
+ Impl.importBaseMemberDecl (importedBaseMethod, importedDC));
4012
+ if (!clonedMethod)
4013
+ return nullptr ;
4014
+
4015
+ bool success = processSpecialImportedFunc (clonedMethod, importedName);
4016
+ if (!success)
4017
+ return nullptr ;
4018
+
4019
+ return clonedMethod;
4020
+ }
4021
+ return nullptr ;
3973
4022
}
3974
4023
3975
4024
// / Add an @objc(name) attribute with the given, optional name expressed as
@@ -8353,11 +8402,17 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
8353
8402
if (Result &&
8354
8403
(!Result->getDeclContext ()->isModuleScopeContext () ||
8355
8404
isa<ClangModuleUnit>(Result->getDeclContext ()))) {
8405
+ // For using declarations that expose a method of a base class, the Clang
8406
+ // decl is synthesized lazily when the method is actually used from Swift.
8407
+ bool hasSynthesizedClangNode =
8408
+ isa<clang::UsingShadowDecl>(ClangDecl) && isa<FuncDecl>(Result);
8409
+
8356
8410
// Either the Swift declaration was from stdlib,
8357
8411
// or we imported the underlying decl of the typedef,
8358
8412
// or we imported the decl itself.
8359
8413
bool ImportedCorrectly =
8360
8414
!Result->getClangDecl () || SkippedOverTypedef ||
8415
+ hasSynthesizedClangNode ||
8361
8416
Result->getClangDecl ()->getCanonicalDecl () == Canon;
8362
8417
8363
8418
// Or the other type is a typedef,
@@ -8380,7 +8435,7 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
8380
8435
}
8381
8436
assert (ImportedCorrectly);
8382
8437
}
8383
- assert (Result->hasClangNode ());
8438
+ assert (Result->hasClangNode () || hasSynthesizedClangNode );
8384
8439
}
8385
8440
#else
8386
8441
(void )SkippedOverTypedef;
0 commit comments