@@ -2697,6 +2697,31 @@ namespace {
2697
2697
// SemaLookup.cpp).
2698
2698
if (!decl->isBeingDefined () && !decl->isDependentContext () &&
2699
2699
areRecordFieldsComplete (decl)) {
2700
+ if (decl->hasInheritedConstructor () &&
2701
+ Impl.isCxxInteropCompatVersionAtLeast (
2702
+ version::getUpcomingCxxInteropCompatVersion ())) {
2703
+ for (auto member : decl->decls ()) {
2704
+ if (auto usingDecl = dyn_cast<clang::UsingDecl>(member)) {
2705
+ for (auto usingShadowDecl : usingDecl->shadows ()) {
2706
+ if (auto ctorUsingShadowDecl =
2707
+ dyn_cast<clang::ConstructorUsingShadowDecl>(
2708
+ usingShadowDecl)) {
2709
+ auto baseCtorDecl = dyn_cast<clang::CXXConstructorDecl>(
2710
+ ctorUsingShadowDecl->getTargetDecl ());
2711
+ if (!baseCtorDecl || baseCtorDecl->isDeleted ())
2712
+ continue ;
2713
+ auto derivedCtorDecl = clangSema.findInheritingConstructor (
2714
+ clang::SourceLocation (), baseCtorDecl,
2715
+ ctorUsingShadowDecl);
2716
+ if (!derivedCtorDecl->isDefined () &&
2717
+ !derivedCtorDecl->isDeleted ())
2718
+ clangSema.DefineInheritingConstructor (
2719
+ clang::SourceLocation (), derivedCtorDecl);
2720
+ }
2721
+ }
2722
+ }
2723
+ }
2724
+ }
2700
2725
if (decl->needsImplicitDefaultConstructor ()) {
2701
2726
clang::CXXConstructorDecl *ctor =
2702
2727
clangSema.DeclareImplicitDefaultConstructor (
@@ -3237,6 +3262,65 @@ namespace {
3237
3262
llvm::None);
3238
3263
}
3239
3264
3265
+ // / Handles special functions such as subscripts and dereference operators.
3266
+ bool processSpecialImportedFunc (FuncDecl *func, ImportedName importedName) {
3267
+ auto dc = func->getDeclContext ();
3268
+
3269
+ if (importedName.isSubscriptAccessor ()) {
3270
+ assert (func->getParameters ()->size () == 1 );
3271
+ auto typeDecl = dc->getSelfNominalTypeDecl ();
3272
+ auto parameter = func->getParameters ()->get (0 );
3273
+ auto parameterType = parameter->getTypeInContext ();
3274
+ if (!typeDecl || !parameterType)
3275
+ return false ;
3276
+ if (parameter->isInOut ())
3277
+ // Subscripts with inout parameters are not allowed in Swift.
3278
+ return false ;
3279
+ // Subscript setter is marked as mutating in Swift even if the
3280
+ // C++ `operator []` is `const`.
3281
+ if (importedName.getAccessorKind () ==
3282
+ ImportedAccessorKind::SubscriptSetter &&
3283
+ !dc->isModuleScopeContext () &&
3284
+ !typeDecl->getDeclaredType ()->isForeignReferenceType ())
3285
+ func->setSelfAccessKind (SelfAccessKind::Mutating);
3286
+
3287
+ auto &getterAndSetter = Impl.cxxSubscripts [{typeDecl, parameterType}];
3288
+
3289
+ switch (importedName.getAccessorKind ()) {
3290
+ case ImportedAccessorKind::SubscriptGetter:
3291
+ getterAndSetter.first = func;
3292
+ break ;
3293
+ case ImportedAccessorKind::SubscriptSetter:
3294
+ getterAndSetter.second = func;
3295
+ break ;
3296
+ default :
3297
+ llvm_unreachable (" invalid subscript kind" );
3298
+ }
3299
+
3300
+ Impl.markUnavailable (func, " use subscript" );
3301
+ }
3302
+
3303
+ if (importedName.isDereferenceAccessor ()) {
3304
+ auto typeDecl = dc->getSelfNominalTypeDecl ();
3305
+ auto &getterAndSetter = Impl.cxxDereferenceOperators [typeDecl];
3306
+
3307
+ switch (importedName.getAccessorKind ()) {
3308
+ case ImportedAccessorKind::DereferenceGetter:
3309
+ getterAndSetter.first = func;
3310
+ break ;
3311
+ case ImportedAccessorKind::DereferenceSetter:
3312
+ getterAndSetter.second = func;
3313
+ break ;
3314
+ default :
3315
+ llvm_unreachable (" invalid dereference operator kind" );
3316
+ }
3317
+
3318
+ Impl.markUnavailable (func, " use .pointee property" );
3319
+ }
3320
+
3321
+ return true ;
3322
+ }
3323
+
3240
3324
Decl *importFunctionDecl (
3241
3325
const clang::FunctionDecl *decl, ImportedName importedName,
3242
3326
llvm::Optional<ImportedName> correctSwiftName,
@@ -3556,69 +3640,14 @@ namespace {
3556
3640
func->setImportAsStaticMember ();
3557
3641
}
3558
3642
}
3643
+ // Someday, maybe this will need to be 'open' for C++ virtual methods.
3644
+ func->setAccess (AccessLevel::Public);
3559
3645
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)
3646
+ if (!importFuncWithoutSignature) {
3647
+ bool success = processSpecialImportedFunc (func, importedName);
3648
+ if (!success)
3568
3649
return nullptr ;
3569
- if (parameter->isInOut ())
3570
- // Subscripts with inout parameters are not allowed in Swift.
3571
- return nullptr ;
3572
- // Subscript setter is marked as mutating in Swift even if the
3573
- // C++ `operator []` is `const`.
3574
- if (importedName.getAccessorKind () ==
3575
- ImportedAccessorKind::SubscriptSetter &&
3576
- !dc->isModuleScopeContext () &&
3577
- !typeDecl->getDeclaredType ()->isForeignReferenceType ())
3578
- func->setSelfAccessKind (SelfAccessKind::Mutating);
3579
-
3580
- auto &getterAndSetter = Impl.cxxSubscripts [{ typeDecl,
3581
- parameterType }];
3582
-
3583
- switch (importedName.getAccessorKind ()) {
3584
- case ImportedAccessorKind::SubscriptGetter:
3585
- getterAndSetter.first = func;
3586
- break ;
3587
- case ImportedAccessorKind::SubscriptSetter:
3588
- getterAndSetter.second = func;
3589
- break ;
3590
- default :
3591
- llvm_unreachable (" invalid subscript kind" );
3592
- }
3593
-
3594
- Impl.markUnavailable (func, " use subscript" );
3595
3650
}
3596
-
3597
- if (importedName.isDereferenceAccessor () &&
3598
- !importFuncWithoutSignature) {
3599
- auto typeDecl = dc->getSelfNominalTypeDecl ();
3600
- auto &getterAndSetter = Impl.cxxDereferenceOperators [typeDecl];
3601
-
3602
- switch (importedName.getAccessorKind ()) {
3603
- case ImportedAccessorKind::DereferenceGetter:
3604
- getterAndSetter.first = func;
3605
- break ;
3606
- case ImportedAccessorKind::DereferenceSetter:
3607
- getterAndSetter.second = func;
3608
- break ;
3609
- default :
3610
- llvm_unreachable (" invalid dereference operator kind" );
3611
- }
3612
-
3613
- Impl.markUnavailable (func, " use .pointee property" );
3614
- makePrivate = true ;
3615
- }
3616
-
3617
- if (makePrivate)
3618
- func->setAccess (AccessLevel::Private);
3619
- else
3620
- // Someday, maybe this will need to be 'open' for C++ virtual methods.
3621
- func->setAccess (AccessLevel::Public);
3622
3651
}
3623
3652
3624
3653
result->setIsObjC (false );
@@ -3931,18 +3960,31 @@ namespace {
3931
3960
}
3932
3961
3933
3962
Decl *VisitUsingDecl (const clang::UsingDecl *decl) {
3934
- // Using declarations are not imported .
3963
+ // See VisitUsingShadowDecl below .
3935
3964
return nullptr ;
3936
3965
}
3937
3966
3938
3967
Decl *VisitUsingShadowDecl (const clang::UsingShadowDecl *decl) {
3939
- // Only import types for now.
3940
- if (!isa<clang::TypeDecl>(decl->getUnderlyingDecl ()))
3968
+ // Only import:
3969
+ // 1. Types
3970
+ // 2. C++ methods from privately inherited base classes
3971
+ if (!isa<clang::TypeDecl>(decl->getTargetDecl ()) &&
3972
+ !(isa<clang::CXXMethodDecl>(decl->getTargetDecl ()) &&
3973
+ Impl.isCxxInteropCompatVersionAtLeast (
3974
+ version::getUpcomingCxxInteropCompatVersion ())))
3975
+ return nullptr ;
3976
+ // Constructors (e.g. `using BaseClass::BaseClass`) are handled in
3977
+ // VisitCXXRecordDecl, since we need them to determine whether a struct
3978
+ // can be imported into Swift.
3979
+ if (isa<clang::CXXConstructorDecl>(decl->getTargetDecl ()))
3941
3980
return nullptr ;
3942
3981
3943
3982
ImportedName importedName;
3944
3983
llvm::Optional<ImportedName> correctSwiftName;
3945
3984
std::tie (importedName, correctSwiftName) = importFullName (decl);
3985
+ // Don't import something that doesn't have a name.
3986
+ if (importedName.getDeclName ().isSpecial ())
3987
+ return nullptr ;
3946
3988
auto Name = importedName.getDeclName ().getBaseIdentifier ();
3947
3989
if (Name.empty ())
3948
3990
return nullptr ;
@@ -3953,30 +3995,66 @@ namespace {
3953
3995
return importCompatibilityTypeAlias (decl, importedName,
3954
3996
*correctSwiftName);
3955
3997
3956
- auto DC =
3998
+ auto importedDC =
3957
3999
Impl.importDeclContextOf (decl, importedName.getEffectiveContext ());
3958
- if (!DC )
4000
+ if (!importedDC )
3959
4001
return nullptr ;
3960
4002
3961
- Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
3962
- if (!SwiftDecl)
3963
- return nullptr ;
4003
+ if (isa<clang::TypeDecl>(decl->getTargetDecl ())) {
4004
+ Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
4005
+ if (!SwiftDecl)
4006
+ return nullptr ;
3964
4007
3965
- const TypeDecl *SwiftTypeDecl = dyn_cast<TypeDecl>(SwiftDecl);
3966
- if (!SwiftTypeDecl)
3967
- return nullptr ;
4008
+ const TypeDecl *SwiftTypeDecl = dyn_cast<TypeDecl>(SwiftDecl);
4009
+ if (!SwiftTypeDecl)
4010
+ return nullptr ;
3968
4011
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 , DC);
3977
- Result->setUnderlyingType (SwiftTypeDecl->getDeclaredInterfaceType ());
4012
+ auto Loc = Impl.importSourceLoc (decl->getLocation ());
4013
+ auto Result = Impl.createDeclWithClangNode <TypeAliasDecl>(
4014
+ decl,
4015
+ AccessLevel::Public,
4016
+ Impl.importSourceLoc (decl->getBeginLoc ()),
4017
+ SourceLoc (), Name,
4018
+ Loc,
4019
+ /* genericparams*/ nullptr , importedDC);
4020
+ Result->setUnderlyingType (SwiftTypeDecl->getDeclaredInterfaceType ());
4021
+
4022
+ return Result;
4023
+ }
4024
+ if (auto targetMethod =
4025
+ dyn_cast<clang::CXXMethodDecl>(decl->getTargetDecl ())) {
4026
+ auto dc = dyn_cast<clang::CXXRecordDecl>(decl->getDeclContext ());
4027
+
4028
+ auto targetDC = targetMethod->getDeclContext ();
4029
+ auto targetRecord = dyn_cast<clang::CXXRecordDecl>(targetDC);
4030
+ if (!targetRecord)
4031
+ return nullptr ;
3978
4032
3979
- return Result;
4033
+ // If this struct is not inherited from the struct where the method is
4034
+ // defined, bail.
4035
+ if (!dc->isDerivedFrom (targetRecord))
4036
+ return nullptr ;
4037
+
4038
+ auto importedBaseMethod = dyn_cast_or_null<FuncDecl>(
4039
+ Impl.importDecl (targetMethod, getActiveSwiftVersion ()));
4040
+ // This will be nullptr for a protected method of base class that is
4041
+ // made public with a using declaration in a derived class. This is
4042
+ // valid in C++ but we do not import such using declarations now.
4043
+ // TODO: make this work for protected base methods.
4044
+ if (!importedBaseMethod)
4045
+ return nullptr ;
4046
+ auto clonedMethod = dyn_cast_or_null<FuncDecl>(
4047
+ Impl.importBaseMemberDecl (importedBaseMethod, importedDC));
4048
+ if (!clonedMethod)
4049
+ return nullptr ;
4050
+
4051
+ bool success = processSpecialImportedFunc (clonedMethod, importedName);
4052
+ if (!success)
4053
+ return nullptr ;
4054
+
4055
+ return clonedMethod;
4056
+ }
4057
+ return nullptr ;
3980
4058
}
3981
4059
3982
4060
// / Add an @objc(name) attribute with the given, optional name expressed as
@@ -8360,11 +8438,17 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
8360
8438
if (Result &&
8361
8439
(!Result->getDeclContext ()->isModuleScopeContext () ||
8362
8440
isa<ClangModuleUnit>(Result->getDeclContext ()))) {
8441
+ // For using declarations that expose a method of a base class, the Clang
8442
+ // decl is synthesized lazily when the method is actually used from Swift.
8443
+ bool hasSynthesizedClangNode =
8444
+ isa<clang::UsingShadowDecl>(ClangDecl) && isa<FuncDecl>(Result);
8445
+
8363
8446
// Either the Swift declaration was from stdlib,
8364
8447
// or we imported the underlying decl of the typedef,
8365
8448
// or we imported the decl itself.
8366
8449
bool ImportedCorrectly =
8367
8450
!Result->getClangDecl () || SkippedOverTypedef ||
8451
+ hasSynthesizedClangNode ||
8368
8452
Result->getClangDecl ()->getCanonicalDecl () == Canon;
8369
8453
8370
8454
// Or the other type is a typedef,
@@ -8387,7 +8471,7 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
8387
8471
}
8388
8472
assert (ImportedCorrectly);
8389
8473
}
8390
- assert (Result->hasClangNode ());
8474
+ assert (Result->hasClangNode () || hasSynthesizedClangNode );
8391
8475
}
8392
8476
#else
8393
8477
(void )SkippedOverTypedef;
0 commit comments