mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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
146 lines
5.0 KiB
C++
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.
|
|
}
|