Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/swift/AST/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -810,6 +810,14 @@ class FileUnit : public DeclContext {
return nullptr;
}

/// Returns the name to use when referencing entities in this file.
///
/// Usually this is the module name itself, but certain Clang features allow
/// substituting another name instead.
virtual StringRef getExportedModuleName() const {
return getParentModule()->getName().str();
}

/// Traverse the decls within this file.
///
/// \returns true if traversal was aborted, false if it completed
Expand Down
6 changes: 6 additions & 0 deletions include/swift/AST/PrintOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,12 @@ struct PrintOptions {
/// type might be ambiguous.
bool FullyQualifiedTypesIfAmbiguous = false;

/// If true, printed module names will use the "exported" name, which may be
/// different from the regular name.
///
/// \see FileUnit::getExportedModuleName
bool UseExportedModuleNames = false;

/// Print Swift.Array and Swift.Optional with sugared syntax
/// ([] and ?), even if there are no sugar type nodes.
bool SynthesizeSugarOnTypes = false;
Expand Down
2 changes: 1 addition & 1 deletion include/swift/ClangImporter/ClangModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class ClangModuleUnit final : public LoadedFile {
/// Retrieve the "exported" name of the module, which is usually the module
/// name, but might be the name of the public module through which this
/// (private) module is re-exported.
std::string getExportedModuleName() const;
StringRef getExportedModuleName() const override;

virtual bool isSystemModule() const override;

Expand Down
11 changes: 9 additions & 2 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ PrintOptions PrintOptions::printParseableInterfaceFile() {
result.TypeDefinitions = true;
result.PrintIfConfig = false;
result.FullyQualifiedTypes = true;
result.UseExportedModuleNames = true;
result.AllowNullTypes = false;
result.SkipImports = true;
result.OmitNameOfInaccessibleProperties = true;
Expand Down Expand Up @@ -3338,8 +3339,14 @@ class TypePrinter : public TypeVisitor<TypePrinter> {

template <typename T>
void printModuleContext(T *Ty) {
ModuleDecl *Mod = Ty->getDecl()->getModuleContext();
Printer.printModuleRef(Mod, Mod->getName());
FileUnit *File = cast<FileUnit>(Ty->getDecl()->getModuleScopeContext());
ModuleDecl *Mod = File->getParentModule();

Identifier Name = Mod->getName();
if (Options.UseExportedModuleNames)
Name = Mod->getASTContext().getIdentifier(File->getExportedModuleName());

Printer.printModuleRef(Mod, Name);
Printer << ".";
}

Expand Down
2 changes: 1 addition & 1 deletion lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3120,7 +3120,7 @@ clang::ASTContext &ClangModuleUnit::getClangASTContext() const {
return owner.getClangASTContext();
}

std::string ClangModuleUnit::getExportedModuleName() const {
StringRef ClangModuleUnit::getExportedModuleName() const {
if (clangModule && !clangModule->ExportAsModule.empty())
return clangModule->ExportAsModule;

Expand Down
2 changes: 1 addition & 1 deletion lib/Serialization/Deserialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1147,7 +1147,7 @@ static bool isReExportedToModule(const ValueDecl *value,
= dyn_cast<ClangModuleUnit>(valueDC->getModuleScopeContext());
if (!fromClangModule)
return false;
std::string exportedName = fromClangModule->getExportedModuleName();
StringRef exportedName = fromClangModule->getExportedModuleName();

auto toClangModule
= dyn_cast<ClangModuleUnit>(expectedModule->getFiles().front());
Expand Down
14 changes: 2 additions & 12 deletions lib/Serialization/ModuleFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
#include "swift/AST/USRGeneration.h"
#include "swift/Basic/Range.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Serialization/BCReadingExtras.h"
#include "swift/Serialization/SerializedModuleLoader.h"
#include "llvm/ADT/StringExtras.h"
Expand Down Expand Up @@ -1842,17 +1841,8 @@ void ModuleFile::loadExtensions(NominalTypeDecl *nominal) {
}

if (nominal->getParent()->isModuleScopeContext()) {
auto parentModule = nominal->getParentModule();
StringRef moduleName = parentModule->getName().str();

// If the originating module is a private module whose interface is
// re-exported via public module, check the name of the public module.
std::string exportedModuleName;
if (auto clangModuleUnit =
dyn_cast<ClangModuleUnit>(parentModule->getFiles().front())) {
exportedModuleName = clangModuleUnit->getExportedModuleName();
moduleName = exportedModuleName;
}
auto parentFile = cast<FileUnit>(nominal->getParent());
StringRef moduleName = parentFile->getExportedModuleName();

for (auto item : *iter) {
if (item.first != moduleName)
Expand Down
42 changes: 19 additions & 23 deletions lib/Serialization/Serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ namespace {
int32_t getNameDataForBase(const NominalTypeDecl *nominal,
StringRef *dataToWrite = nullptr) {
if (nominal->getDeclContext()->isModuleScopeContext())
return -Serializer.addModuleRef(nominal->getParentModule());
return -Serializer.addContainingModuleRef(nominal->getDeclContext());

auto &mangledName = MangledNameCache[nominal];
if (mangledName.empty())
Expand Down Expand Up @@ -731,7 +731,12 @@ IdentifierID Serializer::addFilename(StringRef filename) {
return addUniquedString(filename).second;
}

IdentifierID Serializer::addModuleRef(const ModuleDecl *M) {
IdentifierID Serializer::addContainingModuleRef(const DeclContext *DC) {
assert(!isa<ModuleDecl>(DC) &&
"References should be to things within modules");
const FileUnit *file = cast<FileUnit>(DC->getModuleScopeContext());
const ModuleDecl *M = file->getParentModule();

if (M == this->M)
return CURRENT_MODULE_ID;
if (M == this->M->getASTContext().TheBuiltinModule)
Expand All @@ -743,18 +748,10 @@ IdentifierID Serializer::addModuleRef(const ModuleDecl *M) {
if (M == clangImporter->getImportedHeaderModule())
return OBJC_HEADER_MODULE_ID;

// 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.
if (auto clangModuleUnit =
dyn_cast<ClangModuleUnit>(M->getFiles().front())) {
auto exportedModuleName =
M->getASTContext().getIdentifier(
clangModuleUnit->getExportedModuleName());
return addDeclBaseNameRef(exportedModuleName);
}

assert(!M->getName().empty());
return addDeclBaseNameRef(M->getName());
auto exportedModuleName = file->getExportedModuleName();
assert(!exportedModuleName.empty());
auto exportedModuleID = M->getASTContext().getIdentifier(exportedModuleName);
return addDeclBaseNameRef(exportedModuleID);
}

SILLayoutID Serializer::addSILLayoutRef(SILLayout *layout) {
Expand Down Expand Up @@ -1650,7 +1647,7 @@ Serializer::writeConformance(ProtocolConformanceRef conformanceRef,
abbrCode,
addDeclRef(normal->getProtocol()),
addDeclRef(normal->getType()->getAnyNominal()),
addModuleRef(normal->getDeclContext()->getParentModule()));
addContainingModuleRef(normal->getDeclContext()));
}
break;
}
Expand Down Expand Up @@ -1888,14 +1885,13 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
case DeclContextKind::EnumElementDecl:
llvm_unreachable("cannot cross-reference this context");

case DeclContextKind::FileUnit:
DC = cast<FileUnit>(DC)->getParentModule();
LLVM_FALLTHROUGH;

case DeclContextKind::Module:
llvm_unreachable("should only cross-reference something within a file");

case DeclContextKind::FileUnit:
abbrCode = DeclTypeAbbrCodes[XRefLayout::Code];
XRefLayout::emitRecord(Out, ScratchRecord, abbrCode,
addModuleRef(cast<ModuleDecl>(DC)), pathLen);
addContainingModuleRef(DC), pathLen);
break;

case DeclContextKind::GenericTypeDecl: {
Expand Down Expand Up @@ -1932,7 +1928,7 @@ void Serializer::writeCrossReference(const DeclContext *DC, uint32_t pathLen) {
genericSig = ext->getGenericSignature()->getCanonicalSignature();
}
XRefExtensionPathPieceLayout::emitRecord(
Out, ScratchRecord, abbrCode, addModuleRef(DC->getParentModule()),
Out, ScratchRecord, abbrCode, addContainingModuleRef(DC),
addGenericSignatureRef(genericSig));
break;
}
Expand Down Expand Up @@ -2025,7 +2021,7 @@ void Serializer::writeCrossReference(const Decl *D) {
unsigned abbrCode;

if (auto op = dyn_cast<OperatorDecl>(D)) {
writeCrossReference(op->getModuleContext(), 1);
writeCrossReference(op->getDeclContext(), 1);

abbrCode = DeclTypeAbbrCodes[XRefOperatorOrAccessorPathPieceLayout::Code];
auto nameID = addDeclBaseNameRef(op->getName());
Expand All @@ -2037,7 +2033,7 @@ void Serializer::writeCrossReference(const Decl *D) {
}

if (auto prec = dyn_cast<PrecedenceGroupDecl>(D)) {
writeCrossReference(prec->getModuleContext(), 1);
writeCrossReference(prec->getDeclContext(), 1);

abbrCode = DeclTypeAbbrCodes[XRefOperatorOrAccessorPathPieceLayout::Code];
auto nameID = addDeclBaseNameRef(prec->getName());
Expand Down
9 changes: 6 additions & 3 deletions lib/Serialization/Serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,13 +540,16 @@ class Serializer : public SerializerBase {
/// Records the use of the given SILLayout.
SILLayoutID addSILLayoutRef(SILLayout *layout);

/// Records the use of the given module.
/// Records the module containing \p DC.
///
/// The module's name will be scheduled for serialization if necessary.
/// The module's name will be scheduled for serialization if necessary. This
/// may not be exactly the same as the name of the module containing DC;
/// instead, it will match the containing file's "exported module name".
///
/// \returns The ID for the identifier for the module's name, or one of the
/// special module codes defined above.
IdentifierID addModuleRef(const ModuleDecl *M);
/// \see FileUnit::getExportedModuleName
IdentifierID addContainingModuleRef(const DeclContext *DC);

/// Write a normal protocol conformance.
void writeNormalConformance(const NormalProtocolConformance *conformance);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#import <ExportAsCoreKit.h>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
struct CKThing {
long value;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module CoreKit {
header "CoreKit.h"
header "ExportAsCoreKit.h"
export *
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#import <ExportAsCoreKit.h>
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
struct CKThing {
long value;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module CoreKit {
header "CoreKit.h"
export *
}

module ExportAsCoreKit_BAD {
header "ExportAsCoreKit.h"
export_as CoreKit
export *
}
19 changes: 19 additions & 0 deletions test/ParseableInterface/exported-module-name.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -typecheck -emit-parseable-module-interface-path %t/CoreKitClient.swiftinterface -module-name CoreKitClient -I %S/Inputs/exported-module-name-before %s
// RUN: %FileCheck -implicit-check-not BAD %s < %t/CoreKitClient.swiftinterface

// Test that we can rebuild it even when the "export as" module goes away.
// RUN: %target-swift-frontend -build-module-from-parseable-interface -o %t/CoreKitClient.swiftmodule -I %S/Inputs/exported-module-name-after %t/CoreKitClient.swiftinterface

// CHECK: import CoreKit
import CoreKit

// CHECK-LABEL: public struct CKThingWrapper : RawRepresentable {
public struct CKThingWrapper: RawRepresentable {
public var rawValue: CKThing
public init(rawValue: CKThing) {
self.rawValue = rawValue
}
// Note that this is CoreKit.CKThing, not ExportAsCoreKit.CKThing
// CHECK: public typealias RawValue = CoreKit.CKThing
} // CHECK: {{^}$}}