[Serialization] Handle re-export of error enums mapped via import-as-member.

Thanks to Jordan for coming up with the right combination of features to
trigger this code path.
This commit is contained in:
Doug Gregor
2017-09-15 16:58:26 -07:00
parent fc20debc36
commit e3207f753c
6 changed files with 34 additions and 15 deletions

View File

@@ -24,6 +24,7 @@
#include "swift/AST/PrettyStackTrace.h" #include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/ProtocolConformance.h" #include "swift/AST/ProtocolConformance.h"
#include "swift/ClangImporter/ClangImporter.h" #include "swift/ClangImporter/ClangImporter.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Serialization/BCReadingExtras.h" #include "swift/Serialization/BCReadingExtras.h"
#include "swift/Serialization/SerializedModuleLoader.h" #include "swift/Serialization/SerializedModuleLoader.h"
#include "swift/Basic/Defer.h" #include "swift/Basic/Defer.h"
@@ -1098,6 +1099,23 @@ getActualCtorInitializerKind(uint8_t raw) {
return None; return None;
} }
/// Determine whether the two modules are re-exported to the same module.
static bool reExportedToSameModule(const ModuleDecl *fromModule,
const ModuleDecl *toModule) {
auto fromClangModule
= dyn_cast<ClangModuleUnit>(fromModule->getFiles().front());
if (!fromClangModule)
return false;
auto toClangModule
= dyn_cast<ClangModuleUnit>(toModule->getFiles().front());
if (!toClangModule)
return false;
return fromClangModule->getExportedModuleName() ==
toClangModule->getExportedModuleName();
}
/// Remove values from \p values that don't match the expected type or module. /// Remove values from \p values that don't match the expected type or module.
/// ///
/// Any of \p expectedTy, \p expectedModule, or \p expectedGenericSig can be /// Any of \p expectedTy, \p expectedModule, or \p expectedGenericSig can be
@@ -1130,7 +1148,8 @@ static void filterValues(Type expectedTy, ModuleDecl *expectedModule,
// FIXME: Should be able to move a value from an extension in a derived // FIXME: Should be able to move a value from an extension in a derived
// module to the original definition in a base module. // module to the original definition in a base module.
if (expectedModule && !value->hasClangNode() && if (expectedModule && !value->hasClangNode() &&
value->getModuleContext() != expectedModule) value->getModuleContext() != expectedModule &&
!reExportedToSameModule(value->getModuleContext(), expectedModule))
return true; return true;
// If we're expecting a member within a constrained extension with a // If we're expecting a member within a constrained extension with a

View File

@@ -37,7 +37,6 @@
#include "swift/ClangImporter/ClangModule.h" #include "swift/ClangImporter/ClangModule.h"
#include "swift/Serialization/SerializationOptions.h" #include "swift/Serialization/SerializationOptions.h"
#include "clang/Basic/Module.h"
// FIXME: We're just using CompilerInstance::createOutputFile. // FIXME: We're just using CompilerInstance::createOutputFile.
// This API should be sunk down to LLVM. // This API should be sunk down to LLVM.
#include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInstance.h"
@@ -533,13 +532,14 @@ IdentifierID Serializer::addModuleRef(const ModuleDecl *M) {
// If we're referring to a member of a private module that will be // If we're referring to a member of a private module that will be
// re-exported via a public module, record the public module's name. // re-exported via a public module, record the public module's name.
if (auto clangModule = M->findUnderlyingClangModule()) { if (auto clangModuleUnit =
if (!clangModule->ExportAsModule.empty()) { dyn_cast<ClangModuleUnit>(M->getFiles().front())) {
auto publicModuleName = auto exportedModuleName =
M->getASTContext().getIdentifier(clangModule->ExportAsModule); M->getASTContext().getIdentifier(
return addDeclBaseNameRef(publicModuleName); clangModuleUnit->getExportedModuleName());
} return addDeclBaseNameRef(exportedModuleName);
} }
assert(!M->getName().empty()); assert(!M->getName().empty());
return addDeclBaseNameRef(M->getName()); return addDeclBaseNameRef(M->getName());
} }

View File

@@ -15,13 +15,13 @@ extension NSObject {
public func doSomethingElse(_: SKWidget) { } public func doSomethingElse(_: SKWidget) { }
} }
extension SKWidgetError { extension SKWidget.Error {
public func getCode(from widget: SKWidget) -> SKWidgetError.Code { public func getCode(from widget: SKWidget) -> SKWidget.Error.Code {
return widget.getCurrentError() return widget.getCurrentError()
} }
} }
extension SKWidgetError.Code { extension SKWidget.Error.Code {
public var isBoom: Bool { public var isBoom: Bool {
return self == .boom return self == .boom
} }
@@ -42,7 +42,7 @@ public func inlineWidgetOperations(_ widget: SKWidget) {
widget.doSomethingElse(widget) widget.doSomethingElse(widget)
let obj = widget.anObject let obj = widget.anObject
widget.anObject = obj widget.anObject = obj
_ = SKWidgetError(.boom).getCode(from: widget).isBoom _ = SKWidget.Error(.boom).getCode(from: widget).isBoom
var hao: HasAnObject = widget var hao: HasAnObject = widget
someKitGlobalFunc() someKitGlobalFunc()
hao.anObject = widget hao.anObject = widget

View File

@@ -14,7 +14,7 @@
@end @end
extern NSString * _Nonnull const SKWidgetErrorDomain; extern NSString * _Nonnull const SKWidgetErrorDomain;
typedef enum __attribute__((ns_error_domain(SKWidgetErrorDomain))) SKWidgetErrorCode : NSInteger { typedef enum __attribute__((ns_error_domain(SKWidgetErrorDomain))) __attribute__((swift_name("SKWidget.Error"))) SKWidgetErrorCode : NSInteger {
SKWidgetErrorNone = 0, SKWidgetErrorNone = 0,
SKWidgetErrorBoom = 1 SKWidgetErrorBoom = 1
} SKWidgetErrorCode; } SKWidgetErrorCode;

View File

@@ -15,7 +15,7 @@
@end @end
extern NSString * _Nonnull const SKWidgetErrorDomain; extern NSString * _Nonnull const SKWidgetErrorDomain;
typedef enum __attribute__((ns_error_domain(SKWidgetErrorDomain))) SKWidgetErrorCode : NSInteger { typedef enum __attribute__((ns_error_domain(SKWidgetErrorDomain))) __attribute__((swift_name("SKWidget.Error"))) SKWidgetErrorCode : NSInteger {
SKWidgetErrorNone = 0, SKWidgetErrorNone = 0,
SKWidgetErrorBoom = 1 SKWidgetErrorBoom = 1
} SKWidgetErrorCode; } SKWidgetErrorCode;

View File

@@ -40,7 +40,7 @@ func testWidget(widget: SKWidget) {
} }
func testError(widget: SKWidget) { func testError(widget: SKWidget) {
let c: SKWidgetError.Code = SKWidgetError(.boom).getCode(from: widget) let c: SKWidget.Error.Code = SKWidget.Error(.boom).getCode(from: widget)
if c.isBoom { } if c.isBoom { }
} }