Skip to content

Commit c90cd11

Browse files
committed
[PrintAsObjC] Only include internal decls if we have a bridging header.
The upshot of this is that internal decls in an app target will be in the generated header but internal decls in a framework target will not. This is important since the generated header is part of a framework's public interface. Users always have the option to add members via category to an internal framework type they need to use from Objective-C, or to write the @interface themselves if the entire type is missing. Only internal protocols are left out by this. The presence of the bridging header isn't a /perfect/ way to decide this, but it's close enough. In an app target without a bridging header, it's unlikely that there will be ObjC sources depending on the generated header. Swift SVN r19763
1 parent bb6c62d commit c90cd11

File tree

14 files changed

+64
-31
lines changed

14 files changed

+64
-31
lines changed

include/swift/PrintAsObjC/PrintAsObjC.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_PRINTASOBJC_H
1515

1616
#include "swift/Basic/LLVM.h"
17+
#include "swift/AST/Attr.h"
1718

1819
namespace swift {
1920
class Module;
@@ -22,7 +23,8 @@ namespace swift {
2223
/// header.
2324
///
2425
/// Returns true on error.
25-
bool printAsObjC(raw_ostream &out, Module *M, StringRef bridgingHeader);
26+
bool printAsObjC(raw_ostream &out, Module *M, StringRef bridgingHeader,
27+
Accessibility minRequiredAccess);
2628
}
2729

2830
#endif

lib/PrintAsObjC/PrintAsObjC.cpp

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,6 @@
3030

3131
using namespace swift;
3232

33-
static bool isNonPrivateObjC(const ValueDecl *VD) {
34-
return VD->isObjC() && VD->getAccessibility() != Accessibility::Private;
35-
}
36-
3733
namespace {
3834
class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
3935
private TypeVisitor<ObjCPrinter> {
@@ -51,19 +47,25 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
5147

5248
SmallVector<const FunctionType *, 4> openFunctionTypes;
5349

50+
Accessibility minRequiredAccess;
5451
bool protocolMembersOptional = false;
5552

5653
friend ASTVisitor<ObjCPrinter>;
5754
friend TypeVisitor<ObjCPrinter>;
5855

5956
public:
60-
explicit ObjCPrinter(ASTContext &context, raw_ostream &out)
61-
: ctx(context), os(out) {}
57+
explicit ObjCPrinter(ASTContext &context, raw_ostream &out,
58+
Accessibility access)
59+
: ctx(context), os(out), minRequiredAccess(access) {}
6260

6361
void print(const Decl *D) {
6462
visit(const_cast<Decl *>(D));
6563
}
6664

65+
bool shouldInclude(const ValueDecl *VD) {
66+
return VD->isObjC() && VD->getAccessibility() >= minRequiredAccess;
67+
}
68+
6769
private:
6870
using ASTVisitor::visit;
6971

@@ -75,8 +77,8 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
7577
SmallVector<ProtocolDecl *, 4> protosToPrint;
7678
std::copy_if(protos.begin(), protos.end(),
7779
std::back_inserter(protosToPrint),
78-
[](const ProtocolDecl *PD) -> bool {
79-
if (!isNonPrivateObjC(PD))
80+
[this](const ProtocolDecl *PD) -> bool {
81+
if (!shouldInclude(PD))
8082
return false;
8183
auto knownProtocol = PD->getKnownProtocolKind();
8284
if (!knownProtocol)
@@ -105,7 +107,7 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
105107
void printMembers(DeclRange members) {
106108
for (auto member : members) {
107109
auto VD = dyn_cast<ValueDecl>(member);
108-
if (!VD || !isNonPrivateObjC(VD))
110+
if (!VD || !shouldInclude(VD))
109111
continue;
110112
if (auto FD = dyn_cast<FuncDecl>(VD))
111113
if (FD->isAccessor())
@@ -751,8 +753,8 @@ class ModuleWriter {
751753
StringRef bridgingHeader;
752754
ObjCPrinter printer;
753755
public:
754-
ModuleWriter(Module &mod, StringRef header)
755-
: M(mod), bridgingHeader(header), printer(M.Ctx, os) {}
756+
ModuleWriter(Module &mod, StringRef header, Accessibility access)
757+
: M(mod), bridgingHeader(header), printer(M.Ctx, os, access) {}
756758

757759
/// Returns true if we added the decl's module to the import set, false if
758760
/// the decl is a local decl.
@@ -812,7 +814,7 @@ class ModuleWriter {
812814
void forwardDeclareMemberTypes(DeclRange members) {
813815
for (auto member : members) {
814816
auto VD = dyn_cast<ValueDecl>(member);
815-
if (!VD || !isNonPrivateObjC(VD))
817+
if (!VD || !printer.shouldInclude(VD))
816818
continue;
817819
ReferencedTypeFinder::walk(VD->getType(),
818820
[this](ReferencedTypeFinder &finder,
@@ -849,7 +851,7 @@ class ModuleWriter {
849851
allRequirementsSatisfied &= require(superclass);
850852
}
851853
for (auto proto : CD->getProtocols())
852-
if (isNonPrivateObjC(proto))
854+
if (printer.shouldInclude(proto))
853855
allRequirementsSatisfied &= require(proto);
854856

855857
if (!allRequirementsSatisfied)
@@ -894,7 +896,7 @@ class ModuleWriter {
894896
const ClassDecl *CD = ED->getExtendedType()->getClassOrBoundGenericClass();
895897
allRequirementsSatisfied &= require(CD);
896898
for (auto proto : ED->getProtocols())
897-
if (isNonPrivateObjC(proto))
899+
if (printer.shouldInclude(proto))
898900
allRequirementsSatisfied &= require(proto);
899901

900902
if (!allRequirementsSatisfied)
@@ -1018,13 +1020,13 @@ class ModuleWriter {
10181020
M.getTopLevelDecls(decls);
10191021

10201022
auto newEnd = std::remove_if(decls.begin(), decls.end(),
1021-
[] (const Decl *D) -> bool {
1023+
[this](const Decl *D) -> bool {
10221024
if (auto VD = dyn_cast<ValueDecl>(D))
1023-
return !isNonPrivateObjC(VD);
1025+
return !printer.shouldInclude(VD);
10241026

10251027
if (auto ED = dyn_cast<ExtensionDecl>(D)) {
10261028
auto baseClass = ED->getExtendedType()->getClassOrBoundGenericClass();
1027-
return !baseClass || !isNonPrivateObjC(baseClass);
1029+
return !baseClass || !printer.shouldInclude(baseClass);
10281030
}
10291031
return true;
10301032
});
@@ -1135,6 +1137,7 @@ class ModuleWriter {
11351137
}
11361138

11371139
bool swift::printAsObjC(llvm::raw_ostream &os, Module *M,
1138-
StringRef bridgingHeader) {
1139-
return ModuleWriter(*M, bridgingHeader).writeToStream(os);
1140+
StringRef bridgingHeader,
1141+
Accessibility minRequiredAccess) {
1142+
return ModuleWriter(*M, bridgingHeader, minRequiredAccess).writeToStream(os);
11401143
}

test/Inputs/empty.h

Whitespace-only changes.

test/PrintAsObjC/accessibility.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: rm -rf %t && mkdir %t
2+
// RUN: %swift %s -parse -emit-objc-header-path %t/accessibility.h
3+
// RUN: FileCheck -check-prefix=CHECK -check-prefix=CHECK-PUBLIC %s < %t/accessibility.h
4+
// RUN: %check-in-clang %t/accessibility.h
5+
6+
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache %s -parse -import-objc-header %S/../Inputs/empty.h -emit-objc-header-path %t/accessibility-internal.h
7+
// RUN: FileCheck -check-prefix=CHECK -check-prefix=CHECK-INTERNAL %s < %t/accessibility-internal.h
8+
// RUN: %check-in-clang %t/accessibility-internal.h
9+
10+
// CHECK-LABEL: @interface A_Public{{$}}
11+
// CHECK-INTERNAL-NEXT: init
12+
// CHECK-NEXT: @end
13+
@objc public class A_Public {}
14+
15+
// CHECK-PUBLIC-NOT: B_Internal
16+
// CHECK-INTERNAL-LABEL: @interface B_Internal{{$}}
17+
// CHECK-INTERNAL-NEXT: init
18+
// CHECK-INTERNAL-NEXT: @end
19+
@objc internal class B_Internal {}
20+
21+
// CHECK-NOT: C_Private
22+
@objc private class C_Private {}

test/PrintAsObjC/blocks.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: rm -rf %t
44
// RUN: mkdir %t
55
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -emit-module -o %t %s
6-
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/blocks.swiftmodule -parse -emit-objc-header-path %t/blocks.h
6+
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/blocks.swiftmodule -parse -emit-objc-header-path %t/blocks.h -import-objc-header %S/../Inputs/empty.h
77
// RUN: FileCheck %s < %t/blocks.h
88
// RUN: %check-in-clang %t/blocks.h
99

test/PrintAsObjC/classes.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: rm -rf %t
44
// RUN: mkdir %t
55
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -enable-source-import -emit-module -o %t %s
6-
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/classes.swiftmodule -parse -emit-objc-header-path %t/classes.h
6+
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/classes.swiftmodule -parse -emit-objc-header-path %t/classes.h -import-objc-header %S/../Inputs/empty.h
77
// RUN: FileCheck %s < %t/classes.h
88
// RUN: FileCheck --check-prefix=NEGATIVE %s < %t/classes.h
99
// RUN: %check-in-clang %t/classes.h

test/PrintAsObjC/comments.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: rm -rf %t
44
// RUN: mkdir %t
55
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -enable-source-import -emit-module -emit-module-path %t/comments.swiftmodule -emit-module-doc -emit-module-doc-path %t/comments.swiftdoc -module-name comments %S/../Inputs/comment_to_something_conversion.swift
6-
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/comments.swiftmodule -parse -emit-objc-header-path %t/comments.h
6+
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/comments.swiftmodule -parse -emit-objc-header-path %t/comments.h -import-objc-header %S/../Inputs/empty.h
77
// RUN: sed -n -e '/A000/,$ p' %t/comments.h > %t/comments.h-cleaned
88
// RUN: diff %t/comments.h-cleaned %S/Inputs/comments-expected-output.h
99
// RUN: %check-in-clang %t/comments.h

test/PrintAsObjC/extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: rm -rf %t
44
// RUN: mkdir %t
55
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -emit-module -o %t %s
6-
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/extensions.swiftmodule -parse -emit-objc-header-path %t/extensions.h
6+
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/extensions.swiftmodule -parse -emit-objc-header-path %t/extensions.h -import-objc-header %S/../Inputs/empty.h
77
// RUN: FileCheck %s < %t/extensions.h
88
// RUN: FileCheck --check-prefix=NEGATIVE %s < %t/extensions.h
99
// RUN: %check-in-clang %t/extensions.h

test/PrintAsObjC/local-types.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: rm -rf %t
44
// RUN: mkdir %t
55
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -emit-module -o %t %s -module-name local
6-
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/local.swiftmodule -parse -emit-objc-header-path %t/local.h
6+
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/local.swiftmodule -parse -emit-objc-header-path %t/local.h -import-objc-header %S/../Inputs/empty.h
77
// RUN: FileCheck %s < %t/local.h
88
// RUN: %check-in-clang %t/local.h
99

test/PrintAsObjC/mixed-framework-fwd.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929

3030
import Foundation
3131

32-
class Dummy: NSNumber {
33-
func getProto() -> CustomProto? {
32+
public class Dummy: NSNumber {
33+
public func getProto() -> CustomProto? {
3434
return nil
3535
}
3636
}

test/PrintAsObjC/mixed-framework.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919

2020
import Foundation
2121

22-
class Dummy: NSNumber {
23-
func getIntAlias() -> CIntAlias {
22+
public class Dummy: NSNumber {
23+
public func getIntAlias() -> CIntAlias {
2424
let result: CInt = 0
2525
return result
2626
}

test/PrintAsObjC/protocols.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: rm -rf %t
44
// RUN: mkdir %t
55
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -emit-module -o %t %s
6-
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/protocols.swiftmodule -parse -emit-objc-header-path %t/protocols.h
6+
// RUN: %swift %clang-importer-sdk -module-cache-path %t/clang-module-cache -parse-as-library %t/protocols.swiftmodule -parse -emit-objc-header-path %t/protocols.h -import-objc-header %S/../Inputs/empty.h
77
// RUN: FileCheck %s < %t/protocols.h
88
// RUN: FileCheck --check-prefix=NEGATIVE %s < %t/protocols.h
99
// RUN: %check-in-clang %t/protocols.h

tools/driver/frontend_main.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ static bool printAsObjC(const std::string &path, Module *M,
9797
return true;
9898
}
9999

100-
return printAsObjC(out, M, bridgingHeader);
100+
auto requiredAccess = bridgingHeader.empty() ? Accessibility::Public
101+
: Accessibility::Internal;
102+
return printAsObjC(out, M, bridgingHeader, requiredAccess);
101103
}
102104

103105
/// Performs the compile requested by the user.

utils/buildbot-release-notes.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ Latest
1212
The general principle is that an entity cannot be defined in terms of another
1313
entity with less accessibility.
1414

15+
Along with this, the generated header for a framework will only include
16+
public declarations. Generated headers for applications will include public
17+
and internal declarations.
18+
1519
* CGFloat is now a distinct floating-point type that wraps either a
1620
Float (on 32-bit architectures) or a Double (on 64-bit
1721
architectures). It provides all of the same comparison and

0 commit comments

Comments
 (0)