Skip to content

Commit bd82933

Browse files
committed
Import non-public C++ members
This commit removes the guardrails in ImportDecl.cpp:SwiftDeclConverter that prevent it from importing non-public C++ members. It also accordingly adjusts all code that assumes generated Swift decls should be public.
1 parent cffc639 commit bd82933

File tree

5 files changed

+135
-124
lines changed

5 files changed

+135
-124
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 89 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ void ClangImporter::Implementation::addSynthesizedTypealias(
467467
auto typealias = new (ctx) TypeAliasDecl(SourceLoc(), SourceLoc(), name,
468468
SourceLoc(), nullptr, nominal);
469469
typealias->setUnderlyingType(underlyingType);
470-
typealias->setAccess(AccessLevel::Public);
470+
typealias->setAccess(nominal->getFormalAccess());
471471
typealias->setImplicit();
472472

473473
nominal->addMember(typealias);
@@ -1426,11 +1426,10 @@ namespace {
14261426
// Create a typealias for this CF typedef.
14271427
TypeAliasDecl *typealias = nullptr;
14281428
typealias = Impl.createDeclWithClangNode<TypeAliasDecl>(
1429-
Decl, AccessLevel::Public,
1430-
Impl.importSourceLoc(Decl->getBeginLoc()),
1431-
SourceLoc(), Name,
1432-
Impl.importSourceLoc(Decl->getLocation()),
1433-
/*genericparams*/nullptr, DC);
1429+
Decl, importer::convertClangAccess(Decl->getAccess()),
1430+
Impl.importSourceLoc(Decl->getBeginLoc()), SourceLoc(), Name,
1431+
Impl.importSourceLoc(Decl->getLocation()),
1432+
/*genericparams*/ nullptr, DC);
14341433
typealias->setUnderlyingType(
14351434
underlying->getDeclaredInterfaceType());
14361435

@@ -1445,11 +1444,10 @@ namespace {
14451444
// Create a typealias for this CF typedef.
14461445
TypeAliasDecl *typealias = nullptr;
14471446
typealias = Impl.createDeclWithClangNode<TypeAliasDecl>(
1448-
Decl, AccessLevel::Public,
1449-
Impl.importSourceLoc(Decl->getBeginLoc()),
1450-
SourceLoc(), Name,
1451-
Impl.importSourceLoc(Decl->getLocation()),
1452-
/*genericparams*/nullptr, DC);
1447+
Decl, importer::convertClangAccess(Decl->getAccess()),
1448+
Impl.importSourceLoc(Decl->getBeginLoc()), SourceLoc(), Name,
1449+
Impl.importSourceLoc(Decl->getLocation()),
1450+
/*genericparams*/ nullptr, DC);
14531451
typealias->setUnderlyingType(
14541452
Impl.SwiftContext.getAnyObjectType());
14551453

@@ -1514,12 +1512,10 @@ namespace {
15141512
return nullptr;
15151513

15161514
auto Loc = Impl.importSourceLoc(Decl->getLocation());
1517-
auto Result = Impl.createDeclWithClangNode<TypeAliasDecl>(Decl,
1518-
AccessLevel::Public,
1519-
Impl.importSourceLoc(Decl->getBeginLoc()),
1520-
SourceLoc(), Name,
1521-
Loc,
1522-
/*genericparams*/nullptr, DC);
1515+
auto Result = Impl.createDeclWithClangNode<TypeAliasDecl>(
1516+
Decl, importer::convertClangAccess(Decl->getAccess()),
1517+
Impl.importSourceLoc(Decl->getBeginLoc()), SourceLoc(), Name, Loc,
1518+
/*genericparams*/ nullptr, DC);
15231519

15241520
Result->setUnderlyingType(SwiftType);
15251521
if (SwiftType->isUnsafe())
@@ -1625,8 +1621,8 @@ namespace {
16251621

16261622
auto Loc = Impl.importSourceLoc(decl->getLocation());
16271623
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
1628-
decl, AccessLevel::Public, Loc, name, Loc, std::nullopt, nullptr,
1629-
dc);
1624+
decl, importer::convertClangAccess(decl->getAccess()), Loc, name,
1625+
Loc, std::nullopt, nullptr, dc);
16301626

16311627
auto options = getDefaultMakeStructRawValuedOptions();
16321628
options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
@@ -1674,6 +1670,10 @@ namespace {
16741670
(nsErrorDecl = C.getNSErrorDecl()) &&
16751671
(errorCodeProto =
16761672
C.getProtocol(KnownProtocolKind::ErrorCodeProtocol))) {
1673+
assert(
1674+
decl->getAccess() != clang::AS_private &&
1675+
decl->getAccess() != clang::AS_protected &&
1676+
"NSError enums shouldn't be defined as non-public C++ members");
16771677
// Create the wrapper struct.
16781678
errorWrapper =
16791679
new (C) StructDecl(loc, name, loc, std::nullopt, nullptr, dc);
@@ -1745,9 +1745,9 @@ namespace {
17451745

17461746
// Create the enumeration.
17471747
auto enumDecl = Impl.createDeclWithClangNode<EnumDecl>(
1748-
decl, AccessLevel::Public, loc, enumName,
1749-
Impl.importSourceLoc(decl->getLocation()), std::nullopt, nullptr,
1750-
enumDC);
1748+
decl, importer::convertClangAccess(decl->getAccess()), loc,
1749+
enumName, Impl.importSourceLoc(decl->getLocation()), std::nullopt,
1750+
nullptr, enumDC);
17511751
enumDecl->setHasFixedRawValues();
17521752

17531753
// Annotate as 'frozen' if appropriate.
@@ -1789,7 +1789,7 @@ namespace {
17891789
SourceLoc(), varName,
17901790
enumDecl);
17911791
rawValue->setImplicit();
1792-
rawValue->setAccess(AccessLevel::Public);
1792+
rawValue->copyFormalAccessFrom(enumDecl);
17931793
rawValue->setSetterAccess(AccessLevel::Private);
17941794
rawValue->setInterfaceType(underlyingType);
17951795

@@ -1812,6 +1812,10 @@ namespace {
18121812
// If we have an error wrapper, finish it up now that its
18131813
// nested enum has been constructed.
18141814
if (errorWrapper) {
1815+
assert(
1816+
decl->getAccess() != clang::AS_private &&
1817+
decl->getAccess() != clang::AS_protected &&
1818+
"NSError enums shouldn't be defined as non-public C++ members");
18151819
// Add the ErrorType alias:
18161820
// public typealias ErrorType
18171821
auto alias = Impl.createDeclWithClangNode<TypeAliasDecl>(
@@ -2186,12 +2190,12 @@ namespace {
21862190
auto loc = Impl.importSourceLoc(decl->getLocation());
21872191
if (recordHasReferenceSemantics(decl))
21882192
result = Impl.createDeclWithClangNode<ClassDecl>(
2189-
decl, AccessLevel::Public, loc, name, loc,
2190-
ArrayRef<InheritedEntry>{}, nullptr, dc, false);
2193+
decl, importer::convertClangAccess(decl->getAccess()), loc, name,
2194+
loc, ArrayRef<InheritedEntry>{}, nullptr, dc, false);
21912195
else
21922196
result = Impl.createDeclWithClangNode<StructDecl>(
2193-
decl, AccessLevel::Public, loc, name, loc, std::nullopt, nullptr,
2194-
dc);
2197+
decl, importer::convertClangAccess(decl->getAccess()), loc, name,
2198+
loc, std::nullopt, nullptr, dc);
21952199
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
21962200

21972201
// We have to do this after populating ImportedDecls to avoid importing
@@ -3195,7 +3199,8 @@ namespace {
31953199
name, dc, type, clang::APValue(decl->getInitVal()),
31963200
enumKind == EnumKind::Unknown ? ConstantConvertKind::Construction
31973201
: ConstantConvertKind::None,
3198-
isStatic, decl);
3202+
isStatic, decl,
3203+
importer::convertClangAccess(clangEnum->getAccess()));
31993204
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
32003205

32013206
// If this is a compatibility stub, mark it as such.
@@ -3264,12 +3269,10 @@ namespace {
32643269
auto type = importedType.getType();
32653270

32663271
// Map this indirect field to a Swift variable.
3267-
auto result = Impl.createDeclWithClangNode<VarDecl>(decl,
3268-
AccessLevel::Public,
3269-
/*IsStatic*/false,
3270-
VarDecl::Introducer::Var,
3271-
Impl.importSourceLoc(decl->getBeginLoc()),
3272-
name, dc);
3272+
auto result = Impl.createDeclWithClangNode<VarDecl>(
3273+
decl, importer::convertClangAccess(decl->getAccess()),
3274+
/*IsStatic*/ false, VarDecl::Introducer::Var,
3275+
Impl.importSourceLoc(decl->getBeginLoc()), name, dc);
32733276
result->setInterfaceType(type);
32743277
result->setIsObjC(false);
32753278
result->setIsDynamic(false);
@@ -3897,7 +3900,8 @@ namespace {
38973900
DeclName ctorName(Impl.SwiftContext, DeclBaseName::createConstructor(),
38983901
bodyParams);
38993902
result = Impl.createDeclWithClangNode<ConstructorDecl>(
3900-
clangNode, AccessLevel::Public, ctorName, loc,
3903+
clangNode, importer::convertClangAccess(ctordecl->getAccess()),
3904+
ctorName, loc,
39013905
/*failable=*/false, /*FailabilityLoc=*/SourceLoc(),
39023906
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
39033907
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
@@ -4297,21 +4301,10 @@ namespace {
42974301

42984302
auto type = importedType.getType();
42994303

4300-
// Private C++ fields should also be private in Swift. Since Swift does
4301-
// not have a notion of protected field, map protected C++ fields to
4302-
// private Swift fields.
4303-
AccessLevel accessLevel =
4304-
(decl->getAccess() == clang::AccessSpecifier::AS_private ||
4305-
decl->getAccess() == clang::AccessSpecifier::AS_protected)
4306-
? AccessLevel::Private
4307-
: AccessLevel::Public;
4308-
4309-
auto result =
4310-
Impl.createDeclWithClangNode<VarDecl>(decl, accessLevel,
4311-
/*IsStatic*/ false,
4312-
VarDecl::Introducer::Var,
4313-
Impl.importSourceLoc(decl->getLocation()),
4314-
name, dc);
4304+
auto result = Impl.createDeclWithClangNode<VarDecl>(
4305+
decl, importer::convertClangAccess(decl->getAccess()),
4306+
/*IsStatic*/ false, VarDecl::Introducer::Var,
4307+
Impl.importSourceLoc(decl->getLocation()), name, dc);
43154308
if (decl->getType().isConstQualified()) {
43164309
// Note that in C++ there are ways to change the values of const
43174310
// members, so we don't use WriteImplKind::Immutable storage.
@@ -4374,11 +4367,10 @@ namespace {
43744367
auto introducer = Impl.shouldImportGlobalAsLet(decl->getType())
43754368
? VarDecl::Introducer::Let
43764369
: VarDecl::Introducer::Var;
4377-
auto result = Impl.createDeclWithClangNode<VarDecl>(decl,
4378-
AccessLevel::Public,
4379-
/*IsStatic*/isStatic, introducer,
4380-
Impl.importSourceLoc(decl->getLocation()),
4381-
name, dc);
4370+
auto result = Impl.createDeclWithClangNode<VarDecl>(
4371+
decl, importer::convertClangAccess(decl->getAccess()),
4372+
/*IsStatic*/ isStatic, introducer,
4373+
Impl.importSourceLoc(decl->getLocation()), name, dc);
43824374
result->setIsObjC(false);
43834375
result->setIsDynamic(false);
43844376

@@ -4462,8 +4454,8 @@ namespace {
44624454
Impl.SwiftContext, loc, genericParams, loc);
44634455

44644456
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
4465-
decl, AccessLevel::Public, loc, name, loc, std::nullopt,
4466-
genericParamList, dc);
4457+
decl, importer::convertClangAccess(decl->getAccess()), loc, name, loc,
4458+
std::nullopt, genericParamList, dc);
44674459

44684460
auto attr = AvailableAttr::createUniversallyUnavailable(
44694461
Impl.SwiftContext, "Un-specialized class templates are not currently "
@@ -4530,12 +4522,9 @@ namespace {
45304522

45314523
auto Loc = Impl.importSourceLoc(decl->getLocation());
45324524
auto Result = Impl.createDeclWithClangNode<TypeAliasDecl>(
4533-
decl,
4534-
AccessLevel::Public,
4535-
Impl.importSourceLoc(decl->getBeginLoc()),
4536-
SourceLoc(), Name,
4537-
Loc,
4538-
/*genericparams*/nullptr, importedDC);
4525+
decl, importer::convertClangAccess(decl->getAccess()),
4526+
Impl.importSourceLoc(decl->getBeginLoc()), SourceLoc(), Name, Loc,
4527+
/*genericparams*/ nullptr, importedDC);
45394528
Result->setUnderlyingType(SwiftTypeDecl->getDeclaredInterfaceType());
45404529

45414530
return Result;
@@ -6218,9 +6207,11 @@ Decl *SwiftDeclConverter::importCompatibilityTypeAlias(
62186207

62196208
// Create the type alias.
62206209
auto alias = Impl.createDeclWithClangNode<TypeAliasDecl>(
6221-
decl, AccessLevel::Public, Impl.importSourceLoc(decl->getBeginLoc()),
6222-
SourceLoc(), compatibilityName.getBaseIdentifier(Impl.SwiftContext),
6223-
Impl.importSourceLoc(decl->getLocation()), /*generic params*/nullptr, dc);
6210+
decl, importer::convertClangAccess(decl->getAccess()),
6211+
Impl.importSourceLoc(decl->getBeginLoc()), SourceLoc(),
6212+
compatibilityName.getBaseIdentifier(Impl.SwiftContext),
6213+
Impl.importSourceLoc(decl->getLocation()), /*generic params*/ nullptr,
6214+
dc);
62246215

62256216
auto *GTD = dyn_cast<GenericTypeDecl>(typeDecl);
62266217
if (GTD && !isa<ProtocolDecl>(GTD)) {
@@ -6315,7 +6306,8 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
63156306
auto Loc = Impl.importSourceLoc(decl->getLocation());
63166307

63176308
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
6318-
decl, AccessLevel::Public, Loc, name, Loc, std::nullopt, nullptr, dc);
6309+
decl, importer::convertClangAccess(decl->getAccess()), Loc, name, Loc,
6310+
std::nullopt, nullptr, dc);
63196311

63206312
// Import the type of the underlying storage
63216313
ImportDiagnosticAdder addImportDiag(Impl, decl, decl->getLocation());
@@ -6515,8 +6507,8 @@ Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
65156507
rawValueExpr->setNegative(SourceLoc());
65166508

65176509
auto element = Impl.createDeclWithClangNode<EnumElementDecl>(
6518-
decl, AccessLevel::Public, SourceLoc(), name, nullptr,
6519-
SourceLoc(), rawValueExpr, theEnum);
6510+
decl, importer::convertClangAccess(clangEnum->getAccess()), SourceLoc(),
6511+
name, nullptr, SourceLoc(), rawValueExpr, theEnum);
65206512

65216513
Impl.importAttributes(decl, element);
65226514

@@ -6540,7 +6532,8 @@ SwiftDeclConverter::importOptionConstant(const clang::EnumConstantDecl *decl,
65406532
convertKind = ConstantConvertKind::ConstructionWithUnwrap;
65416533
Decl *CD = synthesizer.createConstant(
65426534
name, theStruct, theStruct->getDeclaredInterfaceType(),
6543-
clang::APValue(decl->getInitVal()), convertKind, /*isStatic*/ true, decl);
6535+
clang::APValue(decl->getInitVal()), convertKind, /*isStatic*/ true, decl,
6536+
importer::convertClangAccess(clangEnum->getAccess()));
65446537
Impl.importAttributes(decl, CD);
65456538

65466539
// NS_OPTIONS members that have a value of 0 (typically named "None") do
@@ -6604,9 +6597,10 @@ Decl *SwiftDeclConverter::importEnumCaseAlias(
66046597
result->setType(original->getInterfaceType());
66056598
}
66066599

6607-
Decl *CD = synthesizer.createConstant(name, importIntoDC, importedEnumTy,
6608-
result, ConstantConvertKind::None,
6609-
/*isStatic*/ true, alias);
6600+
Decl *CD = synthesizer.createConstant(
6601+
name, importIntoDC, importedEnumTy, result, ConstantConvertKind::None,
6602+
/*isStatic*/ true, alias,
6603+
importer::convertClangAccess(clangEnum->getAccess()));
66106604
Impl.importAttributes(alias, CD);
66116605
return CD;
66126606
}
@@ -6620,7 +6614,8 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
66206614

66216615
// Create a struct with the underlying type as a field.
66226616
auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
6623-
decl, AccessLevel::Public, Loc, name, Loc, std::nullopt, nullptr, dc);
6617+
decl, importer::convertClangAccess(decl->getAccess()), Loc, name, Loc,
6618+
std::nullopt, nullptr, dc);
66246619
Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = structDecl;
66256620

66266621
// Compute the underlying type.
@@ -6696,7 +6691,7 @@ Decl *SwiftDeclConverter::importGlobalAsInitializer(
66966691
}
66976692

66986693
auto result = Impl.createDeclWithClangNode<ConstructorDecl>(
6699-
decl, AccessLevel::Public, name,
6694+
decl, importer::convertClangAccess(decl->getAccess()), name,
67006695
Impl.importSourceLoc(decl->getLocation()), failable,
67016696
/*FailabilityLoc=*/SourceLoc(),
67026697
/*Async=*/false, /*AsyncLoc=*/SourceLoc(),
@@ -6877,8 +6872,8 @@ SwiftDeclConverter::getImplicitProperty(ImportedName importedName,
68776872
Type swiftPropertyType = importedType.getType();
68786873

68796874
auto property = Impl.createDeclWithClangNode<VarDecl>(
6880-
getter, AccessLevel::Public, /*IsStatic*/isStatic,
6881-
VarDecl::Introducer::Var, SourceLoc(),
6875+
getter, importer::convertClangAccess(getter->getAccess()),
6876+
/*IsStatic*/ isStatic, VarDecl::Introducer::Var, SourceLoc(),
68826877
propertyName, dc);
68836878
property->setInterfaceType(swiftPropertyType);
68846879
property->setIsObjC(false);
@@ -9231,17 +9226,6 @@ ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
92319226
if (ClangDecl->isInvalidDecl())
92329227
return nullptr;
92339228

9234-
// Private and protected C++ class members should never be used from Swift,
9235-
// however, parts of the Swift typechecker rely on being able to iterate over
9236-
// all of the stored fields of a particular struct. This means we still need
9237-
// to add private fields to the Swift AST.
9238-
//
9239-
// Other kinds of private and protected C++ decls are not relevant for Swift.
9240-
clang::AccessSpecifier access = ClangDecl->getAccess();
9241-
if ((access == clang::AS_protected || access == clang::AS_private) &&
9242-
!isa<clang::FieldDecl>(ClangDecl))
9243-
return nullptr;
9244-
92459229
bool SkippedOverTypedef = false;
92469230
Decl *Result = nullptr;
92479231
if (auto *UnderlyingDecl = canSkipOverTypedef(*this, ClangDecl,
@@ -9869,16 +9853,14 @@ markUnavailable(ValueDecl *decl, StringRef unavailabilityMsgRef) {
98699853

98709854
/// Create a decl with error type and an "unavailable" attribute on it
98719855
/// with the specified message.
9872-
ValueDecl *ClangImporter::Implementation::
9873-
createUnavailableDecl(Identifier name, DeclContext *dc, Type type,
9874-
StringRef UnavailableMessage, bool isStatic,
9875-
ClangNode ClangN) {
9856+
ValueDecl *ClangImporter::Implementation::createUnavailableDecl(
9857+
Identifier name, DeclContext *dc, Type type, StringRef UnavailableMessage,
9858+
bool isStatic, ClangNode ClangN, AccessLevel access) {
98769859

98779860
// Create a new VarDecl with dummy type.
9878-
auto var = createDeclWithClangNode<VarDecl>(ClangN, AccessLevel::Public,
9879-
/*IsStatic*/isStatic,
9880-
VarDecl::Introducer::Var,
9881-
SourceLoc(), name, dc);
9861+
auto var = createDeclWithClangNode<VarDecl>(
9862+
ClangN, access,
9863+
/*IsStatic*/ isStatic, VarDecl::Introducer::Var, SourceLoc(), name, dc);
98829864
var->setIsObjC(false);
98839865
var->setIsDynamic(false);
98849866
var->setInterfaceType(type);
@@ -10373,3 +10355,14 @@ const UnifiedStatsReporter::TraceFormatter*
1037310355
FrontendStatsTracer::getTraceFormatter<const clang::Decl *>() {
1037410356
return &TF;
1037510357
}
10358+
10359+
/*
10360+
* Omissions SwiftDeclConverter:
10361+
* - VisitNamespaceDecl(): namespaces are always "public"
10362+
* - VisitNamespaceAliasDecl(): namespaces are always "public"
10363+
* - VisitEnumDecl(): where enumKind != EnumKind::Unknown:
10364+
* + EnumKind::Constants (anonymous enums): these aren't imported at all
10365+
* + EnumKind::Options: FIXME: do this
10366+
* + EnumKind::{NonFrozenEnum,FrozenEnum}:
10367+
* * Obj-C error enums:
10368+
*/

0 commit comments

Comments
 (0)