Files
swift-mirror/lib/Sema/SourceLoader.cpp
Doug Gregor b3badc601a Handle consistency checking that requires the entire module.
Objective-C method unintended override checking is one such case where
properly checking unintended overrides requires us to essentially look
at the whole module, because one translation unit may declare
something that produces an Objective-C method "setFoo:" in a
superclass while another translation unit declares something with a
distinct name that produces an Objective-C method "setFoo:". So, when
we don't have a primary file (e.g., when we're doing the merge-module
step), delay such checks until after all the source files for the
module have been type-checked. When there is a primary file, we
perform the checking that we can based on type checking that primary
file (and whatever got touched along the way), so we get a subset of
the proper diagnostics.

Swift SVN r23179
2014-11-08 06:20:57 +00:00

146 lines
5.0 KiB
C++

//===--- SourceLoader.cpp - Import .swift files as modules ------*- c++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief A simple module loader that loads .swift source files.
///
//===----------------------------------------------------------------------===//
#include "swift/Sema/SourceLoader.h"
#include "swift/Subsystems.h"
#include "swift/AST/AST.h"
#include "swift/AST/DiagnosticsSema.h"
#include "swift/Parse/DelayedParsingCallbacks.h"
#include "swift/Parse/PersistentParserState.h"
#include "swift/Basic/SourceManager.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SaveAndRestore.h"
#include <system_error>
using namespace swift;
// FIXME: Basically the same as SerializedModuleLoader.
using FileOrError = llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>>;
static FileOrError findModule(ASTContext &ctx, StringRef moduleID,
SourceLoc importLoc) {
llvm::SmallString<128> inputFilename;
for (auto Path : ctx.SearchPathOpts.ImportSearchPaths) {
inputFilename = Path;
llvm::sys::path::append(inputFilename, moduleID);
inputFilename.append(".swift");
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr =
llvm::MemoryBuffer::getFile(inputFilename.str());
// Return if we loaded a file
if (FileBufOrErr)
return FileBufOrErr;
// Or if we get any error other than the file not existing
auto err = FileBufOrErr.getError();
if (err != std::errc::no_such_file_or_directory)
return FileBufOrErr;
}
return make_error_code(std::errc::no_such_file_or_directory);
}
namespace {
/// Don't parse any function bodies except those that are transparent.
class SkipNonTransparentFunctions : public DelayedParsingCallbacks {
bool shouldDelayFunctionBodyParsing(Parser &TheParser,
AbstractFunctionDecl *AFD,
const DeclAttributes &Attrs,
SourceRange BodyRange) override {
return Attrs.hasAttribute<TransparentAttr>();
}
};
} // unnamed namespace
Module *SourceLoader::loadModule(SourceLoc importLoc,
ArrayRef<std::pair<Identifier, SourceLoc>> path) {
// FIXME: Swift submodules?
if (path.size() > 1)
return nullptr;
auto moduleID = path[0];
FileOrError inputFileOrError = findModule(Ctx, moduleID.first.str(),
moduleID.second);
if (!inputFileOrError) {
auto err = inputFileOrError.getError();
if (err != std::errc::no_such_file_or_directory) {
Ctx.Diags.diagnose(moduleID.second, diag::sema_opening_import,
moduleID.first, err.message());
}
return nullptr;
}
std::unique_ptr<llvm::MemoryBuffer> inputFile =
std::move(inputFileOrError.get());
addDependency(inputFile->getBufferIdentifier());
// Turn off debugging while parsing other modules.
llvm::SaveAndRestore<bool> turnOffDebug(Ctx.LangOpts.DebugConstraintSolver,
false);
unsigned bufferID;
if (auto BufID =
Ctx.SourceMgr.getIDForBufferIdentifier(inputFile->getBufferIdentifier()))
bufferID = BufID.getValue();
else
bufferID = Ctx.SourceMgr.addNewSourceBuffer(std::move(inputFile));
auto *importMod = Module::create(moduleID.first, Ctx);
Ctx.LoadedModules[moduleID.first] = importMod;
auto implicitImportKind = SourceFile::ImplicitModuleImportKind::Stdlib;
if (!Ctx.getStdlibModule())
implicitImportKind = SourceFile::ImplicitModuleImportKind::None;
auto *importFile = new (Ctx) SourceFile(*importMod, SourceFileKind::Library,
bufferID, implicitImportKind);
importMod->addFile(*importFile);
bool done;
PersistentParserState persistentState;
SkipNonTransparentFunctions delayCallbacks;
parseIntoSourceFile(*importFile, bufferID, &done, nullptr, &persistentState,
SkipBodies ? &delayCallbacks : nullptr);
assert(done && "Parser returned early?");
(void)done;
if (SkipBodies)
performDelayedParsing(importMod, persistentState, nullptr);
// FIXME: Support recursive definitions in immediate modes by making type
// checking even lazier.
if (SkipBodies)
performNameBinding(*importFile);
else
performTypeChecking(*importFile, persistentState.getTopLevelContext(),
None);
return importMod;
}
void SourceLoader::loadExtensions(NominalTypeDecl *nominal,
unsigned previousGeneration) {
// Type-checking the source automatically loads all extensions; there's
// nothing to do here.
}