@@ -3237,6 +3237,58 @@ namespace {
32373237 llvm::None);
32383238 }
32393239
3240+ // / Handles special functions such as subscripts and dereference operators.
3241+ bool processSpecialImportedFunc (FuncDecl *func, ImportedName importedName) {
3242+ auto dc = func->getDeclContext ();
3243+
3244+ if (importedName.isSubscriptAccessor ()) {
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 ()) {
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+
32403292 Decl *importFunctionDecl (
32413293 const clang::FunctionDecl *decl, ImportedName importedName,
32423294 llvm::Optional<ImportedName> correctSwiftName,
@@ -3556,62 +3608,14 @@ namespace {
35563608 func->setImportAsStaticMember ();
35573609 }
35583610 }
3611+ // Someday, maybe this will need to be 'open' for C++ virtual methods.
3612+ func->setAccess (AccessLevel::Public);
35593613
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)
3614+ if (!importFuncWithoutSignature) {
3615+ bool success = processSpecialImportedFunc (func, importedName);
3616+ if (!success)
35683617 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" );
35883618 }
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);
36153619 }
36163620
36173621 result->setIsObjC (false );
@@ -3924,13 +3928,19 @@ namespace {
39243928 }
39253929
39263930 Decl *VisitUsingDecl (const clang::UsingDecl *decl) {
3927- // Using declarations are not imported .
3931+ // See VisitUsingShadowDecl below .
39283932 return nullptr ;
39293933 }
39303934
39313935 Decl *VisitUsingShadowDecl (const clang::UsingShadowDecl *decl) {
3932- // Only import types for now.
3933- if (!isa<clang::TypeDecl>(decl->getUnderlyingDecl ()))
3936+ // Only import:
3937+ // 1. Types
3938+ // 2. C++ methods from privately inherited base classes
3939+ if (!isa<clang::TypeDecl>(decl->getTargetDecl ()) &&
3940+ !isa<clang::CXXMethodDecl>(decl->getTargetDecl ()))
3941+ return nullptr ;
3942+ // We don't import `using BaseClass::BaseClass` for now.
3943+ if (isa<clang::CXXConstructorDecl>(decl->getTargetDecl ()))
39343944 return nullptr ;
39353945
39363946 ImportedName importedName;
@@ -3946,30 +3956,66 @@ namespace {
39463956 return importCompatibilityTypeAlias (decl, importedName,
39473957 *correctSwiftName);
39483958
3949- auto DC =
3959+ auto importedDC =
39503960 Impl.importDeclContextOf (decl, importedName.getEffectiveContext ());
3951- if (!DC )
3961+ if (!importedDC )
39523962 return nullptr ;
39533963
3954- Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
3955- if (!SwiftDecl)
3956- return nullptr ;
3964+ if (isa<clang::TypeDecl>(decl->getTargetDecl ())) {
3965+ Decl *SwiftDecl = Impl.importDecl (decl->getUnderlyingDecl (), getActiveSwiftVersion ());
3966+ if (!SwiftDecl)
3967+ return nullptr ;
39573968
3958- const TypeDecl *SwiftTypeDecl = dyn_cast<TypeDecl>(SwiftDecl);
3959- if (!SwiftTypeDecl)
3960- return nullptr ;
3969+ const TypeDecl *SwiftTypeDecl = dyn_cast<TypeDecl>(SwiftDecl);
3970+ if (!SwiftTypeDecl)
3971+ return nullptr ;
39613972
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 ());
3973+ auto Loc = Impl.importSourceLoc (decl->getLocation ());
3974+ auto Result = Impl.createDeclWithClangNode <TypeAliasDecl>(
3975+ decl,
3976+ AccessLevel::Public,
3977+ Impl.importSourceLoc (decl->getBeginLoc ()),
3978+ SourceLoc (), Name,
3979+ Loc,
3980+ /* genericparams*/ nullptr , importedDC);
3981+ Result->setUnderlyingType (SwiftTypeDecl->getDeclaredInterfaceType ());
3982+
3983+ return Result;
3984+ }
3985+ if (auto targetMethod =
3986+ dyn_cast<clang::CXXMethodDecl>(decl->getTargetDecl ())) {
3987+ auto dc = dyn_cast<clang::CXXRecordDecl>(decl->getDeclContext ());
3988+
3989+ auto targetDC = targetMethod->getDeclContext ();
3990+ auto targetRecord = dyn_cast<clang::CXXRecordDecl>(targetDC);
3991+ if (!targetRecord)
3992+ return nullptr ;
39713993
3972- return Result;
3994+ // If this struct is not inherited from the struct where the method is
3995+ // defined, bail.
3996+ if (!dc->isDerivedFrom (targetRecord))
3997+ return nullptr ;
3998+
3999+ auto importedBaseMethod = dyn_cast_or_null<FuncDecl>(
4000+ Impl.importDecl (targetMethod, getActiveSwiftVersion ()));
4001+ // This will be nullptr for a protected method of base class that is
4002+ // made public with a using declaration in a derived class. This is
4003+ // valid in C++ but we do not import such using declarations now.
4004+ // TODO: make this work for protected base methods.
4005+ if (!importedBaseMethod)
4006+ return nullptr ;
4007+ auto clonedMethod = dyn_cast_or_null<FuncDecl>(
4008+ Impl.importBaseMemberDecl (importedBaseMethod, importedDC));
4009+ if (!clonedMethod)
4010+ return nullptr ;
4011+
4012+ bool success = processSpecialImportedFunc (clonedMethod, importedName);
4013+ if (!success)
4014+ return nullptr ;
4015+
4016+ return clonedMethod;
4017+ }
4018+ return nullptr ;
39734019 }
39744020
39754021 // / Add an @objc(name) attribute with the given, optional name expressed as
@@ -8353,11 +8399,17 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
83538399 if (Result &&
83548400 (!Result->getDeclContext ()->isModuleScopeContext () ||
83558401 isa<ClangModuleUnit>(Result->getDeclContext ()))) {
8402+ // For using declarations that expose a method of a base class, the Clang
8403+ // decl is synthesized lazily when the method is actually used from Swift.
8404+ bool hasSynthesizedClangNode =
8405+ isa<clang::UsingShadowDecl>(ClangDecl) && isa<FuncDecl>(Result);
8406+
83568407 // Either the Swift declaration was from stdlib,
83578408 // or we imported the underlying decl of the typedef,
83588409 // or we imported the decl itself.
83598410 bool ImportedCorrectly =
83608411 !Result->getClangDecl () || SkippedOverTypedef ||
8412+ hasSynthesizedClangNode ||
83618413 Result->getClangDecl ()->getCanonicalDecl () == Canon;
83628414
83638415 // Or the other type is a typedef,
@@ -8380,7 +8432,7 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
83808432 }
83818433 assert (ImportedCorrectly);
83828434 }
8383- assert (Result->hasClangNode ());
8435+ assert (Result->hasClangNode () || hasSynthesizedClangNode );
83848436 }
83858437#else
83868438 (void )SkippedOverTypedef;
0 commit comments