Skip to content

Commit cffc639

Browse files
committed
Add importer::convertClangAccess helper
1 parent 469f34e commit cffc639

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

include/swift/ClangImporter/ClangImporter.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
#ifndef SWIFT_CLANG_IMPORTER_H
1717
#define SWIFT_CLANG_IMPORTER_H
1818

19+
#include "swift/AST/AttrKind.h"
1920
#include "swift/AST/ClangModuleLoader.h"
21+
#include "clang/Basic/Specifiers.h"
2022
#include "llvm/Support/VirtualFileSystem.h"
2123

2224
/// The maximum number of SIMD vector elements we currently try to import.
@@ -728,7 +730,11 @@ llvm::StringRef getCFTypeName(const clang::TypedefNameDecl *decl);
728730
ValueDecl *getImportedMemberOperator(const DeclBaseName &name,
729731
NominalTypeDecl *selfType,
730732
std::optional<Type> parameterType);
731-
733+
/// Map the access specifier of a Clang record member to a Swift access level.
734+
///
735+
/// This mapping is conservative: the resulting Swift access should be at _most_
736+
/// as permissive as the input C++ access.
737+
AccessLevel convertClangAccess(clang::AccessSpecifier access);
732738
} // namespace importer
733739

734740
struct ClangInvocationFileMapping {

lib/ClangImporter/ClangImporter.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8277,3 +8277,34 @@ bool importer::isCxxConstReferenceType(const clang::Type *type) {
82778277
auto pointeeType = getCxxReferencePointeeTypeOrNone(type);
82788278
return pointeeType && pointeeType->isConstQualified();
82798279
}
8280+
8281+
AccessLevel importer::convertClangAccess(clang::AccessSpecifier access) {
8282+
switch (access) {
8283+
case clang::AS_public:
8284+
// C++ 'public' is actually closer to Swift 'open' than Swift 'public',
8285+
// since C++ 'public' does not prevent users from subclassing a type or
8286+
// overriding a method. However, subclassing and overriding are currently
8287+
// unsupported across the interop boundary, so we conservatively map C++
8288+
// 'public' to Swift 'public' in case there are other C++ subtleties that
8289+
// are being missed at this time (e.g., C++ 'final' vs Swift 'final').
8290+
return AccessLevel::Public;
8291+
8292+
case clang::AS_protected:
8293+
// Swift does not have a notion of protected fields, so map C++ 'protected'
8294+
// to Swift 'private'.
8295+
return AccessLevel::Private;
8296+
8297+
case clang::AS_private:
8298+
// N.B. Swift 'private' is more restrictive than C++ 'private' because it
8299+
// also cares about what source file the member is accessed.
8300+
return AccessLevel::Private;
8301+
8302+
case clang::AS_none:
8303+
// The fictional 'none' specifier is given to top-level C++ declarations,
8304+
// for which C++ lacks the syntax to give an access specifier. (It may also
8305+
// be used in other cases I'm not aware of.) Those declarations are globally
8306+
// visible and thus correspond to Swift 'public' (with the same caveats
8307+
// about Swift 'public' vs 'open'; see above).
8308+
return AccessLevel::Public;
8309+
}
8310+
}

0 commit comments

Comments
 (0)