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