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