@@ -3237,6 +3237,58 @@ namespace {
3237
3237
llvm::None);
3238
3238
}
3239
3239
3240
+ bool postProcessFuncDecl (FuncDecl *func, ImportedName importedName,
3241
+ bool importFuncWithoutSignature) {
3242
+ auto dc = func->getDeclContext ();
3243
+
3244
+ if (importedName.isSubscriptAccessor () && !importFuncWithoutSignature) {
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 () && !importFuncWithoutSignature) {
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,13 @@ 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)
3568
- 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
- }
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);
3614
+ bool success =
3615
+ postProcessFuncDecl (func, importedName, importFuncWithoutSignature);
3616
+ if (!success)
3617
+ return nullptr ;
3615
3618
}
3616
3619
3617
3620
result->setIsObjC (false );
@@ -3924,13 +3927,16 @@ namespace {
3924
3927
}
3925
3928
3926
3929
Decl *VisitUsingDecl (const clang::UsingDecl *decl) {
3927
- // Using declarations are not imported .
3930
+ // See VisitUsingShadowDecl below .
3928
3931
return nullptr ;
3929
3932
}
3930
3933
3931
3934
Decl *VisitUsingShadowDecl (const clang::UsingShadowDecl *decl) {
3932
- // Only import types for now.
3933
- if (!isa<clang::TypeDecl>(decl->getUnderlyingDecl ()))
3935
+ // Only import:
3936
+ // 1. Types
3937
+ // 2. C++ methods from privately inherited base classes
3938
+ if (!isa<clang::TypeDecl>(decl->getTargetDecl ()) &&
3939
+ !isa<clang::CXXMethodDecl>(decl->getTargetDecl ()))
3934
3940
return nullptr ;
3935
3941
3936
3942
ImportedName importedName;
@@ -3946,30 +3952,69 @@ namespace {
3946
3952
return importCompatibilityTypeAlias (decl, importedName,
3947
3953
*correctSwiftName);
3948
3954
3949
- auto DC =
3955
+ auto importedDC =
3950
3956
Impl.importDeclContextOf (decl, importedName.getEffectiveContext ());
3951
- if (!DC )
3957
+ if (!importedDC )
3952
3958
return nullptr ;
3953
3959
3954
- Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
3955
- if (!SwiftDecl)
3956
- return nullptr ;
3960
+ if (isa<clang::TypeDecl>(decl->getTargetDecl ())) {
3961
+ Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
3962
+ if (!SwiftDecl)
3963
+ return nullptr ;
3957
3964
3958
- const TypeDecl *SwiftTypeDecl = dyn_cast<TypeDecl>(SwiftDecl);
3959
- if (!SwiftTypeDecl)
3960
- return nullptr ;
3965
+ const TypeDecl *SwiftTypeDecl = dyn_cast<TypeDecl>(SwiftDecl);
3966
+ if (!SwiftTypeDecl)
3967
+ return nullptr ;
3961
3968
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 ());
3969
+ auto Loc = Impl.importSourceLoc (decl->getLocation ());
3970
+ auto Result = Impl.createDeclWithClangNode <TypeAliasDecl>(
3971
+ decl,
3972
+ AccessLevel::Public,
3973
+ Impl.importSourceLoc (decl->getBeginLoc ()),
3974
+ SourceLoc (), Name,
3975
+ Loc,
3976
+ /* genericparams*/ nullptr , importedDC);
3977
+ Result->setUnderlyingType (SwiftTypeDecl->getDeclaredInterfaceType ());
3978
+
3979
+ return Result;
3980
+ }
3981
+ if (auto targetMethod =
3982
+ dyn_cast<clang::CXXMethodDecl>(decl->getTargetDecl ())) {
3983
+ if (isa<clang::CXXConstructorDecl>(targetMethod))
3984
+ return nullptr ;
3971
3985
3972
- return Result;
3986
+ auto dc = dyn_cast<clang::CXXRecordDecl>(decl->getDeclContext ());
3987
+
3988
+ auto targetDC = targetMethod->getDeclContext ();
3989
+ auto targetRecord = dyn_cast<clang::CXXRecordDecl>(targetDC);
3990
+ if (!targetRecord)
3991
+ return nullptr ;
3992
+
3993
+ // If this struct is not inherited from the struct where the method is
3994
+ // defined, bail.
3995
+ if (!dc->isDerivedFrom (targetRecord))
3996
+ return nullptr ;
3997
+
3998
+ auto importedBaseMethod = dyn_cast_or_null<FuncDecl>(
3999
+ Impl.importDecl (targetMethod, getActiveSwiftVersion ()));
4000
+ // This will be nullptr for a protected method of base class that is
4001
+ // made public with a using declaration in a derived class. This is
4002
+ // valid in C++ but we do not import such using declarations now.
4003
+ // TODO: make this work for protected base methods.
4004
+ if (!importedBaseMethod)
4005
+ return nullptr ;
4006
+ auto clonedMethod = dyn_cast_or_null<FuncDecl>(
4007
+ Impl.importBaseMemberDecl (importedBaseMethod, importedDC));
4008
+ if (!clonedMethod)
4009
+ return nullptr ;
4010
+
4011
+ bool success = postProcessFuncDecl (clonedMethod, importedName, false );
4012
+ if (!success)
4013
+ return nullptr ;
4014
+
4015
+ return clonedMethod;
4016
+ }
4017
+ return nullptr ;
3973
4018
}
3974
4019
3975
4020
// / Add an @objc(name) attribute with the given, optional name expressed as
@@ -8353,11 +8398,17 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
8353
8398
if (Result &&
8354
8399
(!Result->getDeclContext ()->isModuleScopeContext () ||
8355
8400
isa<ClangModuleUnit>(Result->getDeclContext ()))) {
8401
+ // For using declarations that expose a method of a base class, the Clang
8402
+ // decl is synthesized lazily when the method is actually used from Swift.
8403
+ bool hasSynthesizedClangNode =
8404
+ isa<clang::UsingShadowDecl>(ClangDecl) && isa<FuncDecl>(Result);
8405
+
8356
8406
// Either the Swift declaration was from stdlib,
8357
8407
// or we imported the underlying decl of the typedef,
8358
8408
// or we imported the decl itself.
8359
8409
bool ImportedCorrectly =
8360
8410
!Result->getClangDecl () || SkippedOverTypedef ||
8411
+ hasSynthesizedClangNode ||
8361
8412
Result->getClangDecl ()->getCanonicalDecl () == Canon;
8362
8413
8363
8414
// Or the other type is a typedef,
@@ -8380,7 +8431,7 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
8380
8431
}
8381
8432
assert (ImportedCorrectly);
8382
8433
}
8383
- assert (Result->hasClangNode ());
8434
+ assert (Result->hasClangNode () || hasSynthesizedClangNode );
8384
8435
}
8385
8436
#else
8386
8437
(void )SkippedOverTypedef;
0 commit comments