@@ -2697,6 +2697,30 @@ namespace {
2697
2697
// SemaLookup.cpp).
2698
2698
if (!decl->isBeingDefined () && !decl->isDependentContext () &&
2699
2699
areRecordFieldsComplete (decl)) {
2700
+ if (decl->hasInheritedConstructor () &&
2701
+ Impl.isCxxInteropCompatVersionAtLeast (5 , 11 )) {
2702
+ for (auto member : decl->decls ()) {
2703
+ if (auto usingDecl = dyn_cast<clang::UsingDecl>(member)) {
2704
+ for (auto usingShadowDecl : usingDecl->shadows ()) {
2705
+ if (auto ctorUsingShadowDecl =
2706
+ dyn_cast<clang::ConstructorUsingShadowDecl>(
2707
+ usingShadowDecl)) {
2708
+ auto baseCtorDecl = dyn_cast<clang::CXXConstructorDecl>(
2709
+ ctorUsingShadowDecl->getTargetDecl ());
2710
+ if (!baseCtorDecl || baseCtorDecl->isDeleted ())
2711
+ continue ;
2712
+ auto derivedCtorDecl = clangSema.findInheritingConstructor (
2713
+ clang::SourceLocation (), baseCtorDecl,
2714
+ ctorUsingShadowDecl);
2715
+ if (!derivedCtorDecl->isDefined () &&
2716
+ !derivedCtorDecl->isDeleted ())
2717
+ clangSema.DefineInheritingConstructor (
2718
+ clang::SourceLocation (), derivedCtorDecl);
2719
+ }
2720
+ }
2721
+ }
2722
+ }
2723
+ }
2700
2724
if (decl->needsImplicitDefaultConstructor ()) {
2701
2725
clang::CXXConstructorDecl *ctor =
2702
2726
clangSema.DeclareImplicitDefaultConstructor (
@@ -3237,6 +3261,58 @@ namespace {
3237
3261
llvm::None);
3238
3262
}
3239
3263
3264
+ // / Handles special functions such as subscripts and dereference operators.
3265
+ bool processSpecialImportedFunc (FuncDecl *func, ImportedName importedName) {
3266
+ auto dc = func->getDeclContext ();
3267
+
3268
+ if (importedName.isSubscriptAccessor ()) {
3269
+ assert (func->getParameters ()->size () == 1 );
3270
+ auto typeDecl = dc->getSelfNominalTypeDecl ();
3271
+ auto parameter = func->getParameters ()->get (0 );
3272
+ auto parameterType = parameter->getTypeInContext ();
3273
+ if (!typeDecl || !parameterType)
3274
+ return false ;
3275
+ if (parameter->isInOut ())
3276
+ // Subscripts with inout parameters are not allowed in Swift.
3277
+ return false ;
3278
+
3279
+ auto &getterAndSetter = Impl.cxxSubscripts [{typeDecl, parameterType}];
3280
+
3281
+ switch (importedName.getAccessorKind ()) {
3282
+ case ImportedAccessorKind::SubscriptGetter:
3283
+ getterAndSetter.first = func;
3284
+ break ;
3285
+ case ImportedAccessorKind::SubscriptSetter:
3286
+ getterAndSetter.second = func;
3287
+ break ;
3288
+ default :
3289
+ llvm_unreachable (" invalid subscript kind" );
3290
+ }
3291
+
3292
+ Impl.markUnavailable (func, " use subscript" );
3293
+ }
3294
+
3295
+ if (importedName.isDereferenceAccessor ()) {
3296
+ auto typeDecl = dc->getSelfNominalTypeDecl ();
3297
+ auto &getterAndSetter = Impl.cxxDereferenceOperators [typeDecl];
3298
+
3299
+ switch (importedName.getAccessorKind ()) {
3300
+ case ImportedAccessorKind::DereferenceGetter:
3301
+ getterAndSetter.first = func;
3302
+ break ;
3303
+ case ImportedAccessorKind::DereferenceSetter:
3304
+ getterAndSetter.second = func;
3305
+ break ;
3306
+ default :
3307
+ llvm_unreachable (" invalid dereference operator kind" );
3308
+ }
3309
+
3310
+ Impl.markUnavailable (func, " use .pointee property" );
3311
+ }
3312
+
3313
+ return true ;
3314
+ }
3315
+
3240
3316
Decl *importFunctionDecl (
3241
3317
const clang::FunctionDecl *decl, ImportedName importedName,
3242
3318
llvm::Optional<ImportedName> correctSwiftName,
@@ -3556,62 +3632,14 @@ namespace {
3556
3632
func->setImportAsStaticMember ();
3557
3633
}
3558
3634
}
3635
+ // Someday, maybe this will need to be 'open' for C++ virtual methods.
3636
+ func->setAccess (AccessLevel::Public);
3559
3637
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.
3638
+ if (!importFuncWithoutSignature) {
3639
+ bool success = processSpecialImportedFunc (func, importedName);
3640
+ if (!success)
3571
3641
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
3642
}
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);
3615
3643
}
3616
3644
3617
3645
result->setIsObjC (false );
@@ -3924,18 +3952,30 @@ namespace {
3924
3952
}
3925
3953
3926
3954
Decl *VisitUsingDecl (const clang::UsingDecl *decl) {
3927
- // Using declarations are not imported .
3955
+ // See VisitUsingShadowDecl below .
3928
3956
return nullptr ;
3929
3957
}
3930
3958
3931
3959
Decl *VisitUsingShadowDecl (const clang::UsingShadowDecl *decl) {
3932
- // Only import types for now.
3933
- if (!isa<clang::TypeDecl>(decl->getUnderlyingDecl ()))
3960
+ // Only import:
3961
+ // 1. Types
3962
+ // 2. C++ methods from privately inherited base classes
3963
+ if (!isa<clang::TypeDecl>(decl->getTargetDecl ()) &&
3964
+ !(isa<clang::CXXMethodDecl>(decl->getTargetDecl ()) &&
3965
+ Impl.isCxxInteropCompatVersionAtLeast (5 , 11 )))
3966
+ return nullptr ;
3967
+ // Constructors (e.g. `using BaseClass::BaseClass`) are handled in
3968
+ // VisitCXXRecordDecl, since we need them to determine whether a struct
3969
+ // can be imported into Swift.
3970
+ if (isa<clang::CXXConstructorDecl>(decl->getTargetDecl ()))
3934
3971
return nullptr ;
3935
3972
3936
3973
ImportedName importedName;
3937
3974
llvm::Optional<ImportedName> correctSwiftName;
3938
3975
std::tie (importedName, correctSwiftName) = importFullName (decl);
3976
+ // Don't import something that doesn't have a name.
3977
+ if (importedName.getDeclName ().isSpecial ())
3978
+ return nullptr ;
3939
3979
auto Name = importedName.getDeclName ().getBaseIdentifier ();
3940
3980
if (Name.empty ())
3941
3981
return nullptr ;
@@ -3946,30 +3986,66 @@ namespace {
3946
3986
return importCompatibilityTypeAlias (decl, importedName,
3947
3987
*correctSwiftName);
3948
3988
3949
- auto DC =
3989
+ auto importedDC =
3950
3990
Impl.importDeclContextOf (decl, importedName.getEffectiveContext ());
3951
- if (!DC )
3991
+ if (!importedDC )
3952
3992
return nullptr ;
3953
3993
3954
- Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
3955
- if (!SwiftDecl)
3956
- return nullptr ;
3994
+ if (isa<clang::TypeDecl>(decl->getTargetDecl ())) {
3995
+ Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
3996
+ if (!SwiftDecl)
3997
+ return nullptr ;
3957
3998
3958
- const TypeDecl *SwiftTypeDecl = dyn_cast<TypeDecl>(SwiftDecl);
3959
- if (!SwiftTypeDecl)
3960
- return nullptr ;
3999
+ const TypeDecl *SwiftTypeDecl = dyn_cast<TypeDecl>(SwiftDecl);
4000
+ if (!SwiftTypeDecl)
4001
+ return nullptr ;
3961
4002
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 ());
4003
+ auto Loc = Impl.importSourceLoc (decl->getLocation ());
4004
+ auto Result = Impl.createDeclWithClangNode <TypeAliasDecl>(
4005
+ decl,
4006
+ AccessLevel::Public,
4007
+ Impl.importSourceLoc (decl->getBeginLoc ()),
4008
+ SourceLoc (), Name,
4009
+ Loc,
4010
+ /* genericparams*/ nullptr , importedDC);
4011
+ Result->setUnderlyingType (SwiftTypeDecl->getDeclaredInterfaceType ());
4012
+
4013
+ return Result;
4014
+ }
4015
+ if (auto targetMethod =
4016
+ dyn_cast<clang::CXXMethodDecl>(decl->getTargetDecl ())) {
4017
+ auto dc = dyn_cast<clang::CXXRecordDecl>(decl->getDeclContext ());
4018
+
4019
+ auto targetDC = targetMethod->getDeclContext ();
4020
+ auto targetRecord = dyn_cast<clang::CXXRecordDecl>(targetDC);
4021
+ if (!targetRecord)
4022
+ return nullptr ;
3971
4023
3972
- return Result;
4024
+ // If this struct is not inherited from the struct where the method is
4025
+ // defined, bail.
4026
+ if (!dc->isDerivedFrom (targetRecord))
4027
+ return nullptr ;
4028
+
4029
+ auto importedBaseMethod = dyn_cast_or_null<FuncDecl>(
4030
+ Impl.importDecl (targetMethod, getActiveSwiftVersion ()));
4031
+ // This will be nullptr for a protected method of base class that is
4032
+ // made public with a using declaration in a derived class. This is
4033
+ // valid in C++ but we do not import such using declarations now.
4034
+ // TODO: make this work for protected base methods.
4035
+ if (!importedBaseMethod)
4036
+ return nullptr ;
4037
+ auto clonedMethod = dyn_cast_or_null<FuncDecl>(
4038
+ Impl.importBaseMemberDecl (importedBaseMethod, importedDC));
4039
+ if (!clonedMethod)
4040
+ return nullptr ;
4041
+
4042
+ bool success = processSpecialImportedFunc (clonedMethod, importedName);
4043
+ if (!success)
4044
+ return nullptr ;
4045
+
4046
+ return clonedMethod;
4047
+ }
4048
+ return nullptr ;
3973
4049
}
3974
4050
3975
4051
// / Add an @objc(name) attribute with the given, optional name expressed as
@@ -8353,11 +8429,17 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
8353
8429
if (Result &&
8354
8430
(!Result->getDeclContext ()->isModuleScopeContext () ||
8355
8431
isa<ClangModuleUnit>(Result->getDeclContext ()))) {
8432
+ // For using declarations that expose a method of a base class, the Clang
8433
+ // decl is synthesized lazily when the method is actually used from Swift.
8434
+ bool hasSynthesizedClangNode =
8435
+ isa<clang::UsingShadowDecl>(ClangDecl) && isa<FuncDecl>(Result);
8436
+
8356
8437
// Either the Swift declaration was from stdlib,
8357
8438
// or we imported the underlying decl of the typedef,
8358
8439
// or we imported the decl itself.
8359
8440
bool ImportedCorrectly =
8360
8441
!Result->getClangDecl () || SkippedOverTypedef ||
8442
+ hasSynthesizedClangNode ||
8361
8443
Result->getClangDecl ()->getCanonicalDecl () == Canon;
8362
8444
8363
8445
// Or the other type is a typedef,
@@ -8380,7 +8462,7 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
8380
8462
}
8381
8463
assert (ImportedCorrectly);
8382
8464
}
8383
- assert (Result->hasClangNode ());
8465
+ assert (Result->hasClangNode () || hasSynthesizedClangNode );
8384
8466
}
8385
8467
#else
8386
8468
(void )SkippedOverTypedef;
0 commit comments