Skip to content

Preload standard library in ModuleInterfaceBuilder #36594

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 15, 2021
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
5 changes: 5 additions & 0 deletions include/swift/Basic/SourceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,11 @@ class SourceManager {
bool isLocInVirtualFile(SourceLoc Loc) const {
return getVirtualFile(Loc) != nullptr;
}

/// Return a SourceLoc in \c this corresponding to \p otherLoc, which must be
/// owned by \p otherManager. Returns an invalid SourceLoc if it cannot be
/// translated.
SourceLoc getLocForForeignLoc(SourceLoc otherLoc, SourceManager &otherMgr);
};

} // end namespace swift
Expand Down
24 changes: 24 additions & 0 deletions lib/Basic/SourceLoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,3 +395,27 @@ SourceManager::getLocFromExternalSource(StringRef Path, unsigned Line,
return SourceLoc();
return getLocForOffset(BufferId, *Offset);
}

SourceLoc
SourceManager::getLocForForeignLoc(SourceLoc otherLoc,
SourceManager &otherMgr) {
if (&otherMgr == this || otherLoc.isInvalid())
return otherLoc;

assert(otherMgr.isOwning(otherLoc));

if (auto otherBufferID = otherMgr.findBufferContainingLocInternal(otherLoc)) {
auto offset = otherMgr.getLocOffsetInBuffer(otherLoc, *otherBufferID);

auto otherBufferName = otherMgr.getIdentifierForBuffer(*otherBufferID);
auto thisBufferID = getIDForBufferIdentifier(otherBufferName);
if (!thisBufferID) {
thisBufferID = addMemBufferCopy(
otherMgr.getEntireTextForBuffer(*otherBufferID), otherBufferName);
}

return getLocForOffset(*thisBufferID, offset);
}

return SourceLoc();
}
16 changes: 16 additions & 0 deletions lib/Frontend/DiagnosticVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,22 @@ void DiagnosticVerifier::handleDiagnostic(SourceManager &SM,
CapturedDiagnostics.emplace_back(message, StringRef(), Info.Kind, Info.Loc,
0, 0, fixIts, eduNotes);
}

// If this diagnostic came from a different SourceManager (as can happen
// while compiling a module interface), translate its SourceLocs to match the
// verifier's SourceManager.
if (&SM != &(this->SM)) {
auto &capturedDiag = CapturedDiagnostics.back();
auto &correctSM = this->SM;

capturedDiag.Loc = correctSM.getLocForForeignLoc(capturedDiag.Loc, SM);
for (auto &fixIt : capturedDiag.FixIts) {
auto newStart = correctSM.getLocForForeignLoc(fixIt.getRange().getStart(),
SM);
fixIt.getRange() = CharSourceRange(newStart,
fixIt.getRange().getByteLength());
}
}
}

/// Once all diagnostics have been captured, perform verification.
Expand Down
1 change: 1 addition & 0 deletions lib/Frontend/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ bool CompilerInstance::setupDiagnosticVerifierIfNeeded() {
Diagnostics.diagnose(SourceLoc(), diag::error_open_input_file,
filename, result.getError().message());
hadError |= true;
continue;
}

auto bufferID = SourceMgr.addNewSourceBuffer(std::move(result.get()));
Expand Down
7 changes: 7 additions & 0 deletions lib/Frontend/ModuleInterfaceBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,13 @@ bool ModuleInterfaceBuilder::buildSwiftModuleInternal(
InputInfo.getPrimarySpecificPaths().SupplementaryOutputs;
StringRef OutPath = OutputInfo.ModuleOutputPath;

// Bail out if we're going to use the standard library but can't load it. If
// we don't do this before we try to build the interface, we could end up
// trying to rebuild a broken standard library dozens of times due to
// multiple calls to `ASTContext::getStdlibModule()`.
if (SubInstance.loadStdlibIfNeeded())
return std::make_error_code(std::errc::not_supported);

// Build the .swiftmodule; this is a _very_ abridged version of the logic
// in performCompile in libFrontendTool, specialized, to just the one
// module-serialization task we're trying to do here.
Expand Down
19 changes: 19 additions & 0 deletions test/ModuleInterface/BadStdlib.swiftinterface
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// swift-interface-format-version: 1.0
// swift-module-flags: -target x86_64-apple-macos10.9 -module-name BadStdlib

// no-error@-3

// Tests whether -compile-module-from-interface correctly stops early when the
// standard library module interface is broken, rather than trying to limp along
// without a standard library, which tends to cause ClangImporter crashes (among
// other things.)

// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend(mock-sdk: -sdk %/S/Inputs/BadStdlib.sdk -module-cache-path %/t/module-cache -resource-dir %/S/Inputs/BadStdlib.sdk) -compile-module-from-interface -o %/t/BadStdlib.swiftmodule %s -verify -verify-additional-file %/S/Inputs/BadStdlib.sdk/usr/lib/swift/Swift.swiftmodule/x86_64-apple-macos.swiftinterface

import ClangMod

public func useHasPointer(_: HasPointer)

// FIXME: SR-14489
// UNSUPPORTED: windows
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
typedef int * HasPointer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module HasPointer {
header "HasPointer.h"
export *
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// swift-interface-format-version: 1.0
// swift-module-flags: -target x86_64-apple-macos10.9 -module-name Swift -parse-stdlib

// If the test fails, this error will be emitted twice, not once.
// expected-error@-4 {{failed to build module 'Swift' for importation due to the errors above}}

public struct BadType {
public var property: UndeclaredType { get set } // expected-error {{cannot find type 'UndeclaredType' in scope}}
}