@@ -4117,8 +4117,17 @@ namespace {
41174117
41184118 auto type = importedType.getType ();
41194119
4120+ // Private C++ fields should also be private in Swift. Since Swift does
4121+ // not have a notion of protected field, map protected C++ fields to
4122+ // private Swift fields.
4123+ AccessLevel accessLevel =
4124+ (decl->getAccess () == clang::AccessSpecifier::AS_private ||
4125+ decl->getAccess () == clang::AccessSpecifier::AS_protected)
4126+ ? AccessLevel::Private
4127+ : AccessLevel::Public;
4128+
41204129 auto result =
4121- Impl.createDeclWithClangNode <VarDecl>(decl, AccessLevel::Public ,
4130+ Impl.createDeclWithClangNode <VarDecl>(decl, accessLevel ,
41224131 /* IsStatic*/ false ,
41234132 VarDecl::Introducer::Var,
41244133 Impl.importSourceLoc (decl->getLocation ()),
@@ -8825,15 +8834,15 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
88258834 if (ClangDecl->isInvalidDecl ())
88268835 return nullptr ;
88278836
8828- // Private and protected C++ class members should never be used, so we skip
8829- // them entirely (instead of importing them with a corresponding Swift access
8830- // level) to remove clutter from the module interface.
8831- //
8832- // We omit protected members in addition to private members because Swift
8833- // structs can't inherit from C++ classes, so there's effectively no way to
8834- // access them.
8837+ // Private and protected C++ class members should never be used from Swift,
8838+ // however, parts of the Swift typechecker rely on being able to iterate over
8839+ // all of the stored fields of a particular struct. This means we still need
8840+ // to add private fields to the Swift AST.
8841+ //
8842+ // Other kinds of private and protected C++ decls are not relevant for Swift.
88358843 clang::AccessSpecifier access = ClangDecl->getAccess ();
8836- if (access == clang::AS_protected || access == clang::AS_private)
8844+ if ((access == clang::AS_protected || access == clang::AS_private) &&
8845+ !isa<clang::FieldDecl>(ClangDecl))
88378846 return nullptr ;
88388847
88398848 bool SkippedOverTypedef = false ;
@@ -9530,15 +9539,18 @@ void ClangImporter::Implementation::loadAllMembersOfRecordDecl(
95309539 for (auto member: members) {
95319540 // This means we found a member in a C++ record's base class.
95329541 if (swiftDecl->getClangDecl () != clangRecord) {
9542+ auto namedMember = cast<ValueDecl>(member);
9543+ if (namedMember->getFormalAccess () < AccessLevel::Public)
9544+ continue ;
95339545 // Do not clone the base member into the derived class
95349546 // when the derived class already has a member of such
95359547 // name and arity.
95369548 auto memberArity =
9537- getImportedBaseMemberDeclArity (cast<ValueDecl>(member) );
9549+ getImportedBaseMemberDeclArity (namedMember );
95389550 bool shouldAddBaseMember = true ;
95399551 for (const auto *currentMember : swiftDecl->getMembers ()) {
95409552 auto vd = dyn_cast<ValueDecl>(currentMember);
9541- if (vd->getName () == cast<ValueDecl>(member) ->getName ()) {
9553+ if (vd->getName () == namedMember ->getName ()) {
95429554 if (memberArity == getImportedBaseMemberDeclArity (vd)) {
95439555 shouldAddBaseMember = false ;
95449556 break ;
@@ -9548,7 +9560,7 @@ void ClangImporter::Implementation::loadAllMembersOfRecordDecl(
95489560 if (!shouldAddBaseMember)
95499561 continue ;
95509562 // So we need to clone the member into the derived class.
9551- if (auto newDecl = importBaseMemberDecl (cast<ValueDecl>(member) , swiftDecl)) {
9563+ if (auto newDecl = importBaseMemberDecl (namedMember , swiftDecl)) {
95529564 swiftDecl->addMember (newDecl);
95539565 }
95549566 continue ;
0 commit comments