Skip to content

Commit bdc5afd

Browse files
authored
Merge pull request #11955 from DougGregor/rexported-module-cleanup
Minor cleanups for the work to handle re-exported modules
2 parents 1457e4d + e3207f7 commit bdc5afd

File tree

10 files changed

+167
-23
lines changed

10 files changed

+167
-23
lines changed

include/swift/ClangImporter/ClangImporter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,8 +323,8 @@ ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN,
323323
///
324324
/// This routine is used for various hacks that are only permitted within
325325
/// overlays of imported modules, e.g., Objective-C bridging conformances.
326-
bool isInOverlayModuleForImportedModule(DeclContext *overlayDC,
327-
DeclContext *importedDC);
326+
bool isInOverlayModuleForImportedModule(const DeclContext *overlayDC,
327+
const DeclContext *importedDC);
328328

329329
} // end namespace swift
330330

include/swift/ClangImporter/ClangModule.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ class ClangModuleUnit final : public LoadedFile {
5656
/// Returns the Swift module that overlays this Clang module.
5757
ModuleDecl *getAdapterModule() const;
5858

59+
/// Retrieve the "exported" name of the module, which is usually the module
60+
/// name, but might be the name of the public module through which this
61+
/// (private) module is re-exported.
62+
std::string getExportedModuleName() const;
63+
5964
virtual bool isSystemModule() const override;
6065

6166
virtual void lookupValue(ModuleDecl::AccessPathTy accessPath,

lib/ClangImporter/ClangImporter.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2861,6 +2861,13 @@ clang::ASTContext &ClangModuleUnit::getClangASTContext() const {
28612861
return owner.getClangASTContext();
28622862
}
28632863

2864+
std::string ClangModuleUnit::getExportedModuleName() const {
2865+
if (clangModule && !clangModule->ExportAsModule.empty())
2866+
return clangModule->ExportAsModule;
2867+
2868+
return getParentModule()->getName().str();
2869+
}
2870+
28642871
ModuleDecl *ClangModuleUnit::getAdapterModule() const {
28652872
if (!clangModule)
28662873
return nullptr;
@@ -3325,8 +3332,8 @@ importName(const clang::NamedDecl *D,
33253332
getDeclName();
33263333
}
33273334

3328-
bool swift::isInOverlayModuleForImportedModule(DeclContext *overlayDC,
3329-
DeclContext *importedDC) {
3335+
bool swift::isInOverlayModuleForImportedModule(const DeclContext *overlayDC,
3336+
const DeclContext *importedDC) {
33303337
overlayDC = overlayDC->getModuleScopeContext();
33313338
importedDC = importedDC->getModuleScopeContext();
33323339

lib/Serialization/Deserialization.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "swift/AST/PrettyStackTrace.h"
2525
#include "swift/AST/ProtocolConformance.h"
2626
#include "swift/ClangImporter/ClangImporter.h"
27+
#include "swift/ClangImporter/ClangModule.h"
2728
#include "swift/Serialization/BCReadingExtras.h"
2829
#include "swift/Serialization/SerializedModuleLoader.h"
2930
#include "swift/Basic/Defer.h"
@@ -1098,6 +1099,23 @@ getActualCtorInitializerKind(uint8_t raw) {
10981099
return None;
10991100
}
11001101

1102+
/// Determine whether the two modules are re-exported to the same module.
1103+
static bool reExportedToSameModule(const ModuleDecl *fromModule,
1104+
const ModuleDecl *toModule) {
1105+
auto fromClangModule
1106+
= dyn_cast<ClangModuleUnit>(fromModule->getFiles().front());
1107+
if (!fromClangModule)
1108+
return false;
1109+
1110+
auto toClangModule
1111+
= dyn_cast<ClangModuleUnit>(toModule->getFiles().front());
1112+
if (!toClangModule)
1113+
return false;
1114+
1115+
return fromClangModule->getExportedModuleName() ==
1116+
toClangModule->getExportedModuleName();
1117+
}
1118+
11011119
/// Remove values from \p values that don't match the expected type or module.
11021120
///
11031121
/// Any of \p expectedTy, \p expectedModule, or \p expectedGenericSig can be
@@ -1130,7 +1148,8 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
11301148
// FIXME: Should be able to move a value from an extension in a derived
11311149
// module to the original definition in a base module.
11321150
if (expectedModule && !value->hasClangNode() &&
1133-
value->getModuleContext() != expectedModule)
1151+
value->getModuleContext() != expectedModule &&
1152+
!reExportedToSameModule(value->getModuleContext(), expectedModule))
11341153
return true;
11351154

11361155
// If we're expecting a member within a constrained extension with a

lib/Serialization/ModuleFile.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
#include "swift/AST/USRGeneration.h"
2222
#include "swift/Basic/Range.h"
2323
#include "swift/ClangImporter/ClangImporter.h"
24+
#include "swift/ClangImporter/ClangModule.h"
2425
#include "swift/Serialization/BCReadingExtras.h"
2526
#include "swift/Serialization/SerializedModuleLoader.h"
26-
#include "clang/Basic/Module.h"
2727
#include "llvm/ADT/StringExtras.h"
2828
#include "llvm/Support/MemoryBuffer.h"
2929
#include "llvm/Support/OnDiskHashTable.h"
@@ -1562,18 +1562,20 @@ void ModuleFile::loadExtensions(NominalTypeDecl *nominal) {
15621562
}
15631563

15641564
if (nominal->getParent()->isModuleScopeContext()) {
1565-
Identifier moduleName = nominal->getParentModule()->getName();
1565+
auto parentModule = nominal->getParentModule();
1566+
StringRef moduleName = parentModule->getName().str();
15661567

15671568
// If the originating module is a private module whose interface is
15681569
// re-exported via public module, check the name of the public module.
1569-
if (auto clangModule
1570-
= nominal->getParentModule()->findUnderlyingClangModule()) {
1571-
if (!clangModule->ExportAsModule.empty())
1572-
moduleName = getContext().getIdentifier(clangModule->ExportAsModule);
1570+
std::string exportedModuleName;
1571+
if (auto clangModuleUnit =
1572+
dyn_cast<ClangModuleUnit>(parentModule->getFiles().front())) {
1573+
exportedModuleName = clangModuleUnit->getExportedModuleName();
1574+
moduleName = exportedModuleName;
15731575
}
15741576

15751577
for (auto item : *iter) {
1576-
if (item.first != moduleName.str())
1578+
if (item.first != moduleName)
15771579
continue;
15781580
Expected<Decl *> declOrError = getDeclChecked(item.second);
15791581
if (!declOrError) {

lib/Serialization/Serialization.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
#include "swift/ClangImporter/ClangModule.h"
3838
#include "swift/Serialization/SerializationOptions.h"
3939

40-
#include "clang/Basic/Module.h"
4140
// FIXME: We're just using CompilerInstance::createOutputFile.
4241
// This API should be sunk down to LLVM.
4342
#include "clang/Frontend/CompilerInstance.h"
@@ -533,13 +532,14 @@ IdentifierID Serializer::addModuleRef(const ModuleDecl *M) {
533532

534533
// If we're referring to a member of a private module that will be
535534
// re-exported via a public module, record the public module's name.
536-
if (auto clangModule = M->findUnderlyingClangModule()) {
537-
if (!clangModule->ExportAsModule.empty()) {
538-
auto publicModuleName =
539-
M->getASTContext().getIdentifier(clangModule->ExportAsModule);
540-
return addDeclBaseNameRef(publicModuleName);
541-
}
535+
if (auto clangModuleUnit =
536+
dyn_cast<ClangModuleUnit>(M->getFiles().front())) {
537+
auto exportedModuleName =
538+
M->getASTContext().getIdentifier(
539+
clangModuleUnit->getExportedModuleName());
540+
return addDeclBaseNameRef(exportedModuleName);
542541
}
542+
543543
assert(!M->getName().empty());
544544
return addDeclBaseNameRef(M->getName());
545545
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,49 @@
11
@_exported import SomeKit
2+
import Foundation
23

34
extension SKWidget {
45
public func extensionMethod() -> ExtensionType { return ExtensionType() }
56

67
public struct ExtensionType { }
78
}
89

10+
extension SKWidget.ExtensionType {
11+
public func foo() { }
12+
}
13+
14+
extension NSObject {
15+
public func doSomethingElse(_: SKWidget) { }
16+
}
917

18+
extension SKWidget.Error {
19+
public func getCode(from widget: SKWidget) -> SKWidget.Error.Code {
20+
return widget.getCurrentError()
21+
}
22+
}
23+
24+
extension SKWidget.Error.Code {
25+
public var isBoom: Bool {
26+
return self == .boom
27+
}
28+
}
29+
30+
public protocol HasAnObject {
31+
var anObject: NSObject { get set }
32+
}
33+
34+
extension SKWidget : HasAnObject { }
35+
36+
@inline(__always)
37+
public func inlineWidgetOperations(_ widget: SKWidget) {
38+
widget.extensionMethod().foo()
39+
widget.someObjCMethod()
40+
widget.someObjCExtensionMethod()
41+
widget.doSomething(with: widget)
42+
widget.doSomethingElse(widget)
43+
let obj = widget.anObject
44+
widget.anObject = obj
45+
_ = SKWidget.Error(.boom).getCode(from: widget).isBoom
46+
var hao: HasAnObject = widget
47+
someKitGlobalFunc()
48+
hao.anObject = widget
49+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,26 @@
11
@import ObjectiveC;
22

33
@interface SKWidget : NSObject
4+
- (void)someObjCMethod;
45
@end
6+
7+
@interface SKWidget(ObjCAPI)
8+
- (void)someObjCExtensionMethod;
9+
@property (readwrite,strong,nonnull) NSObject *anObject;
10+
@end
11+
12+
@interface NSObject (SKWidget)
13+
- (void)doSomethingWithWidget:(nonnull SKWidget *)widget;
14+
@end
15+
16+
extern NSString * _Nonnull const SKWidgetErrorDomain;
17+
typedef enum __attribute__((ns_error_domain(SKWidgetErrorDomain))) __attribute__((swift_name("SKWidget.Error"))) SKWidgetErrorCode : NSInteger {
18+
SKWidgetErrorNone = 0,
19+
SKWidgetErrorBoom = 1
20+
} SKWidgetErrorCode;
21+
22+
@interface SKWidget(Erroneous)
23+
- (SKWidgetErrorCode)getCurrentError;
24+
@end
25+
26+
extern void someKitGlobalFunc(void);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,27 @@
11
@import ObjectiveC;
2+
@import Foundation;
23

34
@interface SKWidget : NSObject
5+
- (void)someObjCMethod;
46
@end
7+
8+
@interface SKWidget(ObjCAPI)
9+
- (void)someObjCExtensionMethod;
10+
@property (readwrite,strong,nonnull) NSObject *anObject;
11+
@end
12+
13+
@interface NSObject (SKWidget)
14+
- (void)doSomethingWithWidget:(nonnull SKWidget *)widget;
15+
@end
16+
17+
extern NSString * _Nonnull const SKWidgetErrorDomain;
18+
typedef enum __attribute__((ns_error_domain(SKWidgetErrorDomain))) __attribute__((swift_name("SKWidget.Error"))) SKWidgetErrorCode : NSInteger {
19+
SKWidgetErrorNone = 0,
20+
SKWidgetErrorBoom = 1
21+
} SKWidgetErrorCode;
22+
23+
@interface SKWidget(Erroneous)
24+
- (SKWidgetErrorCode)getCurrentError;
25+
@end
26+
27+
extern void someKitGlobalFunc(void);
Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,46 @@
11
// RUN: rm -rf %t
22
// RUN: mkdir -p %t
33

4+
// FIXME: BEGIN -enable-source-import hackaround
5+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource) -emit-module -o %t %clang-importer-sdk-path/swift-modules/CoreGraphics.swift
6+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -o %t %clang-importer-sdk-path/swift-modules/Foundation.swift
7+
// FIXME: END -enable-source-import hackaround
8+
49
// Build the overlay with private frameworks.
5-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-module -F %S/Inputs/privateframeworks/withprivate -o %t %S/Inputs/privateframeworks/overlay/SomeKit.swift
10+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -F %S/Inputs/privateframeworks/withprivate -o %t %S/Inputs/privateframeworks/overlay/SomeKit.swift
11+
12+
// Use the overlay with private frameworks.
13+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withprivate %s -verify
14+
15+
// Use the overlay without private frameworks.
16+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withoutprivate -I %t %s
17+
18+
// Build the overlay with public frameworks.
19+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-module -F %S/Inputs/privateframeworks/withoutprivate -o %t %S/Inputs/privateframeworks/overlay/SomeKit.swift
620

721
// Use the overlay with private frameworks.
8-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -F %S/Inputs/privateframeworks/withprivate -I %t %s -verify
22+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withprivate %s -verify
923

1024
// Use the overlay without private frameworks.
11-
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -F %S/Inputs/privateframeworks/withoutprivate -I %t %s -verify
25+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk-nosource -I %t) -emit-sil -o /dev/null -F %S/Inputs/privateframeworks/withoutprivate -I %t %s
1226

1327
// REQUIRES: objc_interop
1428

1529
import SomeKit
1630

1731
func testWidget(widget: SKWidget) {
18-
_ = widget.extensionMethod()
32+
_ = widget.someObjCMethod()
33+
_ = widget.someObjCExtensionMethod()
34+
35+
let ext = widget.extensionMethod()
36+
ext.foo()
37+
38+
widget.doSomethingElse(widget)
39+
inlineWidgetOperations(widget)
40+
}
41+
42+
func testError(widget: SKWidget) {
43+
let c: SKWidget.Error.Code = SKWidget.Error(.boom).getCode(from: widget)
44+
if c.isBoom { }
1945
}
2046

0 commit comments

Comments
 (0)