2009-11-13 11:51:44 +08:00
|
|
|
//===--- CompilerInstance.cpp ---------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
2009-11-14 10:47:17 +08:00
|
|
|
#include "clang/AST/ASTConsumer.h"
|
2009-11-13 16:20:47 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2011-12-03 07:42:12 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
2009-11-13 11:51:44 +08:00
|
|
|
#include "clang/Basic/Diagnostic.h"
|
2009-11-13 12:12:06 +08:00
|
|
|
#include "clang/Basic/FileManager.h"
|
|
|
|
#include "clang/Basic/SourceManager.h"
|
2009-11-13 11:51:44 +08:00
|
|
|
#include "clang/Basic/TargetInfo.h"
|
2010-01-13 08:48:06 +08:00
|
|
|
#include "clang/Basic/Version.h"
|
2014-06-06 18:36:22 +08:00
|
|
|
#include "clang/Config/config.h"
|
2011-09-26 08:21:47 +08:00
|
|
|
#include "clang/Frontend/ChainedDiagnosticConsumer.h"
|
2010-01-13 08:48:06 +08:00
|
|
|
#include "clang/Frontend/FrontendAction.h"
|
2011-09-13 07:31:24 +08:00
|
|
|
#include "clang/Frontend/FrontendActions.h"
|
2009-11-13 17:36:05 +08:00
|
|
|
#include "clang/Frontend/FrontendDiagnostic.h"
|
2011-04-08 02:31:10 +08:00
|
|
|
#include "clang/Frontend/LogDiagnosticPrinter.h"
|
2011-10-29 08:12:39 +08:00
|
|
|
#include "clang/Frontend/SerializedDiagnosticPrinter.h"
|
2009-11-13 13:52:34 +08:00
|
|
|
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
2009-11-13 13:52:11 +08:00
|
|
|
#include "clang/Frontend/Utils.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Frontend/VerifyDiagnosticConsumer.h"
|
|
|
|
#include "clang/Lex/HeaderSearch.h"
|
|
|
|
#include "clang/Lex/PTHManager.h"
|
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2016-07-19 03:02:11 +08:00
|
|
|
#include "clang/Lex/PreprocessorOptions.h"
|
2009-11-13 17:36:05 +08:00
|
|
|
#include "clang/Sema/CodeCompleteConsumer.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "clang/Sema/Sema.h"
|
|
|
|
#include "clang/Serialization/ASTReader.h"
|
2014-04-23 20:57:01 +08:00
|
|
|
#include "clang/Serialization/GlobalModuleIndex.h"
|
2010-03-31 01:33:59 +08:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "llvm/Support/CrashRecoveryContext.h"
|
2014-06-14 01:20:50 +08:00
|
|
|
#include "llvm/Support/Errc.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "llvm/Support/FileSystem.h"
|
2010-11-30 02:12:39 +08:00
|
|
|
#include "llvm/Support/Host.h"
|
2012-01-30 04:15:24 +08:00
|
|
|
#include "llvm/Support/LockFileManager.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2010-11-30 02:12:39 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
|
|
|
#include "llvm/Support/Program.h"
|
|
|
|
#include "llvm/Support/Signals.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "llvm/Support/Timer.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2013-03-26 05:19:16 +08:00
|
|
|
#include <sys/stat.h>
|
2014-06-13 01:19:42 +08:00
|
|
|
#include <system_error>
|
2013-03-26 05:51:16 +08:00
|
|
|
#include <time.h>
|
2016-05-27 22:27:13 +08:00
|
|
|
#include <utility>
|
2011-10-05 22:53:30 +08:00
|
|
|
|
2009-11-13 11:51:44 +08:00
|
|
|
using namespace clang;
|
|
|
|
|
2015-06-21 02:53:08 +08:00
|
|
|
CompilerInstance::CompilerInstance(
|
|
|
|
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
|
|
|
|
bool BuildingModule)
|
|
|
|
: ModuleLoader(BuildingModule), Invocation(new CompilerInvocation()),
|
2016-05-27 22:27:13 +08:00
|
|
|
ModuleManager(nullptr),
|
|
|
|
ThePCHContainerOperations(std::move(PCHContainerOps)),
|
2015-06-21 02:53:08 +08:00
|
|
|
BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false),
|
|
|
|
ModuleBuildFailed(false) {}
|
2009-11-13 11:51:44 +08:00
|
|
|
|
|
|
|
CompilerInstance::~CompilerInstance() {
|
2012-10-15 03:21:21 +08:00
|
|
|
assert(OutputFiles.empty() && "Still output files in flight?");
|
2010-02-16 09:54:47 +08:00
|
|
|
}
|
|
|
|
|
2010-01-31 05:47:07 +08:00
|
|
|
void CompilerInstance::setInvocation(CompilerInvocation *Value) {
|
2011-03-22 02:40:17 +08:00
|
|
|
Invocation = Value;
|
2010-01-31 05:47:07 +08:00
|
|
|
}
|
|
|
|
|
2013-01-25 08:45:27 +08:00
|
|
|
bool CompilerInstance::shouldBuildGlobalModuleIndex() const {
|
2013-01-25 09:03:03 +08:00
|
|
|
return (BuildGlobalModuleIndex ||
|
2013-03-23 05:26:48 +08:00
|
|
|
(ModuleManager && ModuleManager->isGlobalIndexUnavailable() &&
|
|
|
|
getFrontendOpts().GenerateGlobalModuleIndex)) &&
|
2013-01-25 09:03:03 +08:00
|
|
|
!ModuleBuildFailed;
|
2013-01-25 08:45:27 +08:00
|
|
|
}
|
|
|
|
|
2011-09-26 07:23:43 +08:00
|
|
|
void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
|
2010-04-06 07:52:57 +08:00
|
|
|
Diagnostics = Value;
|
2009-11-14 09:20:40 +08:00
|
|
|
}
|
|
|
|
|
2015-09-23 01:23:22 +08:00
|
|
|
void CompilerInstance::setTarget(TargetInfo *Value) { Target = Value; }
|
|
|
|
void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; }
|
2009-11-14 09:20:40 +08:00
|
|
|
|
|
|
|
void CompilerInstance::setFileManager(FileManager *Value) {
|
2011-03-22 02:40:17 +08:00
|
|
|
FileMgr = Value;
|
2014-02-21 05:59:23 +08:00
|
|
|
if (Value)
|
|
|
|
VirtualFileSystem = Value->getVirtualFileSystem();
|
|
|
|
else
|
|
|
|
VirtualFileSystem.reset();
|
2009-11-14 09:20:40 +08:00
|
|
|
}
|
|
|
|
|
2011-10-08 19:31:46 +08:00
|
|
|
void CompilerInstance::setSourceManager(SourceManager *Value) {
|
2011-03-22 02:40:17 +08:00
|
|
|
SourceMgr = Value;
|
2009-11-14 09:20:40 +08:00
|
|
|
}
|
|
|
|
|
2011-03-22 02:40:17 +08:00
|
|
|
void CompilerInstance::setPreprocessor(Preprocessor *Value) { PP = Value; }
|
2009-11-14 09:20:40 +08:00
|
|
|
|
2015-08-19 04:39:29 +08:00
|
|
|
void CompilerInstance::setASTContext(ASTContext *Value) {
|
|
|
|
Context = Value;
|
|
|
|
|
|
|
|
if (Context && Consumer)
|
|
|
|
getASTConsumer().Initialize(getASTContext());
|
|
|
|
}
|
2009-11-14 10:47:17 +08:00
|
|
|
|
2010-08-13 07:31:19 +08:00
|
|
|
void CompilerInstance::setSema(Sema *S) {
|
|
|
|
TheSema.reset(S);
|
|
|
|
}
|
|
|
|
|
2014-08-11 03:56:51 +08:00
|
|
|
void CompilerInstance::setASTConsumer(std::unique_ptr<ASTConsumer> Value) {
|
|
|
|
Consumer = std::move(Value);
|
2015-08-19 04:39:29 +08:00
|
|
|
|
|
|
|
if (Context && Consumer)
|
|
|
|
getASTConsumer().Initialize(getASTContext());
|
2009-11-14 09:20:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
|
|
|
|
CompletionConsumer.reset(Value);
|
|
|
|
}
|
2014-08-11 04:12:39 +08:00
|
|
|
|
|
|
|
std::unique_ptr<Sema> CompilerInstance::takeSema() {
|
|
|
|
return std::move(TheSema);
|
|
|
|
}
|
|
|
|
|
2014-02-27 12:11:59 +08:00
|
|
|
IntrusiveRefCntPtr<ASTReader> CompilerInstance::getModuleManager() const {
|
|
|
|
return ModuleManager;
|
|
|
|
}
|
|
|
|
void CompilerInstance::setModuleManager(IntrusiveRefCntPtr<ASTReader> Reader) {
|
2016-06-13 04:05:23 +08:00
|
|
|
ModuleManager = std::move(Reader);
|
2014-02-27 12:11:59 +08:00
|
|
|
}
|
2009-11-14 09:20:40 +08:00
|
|
|
|
2014-06-20 03:36:03 +08:00
|
|
|
std::shared_ptr<ModuleDependencyCollector>
|
|
|
|
CompilerInstance::getModuleDepCollector() const {
|
|
|
|
return ModuleDepCollector;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CompilerInstance::setModuleDepCollector(
|
|
|
|
std::shared_ptr<ModuleDependencyCollector> Collector) {
|
2016-06-13 04:05:23 +08:00
|
|
|
ModuleDepCollector = std::move(Collector);
|
2014-06-20 03:36:03 +08:00
|
|
|
}
|
|
|
|
|
2009-11-13 13:52:34 +08:00
|
|
|
// Diagnostics
|
2012-10-24 06:26:28 +08:00
|
|
|
static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts,
|
2011-04-08 02:59:02 +08:00
|
|
|
const CodeGenOptions *CodeGenOpts,
|
2011-09-26 07:23:43 +08:00
|
|
|
DiagnosticsEngine &Diags) {
|
2014-08-26 02:17:04 +08:00
|
|
|
std::error_code EC;
|
2014-09-16 01:30:56 +08:00
|
|
|
std::unique_ptr<raw_ostream> StreamOwner;
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream *OS = &llvm::errs();
|
2012-10-24 06:26:28 +08:00
|
|
|
if (DiagOpts->DiagnosticLogFile != "-") {
|
2011-04-08 02:31:10 +08:00
|
|
|
// Create the output stream.
|
2014-09-16 01:30:56 +08:00
|
|
|
auto FileOS = llvm::make_unique<llvm::raw_fd_ostream>(
|
2014-08-26 02:17:04 +08:00
|
|
|
DiagOpts->DiagnosticLogFile, EC,
|
2014-09-16 01:30:56 +08:00
|
|
|
llvm::sys::fs::F_Append | llvm::sys::fs::F_Text);
|
2014-08-26 02:17:04 +08:00
|
|
|
if (EC) {
|
2011-04-08 02:31:10 +08:00
|
|
|
Diags.Report(diag::warn_fe_cc_log_diagnostics_failure)
|
2014-08-26 02:17:04 +08:00
|
|
|
<< DiagOpts->DiagnosticLogFile << EC.message();
|
2011-04-08 02:31:10 +08:00
|
|
|
} else {
|
|
|
|
FileOS->SetUnbuffered();
|
2014-09-16 01:30:56 +08:00
|
|
|
OS = FileOS.get();
|
|
|
|
StreamOwner = std::move(FileOS);
|
2011-04-08 02:31:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Chain in the diagnostic client which will log the diagnostics.
|
2014-09-16 01:50:10 +08:00
|
|
|
auto Logger = llvm::make_unique<LogDiagnosticPrinter>(*OS, DiagOpts,
|
|
|
|
std::move(StreamOwner));
|
2011-04-08 02:59:02 +08:00
|
|
|
if (CodeGenOpts)
|
|
|
|
Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags);
|
2014-09-16 01:50:10 +08:00
|
|
|
assert(Diags.ownsClient());
|
2014-11-18 07:46:02 +08:00
|
|
|
Diags.setClient(
|
|
|
|
new ChainedDiagnosticConsumer(Diags.takeClient(), std::move(Logger)));
|
2011-04-08 02:31:10 +08:00
|
|
|
}
|
|
|
|
|
2012-10-24 06:26:28 +08:00
|
|
|
static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts,
|
2011-10-29 08:12:39 +08:00
|
|
|
DiagnosticsEngine &Diags,
|
|
|
|
StringRef OutputFile) {
|
2014-09-16 01:50:10 +08:00
|
|
|
auto SerializedConsumer =
|
2014-10-24 06:20:11 +08:00
|
|
|
clang::serialized_diags::create(OutputFile, DiagOpts);
|
2011-10-29 08:12:39 +08:00
|
|
|
|
2014-11-13 21:08:27 +08:00
|
|
|
if (Diags.ownsClient()) {
|
|
|
|
Diags.setClient(new ChainedDiagnosticConsumer(
|
2014-11-18 07:46:02 +08:00
|
|
|
Diags.takeClient(), std::move(SerializedConsumer)));
|
2014-11-13 21:08:27 +08:00
|
|
|
} else {
|
|
|
|
Diags.setClient(new ChainedDiagnosticConsumer(
|
2014-11-17 22:46:28 +08:00
|
|
|
Diags.getClient(), std::move(SerializedConsumer)));
|
2014-11-13 21:08:27 +08:00
|
|
|
}
|
2011-10-29 08:12:39 +08:00
|
|
|
}
|
|
|
|
|
2013-01-20 09:58:28 +08:00
|
|
|
void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client,
|
2013-05-04 07:07:45 +08:00
|
|
|
bool ShouldOwnClient) {
|
2013-01-20 09:58:28 +08:00
|
|
|
Diagnostics = createDiagnostics(&getDiagnosticOpts(), Client,
|
2013-05-04 07:07:45 +08:00
|
|
|
ShouldOwnClient, &getCodeGenOpts());
|
2009-11-13 13:52:34 +08:00
|
|
|
}
|
|
|
|
|
2012-02-20 22:00:23 +08:00
|
|
|
IntrusiveRefCntPtr<DiagnosticsEngine>
|
2012-10-24 06:26:28 +08:00
|
|
|
CompilerInstance::createDiagnostics(DiagnosticOptions *Opts,
|
2011-09-26 07:39:51 +08:00
|
|
|
DiagnosticConsumer *Client,
|
2011-09-13 09:26:44 +08:00
|
|
|
bool ShouldOwnClient,
|
2011-04-08 02:59:02 +08:00
|
|
|
const CodeGenOptions *CodeGenOpts) {
|
2012-02-20 22:00:23 +08:00
|
|
|
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
|
|
|
|
IntrusiveRefCntPtr<DiagnosticsEngine>
|
2012-10-24 06:26:28 +08:00
|
|
|
Diags(new DiagnosticsEngine(DiagID, Opts));
|
2009-11-14 15:53:24 +08:00
|
|
|
|
2009-11-13 13:52:34 +08:00
|
|
|
// Create the diagnostic client for reporting errors or for
|
|
|
|
// implementing -verify.
|
2011-09-29 08:38:00 +08:00
|
|
|
if (Client) {
|
2013-05-04 07:07:45 +08:00
|
|
|
Diags->setClient(Client, ShouldOwnClient);
|
2011-09-29 08:38:00 +08:00
|
|
|
} else
|
2010-11-11 08:39:14 +08:00
|
|
|
Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
|
2009-11-14 11:24:39 +08:00
|
|
|
|
|
|
|
// Chain in -verify checker, if requested.
|
2012-10-24 06:26:28 +08:00
|
|
|
if (Opts->VerifyDiagnostics)
|
2011-09-26 08:38:03 +08:00
|
|
|
Diags->setClient(new VerifyDiagnosticConsumer(*Diags));
|
2009-11-13 13:52:34 +08:00
|
|
|
|
2011-04-08 02:31:10 +08:00
|
|
|
// Chain in -diagnostic-log-file dumper, if requested.
|
2012-10-24 06:26:28 +08:00
|
|
|
if (!Opts->DiagnosticLogFile.empty())
|
2011-04-08 02:59:02 +08:00
|
|
|
SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2012-10-24 06:26:28 +08:00
|
|
|
if (!Opts->DiagnosticSerializationFile.empty())
|
2011-10-29 08:12:39 +08:00
|
|
|
SetupSerializedDiagnostics(Opts, *Diags,
|
2012-10-24 06:26:28 +08:00
|
|
|
Opts->DiagnosticSerializationFile);
|
2011-10-29 08:12:39 +08:00
|
|
|
|
2009-11-13 13:52:34 +08:00
|
|
|
// Configure our handling of diagnostics.
|
2012-10-24 06:26:28 +08:00
|
|
|
ProcessWarningOptions(*Diags, *Opts);
|
2009-11-13 13:52:34 +08:00
|
|
|
|
2010-04-06 07:52:57 +08:00
|
|
|
return Diags;
|
2009-11-13 13:52:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// File Manager
|
|
|
|
|
2009-11-13 12:12:06 +08:00
|
|
|
void CompilerInstance::createFileManager() {
|
2014-02-21 05:59:23 +08:00
|
|
|
if (!hasVirtualFileSystem()) {
|
|
|
|
// TODO: choose the virtual file system based on the CompilerInvocation.
|
|
|
|
setVirtualFileSystem(vfs::getRealFileSystem());
|
|
|
|
}
|
|
|
|
FileMgr = new FileManager(getFileSystemOpts(), VirtualFileSystem);
|
2009-11-13 12:12:06 +08:00
|
|
|
}
|
|
|
|
|
2009-11-13 13:52:34 +08:00
|
|
|
// Source Manager
|
|
|
|
|
2010-11-23 16:35:12 +08:00
|
|
|
void CompilerInstance::createSourceManager(FileManager &FileMgr) {
|
2011-03-22 02:40:17 +08:00
|
|
|
SourceMgr = new SourceManager(getDiagnostics(), FileMgr);
|
2009-11-13 12:12:06 +08:00
|
|
|
}
|
2009-11-13 13:52:11 +08:00
|
|
|
|
2014-07-07 14:05:00 +08:00
|
|
|
// Initialize the remapping of files to alternative contents, e.g.,
|
|
|
|
// those specified through other files.
|
|
|
|
static void InitializeFileRemapping(DiagnosticsEngine &Diags,
|
|
|
|
SourceManager &SourceMgr,
|
|
|
|
FileManager &FileMgr,
|
|
|
|
const PreprocessorOptions &InitOpts) {
|
|
|
|
// Remap files in the source manager (with buffers).
|
2014-07-07 15:47:20 +08:00
|
|
|
for (const auto &RB : InitOpts.RemappedFileBuffers) {
|
2014-07-07 14:05:00 +08:00
|
|
|
// Create the file entry for the file that we're mapping from.
|
|
|
|
const FileEntry *FromFile =
|
2014-07-07 15:47:20 +08:00
|
|
|
FileMgr.getVirtualFile(RB.first, RB.second->getBufferSize(), 0);
|
2014-07-07 14:05:00 +08:00
|
|
|
if (!FromFile) {
|
2014-07-07 15:47:20 +08:00
|
|
|
Diags.Report(diag::err_fe_remap_missing_from_file) << RB.first;
|
2014-07-07 14:05:00 +08:00
|
|
|
if (!InitOpts.RetainRemappedFileBuffers)
|
2014-07-07 15:47:20 +08:00
|
|
|
delete RB.second;
|
2014-07-07 14:05:00 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Override the contents of the "from" file with the contents of
|
|
|
|
// the "to" file.
|
2014-07-07 15:47:20 +08:00
|
|
|
SourceMgr.overrideFileContents(FromFile, RB.second,
|
2014-07-07 14:05:00 +08:00
|
|
|
InitOpts.RetainRemappedFileBuffers);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remap files in the source manager (with other files).
|
2014-07-07 15:47:20 +08:00
|
|
|
for (const auto &RF : InitOpts.RemappedFiles) {
|
2014-07-07 14:05:00 +08:00
|
|
|
// Find the file that we're mapping to.
|
2014-07-07 15:47:20 +08:00
|
|
|
const FileEntry *ToFile = FileMgr.getFile(RF.second);
|
2014-07-07 14:05:00 +08:00
|
|
|
if (!ToFile) {
|
2014-07-07 15:47:20 +08:00
|
|
|
Diags.Report(diag::err_fe_remap_missing_to_file) << RF.first << RF.second;
|
2014-07-07 14:05:00 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the file entry for the file that we're mapping from.
|
|
|
|
const FileEntry *FromFile =
|
2014-07-07 15:47:20 +08:00
|
|
|
FileMgr.getVirtualFile(RF.first, ToFile->getSize(), 0);
|
2014-07-07 14:05:00 +08:00
|
|
|
if (!FromFile) {
|
2014-07-07 15:47:20 +08:00
|
|
|
Diags.Report(diag::err_fe_remap_missing_from_file) << RF.first;
|
2014-07-07 14:05:00 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Override the contents of the "from" file with the contents of
|
|
|
|
// the "to" file.
|
|
|
|
SourceMgr.overrideFileContents(FromFile, ToFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
SourceMgr.setOverridenFilesKeepOriginalName(
|
|
|
|
InitOpts.RemappedFilesKeepOriginalName);
|
|
|
|
}
|
|
|
|
|
2009-11-13 13:52:34 +08:00
|
|
|
// Preprocessor
|
|
|
|
|
2014-03-07 15:47:58 +08:00
|
|
|
void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
|
2011-08-27 07:56:07 +08:00
|
|
|
const PreprocessorOptions &PPOpts = getPreprocessorOpts();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-11-13 13:52:11 +08:00
|
|
|
// Create a PTH manager if we are using some form of a token cache.
|
2014-05-22 12:46:25 +08:00
|
|
|
PTHManager *PTHMgr = nullptr;
|
2009-11-17 13:52:41 +08:00
|
|
|
if (!PPOpts.TokenCache.empty())
|
2011-08-27 07:56:07 +08:00
|
|
|
PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics());
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-11-13 13:52:11 +08:00
|
|
|
// Create the Preprocessor.
|
2012-10-25 00:19:39 +08:00
|
|
|
HeaderSearch *HeaderInfo = new HeaderSearch(&getHeaderSearchOpts(),
|
Use the same SourceManager for ModuleMaps and compilations.
This allows using virtual file mappings on the original SourceManager to
map in virtual module.map files. Without this patch, the ModuleMap
search will find a module.map file (as the FileEntry exists in the
FileManager), but will be unable to get the content from the
SourceManager (as ModuleMap previously created its own SourceManager).
Two problems needed to be fixed which this patch exposed:
1. Storing the inferred module map
When writing out a module, the ASTWriter stores the names of the files
in the main source manager; when loading the AST again, the ASTReader
errs out if such a file is found missing, unless it is overridden.
Previously CompilerInstance's compileModule method would store the
inferred module map to a temporary file; the problem with this approach
is that now that the module map is handled by the main source manager,
the ASTWriter stores the name of the temporary module map as source to
the compilation; later, when the module is loaded, the temporary file
has already been deleted, which leads to a compilation error. This patch
changes the inferred module map to instead inject a virtual file into
the source manager. This both saves some disk IO, and works with how the
ASTWriter/ASTReader handle overridden source files.
2. Changing test input in test/Modules/Inputs/*
Now that the module map file is handled by the main source manager, the
VerifyDiagnosticConsumer will not ignore diagnostics created while
parsing the module map file. The module test test/Modules/renamed.m uses
-I test/Modules/Inputs and triggers recursive loading of all module maps
in test/Modules/Inputs, some of which had conflicting names, thus
leading errors while parsing the module maps. Those diagnostics already
occur on trunk, but before this patch they would not break the test, as
they were ignored by the VerifyDiagnosticConsumer. This patch thus
changes the module maps that have been recently introduced which broke
the invariant of compatible modules maps in test/Modules/Inputs.
llvm-svn: 193314
2013-10-24 15:51:24 +08:00
|
|
|
getSourceManager(),
|
2011-12-31 12:05:44 +08:00
|
|
|
getDiagnostics(),
|
2012-01-30 14:01:29 +08:00
|
|
|
getLangOpts(),
|
|
|
|
&getTarget());
|
2014-05-02 11:43:38 +08:00
|
|
|
PP = new Preprocessor(&getPreprocessorOpts(), getDiagnostics(), getLangOpts(),
|
2011-08-27 07:56:07 +08:00
|
|
|
getSourceManager(), *HeaderInfo, *this, PTHMgr,
|
2014-05-02 11:43:38 +08:00
|
|
|
/*OwnsHeaderSearch=*/true, TUKind);
|
2015-09-23 01:23:22 +08:00
|
|
|
PP->Initialize(getTarget(), getAuxTarget());
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-11-13 13:52:11 +08:00
|
|
|
// Note that this is different then passing PTHMgr to Preprocessor's ctor.
|
|
|
|
// That argument is used as the IdentifierInfoLookup argument to
|
|
|
|
// IdentifierTable's ctor.
|
|
|
|
if (PTHMgr) {
|
2011-08-27 07:56:07 +08:00
|
|
|
PTHMgr->setPreprocessor(&*PP);
|
2009-11-13 13:52:11 +08:00
|
|
|
PP->setPTHManager(PTHMgr);
|
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2010-03-20 00:15:56 +08:00
|
|
|
if (PPOpts.DetailedRecord)
|
2012-12-04 15:27:05 +08:00
|
|
|
PP->createPreprocessingRecord();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2014-07-07 14:05:00 +08:00
|
|
|
// Apply remappings to the source manager.
|
|
|
|
InitializeFileRemapping(PP->getDiagnostics(), PP->getSourceManager(),
|
|
|
|
PP->getFileManager(), PPOpts);
|
|
|
|
|
|
|
|
// Predefine macros and configure the preprocessor.
|
2015-07-17 09:19:54 +08:00
|
|
|
InitializePreprocessor(*PP, PPOpts, getPCHContainerReader(),
|
2015-06-21 02:53:08 +08:00
|
|
|
getFrontendOpts());
|
2014-07-07 14:05:00 +08:00
|
|
|
|
|
|
|
// Initialize the header search object.
|
|
|
|
ApplyHeaderSearchOptions(PP->getHeaderSearchInfo(), getHeaderSearchOpts(),
|
|
|
|
PP->getLangOpts(), PP->getTargetInfo().getTriple());
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2013-01-30 09:52:57 +08:00
|
|
|
PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP);
|
|
|
|
|
2015-08-15 08:34:15 +08:00
|
|
|
if (PP->getLangOpts().Modules && PP->getLangOpts().ImplicitModules)
|
2015-03-28 09:10:44 +08:00
|
|
|
PP->getHeaderSearchInfo().setModuleCachePath(getSpecificModuleCachePath());
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2009-11-13 13:52:11 +08:00
|
|
|
// Handle generating dependencies, if requested.
|
2011-08-27 07:56:07 +08:00
|
|
|
const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
|
2009-11-13 13:52:11 +08:00
|
|
|
if (!DepOpts.OutputFile.empty())
|
2014-03-07 14:40:32 +08:00
|
|
|
TheDependencyFileGenerator.reset(
|
|
|
|
DependencyFileGenerator::CreateAndAttachToPreprocessor(*PP, DepOpts));
|
2012-02-03 07:45:13 +08:00
|
|
|
if (!DepOpts.DOTOutputFile.empty())
|
|
|
|
AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile,
|
2012-02-02 08:54:52 +08:00
|
|
|
getHeaderSearchOpts().Sysroot);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2014-06-20 03:36:03 +08:00
|
|
|
// If we don't have a collector, but we are collecting module dependencies,
|
|
|
|
// then we're the top level compiler instance and need to create one.
|
2016-03-30 07:47:40 +08:00
|
|
|
if (!ModuleDepCollector && !DepOpts.ModuleDependencyOutputDir.empty()) {
|
2014-06-20 03:36:03 +08:00
|
|
|
ModuleDepCollector = std::make_shared<ModuleDependencyCollector>(
|
|
|
|
DepOpts.ModuleDependencyOutputDir);
|
2016-03-30 07:47:40 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ModuleDepCollector)
|
|
|
|
addDependencyCollector(ModuleDepCollector);
|
|
|
|
|
|
|
|
for (auto &Listener : DependencyCollectors)
|
|
|
|
Listener->attachToPreprocessor(*PP);
|
2013-08-09 08:32:23 +08:00
|
|
|
|
2011-02-02 23:41:17 +08:00
|
|
|
// Handle generating header include information, if requested.
|
|
|
|
if (DepOpts.ShowHeaderIncludes)
|
2016-03-24 02:46:57 +08:00
|
|
|
AttachHeaderIncludeGen(*PP, DepOpts);
|
2011-02-03 05:11:31 +08:00
|
|
|
if (!DepOpts.HeaderIncludeOutputFile.empty()) {
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef OutputPath = DepOpts.HeaderIncludeOutputFile;
|
2011-02-03 05:11:31 +08:00
|
|
|
if (OutputPath == "-")
|
|
|
|
OutputPath = "";
|
2016-03-24 02:46:57 +08:00
|
|
|
AttachHeaderIncludeGen(*PP, DepOpts,
|
2015-08-13 12:04:37 +08:00
|
|
|
/*ShowAllHeaders=*/true, OutputPath,
|
2011-03-22 03:37:38 +08:00
|
|
|
/*ShowDepth=*/false);
|
2011-02-03 05:11:31 +08:00
|
|
|
}
|
2013-08-09 08:32:23 +08:00
|
|
|
|
|
|
|
if (DepOpts.PrintShowIncludes) {
|
2016-03-24 02:46:57 +08:00
|
|
|
AttachHeaderIncludeGen(*PP, DepOpts,
|
2016-03-24 02:00:22 +08:00
|
|
|
/*ShowAllHeaders=*/true, /*OutputPath=*/"",
|
2013-08-09 08:32:23 +08:00
|
|
|
/*ShowDepth=*/true, /*MSStyle=*/true);
|
|
|
|
}
|
2009-11-13 13:52:11 +08:00
|
|
|
}
|
2009-11-13 16:20:47 +08:00
|
|
|
|
2015-02-20 04:12:20 +08:00
|
|
|
std::string CompilerInstance::getSpecificModuleCachePath() {
|
|
|
|
// Set up the module path, including the hash for the
|
|
|
|
// module-creation options.
|
2015-07-22 02:07:47 +08:00
|
|
|
SmallString<256> SpecificModuleCache(getHeaderSearchOpts().ModuleCachePath);
|
|
|
|
if (!SpecificModuleCache.empty() && !getHeaderSearchOpts().DisableModuleHash)
|
2015-02-20 04:12:20 +08:00
|
|
|
llvm::sys::path::append(SpecificModuleCache,
|
|
|
|
getInvocation().getModuleHash());
|
|
|
|
return SpecificModuleCache.str();
|
|
|
|
}
|
|
|
|
|
2009-11-13 16:20:47 +08:00
|
|
|
// ASTContext
|
|
|
|
|
|
|
|
void CompilerInstance::createASTContext() {
|
|
|
|
Preprocessor &PP = getPreprocessor();
|
2015-08-19 04:39:29 +08:00
|
|
|
auto *Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
|
|
|
|
PP.getIdentifierTable(), PP.getSelectorTable(),
|
|
|
|
PP.getBuiltinInfo());
|
2015-09-23 01:23:22 +08:00
|
|
|
Context->InitBuiltinTypes(getTarget(), getAuxTarget());
|
2015-08-19 04:39:29 +08:00
|
|
|
setASTContext(Context);
|
2009-11-13 16:20:47 +08:00
|
|
|
}
|
2009-11-13 16:21:10 +08:00
|
|
|
|
|
|
|
// ExternalASTSource
|
|
|
|
|
2014-05-08 12:26:47 +08:00
|
|
|
void CompilerInstance::createPCHExternalASTSource(
|
|
|
|
StringRef Path, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors,
|
|
|
|
void *DeserializationListener, bool OwnDeserializationListener) {
|
2010-10-06 00:15:19 +08:00
|
|
|
bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
|
2015-02-05 07:37:59 +08:00
|
|
|
ModuleManager = createPCHExternalASTSource(
|
2014-05-08 12:26:47 +08:00
|
|
|
Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation,
|
|
|
|
AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(),
|
2015-11-04 02:33:07 +08:00
|
|
|
getPCHContainerReader(),
|
|
|
|
getFrontendOpts().ModuleFileExtensions,
|
|
|
|
DeserializationListener,
|
2015-06-21 02:53:08 +08:00
|
|
|
OwnDeserializationListener, Preamble,
|
2014-05-08 12:26:47 +08:00
|
|
|
getFrontendOpts().UseGlobalModuleIndex);
|
2009-11-13 16:21:10 +08:00
|
|
|
}
|
|
|
|
|
2015-02-05 07:37:59 +08:00
|
|
|
IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
|
2015-07-06 16:47:15 +08:00
|
|
|
StringRef Path, StringRef Sysroot, bool DisablePCHValidation,
|
2014-05-08 12:26:47 +08:00
|
|
|
bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context,
|
2015-07-17 09:19:54 +08:00
|
|
|
const PCHContainerReader &PCHContainerRdr,
|
2015-11-04 02:33:07 +08:00
|
|
|
ArrayRef<IntrusiveRefCntPtr<ModuleFileExtension>> Extensions,
|
2014-05-08 12:26:47 +08:00
|
|
|
void *DeserializationListener, bool OwnDeserializationListener,
|
|
|
|
bool Preamble, bool UseGlobalModuleIndex) {
|
2014-03-12 08:06:17 +08:00
|
|
|
HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
|
|
|
|
|
2015-06-21 02:53:08 +08:00
|
|
|
IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader(
|
2015-11-04 02:33:07 +08:00
|
|
|
PP, Context, PCHContainerRdr, Extensions,
|
|
|
|
Sysroot.empty() ? "" : Sysroot.data(), DisablePCHValidation,
|
|
|
|
AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false,
|
|
|
|
HSOpts.ModulesValidateSystemHeaders, UseGlobalModuleIndex));
|
2015-02-05 07:37:59 +08:00
|
|
|
|
|
|
|
// We need the external source to be set up before we read the AST, because
|
|
|
|
// eagerly-deserialized declarations may use it.
|
|
|
|
Context.setExternalSource(Reader.get());
|
2009-11-13 16:21:10 +08:00
|
|
|
|
2010-07-30 08:29:29 +08:00
|
|
|
Reader->setDeserializationListener(
|
2014-05-08 12:26:47 +08:00
|
|
|
static_cast<ASTDeserializationListener *>(DeserializationListener),
|
|
|
|
/*TakeOwnership=*/OwnDeserializationListener);
|
2011-10-08 19:31:46 +08:00
|
|
|
switch (Reader->ReadAST(Path,
|
|
|
|
Preamble ? serialization::MK_Preamble
|
2012-10-23 07:51:00 +08:00
|
|
|
: serialization::MK_PCH,
|
2012-11-16 02:57:22 +08:00
|
|
|
SourceLocation(),
|
2014-02-08 01:31:11 +08:00
|
|
|
ASTReader::ARR_None)) {
|
2010-08-19 07:56:43 +08:00
|
|
|
case ASTReader::Success:
|
2009-11-13 16:21:10 +08:00
|
|
|
// Set the predefines buffer as suggested by the PCH reader. Typically, the
|
|
|
|
// predefines buffer will be empty.
|
|
|
|
PP.setPredefines(Reader->getSuggestedPredefines());
|
2015-02-05 07:37:59 +08:00
|
|
|
return Reader;
|
2009-11-13 16:21:10 +08:00
|
|
|
|
2010-08-19 07:56:43 +08:00
|
|
|
case ASTReader::Failure:
|
2009-11-13 16:21:10 +08:00
|
|
|
// Unrecoverable failure: don't even try to process the input file.
|
|
|
|
break;
|
|
|
|
|
2013-03-19 08:28:20 +08:00
|
|
|
case ASTReader::Missing:
|
2012-10-23 06:50:17 +08:00
|
|
|
case ASTReader::OutOfDate:
|
|
|
|
case ASTReader::VersionMismatch:
|
|
|
|
case ASTReader::ConfigurationMismatch:
|
|
|
|
case ASTReader::HadErrors:
|
2009-11-13 16:21:10 +08:00
|
|
|
// No suitable PCH file could be found. Return an error.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-02-05 07:37:59 +08:00
|
|
|
Context.setExternalSource(nullptr);
|
2014-05-22 12:46:25 +08:00
|
|
|
return nullptr;
|
2009-11-13 16:21:10 +08:00
|
|
|
}
|
2009-11-13 17:36:05 +08:00
|
|
|
|
|
|
|
// Code Completion
|
|
|
|
|
2011-10-08 19:31:46 +08:00
|
|
|
static bool EnableCodeCompletion(Preprocessor &PP,
|
2016-02-13 21:42:54 +08:00
|
|
|
StringRef Filename,
|
2010-08-05 00:47:14 +08:00
|
|
|
unsigned Line,
|
|
|
|
unsigned Column) {
|
|
|
|
// Tell the source manager to chop off the given file at a specific
|
|
|
|
// line and column.
|
2010-11-23 16:35:12 +08:00
|
|
|
const FileEntry *Entry = PP.getFileManager().getFile(Filename);
|
2010-08-05 00:47:14 +08:00
|
|
|
if (!Entry) {
|
|
|
|
PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
|
|
|
|
<< Filename;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Truncate the named file at the given line/column.
|
|
|
|
PP.SetCodeCompletionPoint(Entry, Line, Column);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-11-13 17:36:05 +08:00
|
|
|
void CompilerInstance::createCodeCompletionConsumer() {
|
|
|
|
const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
|
2010-08-05 00:47:14 +08:00
|
|
|
if (!CompletionConsumer) {
|
2012-04-12 18:31:12 +08:00
|
|
|
setCodeCompletionConsumer(
|
2010-08-05 00:47:14 +08:00
|
|
|
createCodeCompletionConsumer(getPreprocessor(),
|
|
|
|
Loc.FileName, Loc.Line, Loc.Column,
|
2012-07-03 01:35:10 +08:00
|
|
|
getFrontendOpts().CodeCompleteOpts,
|
2010-08-05 00:47:14 +08:00
|
|
|
llvm::outs()));
|
|
|
|
if (!CompletionConsumer)
|
|
|
|
return;
|
|
|
|
} else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName,
|
|
|
|
Loc.Line, Loc.Column)) {
|
2014-05-22 12:46:25 +08:00
|
|
|
setCodeCompletionConsumer(nullptr);
|
2010-03-16 14:04:47 +08:00
|
|
|
return;
|
2010-08-05 00:47:14 +08:00
|
|
|
}
|
2009-12-01 13:55:20 +08:00
|
|
|
|
|
|
|
if (CompletionConsumer->isOutputBinary() &&
|
2013-06-13 04:44:26 +08:00
|
|
|
llvm::sys::ChangeStdoutToBinary()) {
|
2009-12-01 13:55:20 +08:00
|
|
|
getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
|
2014-05-22 12:46:25 +08:00
|
|
|
setCodeCompletionConsumer(nullptr);
|
2009-12-01 13:55:20 +08:00
|
|
|
}
|
2009-11-13 17:36:05 +08:00
|
|
|
}
|
|
|
|
|
2009-11-29 17:57:35 +08:00
|
|
|
void CompilerInstance::createFrontendTimer() {
|
2015-07-14 08:26:00 +08:00
|
|
|
FrontendTimerGroup.reset(new llvm::TimerGroup("Clang front-end time report"));
|
|
|
|
FrontendTimer.reset(
|
|
|
|
new llvm::Timer("Clang front-end timer", *FrontendTimerGroup));
|
2009-11-29 17:57:35 +08:00
|
|
|
}
|
|
|
|
|
2009-11-13 17:36:05 +08:00
|
|
|
CodeCompleteConsumer *
|
|
|
|
CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
|
2015-07-06 16:47:15 +08:00
|
|
|
StringRef Filename,
|
2009-11-13 17:36:05 +08:00
|
|
|
unsigned Line,
|
|
|
|
unsigned Column,
|
2012-07-03 01:35:10 +08:00
|
|
|
const CodeCompleteOptions &Opts,
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream &OS) {
|
2010-08-05 00:47:14 +08:00
|
|
|
if (EnableCodeCompletion(PP, Filename, Line, Column))
|
2014-05-22 12:46:25 +08:00
|
|
|
return nullptr;
|
2009-11-13 17:36:05 +08:00
|
|
|
|
|
|
|
// Set up the creation routine for code-completion.
|
2012-07-03 01:35:10 +08:00
|
|
|
return new PrintingCodeCompleteConsumer(Opts, OS);
|
2009-11-13 17:36:05 +08:00
|
|
|
}
|
2009-11-13 18:37:48 +08:00
|
|
|
|
2011-08-26 06:30:56 +08:00
|
|
|
void CompilerInstance::createSema(TranslationUnitKind TUKind,
|
2010-08-13 07:31:19 +08:00
|
|
|
CodeCompleteConsumer *CompletionConsumer) {
|
|
|
|
TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
|
2011-08-26 06:30:56 +08:00
|
|
|
TUKind, CompletionConsumer));
|
2016-11-17 02:15:26 +08:00
|
|
|
// Attach the external sema source if there is any.
|
|
|
|
if (ExternalSemaSrc) {
|
|
|
|
TheSema->addExternalSource(ExternalSemaSrc.get());
|
|
|
|
ExternalSemaSrc->InitializeSema(*TheSema);
|
|
|
|
}
|
2010-08-13 07:31:19 +08:00
|
|
|
}
|
|
|
|
|
2009-11-13 18:37:48 +08:00
|
|
|
// Output Files
|
|
|
|
|
2015-04-10 22:11:52 +08:00
|
|
|
void CompilerInstance::addOutputFile(OutputFile &&OutFile) {
|
|
|
|
OutputFiles.push_back(std::move(OutFile));
|
2009-11-13 18:37:48 +08:00
|
|
|
}
|
|
|
|
|
2010-03-06 20:07:48 +08:00
|
|
|
void CompilerInstance::clearOutputFiles(bool EraseFiles) {
|
2015-04-11 01:27:58 +08:00
|
|
|
for (OutputFile &OF : OutputFiles) {
|
|
|
|
if (!OF.TempFilename.empty()) {
|
2011-03-07 06:25:35 +08:00
|
|
|
if (EraseFiles) {
|
2015-04-11 01:27:58 +08:00
|
|
|
llvm::sys::fs::remove(OF.TempFilename);
|
2011-03-07 06:25:35 +08:00
|
|
|
} else {
|
2015-04-11 01:27:58 +08:00
|
|
|
SmallString<128> NewOutFile(OF.Filename);
|
2011-03-07 06:25:35 +08:00
|
|
|
|
2010-11-04 06:45:23 +08:00
|
|
|
// If '-working-directory' was passed, the output filename should be
|
|
|
|
// relative to that.
|
2011-03-14 09:13:54 +08:00
|
|
|
FileMgr->FixupRelativePath(NewOutFile);
|
2014-06-12 22:02:15 +08:00
|
|
|
if (std::error_code ec =
|
2015-04-11 01:27:58 +08:00
|
|
|
llvm::sys::fs::rename(OF.TempFilename, NewOutFile)) {
|
2012-05-17 04:55:58 +08:00
|
|
|
getDiagnostics().Report(diag::err_unable_to_rename_temp)
|
2015-04-11 01:27:58 +08:00
|
|
|
<< OF.TempFilename << OF.Filename << ec.message();
|
2011-03-07 06:25:35 +08:00
|
|
|
|
2015-04-11 01:27:58 +08:00
|
|
|
llvm::sys::fs::remove(OF.TempFilename);
|
2010-09-18 01:38:48 +08:00
|
|
|
}
|
|
|
|
}
|
2015-04-11 01:27:58 +08:00
|
|
|
} else if (!OF.Filename.empty() && EraseFiles)
|
|
|
|
llvm::sys::fs::remove(OF.Filename);
|
2009-11-13 18:37:48 +08:00
|
|
|
}
|
|
|
|
OutputFiles.clear();
|
2015-04-14 23:15:49 +08:00
|
|
|
NonSeekStream.reset();
|
2009-11-13 18:37:48 +08:00
|
|
|
}
|
|
|
|
|
2016-07-15 08:55:40 +08:00
|
|
|
std::unique_ptr<raw_pwrite_stream>
|
2015-04-14 23:15:49 +08:00
|
|
|
CompilerInstance::createDefaultOutputFile(bool Binary, StringRef InFile,
|
2011-07-23 18:55:15 +08:00
|
|
|
StringRef Extension) {
|
2009-11-14 02:32:08 +08:00
|
|
|
return createOutputFile(getFrontendOpts().OutputFile, Binary,
|
2012-03-03 08:36:06 +08:00
|
|
|
/*RemoveFileOnSignal=*/true, InFile, Extension,
|
|
|
|
/*UseTemporary=*/true);
|
2009-11-14 02:32:08 +08:00
|
|
|
}
|
|
|
|
|
2016-07-15 08:55:40 +08:00
|
|
|
std::unique_ptr<raw_pwrite_stream> CompilerInstance::createNullOutputFile() {
|
|
|
|
return llvm::make_unique<llvm::raw_null_ostream>();
|
2014-06-04 01:23:34 +08:00
|
|
|
}
|
|
|
|
|
2016-07-15 08:55:40 +08:00
|
|
|
std::unique_ptr<raw_pwrite_stream>
|
2015-04-14 23:15:49 +08:00
|
|
|
CompilerInstance::createOutputFile(StringRef OutputPath, bool Binary,
|
|
|
|
bool RemoveFileOnSignal, StringRef InFile,
|
|
|
|
StringRef Extension, bool UseTemporary,
|
2012-03-03 08:36:02 +08:00
|
|
|
bool CreateMissingDirectories) {
|
2014-08-26 02:17:04 +08:00
|
|
|
std::string OutputPathName, TempPathName;
|
|
|
|
std::error_code EC;
|
2015-04-14 23:15:49 +08:00
|
|
|
std::unique_ptr<raw_pwrite_stream> OS = createOutputFile(
|
2014-08-26 02:17:04 +08:00
|
|
|
OutputPath, EC, Binary, RemoveFileOnSignal, InFile, Extension,
|
2015-04-10 22:30:43 +08:00
|
|
|
UseTemporary, CreateMissingDirectories, &OutputPathName, &TempPathName);
|
2009-11-14 02:32:08 +08:00
|
|
|
if (!OS) {
|
2014-08-26 02:17:04 +08:00
|
|
|
getDiagnostics().Report(diag::err_fe_unable_to_open_output) << OutputPath
|
|
|
|
<< EC.message();
|
2014-05-22 12:46:25 +08:00
|
|
|
return nullptr;
|
2009-11-14 02:32:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add the output file -- but don't try to remove "-", since this means we are
|
|
|
|
// using stdin.
|
2016-07-15 08:55:40 +08:00
|
|
|
addOutputFile(
|
|
|
|
OutputFile((OutputPathName != "-") ? OutputPathName : "", TempPathName));
|
2009-11-14 02:32:08 +08:00
|
|
|
|
2016-07-15 08:55:40 +08:00
|
|
|
return OS;
|
2009-11-14 02:32:08 +08:00
|
|
|
}
|
|
|
|
|
2015-04-14 23:15:49 +08:00
|
|
|
std::unique_ptr<llvm::raw_pwrite_stream> CompilerInstance::createOutputFile(
|
2014-08-26 02:17:04 +08:00
|
|
|
StringRef OutputPath, std::error_code &Error, bool Binary,
|
|
|
|
bool RemoveFileOnSignal, StringRef InFile, StringRef Extension,
|
|
|
|
bool UseTemporary, bool CreateMissingDirectories,
|
|
|
|
std::string *ResultPathName, std::string *TempPathName) {
|
2012-03-03 08:36:02 +08:00
|
|
|
assert((!CreateMissingDirectories || UseTemporary) &&
|
|
|
|
"CreateMissingDirectories is only allowed when using temporary files");
|
|
|
|
|
2010-09-18 01:38:48 +08:00
|
|
|
std::string OutFile, TempFile;
|
2009-11-14 02:32:08 +08:00
|
|
|
if (!OutputPath.empty()) {
|
|
|
|
OutFile = OutputPath;
|
|
|
|
} else if (InFile == "-") {
|
|
|
|
OutFile = "-";
|
|
|
|
} else if (!Extension.empty()) {
|
2013-06-26 12:32:59 +08:00
|
|
|
SmallString<128> Path(InFile);
|
|
|
|
llvm::sys::path::replace_extension(Path, Extension);
|
2009-11-14 02:32:08 +08:00
|
|
|
OutFile = Path.str();
|
|
|
|
} else {
|
|
|
|
OutFile = "-";
|
|
|
|
}
|
2011-07-28 08:45:10 +08:00
|
|
|
|
2014-03-08 04:03:18 +08:00
|
|
|
std::unique_ptr<llvm::raw_fd_ostream> OS;
|
2011-07-28 08:45:10 +08:00
|
|
|
std::string OSFile;
|
|
|
|
|
2013-06-28 02:26:26 +08:00
|
|
|
if (UseTemporary) {
|
|
|
|
if (OutFile == "-")
|
|
|
|
UseTemporary = false;
|
|
|
|
else {
|
|
|
|
llvm::sys::fs::file_status Status;
|
|
|
|
llvm::sys::fs::status(OutputPath, Status);
|
|
|
|
if (llvm::sys::fs::exists(Status)) {
|
|
|
|
// Fail early if we can't write to the final destination.
|
2015-09-18 00:45:12 +08:00
|
|
|
if (!llvm::sys::fs::can_write(OutputPath)) {
|
2015-10-05 19:49:35 +08:00
|
|
|
Error = make_error_code(llvm::errc::operation_not_permitted);
|
2014-05-22 12:46:25 +08:00
|
|
|
return nullptr;
|
2015-09-18 00:45:12 +08:00
|
|
|
}
|
2013-06-28 02:26:26 +08:00
|
|
|
|
|
|
|
// Don't use a temporary if the output is a special file. This handles
|
|
|
|
// things like '-o /dev/null'
|
|
|
|
if (!llvm::sys::fs::is_regular_file(Status))
|
|
|
|
UseTemporary = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (UseTemporary) {
|
|
|
|
// Create a temporary file.
|
|
|
|
SmallString<128> TempPath;
|
|
|
|
TempPath = OutFile;
|
|
|
|
TempPath += "-%%%%%%%%";
|
|
|
|
int fd;
|
2014-06-12 22:02:15 +08:00
|
|
|
std::error_code EC =
|
2015-03-18 18:17:07 +08:00
|
|
|
llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath);
|
2013-06-28 11:49:04 +08:00
|
|
|
|
|
|
|
if (CreateMissingDirectories &&
|
2014-06-14 01:20:50 +08:00
|
|
|
EC == llvm::errc::no_such_file_or_directory) {
|
2013-06-28 11:49:04 +08:00
|
|
|
StringRef Parent = llvm::sys::path::parent_path(OutputPath);
|
|
|
|
EC = llvm::sys::fs::create_directories(Parent);
|
|
|
|
if (!EC) {
|
2015-03-18 18:17:07 +08:00
|
|
|
EC = llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath);
|
2013-06-28 11:49:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!EC) {
|
2014-08-11 14:53:11 +08:00
|
|
|
OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
|
2013-06-28 02:26:26 +08:00
|
|
|
OSFile = TempFile = TempPath.str();
|
2010-09-18 01:38:48 +08:00
|
|
|
}
|
2013-06-28 02:26:26 +08:00
|
|
|
// If we failed to create the temporary, fallback to writing to the file
|
|
|
|
// directly. This handles the corner case where we cannot write to the
|
|
|
|
// directory, but can write to the file.
|
2010-09-18 01:38:48 +08:00
|
|
|
}
|
|
|
|
|
2011-07-28 08:45:10 +08:00
|
|
|
if (!OS) {
|
|
|
|
OSFile = OutFile;
|
2014-08-11 14:53:11 +08:00
|
|
|
OS.reset(new llvm::raw_fd_ostream(
|
2014-08-26 02:17:04 +08:00
|
|
|
OSFile, Error,
|
2014-08-11 14:53:11 +08:00
|
|
|
(Binary ? llvm::sys::fs::F_None : llvm::sys::fs::F_Text)));
|
2014-08-26 02:17:04 +08:00
|
|
|
if (Error)
|
2014-05-22 12:46:25 +08:00
|
|
|
return nullptr;
|
2011-07-28 08:45:10 +08:00
|
|
|
}
|
2009-11-14 02:32:08 +08:00
|
|
|
|
2010-09-18 01:38:48 +08:00
|
|
|
// Make sure the out stream file gets removed if we crash.
|
2011-02-01 06:00:42 +08:00
|
|
|
if (RemoveFileOnSignal)
|
2013-06-14 05:02:40 +08:00
|
|
|
llvm::sys::RemoveFileOnSignal(OSFile);
|
2010-09-18 01:38:48 +08:00
|
|
|
|
2009-11-14 02:32:08 +08:00
|
|
|
if (ResultPathName)
|
|
|
|
*ResultPathName = OutFile;
|
2010-09-18 01:38:48 +08:00
|
|
|
if (TempPathName)
|
|
|
|
*TempPathName = TempFile;
|
2009-11-14 02:32:08 +08:00
|
|
|
|
2015-04-14 23:15:49 +08:00
|
|
|
if (!Binary || OS->supportsSeeking())
|
|
|
|
return std::move(OS);
|
|
|
|
|
|
|
|
auto B = llvm::make_unique<llvm::buffer_ostream>(*OS);
|
|
|
|
assert(!NonSeekStream);
|
|
|
|
NonSeekStream = std::move(OS);
|
|
|
|
return std::move(B);
|
2009-11-14 02:32:08 +08:00
|
|
|
}
|
2009-11-14 15:53:04 +08:00
|
|
|
|
|
|
|
// Initialization Utilities
|
|
|
|
|
2012-11-10 03:40:33 +08:00
|
|
|
bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input){
|
clang-cl: Implement initial limited support for precompiled headers.
In the gcc precompiled header model, one explicitly runs clang with `-x
c++-header` on a .h file to produce a gch file, and then includes the header
with `-include foo.h` and if a .gch file exists for that header it gets used.
This is documented at
http://clang.llvm.org/docs/UsersManual.html#precompiled-headers
cl.exe's model is fairly different, and controlled by the two flags /Yc and
/Yu. A pch file is generated as a side effect of a regular compilation when
/Ycheader.h is passed. While the compilation is running, the compiler keeps
track of #include lines in the main translation unit and writes everything up
to an `#include "header.h"` line into a pch file. Conversely, /Yuheader.h tells
the compiler to skip all code in the main TU up to and including `#include
"header.h"` and instead load header.pch. (It's also possible to use /Yc and /Yu
without an argument, in that case a `#pragma hrdstop` takes the role of
controlling the point where pch ends and real code begins.)
This patch implements limited support for this in that it requires the pch
header to be passed as a /FI force include flag – with this restriction,
it can be implemented almost completely in the driver with fairly small amounts
of code. For /Yu, this is trivial, and for /Yc a separate pch action is added
that runs before the actual compilation. After r261774, the first failing
command makes a compilation stop – this means if the pch fails to build the
main compilation won't run, which is what we want. However, in /fallback builds
we need to run the main compilation even if the pch build fails so that the
main compilation's fallback can run. To achieve this, add a ForceSuccessCommand
that pretends that the pch build always succeeded in /fallback builds (the main
compilation will then fail to open the pch and run the fallback cl.exe
invocation).
If /Yc /Yu are used in a setup that clang-cl doesn't implement yet, clang-cl
will now emit a "not implemented yet; flag ignored" warning that can be
disabled using -Wno-clang-cl-pch.
Since clang-cl doesn't yet serialize some important things (most notably
`pragma comment(lib, ...)`, this feature is disabled by default and only
enabled by an internal driver flag. Once it's more stable, this internal flag
will disappear.
(The default stdafx.h setup passes stdafx.h as explicit argument to /Yc but not
as /FI – instead every single TU has to `#include <stdafx.h>` as first thing it
does. Implementing support for this should be possible with the approach in
this patch with minimal frontend changes by passing a --stop-at / --start-at
flag from the driver to the frontend. This is left for a follow-up. I don't
think we ever want to support `#pragma hdrstop`, and supporting it with this
approach isn't easy: This approach relies on the driver knowing the pch
filename in advance, and `#pragma hdrstop(out.pch)` can set the output
filename, so the driver can't know about it in advance.)
clang-cl now also honors /Fp and puts pch files in the same spot that cl.exe
would put them, but the pch file format is of course incompatible. This has
ramifications on /fallback, so /Yc /Yu aren't passed through to cl.exe in
/fallback builds.
http://reviews.llvm.org/D17695
llvm-svn: 262420
2016-03-02 07:16:44 +08:00
|
|
|
return InitializeSourceManager(
|
|
|
|
Input, getDiagnostics(), getFileManager(), getSourceManager(),
|
|
|
|
hasPreprocessor() ? &getPreprocessor().getHeaderSearchInfo() : nullptr,
|
2016-03-13 10:44:13 +08:00
|
|
|
getDependencyOutputOpts(), getFrontendOpts());
|
2009-11-14 15:53:04 +08:00
|
|
|
}
|
|
|
|
|
clang-cl: Implement initial limited support for precompiled headers.
In the gcc precompiled header model, one explicitly runs clang with `-x
c++-header` on a .h file to produce a gch file, and then includes the header
with `-include foo.h` and if a .gch file exists for that header it gets used.
This is documented at
http://clang.llvm.org/docs/UsersManual.html#precompiled-headers
cl.exe's model is fairly different, and controlled by the two flags /Yc and
/Yu. A pch file is generated as a side effect of a regular compilation when
/Ycheader.h is passed. While the compilation is running, the compiler keeps
track of #include lines in the main translation unit and writes everything up
to an `#include "header.h"` line into a pch file. Conversely, /Yuheader.h tells
the compiler to skip all code in the main TU up to and including `#include
"header.h"` and instead load header.pch. (It's also possible to use /Yc and /Yu
without an argument, in that case a `#pragma hrdstop` takes the role of
controlling the point where pch ends and real code begins.)
This patch implements limited support for this in that it requires the pch
header to be passed as a /FI force include flag – with this restriction,
it can be implemented almost completely in the driver with fairly small amounts
of code. For /Yu, this is trivial, and for /Yc a separate pch action is added
that runs before the actual compilation. After r261774, the first failing
command makes a compilation stop – this means if the pch fails to build the
main compilation won't run, which is what we want. However, in /fallback builds
we need to run the main compilation even if the pch build fails so that the
main compilation's fallback can run. To achieve this, add a ForceSuccessCommand
that pretends that the pch build always succeeded in /fallback builds (the main
compilation will then fail to open the pch and run the fallback cl.exe
invocation).
If /Yc /Yu are used in a setup that clang-cl doesn't implement yet, clang-cl
will now emit a "not implemented yet; flag ignored" warning that can be
disabled using -Wno-clang-cl-pch.
Since clang-cl doesn't yet serialize some important things (most notably
`pragma comment(lib, ...)`, this feature is disabled by default and only
enabled by an internal driver flag. Once it's more stable, this internal flag
will disappear.
(The default stdafx.h setup passes stdafx.h as explicit argument to /Yc but not
as /FI – instead every single TU has to `#include <stdafx.h>` as first thing it
does. Implementing support for this should be possible with the approach in
this patch with minimal frontend changes by passing a --stop-at / --start-at
flag from the driver to the frontend. This is left for a follow-up. I don't
think we ever want to support `#pragma hdrstop`, and supporting it with this
approach isn't easy: This approach relies on the driver knowing the pch
filename in advance, and `#pragma hdrstop(out.pch)` can set the output
filename, so the driver can't know about it in advance.)
clang-cl now also honors /Fp and puts pch files in the same spot that cl.exe
would put them, but the pch file format is of course incompatible. This has
ramifications on /fallback, so /Yc /Yu aren't passed through to cl.exe in
/fallback builds.
http://reviews.llvm.org/D17695
llvm-svn: 262420
2016-03-02 07:16:44 +08:00
|
|
|
// static
|
2016-03-13 10:44:13 +08:00
|
|
|
bool CompilerInstance::InitializeSourceManager(
|
|
|
|
const FrontendInputFile &Input, DiagnosticsEngine &Diags,
|
|
|
|
FileManager &FileMgr, SourceManager &SourceMgr, HeaderSearch *HS,
|
|
|
|
DependencyOutputOptions &DepOpts, const FrontendOptions &Opts) {
|
2012-11-10 03:40:33 +08:00
|
|
|
SrcMgr::CharacteristicKind
|
2012-11-10 03:40:39 +08:00
|
|
|
Kind = Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
|
2012-11-10 03:40:33 +08:00
|
|
|
|
2012-11-10 03:40:45 +08:00
|
|
|
if (Input.isBuffer()) {
|
2014-08-29 15:59:55 +08:00
|
|
|
SourceMgr.setMainFileID(SourceMgr.createFileID(
|
|
|
|
std::unique_ptr<llvm::MemoryBuffer>(Input.getBuffer()), Kind));
|
2015-10-03 18:46:20 +08:00
|
|
|
assert(SourceMgr.getMainFileID().isValid() &&
|
2012-11-10 03:40:45 +08:00
|
|
|
"Couldn't establish MainFileID!");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
StringRef InputFile = Input.getFile();
|
|
|
|
|
2011-09-20 04:40:35 +08:00
|
|
|
// Figure out where to get and map in the main file.
|
|
|
|
if (InputFile != "-") {
|
clang-cl: Implement initial limited support for precompiled headers.
In the gcc precompiled header model, one explicitly runs clang with `-x
c++-header` on a .h file to produce a gch file, and then includes the header
with `-include foo.h` and if a .gch file exists for that header it gets used.
This is documented at
http://clang.llvm.org/docs/UsersManual.html#precompiled-headers
cl.exe's model is fairly different, and controlled by the two flags /Yc and
/Yu. A pch file is generated as a side effect of a regular compilation when
/Ycheader.h is passed. While the compilation is running, the compiler keeps
track of #include lines in the main translation unit and writes everything up
to an `#include "header.h"` line into a pch file. Conversely, /Yuheader.h tells
the compiler to skip all code in the main TU up to and including `#include
"header.h"` and instead load header.pch. (It's also possible to use /Yc and /Yu
without an argument, in that case a `#pragma hrdstop` takes the role of
controlling the point where pch ends and real code begins.)
This patch implements limited support for this in that it requires the pch
header to be passed as a /FI force include flag – with this restriction,
it can be implemented almost completely in the driver with fairly small amounts
of code. For /Yu, this is trivial, and for /Yc a separate pch action is added
that runs before the actual compilation. After r261774, the first failing
command makes a compilation stop – this means if the pch fails to build the
main compilation won't run, which is what we want. However, in /fallback builds
we need to run the main compilation even if the pch build fails so that the
main compilation's fallback can run. To achieve this, add a ForceSuccessCommand
that pretends that the pch build always succeeded in /fallback builds (the main
compilation will then fail to open the pch and run the fallback cl.exe
invocation).
If /Yc /Yu are used in a setup that clang-cl doesn't implement yet, clang-cl
will now emit a "not implemented yet; flag ignored" warning that can be
disabled using -Wno-clang-cl-pch.
Since clang-cl doesn't yet serialize some important things (most notably
`pragma comment(lib, ...)`, this feature is disabled by default and only
enabled by an internal driver flag. Once it's more stable, this internal flag
will disappear.
(The default stdafx.h setup passes stdafx.h as explicit argument to /Yc but not
as /FI – instead every single TU has to `#include <stdafx.h>` as first thing it
does. Implementing support for this should be possible with the approach in
this patch with minimal frontend changes by passing a --stop-at / --start-at
flag from the driver to the frontend. This is left for a follow-up. I don't
think we ever want to support `#pragma hdrstop`, and supporting it with this
approach isn't easy: This approach relies on the driver knowing the pch
filename in advance, and `#pragma hdrstop(out.pch)` can set the output
filename, so the driver can't know about it in advance.)
clang-cl now also honors /Fp and puts pch files in the same spot that cl.exe
would put them, but the pch file format is of course incompatible. This has
ramifications on /fallback, so /Yc /Yu aren't passed through to cl.exe in
/fallback builds.
http://reviews.llvm.org/D17695
llvm-svn: 262420
2016-03-02 07:16:44 +08:00
|
|
|
const FileEntry *File;
|
|
|
|
if (Opts.FindPchSource.empty()) {
|
|
|
|
File = FileMgr.getFile(InputFile, /*OpenFile=*/true);
|
|
|
|
} else {
|
|
|
|
// When building a pch file in clang-cl mode, the .h file is built as if
|
|
|
|
// it was included by a cc file. Since the driver doesn't know about
|
|
|
|
// all include search directories, the frontend must search the input
|
|
|
|
// file through HeaderSearch here, as if it had been included by the
|
|
|
|
// cc file at Opts.FindPchSource.
|
|
|
|
const FileEntry *FindFile = FileMgr.getFile(Opts.FindPchSource);
|
|
|
|
if (!FindFile) {
|
|
|
|
Diags.Report(diag::err_fe_error_reading) << Opts.FindPchSource;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
const DirectoryLookup *UnusedCurDir;
|
|
|
|
SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 16>
|
|
|
|
Includers;
|
|
|
|
Includers.push_back(std::make_pair(FindFile, FindFile->getDir()));
|
|
|
|
File = HS->LookupFile(InputFile, SourceLocation(), /*isAngled=*/false,
|
|
|
|
/*FromDir=*/nullptr,
|
|
|
|
/*CurDir=*/UnusedCurDir, Includers,
|
|
|
|
/*SearchPath=*/nullptr,
|
|
|
|
/*RelativePath=*/nullptr,
|
|
|
|
/*RequestingModule=*/nullptr,
|
|
|
|
/*SuggestedModule=*/nullptr, /*SkipCache=*/true);
|
2016-03-13 10:44:13 +08:00
|
|
|
// Also add the header to /showIncludes output.
|
|
|
|
if (File)
|
2016-03-24 02:46:57 +08:00
|
|
|
DepOpts.ShowIncludesPretendHeader = File->getName();
|
clang-cl: Implement initial limited support for precompiled headers.
In the gcc precompiled header model, one explicitly runs clang with `-x
c++-header` on a .h file to produce a gch file, and then includes the header
with `-include foo.h` and if a .gch file exists for that header it gets used.
This is documented at
http://clang.llvm.org/docs/UsersManual.html#precompiled-headers
cl.exe's model is fairly different, and controlled by the two flags /Yc and
/Yu. A pch file is generated as a side effect of a regular compilation when
/Ycheader.h is passed. While the compilation is running, the compiler keeps
track of #include lines in the main translation unit and writes everything up
to an `#include "header.h"` line into a pch file. Conversely, /Yuheader.h tells
the compiler to skip all code in the main TU up to and including `#include
"header.h"` and instead load header.pch. (It's also possible to use /Yc and /Yu
without an argument, in that case a `#pragma hrdstop` takes the role of
controlling the point where pch ends and real code begins.)
This patch implements limited support for this in that it requires the pch
header to be passed as a /FI force include flag – with this restriction,
it can be implemented almost completely in the driver with fairly small amounts
of code. For /Yu, this is trivial, and for /Yc a separate pch action is added
that runs before the actual compilation. After r261774, the first failing
command makes a compilation stop – this means if the pch fails to build the
main compilation won't run, which is what we want. However, in /fallback builds
we need to run the main compilation even if the pch build fails so that the
main compilation's fallback can run. To achieve this, add a ForceSuccessCommand
that pretends that the pch build always succeeded in /fallback builds (the main
compilation will then fail to open the pch and run the fallback cl.exe
invocation).
If /Yc /Yu are used in a setup that clang-cl doesn't implement yet, clang-cl
will now emit a "not implemented yet; flag ignored" warning that can be
disabled using -Wno-clang-cl-pch.
Since clang-cl doesn't yet serialize some important things (most notably
`pragma comment(lib, ...)`, this feature is disabled by default and only
enabled by an internal driver flag. Once it's more stable, this internal flag
will disappear.
(The default stdafx.h setup passes stdafx.h as explicit argument to /Yc but not
as /FI – instead every single TU has to `#include <stdafx.h>` as first thing it
does. Implementing support for this should be possible with the approach in
this patch with minimal frontend changes by passing a --stop-at / --start-at
flag from the driver to the frontend. This is left for a follow-up. I don't
think we ever want to support `#pragma hdrstop`, and supporting it with this
approach isn't easy: This approach relies on the driver knowing the pch
filename in advance, and `#pragma hdrstop(out.pch)` can set the output
filename, so the driver can't know about it in advance.)
clang-cl now also honors /Fp and puts pch files in the same spot that cl.exe
would put them, but the pch file format is of course incompatible. This has
ramifications on /fallback, so /Yc /Yu aren't passed through to cl.exe in
/fallback builds.
http://reviews.llvm.org/D17695
llvm-svn: 262420
2016-03-02 07:16:44 +08:00
|
|
|
}
|
2010-10-27 05:13:51 +08:00
|
|
|
if (!File) {
|
2009-11-14 15:53:04 +08:00
|
|
|
Diags.Report(diag::err_fe_error_reading) << InputFile;
|
|
|
|
return false;
|
|
|
|
}
|
2012-11-06 06:53:33 +08:00
|
|
|
|
|
|
|
// The natural SourceManager infrastructure can't currently handle named
|
|
|
|
// pipes, but we would at least like to accept them for the main
|
2013-08-12 21:46:52 +08:00
|
|
|
// file. Detect them here, read them with the volatile flag so FileMgr will
|
|
|
|
// pick up the correct size, and simply override their contents as we do for
|
|
|
|
// STDIN.
|
2012-11-06 06:53:33 +08:00
|
|
|
if (File->isNamedPipe()) {
|
2014-10-27 06:44:13 +08:00
|
|
|
auto MB = FileMgr.getBufferForFile(File, /*isVolatile=*/true);
|
|
|
|
if (MB) {
|
2013-08-12 21:46:52 +08:00
|
|
|
// Create a new virtual file that will have the correct size.
|
2014-10-27 06:44:13 +08:00
|
|
|
File = FileMgr.getVirtualFile(InputFile, (*MB)->getBufferSize(), 0);
|
|
|
|
SourceMgr.overrideFileContents(File, std::move(*MB));
|
2013-08-12 21:46:52 +08:00
|
|
|
} else {
|
2014-10-27 06:44:13 +08:00
|
|
|
Diags.Report(diag::err_cannot_open_file) << InputFile
|
|
|
|
<< MB.getError().message();
|
2012-11-06 06:53:33 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2012-11-27 08:04:16 +08:00
|
|
|
|
2014-05-21 09:12:41 +08:00
|
|
|
SourceMgr.setMainFileID(
|
|
|
|
SourceMgr.createFileID(File, SourceLocation(), Kind));
|
2009-11-14 15:53:04 +08:00
|
|
|
} else {
|
2014-07-07 01:43:24 +08:00
|
|
|
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> SBOrErr =
|
|
|
|
llvm::MemoryBuffer::getSTDIN();
|
|
|
|
if (std::error_code EC = SBOrErr.getError()) {
|
|
|
|
Diags.Report(diag::err_fe_error_reading_stdin) << EC.message();
|
2009-11-14 15:53:04 +08:00
|
|
|
return false;
|
|
|
|
}
|
2014-07-07 01:43:24 +08:00
|
|
|
std::unique_ptr<llvm::MemoryBuffer> SB = std::move(SBOrErr.get());
|
|
|
|
|
2010-10-27 07:21:25 +08:00
|
|
|
const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
|
2010-11-23 16:35:12 +08:00
|
|
|
SB->getBufferSize(), 0);
|
2014-05-21 09:12:41 +08:00
|
|
|
SourceMgr.setMainFileID(
|
|
|
|
SourceMgr.createFileID(File, SourceLocation(), Kind));
|
2014-08-28 04:54:45 +08:00
|
|
|
SourceMgr.overrideFileContents(File, std::move(SB));
|
2009-11-14 15:53:04 +08:00
|
|
|
}
|
|
|
|
|
2015-10-03 18:46:20 +08:00
|
|
|
assert(SourceMgr.getMainFileID().isValid() &&
|
2010-10-27 05:13:51 +08:00
|
|
|
"Couldn't establish MainFileID!");
|
2009-11-14 15:53:04 +08:00
|
|
|
return true;
|
|
|
|
}
|
2010-01-13 08:48:06 +08:00
|
|
|
|
|
|
|
// High-Level Operations
|
|
|
|
|
|
|
|
bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
|
|
|
|
assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
|
|
|
|
assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
|
|
|
|
assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
|
|
|
|
|
|
|
|
// FIXME: Take this as an argument, once all the APIs we used have moved to
|
|
|
|
// taking it as an input instead of hard-coding llvm::errs.
|
2011-07-23 18:55:15 +08:00
|
|
|
raw_ostream &OS = llvm::errs();
|
2010-01-13 08:48:06 +08:00
|
|
|
|
|
|
|
// Create the target instance.
|
2014-07-06 13:26:44 +08:00
|
|
|
setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(),
|
2016-04-09 00:52:00 +08:00
|
|
|
getInvocation().TargetOpts));
|
2010-01-13 08:48:06 +08:00
|
|
|
if (!hasTarget())
|
|
|
|
return false;
|
|
|
|
|
2015-09-23 01:23:22 +08:00
|
|
|
// Create TargetInfo for the other side of CUDA compilation.
|
|
|
|
if (getLangOpts().CUDA && !getFrontendOpts().AuxTriple.empty()) {
|
2016-04-30 07:05:19 +08:00
|
|
|
auto TO = std::make_shared<TargetOptions>();
|
2015-09-23 01:23:22 +08:00
|
|
|
TO->Triple = getFrontendOpts().AuxTriple;
|
2016-04-30 07:05:19 +08:00
|
|
|
TO->HostTriple = getTarget().getTriple().str();
|
2016-04-09 00:52:00 +08:00
|
|
|
setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO));
|
2015-09-23 01:23:22 +08:00
|
|
|
}
|
|
|
|
|
2010-01-13 08:48:06 +08:00
|
|
|
// Inform the target of the language options.
|
|
|
|
//
|
|
|
|
// FIXME: We shouldn't need to do this, the target should be immutable once
|
|
|
|
// created. This complexity should be lifted elsewhere.
|
2014-07-06 13:14:24 +08:00
|
|
|
getTarget().adjust(getLangOpts());
|
2010-01-13 08:48:06 +08:00
|
|
|
|
2016-08-10 03:43:38 +08:00
|
|
|
// Adjust target options based on codegen options.
|
|
|
|
getTarget().adjustTargetOptions(getCodeGenOpts(), getTargetOpts());
|
|
|
|
|
2012-04-17 05:03:30 +08:00
|
|
|
// rewriter project will change target built-in bool type from its default.
|
|
|
|
if (getFrontendOpts().ProgramAction == frontend::RewriteObjC)
|
|
|
|
getTarget().noSignedCharForObjCBool();
|
|
|
|
|
2010-01-13 08:48:06 +08:00
|
|
|
// Validate/process some options.
|
|
|
|
if (getHeaderSearchOpts().Verbose)
|
|
|
|
OS << "clang -cc1 version " CLANG_VERSION_STRING
|
2014-06-06 18:36:22 +08:00
|
|
|
<< " based upon " << BACKEND_PACKAGE_STRING
|
2011-11-02 05:33:06 +08:00
|
|
|
<< " default target " << llvm::sys::getDefaultTargetTriple() << "\n";
|
2010-01-13 08:48:06 +08:00
|
|
|
|
|
|
|
if (getFrontendOpts().ShowTimers)
|
|
|
|
createFrontendTimer();
|
|
|
|
|
2016-09-27 02:53:34 +08:00
|
|
|
if (getFrontendOpts().ShowStats || !getFrontendOpts().StatsFile.empty())
|
2016-09-28 03:38:59 +08:00
|
|
|
llvm::EnableStatistics(false);
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2015-11-16 08:59:34 +08:00
|
|
|
for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) {
|
Add support for the static analyzer to synthesize function implementations from external model files.
Currently the analyzer lazily models some functions using 'BodyFarm',
which constructs a fake function implementation that the analyzer
can simulate that approximates the semantics of the function when
it is called. BodyFarm does this by constructing the AST for
such definitions on-the-fly. One strength of BodyFarm
is that all symbols and types referenced by synthesized function
bodies are contextual adapted to the containing translation unit.
The downside is that these ASTs are hardcoded in Clang's own
source code.
A more scalable model is to allow these models to be defined as source
code in separate "model" files and have the analyzer use those
definitions lazily when a function body is needed. Among other things,
it will allow more customization of the analyzer for specific APIs
and platforms.
This patch provides the initial infrastructure for this feature.
It extends BodyFarm to use an abstract API 'CodeInjector' that can be
used to synthesize function bodies. That 'CodeInjector' is
implemented using a new 'ModelInjector' in libFrontend, which lazily
parses a model file and injects the ASTs into the current translation
unit.
Models are currently found by specifying a 'model-path' as an
analyzer option; if no path is specified the CodeInjector is not
used, thus defaulting to the current behavior in the analyzer.
Models currently contain a single function definition, and can
be found by finding the file <function name>.model. This is an
initial starting point for something more rich, but it bootstraps
this feature for future evolution.
This patch was contributed by Gábor Horváth as part of his
Google Summer of Code project.
Some notes:
- This introduces the notion of a "model file" into
FrontendAction and the Preprocessor. This nomenclature
is specific to the static analyzer, but possibly could be
generalized. Essentially these are sources pulled in
exogenously from the principal translation.
Preprocessor gets a 'InitializeForModelFile' and
'FinalizeForModelFile' which could possibly be hoisted out
of Preprocessor if Preprocessor exposed a new API to
change the PragmaHandlers and some other internal pieces. This
can be revisited.
FrontendAction gets a 'isModelParsingAction()' predicate function
used to allow a new FrontendAction to recycle the Preprocessor
and ASTContext. This name could probably be made something
more general (i.e., not tied to 'model files') at the expense
of losing the intent of why it exists. This can be revisited.
- This is a moderate sized patch; it has gone through some amount of
offline code review. Most of the changes to the non-analyzer
parts are fairly small, and would make little sense without
the analyzer changes.
- Most of the analyzer changes are plumbing, with the interesting
behavior being introduced by ModelInjector.cpp and
ModelConsumer.cpp.
- The new functionality introduced by this change is off-by-default.
It requires an analyzer config option to enable.
llvm-svn: 216550
2014-08-27 23:14:15 +08:00
|
|
|
// Reset the ID tables if we are reusing the SourceManager and parsing
|
|
|
|
// regular files.
|
|
|
|
if (hasSourceManager() && !Act.isModelParsingAction())
|
2010-06-08 07:23:50 +08:00
|
|
|
getSourceManager().clearIDTables();
|
2010-01-13 08:48:06 +08:00
|
|
|
|
2015-11-16 08:59:34 +08:00
|
|
|
if (Act.BeginSourceFile(*this, FIF)) {
|
2010-01-13 08:48:06 +08:00
|
|
|
Act.Execute();
|
|
|
|
Act.EndSourceFile();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-07 13:52:12 +08:00
|
|
|
// Notify the diagnostic client that all files were processed.
|
|
|
|
getDiagnostics().getClient()->finish();
|
|
|
|
|
2010-04-08 02:47:42 +08:00
|
|
|
if (getDiagnosticOpts().ShowCarets) {
|
2010-11-19 04:06:46 +08:00
|
|
|
// We can have multiple diagnostics sharing one diagnostic client.
|
|
|
|
// Get the total number of warnings/errors from the client.
|
|
|
|
unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings();
|
|
|
|
unsigned NumErrors = getDiagnostics().getClient()->getNumErrors();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2010-04-08 02:47:42 +08:00
|
|
|
if (NumWarnings)
|
|
|
|
OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
|
|
|
|
if (NumWarnings && NumErrors)
|
|
|
|
OS << " and ";
|
|
|
|
if (NumErrors)
|
|
|
|
OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
|
|
|
|
if (NumWarnings || NumErrors)
|
|
|
|
OS << " generated.\n";
|
|
|
|
}
|
2010-01-13 08:48:06 +08:00
|
|
|
|
2016-09-27 02:53:34 +08:00
|
|
|
if (getFrontendOpts().ShowStats) {
|
|
|
|
if (hasFileManager()) {
|
|
|
|
getFileManager().PrintStats();
|
|
|
|
OS << '\n';
|
|
|
|
}
|
|
|
|
llvm::PrintStatistics(OS);
|
|
|
|
}
|
|
|
|
StringRef StatsFile = getFrontendOpts().StatsFile;
|
|
|
|
if (!StatsFile.empty()) {
|
|
|
|
std::error_code EC;
|
|
|
|
auto StatS = llvm::make_unique<llvm::raw_fd_ostream>(StatsFile, EC,
|
|
|
|
llvm::sys::fs::F_Text);
|
|
|
|
if (EC) {
|
|
|
|
getDiagnostics().Report(diag::warn_fe_unable_to_open_stats_file)
|
|
|
|
<< StatsFile << EC.message();
|
|
|
|
} else {
|
|
|
|
llvm::PrintStatisticsJSON(*StatS);
|
|
|
|
}
|
2010-01-13 08:48:06 +08:00
|
|
|
}
|
|
|
|
|
2010-11-19 05:13:57 +08:00
|
|
|
return !getDiagnostics().getClient()->getNumErrors();
|
2010-01-13 08:48:06 +08:00
|
|
|
}
|
|
|
|
|
2011-09-13 07:31:24 +08:00
|
|
|
/// \brief Determine the appropriate source input kind based on language
|
|
|
|
/// options.
|
|
|
|
static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) {
|
|
|
|
if (LangOpts.OpenCL)
|
|
|
|
return IK_OpenCL;
|
|
|
|
if (LangOpts.CUDA)
|
|
|
|
return IK_CUDA;
|
|
|
|
if (LangOpts.ObjC1)
|
|
|
|
return LangOpts.CPlusPlus? IK_ObjCXX : IK_ObjC;
|
|
|
|
return LangOpts.CPlusPlus? IK_CXX : IK_C;
|
|
|
|
}
|
|
|
|
|
2011-11-30 03:06:37 +08:00
|
|
|
/// \brief Compile a module file for the given module, using the options
|
2014-07-20 00:29:28 +08:00
|
|
|
/// provided by the importing compiler instance. Returns true if the module
|
|
|
|
/// was built without errors.
|
|
|
|
static bool compileModuleImpl(CompilerInstance &ImportingInstance,
|
|
|
|
SourceLocation ImportLoc,
|
|
|
|
Module *Module,
|
|
|
|
StringRef ModuleFileName) {
|
2011-11-30 03:06:37 +08:00
|
|
|
ModuleMap &ModMap
|
|
|
|
= ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
|
|
|
|
|
2011-09-13 07:31:24 +08:00
|
|
|
// Construct a compiler invocation for creating this module.
|
2012-02-20 22:00:23 +08:00
|
|
|
IntrusiveRefCntPtr<CompilerInvocation> Invocation
|
2011-09-13 07:31:24 +08:00
|
|
|
(new CompilerInvocation(ImportingInstance.getInvocation()));
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-11-30 05:59:16 +08:00
|
|
|
PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
|
|
|
|
|
2011-09-16 04:53:28 +08:00
|
|
|
// For any options that aren't intended to affect how a module is built,
|
|
|
|
// reset them to their default values.
|
2011-11-18 07:01:24 +08:00
|
|
|
Invocation->getLangOpts()->resetNonModularOptions();
|
2011-11-30 05:59:16 +08:00
|
|
|
PPOpts.resetNonModularOptions();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2013-02-07 08:21:12 +08:00
|
|
|
// Remove any macro definitions that are explicitly ignored by the module.
|
|
|
|
// They aren't supposed to affect how the module is built anyway.
|
|
|
|
const HeaderSearchOptions &HSOpts = Invocation->getHeaderSearchOpts();
|
2014-03-01 22:48:57 +08:00
|
|
|
PPOpts.Macros.erase(
|
|
|
|
std::remove_if(PPOpts.Macros.begin(), PPOpts.Macros.end(),
|
|
|
|
[&HSOpts](const std::pair<std::string, bool> &def) {
|
|
|
|
StringRef MacroDef = def.first;
|
2016-10-22 05:45:01 +08:00
|
|
|
return HSOpts.ModulesIgnoreMacros.count(
|
|
|
|
llvm::CachedHashString(MacroDef.split('=').first)) > 0;
|
2014-03-01 22:48:57 +08:00
|
|
|
}),
|
|
|
|
PPOpts.Macros.end());
|
2013-02-07 08:21:12 +08:00
|
|
|
|
2011-11-16 03:35:01 +08:00
|
|
|
// Note the name of the module we're building.
|
2011-11-30 02:31:39 +08:00
|
|
|
Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName();
|
2011-11-16 03:35:01 +08:00
|
|
|
|
2012-11-30 07:55:25 +08:00
|
|
|
// Make sure that the failed-module structure has been allocated in
|
|
|
|
// the importing instance, and propagate the pointer to the newly-created
|
|
|
|
// instance.
|
|
|
|
PreprocessorOptions &ImportingPPOpts
|
|
|
|
= ImportingInstance.getInvocation().getPreprocessorOpts();
|
|
|
|
if (!ImportingPPOpts.FailedModules)
|
|
|
|
ImportingPPOpts.FailedModules = new PreprocessorOptions::FailedModulesSet;
|
|
|
|
PPOpts.FailedModules = ImportingPPOpts.FailedModules;
|
|
|
|
|
2011-11-30 05:59:16 +08:00
|
|
|
// If there is a module map file, build the module using the module map.
|
2011-09-16 04:53:28 +08:00
|
|
|
// Set up the inputs/outputs so that we build the module from its umbrella
|
|
|
|
// header.
|
2011-09-13 07:31:24 +08:00
|
|
|
FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
|
2011-09-14 07:15:45 +08:00
|
|
|
FrontendOpts.OutputFile = ModuleFileName.str();
|
2011-09-13 07:31:24 +08:00
|
|
|
FrontendOpts.DisableFree = false;
|
2013-01-25 08:45:27 +08:00
|
|
|
FrontendOpts.GenerateGlobalModuleIndex = false;
|
2015-08-17 15:13:32 +08:00
|
|
|
FrontendOpts.BuildingImplicitModule = true;
|
2011-09-13 07:31:24 +08:00
|
|
|
FrontendOpts.Inputs.clear();
|
2011-11-30 05:59:16 +08:00
|
|
|
InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts());
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-11-30 05:59:16 +08:00
|
|
|
// Don't free the remapped file buffers; they are owned by our caller.
|
|
|
|
PPOpts.RetainRemappedFileBuffers = true;
|
|
|
|
|
|
|
|
Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
|
2011-09-14 07:20:27 +08:00
|
|
|
assert(ImportingInstance.getInvocation().getModuleHash() ==
|
2011-11-30 05:59:16 +08:00
|
|
|
Invocation->getModuleHash() && "Module hash mismatch!");
|
|
|
|
|
2011-09-13 07:31:24 +08:00
|
|
|
// Construct a compiler instance that will be used to actually create the
|
|
|
|
// module.
|
2015-06-21 02:53:08 +08:00
|
|
|
CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(),
|
|
|
|
/*BuildingModule=*/true);
|
2011-09-13 07:31:24 +08:00
|
|
|
Instance.setInvocation(&*Invocation);
|
2013-05-04 06:58:43 +08:00
|
|
|
|
|
|
|
Instance.createDiagnostics(new ForwardingDiagnosticConsumer(
|
|
|
|
ImportingInstance.getDiagnosticClient()),
|
2013-05-04 07:07:45 +08:00
|
|
|
/*ShouldOwnClient=*/true);
|
2012-12-01 02:38:50 +08:00
|
|
|
|
2014-02-21 05:59:23 +08:00
|
|
|
Instance.setVirtualFileSystem(&ImportingInstance.getVirtualFileSystem());
|
|
|
|
|
2012-12-01 06:11:57 +08:00
|
|
|
// Note that this module is part of the module build stack, so that we
|
2012-12-01 02:38:50 +08:00
|
|
|
// can detect cycles in the module graph.
|
2014-03-01 05:16:07 +08:00
|
|
|
Instance.setFileManager(&ImportingInstance.getFileManager());
|
2012-12-01 02:38:50 +08:00
|
|
|
Instance.createSourceManager(Instance.getFileManager());
|
|
|
|
SourceManager &SourceMgr = Instance.getSourceManager();
|
2012-12-01 06:11:57 +08:00
|
|
|
SourceMgr.setModuleBuildStack(
|
|
|
|
ImportingInstance.getSourceManager().getModuleBuildStack());
|
|
|
|
SourceMgr.pushModuleBuildStack(Module->getTopLevelModuleName(),
|
2012-12-01 02:38:50 +08:00
|
|
|
FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager()));
|
|
|
|
|
2014-06-20 03:36:03 +08:00
|
|
|
// If we're collecting module dependencies, we need to share a collector
|
2015-08-09 14:03:55 +08:00
|
|
|
// between all of the module CompilerInstances. Other than that, we don't
|
|
|
|
// want to produce any dependency output from the module build.
|
2014-06-20 03:36:03 +08:00
|
|
|
Instance.setModuleDepCollector(ImportingInstance.getModuleDepCollector());
|
2015-08-09 14:03:55 +08:00
|
|
|
Invocation->getDependencyOutputOpts() = DependencyOutputOptions();
|
2014-06-20 03:36:03 +08:00
|
|
|
|
Use the same SourceManager for ModuleMaps and compilations.
This allows using virtual file mappings on the original SourceManager to
map in virtual module.map files. Without this patch, the ModuleMap
search will find a module.map file (as the FileEntry exists in the
FileManager), but will be unable to get the content from the
SourceManager (as ModuleMap previously created its own SourceManager).
Two problems needed to be fixed which this patch exposed:
1. Storing the inferred module map
When writing out a module, the ASTWriter stores the names of the files
in the main source manager; when loading the AST again, the ASTReader
errs out if such a file is found missing, unless it is overridden.
Previously CompilerInstance's compileModule method would store the
inferred module map to a temporary file; the problem with this approach
is that now that the module map is handled by the main source manager,
the ASTWriter stores the name of the temporary module map as source to
the compilation; later, when the module is loaded, the temporary file
has already been deleted, which leads to a compilation error. This patch
changes the inferred module map to instead inject a virtual file into
the source manager. This both saves some disk IO, and works with how the
ASTWriter/ASTReader handle overridden source files.
2. Changing test input in test/Modules/Inputs/*
Now that the module map file is handled by the main source manager, the
VerifyDiagnosticConsumer will not ignore diagnostics created while
parsing the module map file. The module test test/Modules/renamed.m uses
-I test/Modules/Inputs and triggers recursive loading of all module maps
in test/Modules/Inputs, some of which had conflicting names, thus
leading errors while parsing the module maps. Those diagnostics already
occur on trunk, but before this patch they would not break the test, as
they were ignored by the VerifyDiagnosticConsumer. This patch thus
changes the module maps that have been recently introduced which broke
the invariant of compatible modules maps in test/Modules/Inputs.
llvm-svn: 193314
2013-10-24 15:51:24 +08:00
|
|
|
// Get or create the module map that we'll use to build this module.
|
|
|
|
std::string InferredModuleMapContent;
|
|
|
|
if (const FileEntry *ModuleMapFile =
|
|
|
|
ModMap.getContainingModuleMapFile(Module)) {
|
|
|
|
// Use the module map where this module resides.
|
2015-05-30 03:42:19 +08:00
|
|
|
FrontendOpts.Inputs.emplace_back(ModuleMapFile->getName(), IK);
|
Use the same SourceManager for ModuleMaps and compilations.
This allows using virtual file mappings on the original SourceManager to
map in virtual module.map files. Without this patch, the ModuleMap
search will find a module.map file (as the FileEntry exists in the
FileManager), but will be unable to get the content from the
SourceManager (as ModuleMap previously created its own SourceManager).
Two problems needed to be fixed which this patch exposed:
1. Storing the inferred module map
When writing out a module, the ASTWriter stores the names of the files
in the main source manager; when loading the AST again, the ASTReader
errs out if such a file is found missing, unless it is overridden.
Previously CompilerInstance's compileModule method would store the
inferred module map to a temporary file; the problem with this approach
is that now that the module map is handled by the main source manager,
the ASTWriter stores the name of the temporary module map as source to
the compilation; later, when the module is loaded, the temporary file
has already been deleted, which leads to a compilation error. This patch
changes the inferred module map to instead inject a virtual file into
the source manager. This both saves some disk IO, and works with how the
ASTWriter/ASTReader handle overridden source files.
2. Changing test input in test/Modules/Inputs/*
Now that the module map file is handled by the main source manager, the
VerifyDiagnosticConsumer will not ignore diagnostics created while
parsing the module map file. The module test test/Modules/renamed.m uses
-I test/Modules/Inputs and triggers recursive loading of all module maps
in test/Modules/Inputs, some of which had conflicting names, thus
leading errors while parsing the module maps. Those diagnostics already
occur on trunk, but before this patch they would not break the test, as
they were ignored by the VerifyDiagnosticConsumer. This patch thus
changes the module maps that have been recently introduced which broke
the invariant of compatible modules maps in test/Modules/Inputs.
llvm-svn: 193314
2013-10-24 15:51:24 +08:00
|
|
|
} else {
|
2015-05-16 10:28:53 +08:00
|
|
|
SmallString<128> FakeModuleMapFile(Module->Directory->getName());
|
|
|
|
llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map");
|
2015-05-30 03:42:19 +08:00
|
|
|
FrontendOpts.Inputs.emplace_back(FakeModuleMapFile, IK);
|
2015-05-16 10:28:53 +08:00
|
|
|
|
Use the same SourceManager for ModuleMaps and compilations.
This allows using virtual file mappings on the original SourceManager to
map in virtual module.map files. Without this patch, the ModuleMap
search will find a module.map file (as the FileEntry exists in the
FileManager), but will be unable to get the content from the
SourceManager (as ModuleMap previously created its own SourceManager).
Two problems needed to be fixed which this patch exposed:
1. Storing the inferred module map
When writing out a module, the ASTWriter stores the names of the files
in the main source manager; when loading the AST again, the ASTReader
errs out if such a file is found missing, unless it is overridden.
Previously CompilerInstance's compileModule method would store the
inferred module map to a temporary file; the problem with this approach
is that now that the module map is handled by the main source manager,
the ASTWriter stores the name of the temporary module map as source to
the compilation; later, when the module is loaded, the temporary file
has already been deleted, which leads to a compilation error. This patch
changes the inferred module map to instead inject a virtual file into
the source manager. This both saves some disk IO, and works with how the
ASTWriter/ASTReader handle overridden source files.
2. Changing test input in test/Modules/Inputs/*
Now that the module map file is handled by the main source manager, the
VerifyDiagnosticConsumer will not ignore diagnostics created while
parsing the module map file. The module test test/Modules/renamed.m uses
-I test/Modules/Inputs and triggers recursive loading of all module maps
in test/Modules/Inputs, some of which had conflicting names, thus
leading errors while parsing the module maps. Those diagnostics already
occur on trunk, but before this patch they would not break the test, as
they were ignored by the VerifyDiagnosticConsumer. This patch thus
changes the module maps that have been recently introduced which broke
the invariant of compatible modules maps in test/Modules/Inputs.
llvm-svn: 193314
2013-10-24 15:51:24 +08:00
|
|
|
llvm::raw_string_ostream OS(InferredModuleMapContent);
|
|
|
|
Module->print(OS);
|
|
|
|
OS.flush();
|
|
|
|
|
2014-08-28 04:03:29 +08:00
|
|
|
std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
|
Use the same SourceManager for ModuleMaps and compilations.
This allows using virtual file mappings on the original SourceManager to
map in virtual module.map files. Without this patch, the ModuleMap
search will find a module.map file (as the FileEntry exists in the
FileManager), but will be unable to get the content from the
SourceManager (as ModuleMap previously created its own SourceManager).
Two problems needed to be fixed which this patch exposed:
1. Storing the inferred module map
When writing out a module, the ASTWriter stores the names of the files
in the main source manager; when loading the AST again, the ASTReader
errs out if such a file is found missing, unless it is overridden.
Previously CompilerInstance's compileModule method would store the
inferred module map to a temporary file; the problem with this approach
is that now that the module map is handled by the main source manager,
the ASTWriter stores the name of the temporary module map as source to
the compilation; later, when the module is loaded, the temporary file
has already been deleted, which leads to a compilation error. This patch
changes the inferred module map to instead inject a virtual file into
the source manager. This both saves some disk IO, and works with how the
ASTWriter/ASTReader handle overridden source files.
2. Changing test input in test/Modules/Inputs/*
Now that the module map file is handled by the main source manager, the
VerifyDiagnosticConsumer will not ignore diagnostics created while
parsing the module map file. The module test test/Modules/renamed.m uses
-I test/Modules/Inputs and triggers recursive loading of all module maps
in test/Modules/Inputs, some of which had conflicting names, thus
leading errors while parsing the module maps. Those diagnostics already
occur on trunk, but before this patch they would not break the test, as
they were ignored by the VerifyDiagnosticConsumer. This patch thus
changes the module maps that have been recently introduced which broke
the invariant of compatible modules maps in test/Modules/Inputs.
llvm-svn: 193314
2013-10-24 15:51:24 +08:00
|
|
|
llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);
|
|
|
|
ModuleMapFile = Instance.getFileManager().getVirtualFile(
|
2015-05-16 10:28:53 +08:00
|
|
|
FakeModuleMapFile, InferredModuleMapContent.size(), 0);
|
2014-08-28 04:54:45 +08:00
|
|
|
SourceMgr.overrideFileContents(ModuleMapFile, std::move(ModuleMapBuffer));
|
Use the same SourceManager for ModuleMaps and compilations.
This allows using virtual file mappings on the original SourceManager to
map in virtual module.map files. Without this patch, the ModuleMap
search will find a module.map file (as the FileEntry exists in the
FileManager), but will be unable to get the content from the
SourceManager (as ModuleMap previously created its own SourceManager).
Two problems needed to be fixed which this patch exposed:
1. Storing the inferred module map
When writing out a module, the ASTWriter stores the names of the files
in the main source manager; when loading the AST again, the ASTReader
errs out if such a file is found missing, unless it is overridden.
Previously CompilerInstance's compileModule method would store the
inferred module map to a temporary file; the problem with this approach
is that now that the module map is handled by the main source manager,
the ASTWriter stores the name of the temporary module map as source to
the compilation; later, when the module is loaded, the temporary file
has already been deleted, which leads to a compilation error. This patch
changes the inferred module map to instead inject a virtual file into
the source manager. This both saves some disk IO, and works with how the
ASTWriter/ASTReader handle overridden source files.
2. Changing test input in test/Modules/Inputs/*
Now that the module map file is handled by the main source manager, the
VerifyDiagnosticConsumer will not ignore diagnostics created while
parsing the module map file. The module test test/Modules/renamed.m uses
-I test/Modules/Inputs and triggers recursive loading of all module maps
in test/Modules/Inputs, some of which had conflicting names, thus
leading errors while parsing the module maps. Those diagnostics already
occur on trunk, but before this patch they would not break the test, as
they were ignored by the VerifyDiagnosticConsumer. This patch thus
changes the module maps that have been recently introduced which broke
the invariant of compatible modules maps in test/Modules/Inputs.
llvm-svn: 193314
2013-10-24 15:51:24 +08:00
|
|
|
}
|
2012-12-01 02:38:50 +08:00
|
|
|
|
2014-08-09 08:57:23 +08:00
|
|
|
// Construct a module-generating action. Passing through the module map is
|
2014-04-15 02:00:01 +08:00
|
|
|
// safe because the FileManager is shared between the compiler instances.
|
2016-08-26 08:14:38 +08:00
|
|
|
GenerateModuleFromModuleMapAction CreateModuleAction(
|
2014-08-09 08:57:23 +08:00
|
|
|
ModMap.getModuleMapFileForUniquing(Module), Module->IsSystem);
|
2014-10-14 10:08:30 +08:00
|
|
|
|
|
|
|
ImportingInstance.getDiagnostics().Report(ImportLoc,
|
|
|
|
diag::remark_module_build)
|
|
|
|
<< Module->Name << ModuleFileName;
|
|
|
|
|
2011-10-04 08:21:21 +08:00
|
|
|
// Execute the action to actually build the module in-place. Use a separate
|
|
|
|
// thread so that we get a stack large enough.
|
|
|
|
const unsigned ThreadStackSize = 8 << 20;
|
|
|
|
llvm::CrashRecoveryContext CRC;
|
2014-03-05 05:50:01 +08:00
|
|
|
CRC.RunSafelyOnThread([&]() { Instance.ExecuteAction(CreateModuleAction); },
|
|
|
|
ThreadStackSize);
|
2013-05-04 06:58:43 +08:00
|
|
|
|
2014-10-14 10:08:30 +08:00
|
|
|
ImportingInstance.getDiagnostics().Report(ImportLoc,
|
|
|
|
diag::remark_module_build_done)
|
|
|
|
<< Module->Name;
|
|
|
|
|
2011-11-30 05:59:16 +08:00
|
|
|
// Delete the temporary module map file.
|
|
|
|
// FIXME: Even though we're executing under crash protection, it would still
|
|
|
|
// be nice to do this with RemoveFileOnSignal when we can. However, that
|
|
|
|
// doesn't make sense for all clients, so clean this up manually.
|
2012-10-15 03:50:53 +08:00
|
|
|
Instance.clearOutputFiles(/*EraseFiles=*/true);
|
2013-01-24 06:38:11 +08:00
|
|
|
|
|
|
|
// We've rebuilt a module. If we're allowed to generate or update the global
|
|
|
|
// module index, record that fact in the importing compiler instance.
|
2013-01-25 08:45:27 +08:00
|
|
|
if (ImportingInstance.getFrontendOpts().GenerateGlobalModuleIndex) {
|
2013-01-24 06:38:11 +08:00
|
|
|
ImportingInstance.setBuildGlobalModuleIndex(true);
|
|
|
|
}
|
2014-07-20 00:29:28 +08:00
|
|
|
|
|
|
|
return !Instance.getDiagnostics().hasErrorOccurred();
|
2011-10-08 19:31:46 +08:00
|
|
|
}
|
2011-09-13 07:31:24 +08:00
|
|
|
|
2014-06-18 06:35:27 +08:00
|
|
|
static bool compileAndLoadModule(CompilerInstance &ImportingInstance,
|
|
|
|
SourceLocation ImportLoc,
|
2014-07-20 00:29:28 +08:00
|
|
|
SourceLocation ModuleNameLoc, Module *Module,
|
2014-06-18 06:35:27 +08:00
|
|
|
StringRef ModuleFileName) {
|
2014-09-27 06:42:23 +08:00
|
|
|
DiagnosticsEngine &Diags = ImportingInstance.getDiagnostics();
|
|
|
|
|
2014-07-20 00:29:28 +08:00
|
|
|
auto diagnoseBuildFailure = [&] {
|
2014-09-27 06:42:23 +08:00
|
|
|
Diags.Report(ModuleNameLoc, diag::err_module_not_built)
|
2014-07-20 00:29:28 +08:00
|
|
|
<< Module->Name << SourceRange(ImportLoc, ModuleNameLoc);
|
|
|
|
};
|
|
|
|
|
2014-04-06 11:21:44 +08:00
|
|
|
// FIXME: have LockFileManager return an error_code so that we can
|
|
|
|
// avoid the mkdir when the directory already exists.
|
|
|
|
StringRef Dir = llvm::sys::path::parent_path(ModuleFileName);
|
|
|
|
llvm::sys::fs::create_directories(Dir);
|
|
|
|
|
|
|
|
while (1) {
|
2014-06-18 06:35:27 +08:00
|
|
|
unsigned ModuleLoadCapabilities = ASTReader::ARR_Missing;
|
2014-04-06 11:21:44 +08:00
|
|
|
llvm::LockFileManager Locked(ModuleFileName);
|
|
|
|
switch (Locked) {
|
|
|
|
case llvm::LockFileManager::LFS_Error:
|
2014-09-27 06:42:23 +08:00
|
|
|
Diags.Report(ModuleNameLoc, diag::err_module_lock_failure)
|
2016-06-04 09:13:22 +08:00
|
|
|
<< Module->Name << Locked.getErrorMessage();
|
2014-06-18 06:35:27 +08:00
|
|
|
return false;
|
2014-04-06 11:21:44 +08:00
|
|
|
|
|
|
|
case llvm::LockFileManager::LFS_Owned:
|
2014-06-18 06:35:27 +08:00
|
|
|
// We're responsible for building the module ourselves.
|
2014-07-20 00:29:28 +08:00
|
|
|
if (!compileModuleImpl(ImportingInstance, ModuleNameLoc, Module,
|
|
|
|
ModuleFileName)) {
|
|
|
|
diagnoseBuildFailure();
|
|
|
|
return false;
|
|
|
|
}
|
2014-04-06 11:21:44 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case llvm::LockFileManager::LFS_Shared:
|
|
|
|
// Someone else is responsible for building the module. Wait for them to
|
|
|
|
// finish.
|
2015-02-10 04:35:13 +08:00
|
|
|
switch (Locked.waitForUnlock()) {
|
|
|
|
case llvm::LockFileManager::Res_Success:
|
|
|
|
ModuleLoadCapabilities |= ASTReader::ARR_OutOfDate;
|
|
|
|
break;
|
|
|
|
case llvm::LockFileManager::Res_OwnerDied:
|
2014-04-06 11:21:44 +08:00
|
|
|
continue; // try again to get the lock.
|
2015-02-10 04:35:13 +08:00
|
|
|
case llvm::LockFileManager::Res_Timeout:
|
|
|
|
Diags.Report(ModuleNameLoc, diag::err_module_lock_timeout)
|
|
|
|
<< Module->Name;
|
|
|
|
// Clear the lock file so that future invokations can make progress.
|
|
|
|
Locked.unsafeRemoveLockFile();
|
|
|
|
return false;
|
|
|
|
}
|
2014-06-18 06:35:27 +08:00
|
|
|
break;
|
2014-04-06 11:21:44 +08:00
|
|
|
}
|
|
|
|
|
2014-06-18 06:35:27 +08:00
|
|
|
// Try to read the module file, now that we've compiled it.
|
|
|
|
ASTReader::ASTReadResult ReadResult =
|
|
|
|
ImportingInstance.getModuleManager()->ReadAST(
|
2014-10-22 10:05:46 +08:00
|
|
|
ModuleFileName, serialization::MK_ImplicitModule, ImportLoc,
|
2014-06-18 06:35:27 +08:00
|
|
|
ModuleLoadCapabilities);
|
|
|
|
|
|
|
|
if (ReadResult == ASTReader::OutOfDate &&
|
|
|
|
Locked == llvm::LockFileManager::LFS_Shared) {
|
|
|
|
// The module may be out of date in the presence of file system races,
|
|
|
|
// or if one of its imports depends on header search paths that are not
|
|
|
|
// consistent with this ImportingInstance. Try again...
|
|
|
|
continue;
|
|
|
|
} else if (ReadResult == ASTReader::Missing) {
|
2014-07-20 00:29:28 +08:00
|
|
|
diagnoseBuildFailure();
|
2014-09-27 06:42:23 +08:00
|
|
|
} else if (ReadResult != ASTReader::Success &&
|
|
|
|
!Diags.hasErrorOccurred()) {
|
|
|
|
// The ASTReader didn't diagnose the error, so conservatively report it.
|
|
|
|
diagnoseBuildFailure();
|
2014-06-18 06:35:27 +08:00
|
|
|
}
|
|
|
|
return ReadResult == ASTReader::Success;
|
2014-04-06 11:21:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-20 08:22:05 +08:00
|
|
|
/// \brief Diagnose differences between the current definition of the given
|
|
|
|
/// configuration macro and the definition provided on the command line.
|
|
|
|
static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
|
|
|
|
Module *Mod, SourceLocation ImportLoc) {
|
|
|
|
IdentifierInfo *Id = PP.getIdentifierInfo(ConfigMacro);
|
|
|
|
SourceManager &SourceMgr = PP.getSourceManager();
|
|
|
|
|
|
|
|
// If this identifier has never had a macro definition, then it could
|
|
|
|
// not have changed.
|
|
|
|
if (!Id->hadMacroDefinition())
|
|
|
|
return;
|
2015-04-30 07:20:19 +08:00
|
|
|
auto *LatestLocalMD = PP.getLocalMacroDirectiveHistory(Id);
|
2013-03-20 08:22:05 +08:00
|
|
|
|
2015-04-30 07:20:19 +08:00
|
|
|
// Find the macro definition from the command line.
|
|
|
|
MacroInfo *CmdLineDefinition = nullptr;
|
|
|
|
for (auto *MD = LatestLocalMD; MD; MD = MD->getPrevious()) {
|
2013-03-20 08:22:05 +08:00
|
|
|
// We only care about the predefines buffer.
|
2015-04-30 07:20:19 +08:00
|
|
|
FileID FID = SourceMgr.getFileID(MD->getLocation());
|
|
|
|
if (FID.isInvalid() || FID != PP.getPredefinesFileID())
|
2013-03-20 08:22:05 +08:00
|
|
|
continue;
|
2015-04-30 07:20:19 +08:00
|
|
|
if (auto *DMD = dyn_cast<DefMacroDirective>(MD))
|
|
|
|
CmdLineDefinition = DMD->getMacroInfo();
|
2013-03-20 08:22:05 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2015-04-30 07:20:19 +08:00
|
|
|
auto *CurrentDefinition = PP.getMacroInfo(Id);
|
|
|
|
if (CurrentDefinition == CmdLineDefinition) {
|
|
|
|
// Macro matches. Nothing to do.
|
|
|
|
} else if (!CurrentDefinition) {
|
|
|
|
// This macro was defined on the command line, then #undef'd later.
|
|
|
|
// Complain.
|
|
|
|
PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
|
|
|
|
<< true << ConfigMacro << Mod->getFullModuleName();
|
|
|
|
auto LatestDef = LatestLocalMD->getDefinition();
|
|
|
|
assert(LatestDef.isUndefined() &&
|
|
|
|
"predefined macro went away with no #undef?");
|
|
|
|
PP.Diag(LatestDef.getUndefLocation(), diag::note_module_def_undef_here)
|
|
|
|
<< true;
|
|
|
|
return;
|
|
|
|
} else if (!CmdLineDefinition) {
|
|
|
|
// There was no definition for this macro in the predefines buffer,
|
|
|
|
// but there was a local definition. Complain.
|
2013-03-20 08:22:05 +08:00
|
|
|
PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
|
|
|
|
<< false << ConfigMacro << Mod->getFullModuleName();
|
2015-04-30 07:20:19 +08:00
|
|
|
PP.Diag(CurrentDefinition->getDefinitionLoc(),
|
|
|
|
diag::note_module_def_undef_here)
|
|
|
|
<< false;
|
|
|
|
} else if (!CurrentDefinition->isIdenticalTo(*CmdLineDefinition, PP,
|
|
|
|
/*Syntactically=*/true)) {
|
|
|
|
// The macro definitions differ.
|
|
|
|
PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
|
|
|
|
<< false << ConfigMacro << Mod->getFullModuleName();
|
|
|
|
PP.Diag(CurrentDefinition->getDefinitionLoc(),
|
|
|
|
diag::note_module_def_undef_here)
|
2013-03-20 08:22:05 +08:00
|
|
|
<< false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-26 05:19:16 +08:00
|
|
|
/// \brief Write a new timestamp file with the given path.
|
|
|
|
static void writeTimestampFile(StringRef TimestampFile) {
|
2014-08-26 02:17:04 +08:00
|
|
|
std::error_code EC;
|
|
|
|
llvm::raw_fd_ostream Out(TimestampFile.str(), EC, llvm::sys::fs::F_None);
|
2013-03-26 05:19:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Prune the module cache of modules that haven't been accessed in
|
|
|
|
/// a long time.
|
|
|
|
static void pruneModuleCache(const HeaderSearchOptions &HSOpts) {
|
|
|
|
struct stat StatBuf;
|
|
|
|
llvm::SmallString<128> TimestampFile;
|
|
|
|
TimestampFile = HSOpts.ModuleCachePath;
|
2015-08-15 08:34:15 +08:00
|
|
|
assert(!TimestampFile.empty());
|
2013-03-26 05:19:16 +08:00
|
|
|
llvm::sys::path::append(TimestampFile, "modules.timestamp");
|
|
|
|
|
|
|
|
// Try to stat() the timestamp file.
|
|
|
|
if (::stat(TimestampFile.c_str(), &StatBuf)) {
|
|
|
|
// If the timestamp file wasn't there, create one now.
|
|
|
|
if (errno == ENOENT) {
|
|
|
|
writeTimestampFile(TimestampFile);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the time stamp is older than our pruning interval.
|
|
|
|
// If not, do nothing.
|
|
|
|
time_t TimeStampModTime = StatBuf.st_mtime;
|
2014-05-22 12:46:25 +08:00
|
|
|
time_t CurrentTime = time(nullptr);
|
2013-03-30 01:39:43 +08:00
|
|
|
if (CurrentTime - TimeStampModTime <= time_t(HSOpts.ModuleCachePruneInterval))
|
2013-03-26 05:19:16 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Write a new timestamp file so that nobody else attempts to prune.
|
|
|
|
// There is a benign race condition here, if two Clang instances happen to
|
|
|
|
// notice at the same time that the timestamp is out-of-date.
|
|
|
|
writeTimestampFile(TimestampFile);
|
|
|
|
|
|
|
|
// Walk the entire module cache, looking for unused module files and module
|
|
|
|
// indices.
|
2014-06-12 22:02:15 +08:00
|
|
|
std::error_code EC;
|
2013-03-26 05:19:16 +08:00
|
|
|
SmallString<128> ModuleCachePathNative;
|
|
|
|
llvm::sys::path::native(HSOpts.ModuleCachePath, ModuleCachePathNative);
|
2015-03-18 18:17:07 +08:00
|
|
|
for (llvm::sys::fs::directory_iterator Dir(ModuleCachePathNative, EC), DirEnd;
|
2013-03-26 05:19:16 +08:00
|
|
|
Dir != DirEnd && !EC; Dir.increment(EC)) {
|
|
|
|
// If we don't have a directory, there's nothing to look into.
|
2013-07-17 12:23:07 +08:00
|
|
|
if (!llvm::sys::fs::is_directory(Dir->path()))
|
2013-03-26 05:19:16 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Walk all of the files within this directory.
|
|
|
|
for (llvm::sys::fs::directory_iterator File(Dir->path(), EC), FileEnd;
|
|
|
|
File != FileEnd && !EC; File.increment(EC)) {
|
|
|
|
// We only care about module and global module index files.
|
Add an option to allow Clang verify source files for a module only once during
the build
When Clang loads the module, it verifies the user source files that the module
was built from. If any file was changed, the module is rebuilt. There are two
problems with this:
1. correctness: we don't verify system files (there are too many of them, and
stat'ing all of them would take a lot of time);
2. performance: the same module file is verified again and again during a
single build.
This change allows the build system to optimize source file verification. The
idea is based on the fact that while the project is being built, the source
files don't change. This allows us to verify the module only once during a
single build session. The build system passes a flag,
-fbuild-session-timestamp=, to inform Clang of the time when the build started.
The build system also requests to enable this feature by passing
-fmodules-validate-once-per-build-session. If these flags are not passed, the
behavior is not changed. When Clang verifies the module the first time, it
writes out a timestamp file. Then, when Clang loads the module the second
time, it finds a timestamp file, so it can compare the verification timestamp
of the module with the time when the build started. If the verification
timestamp is too old, the module is verified again, and the timestamp file is
updated.
llvm-svn: 201224
2014-02-12 18:33:14 +08:00
|
|
|
StringRef Extension = llvm::sys::path::extension(File->path());
|
|
|
|
if (Extension != ".pcm" && Extension != ".timestamp" &&
|
|
|
|
llvm::sys::path::filename(File->path()) != "modules.idx")
|
2013-03-26 05:19:16 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// Look at this file. If we can't stat it, there's nothing interesting
|
|
|
|
// there.
|
Add an option to allow Clang verify source files for a module only once during
the build
When Clang loads the module, it verifies the user source files that the module
was built from. If any file was changed, the module is rebuilt. There are two
problems with this:
1. correctness: we don't verify system files (there are too many of them, and
stat'ing all of them would take a lot of time);
2. performance: the same module file is verified again and again during a
single build.
This change allows the build system to optimize source file verification. The
idea is based on the fact that while the project is being built, the source
files don't change. This allows us to verify the module only once during a
single build session. The build system passes a flag,
-fbuild-session-timestamp=, to inform Clang of the time when the build started.
The build system also requests to enable this feature by passing
-fmodules-validate-once-per-build-session. If these flags are not passed, the
behavior is not changed. When Clang verifies the module the first time, it
writes out a timestamp file. Then, when Clang loads the module the second
time, it finds a timestamp file, so it can compare the verification timestamp
of the module with the time when the build started. If the verification
timestamp is too old, the module is verified again, and the timestamp file is
updated.
llvm-svn: 201224
2014-02-12 18:33:14 +08:00
|
|
|
if (::stat(File->path().c_str(), &StatBuf))
|
2013-03-26 05:19:16 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// If the file has been used recently enough, leave it there.
|
|
|
|
time_t FileAccessTime = StatBuf.st_atime;
|
2013-03-30 01:39:43 +08:00
|
|
|
if (CurrentTime - FileAccessTime <=
|
|
|
|
time_t(HSOpts.ModuleCachePruneAfter)) {
|
2013-03-26 05:19:16 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the file.
|
Add an option to allow Clang verify source files for a module only once during
the build
When Clang loads the module, it verifies the user source files that the module
was built from. If any file was changed, the module is rebuilt. There are two
problems with this:
1. correctness: we don't verify system files (there are too many of them, and
stat'ing all of them would take a lot of time);
2. performance: the same module file is verified again and again during a
single build.
This change allows the build system to optimize source file verification. The
idea is based on the fact that while the project is being built, the source
files don't change. This allows us to verify the module only once during a
single build session. The build system passes a flag,
-fbuild-session-timestamp=, to inform Clang of the time when the build started.
The build system also requests to enable this feature by passing
-fmodules-validate-once-per-build-session. If these flags are not passed, the
behavior is not changed. When Clang verifies the module the first time, it
writes out a timestamp file. Then, when Clang loads the module the second
time, it finds a timestamp file, so it can compare the verification timestamp
of the module with the time when the build started. If the verification
timestamp is too old, the module is verified again, and the timestamp file is
updated.
llvm-svn: 201224
2014-02-12 18:33:14 +08:00
|
|
|
llvm::sys::fs::remove(File->path());
|
|
|
|
|
|
|
|
// Remove the timestamp file.
|
|
|
|
std::string TimpestampFilename = File->path() + ".timestamp";
|
|
|
|
llvm::sys::fs::remove(TimpestampFilename);
|
2013-03-26 05:19:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// If we removed all of the files in the directory, remove the directory
|
|
|
|
// itself.
|
Add an option to allow Clang verify source files for a module only once during
the build
When Clang loads the module, it verifies the user source files that the module
was built from. If any file was changed, the module is rebuilt. There are two
problems with this:
1. correctness: we don't verify system files (there are too many of them, and
stat'ing all of them would take a lot of time);
2. performance: the same module file is verified again and again during a
single build.
This change allows the build system to optimize source file verification. The
idea is based on the fact that while the project is being built, the source
files don't change. This allows us to verify the module only once during a
single build session. The build system passes a flag,
-fbuild-session-timestamp=, to inform Clang of the time when the build started.
The build system also requests to enable this feature by passing
-fmodules-validate-once-per-build-session. If these flags are not passed, the
behavior is not changed. When Clang verifies the module the first time, it
writes out a timestamp file. Then, when Clang loads the module the second
time, it finds a timestamp file, so it can compare the verification timestamp
of the module with the time when the build started. If the verification
timestamp is too old, the module is verified again, and the timestamp file is
updated.
llvm-svn: 201224
2014-02-12 18:33:14 +08:00
|
|
|
if (llvm::sys::fs::directory_iterator(Dir->path(), EC) ==
|
|
|
|
llvm::sys::fs::directory_iterator() && !EC)
|
2014-01-11 05:32:14 +08:00
|
|
|
llvm::sys::fs::remove(Dir->path());
|
2013-03-26 05:19:16 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-23 20:57:01 +08:00
|
|
|
void CompilerInstance::createModuleManager() {
|
|
|
|
if (!ModuleManager) {
|
|
|
|
if (!hasASTContext())
|
|
|
|
createASTContext();
|
|
|
|
|
2015-03-25 05:44:25 +08:00
|
|
|
// If we're implicitly building modules but not currently recursively
|
|
|
|
// building a module, check whether we need to prune the module cache.
|
2015-08-15 08:34:15 +08:00
|
|
|
if (getSourceManager().getModuleBuildStack().empty() &&
|
|
|
|
!getPreprocessor().getHeaderSearchInfo().getModuleCachePath().empty() &&
|
2014-04-23 20:57:01 +08:00
|
|
|
getHeaderSearchOpts().ModuleCachePruneInterval > 0 &&
|
|
|
|
getHeaderSearchOpts().ModuleCachePruneAfter > 0) {
|
|
|
|
pruneModuleCache(getHeaderSearchOpts());
|
|
|
|
}
|
|
|
|
|
|
|
|
HeaderSearchOptions &HSOpts = getHeaderSearchOpts();
|
|
|
|
std::string Sysroot = HSOpts.Sysroot;
|
|
|
|
const PreprocessorOptions &PPOpts = getPreprocessorOpts();
|
2015-07-14 08:26:00 +08:00
|
|
|
std::unique_ptr<llvm::Timer> ReadTimer;
|
|
|
|
if (FrontendTimerGroup)
|
|
|
|
ReadTimer = llvm::make_unique<llvm::Timer>("Reading modules",
|
|
|
|
*FrontendTimerGroup);
|
2015-06-21 02:53:08 +08:00
|
|
|
ModuleManager = new ASTReader(
|
2015-08-19 04:39:29 +08:00
|
|
|
getPreprocessor(), getASTContext(), getPCHContainerReader(),
|
2015-11-04 02:33:07 +08:00
|
|
|
getFrontendOpts().ModuleFileExtensions,
|
2015-06-21 02:53:08 +08:00
|
|
|
Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation,
|
|
|
|
/*AllowASTWithCompilerErrors=*/false,
|
|
|
|
/*AllowConfigurationMismatch=*/false,
|
|
|
|
HSOpts.ModulesValidateSystemHeaders,
|
2015-07-14 08:26:00 +08:00
|
|
|
getFrontendOpts().UseGlobalModuleIndex,
|
|
|
|
std::move(ReadTimer));
|
2014-04-23 20:57:01 +08:00
|
|
|
if (hasASTConsumer()) {
|
|
|
|
ModuleManager->setDeserializationListener(
|
|
|
|
getASTConsumer().GetASTDeserializationListener());
|
|
|
|
getASTContext().setASTMutationListener(
|
|
|
|
getASTConsumer().GetASTMutationListener());
|
|
|
|
}
|
|
|
|
getASTContext().setExternalSource(ModuleManager);
|
|
|
|
if (hasSema())
|
|
|
|
ModuleManager->InitializeSema(getSema());
|
2015-08-19 04:39:29 +08:00
|
|
|
if (hasASTConsumer())
|
2014-04-23 20:57:01 +08:00
|
|
|
ModuleManager->StartTranslationUnit(&getASTConsumer());
|
2015-08-09 10:28:42 +08:00
|
|
|
|
|
|
|
if (TheDependencyFileGenerator)
|
|
|
|
TheDependencyFileGenerator->AttachToASTReader(*ModuleManager);
|
|
|
|
for (auto &Listener : DependencyCollectors)
|
|
|
|
Listener->attachToASTReader(*ModuleManager);
|
2014-04-23 20:57:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-28 07:01:16 +08:00
|
|
|
bool CompilerInstance::loadModuleFile(StringRef FileName) {
|
2015-07-14 08:26:00 +08:00
|
|
|
llvm::Timer Timer;
|
|
|
|
if (FrontendTimerGroup)
|
|
|
|
Timer.init("Preloading " + FileName.str(), *FrontendTimerGroup);
|
|
|
|
llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
|
|
|
|
|
2014-10-28 07:01:16 +08:00
|
|
|
// Helper to recursively read the module names for all modules we're adding.
|
|
|
|
// We mark these as known and redirect any attempt to load that module to
|
|
|
|
// the files we were handed.
|
|
|
|
struct ReadModuleNames : ASTReaderListener {
|
|
|
|
CompilerInstance &CI;
|
2015-08-09 16:48:41 +08:00
|
|
|
llvm::SmallVector<IdentifierInfo*, 8> LoadedModules;
|
2014-10-28 07:01:16 +08:00
|
|
|
|
2015-08-09 16:48:41 +08:00
|
|
|
ReadModuleNames(CompilerInstance &CI) : CI(CI) {}
|
2015-02-25 08:56:02 +08:00
|
|
|
|
2015-08-09 16:48:41 +08:00
|
|
|
void ReadModuleName(StringRef ModuleName) override {
|
|
|
|
LoadedModules.push_back(
|
|
|
|
CI.getPreprocessor().getIdentifierInfo(ModuleName));
|
2014-10-28 07:01:16 +08:00
|
|
|
}
|
2014-10-22 10:05:46 +08:00
|
|
|
|
2015-08-09 16:48:41 +08:00
|
|
|
void registerAll() {
|
|
|
|
for (auto *II : LoadedModules) {
|
|
|
|
CI.KnownModules[II] = CI.getPreprocessor()
|
|
|
|
.getHeaderSearchInfo()
|
|
|
|
.getModuleMap()
|
|
|
|
.findModule(II->getName());
|
|
|
|
}
|
|
|
|
LoadedModules.clear();
|
2014-10-28 07:01:16 +08:00
|
|
|
}
|
2015-11-05 08:54:55 +08:00
|
|
|
|
|
|
|
void markAllUnavailable() {
|
|
|
|
for (auto *II : LoadedModules) {
|
|
|
|
if (Module *M = CI.getPreprocessor()
|
|
|
|
.getHeaderSearchInfo()
|
|
|
|
.getModuleMap()
|
|
|
|
.findModule(II->getName()))
|
|
|
|
M->HasIncompatibleModuleFile = true;
|
|
|
|
}
|
|
|
|
LoadedModules.clear();
|
|
|
|
}
|
2015-08-09 16:48:41 +08:00
|
|
|
};
|
2014-10-28 07:01:16 +08:00
|
|
|
|
2015-03-18 09:42:29 +08:00
|
|
|
// If we don't already have an ASTReader, create one now.
|
|
|
|
if (!ModuleManager)
|
|
|
|
createModuleManager();
|
|
|
|
|
2015-08-09 16:48:41 +08:00
|
|
|
auto Listener = llvm::make_unique<ReadModuleNames>(*this);
|
|
|
|
auto &ListenerRef = *Listener;
|
|
|
|
ASTReader::ListenerScope ReadModuleNamesListener(*ModuleManager,
|
|
|
|
std::move(Listener));
|
2014-10-28 07:01:16 +08:00
|
|
|
|
2015-08-09 16:48:41 +08:00
|
|
|
// Try to load the module file.
|
2015-10-17 07:20:19 +08:00
|
|
|
switch (ModuleManager->ReadAST(FileName, serialization::MK_ExplicitModule,
|
|
|
|
SourceLocation(),
|
|
|
|
ASTReader::ARR_ConfigurationMismatch)) {
|
|
|
|
case ASTReader::Success:
|
2015-11-05 08:54:55 +08:00
|
|
|
// We successfully loaded the module file; remember the set of provided
|
|
|
|
// modules so that we don't try to load implicit modules for them.
|
|
|
|
ListenerRef.registerAll();
|
|
|
|
return true;
|
2015-10-17 07:20:19 +08:00
|
|
|
|
|
|
|
case ASTReader::ConfigurationMismatch:
|
|
|
|
// Ignore unusable module files.
|
|
|
|
getDiagnostics().Report(SourceLocation(), diag::warn_module_config_mismatch)
|
|
|
|
<< FileName;
|
2015-11-05 08:54:55 +08:00
|
|
|
// All modules provided by any files we tried and failed to load are now
|
|
|
|
// unavailable; includes of those modules should now be handled textually.
|
|
|
|
ListenerRef.markAllUnavailable();
|
2015-10-17 07:20:19 +08:00
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
2014-10-22 10:05:46 +08:00
|
|
|
}
|
|
|
|
|
2012-11-30 07:55:25 +08:00
|
|
|
ModuleLoadResult
|
|
|
|
CompilerInstance::loadModule(SourceLocation ImportLoc,
|
|
|
|
ModuleIdPath Path,
|
|
|
|
Module::NameVisibilityKind Visibility,
|
|
|
|
bool IsInclusionDirective) {
|
2013-10-19 06:48:20 +08:00
|
|
|
// Determine what file we're searching from.
|
|
|
|
StringRef ModuleName = Path[0].first->getName();
|
|
|
|
SourceLocation ModuleNameLoc = Path[0].second;
|
|
|
|
|
2011-11-30 12:26:53 +08:00
|
|
|
// If we've already handled this import, just return the cached result.
|
|
|
|
// This one-element cache is important to eliminate redundant diagnostics
|
|
|
|
// when both the preprocessor and parser see the same import declaration.
|
2015-10-03 18:46:20 +08:00
|
|
|
if (ImportLoc.isValid() && LastModuleImportLoc == ImportLoc) {
|
2011-12-02 01:11:21 +08:00
|
|
|
// Make the named module visible.
|
2016-02-20 06:25:36 +08:00
|
|
|
if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule)
|
2013-02-02 00:36:12 +08:00
|
|
|
ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility,
|
2015-05-01 09:53:09 +08:00
|
|
|
ImportLoc);
|
2011-12-01 01:33:56 +08:00
|
|
|
return LastModuleImportResult;
|
2011-12-02 01:11:21 +08:00
|
|
|
}
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2014-05-22 12:46:25 +08:00
|
|
|
clang::Module *Module = nullptr;
|
2013-10-19 06:48:20 +08:00
|
|
|
|
2011-11-30 12:03:44 +08:00
|
|
|
// If we don't already have information on this module, load the module now.
|
2011-12-01 07:21:26 +08:00
|
|
|
llvm::DenseMap<const IdentifierInfo *, clang::Module *>::iterator Known
|
2011-12-01 01:33:56 +08:00
|
|
|
= KnownModules.find(Path[0].first);
|
2011-12-09 01:01:29 +08:00
|
|
|
if (Known != KnownModules.end()) {
|
|
|
|
// Retrieve the cached top-level module.
|
|
|
|
Module = Known->second;
|
2016-02-20 06:25:36 +08:00
|
|
|
} else if (ModuleName == getLangOpts().CurrentModule) {
|
2011-12-09 01:01:29 +08:00
|
|
|
// This is the module we're building.
|
2014-05-05 13:31:33 +08:00
|
|
|
Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
|
2011-12-09 01:01:29 +08:00
|
|
|
Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
|
|
|
|
} else {
|
2011-11-30 12:03:44 +08:00
|
|
|
// Search for a module with the given name.
|
2012-01-30 01:08:11 +08:00
|
|
|
Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
|
2016-08-19 01:42:15 +08:00
|
|
|
HeaderSearchOptions &HSOpts =
|
|
|
|
PP->getHeaderSearchInfo().getHeaderSearchOpts();
|
|
|
|
|
|
|
|
std::string ModuleFileName;
|
|
|
|
bool LoadFromPrebuiltModulePath = false;
|
|
|
|
// We try to load the module from the prebuilt module paths. If not
|
|
|
|
// successful, we then try to find it in the module cache.
|
|
|
|
if (!HSOpts.PrebuiltModulePaths.empty()) {
|
|
|
|
// Load the module from the prebuilt module path.
|
|
|
|
ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(
|
|
|
|
ModuleName, "", /*UsePrebuiltPath*/ true);
|
|
|
|
if (!ModuleFileName.empty())
|
|
|
|
LoadFromPrebuiltModulePath = true;
|
|
|
|
}
|
|
|
|
if (!LoadFromPrebuiltModulePath && Module) {
|
|
|
|
// Load the module from the module cache.
|
|
|
|
ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module);
|
|
|
|
} else if (!LoadFromPrebuiltModulePath) {
|
|
|
|
// We can't find a module, error out here.
|
2014-01-23 07:19:39 +08:00
|
|
|
getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
|
|
|
|
<< ModuleName
|
|
|
|
<< SourceRange(ImportLoc, ModuleNameLoc);
|
|
|
|
ModuleBuildFailed = true;
|
|
|
|
return ModuleLoadResult();
|
|
|
|
}
|
|
|
|
|
2015-07-22 02:07:47 +08:00
|
|
|
if (ModuleFileName.empty()) {
|
2016-08-19 01:42:15 +08:00
|
|
|
if (Module && Module->HasIncompatibleModuleFile) {
|
2015-11-05 08:54:55 +08:00
|
|
|
// We tried and failed to load a module file for this module. Fall
|
|
|
|
// back to textual inclusion for its headers.
|
|
|
|
return ModuleLoadResult(nullptr, /*missingExpected*/true);
|
|
|
|
}
|
|
|
|
|
2015-02-20 19:44:41 +08:00
|
|
|
getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled)
|
|
|
|
<< ModuleName;
|
|
|
|
ModuleBuildFailed = true;
|
|
|
|
return ModuleLoadResult();
|
|
|
|
}
|
2014-10-28 07:01:16 +08:00
|
|
|
|
2011-11-30 12:03:44 +08:00
|
|
|
// If we don't already have an ASTReader, create one now.
|
2014-04-23 20:57:01 +08:00
|
|
|
if (!ModuleManager)
|
|
|
|
createModuleManager();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2015-07-14 08:26:00 +08:00
|
|
|
llvm::Timer Timer;
|
|
|
|
if (FrontendTimerGroup)
|
|
|
|
Timer.init("Loading " + ModuleFileName, *FrontendTimerGroup);
|
|
|
|
llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
|
|
|
|
|
2016-08-19 01:42:15 +08:00
|
|
|
// Try to load the module file. If we are trying to load from the prebuilt
|
|
|
|
// module path, we don't have the module map files and don't know how to
|
|
|
|
// rebuild modules.
|
|
|
|
unsigned ARRFlags = LoadFromPrebuiltModulePath ?
|
|
|
|
ASTReader::ARR_ConfigurationMismatch :
|
|
|
|
ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing;
|
2014-10-22 10:05:46 +08:00
|
|
|
switch (ModuleManager->ReadAST(ModuleFileName,
|
2016-08-19 01:42:15 +08:00
|
|
|
LoadFromPrebuiltModulePath ?
|
|
|
|
serialization::MK_PrebuiltModule :
|
2015-08-09 16:58:36 +08:00
|
|
|
serialization::MK_ImplicitModule,
|
2016-08-19 01:42:15 +08:00
|
|
|
ImportLoc,
|
|
|
|
ARRFlags)) {
|
|
|
|
case ASTReader::Success: {
|
|
|
|
if (LoadFromPrebuiltModulePath && !Module) {
|
|
|
|
Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
|
|
|
|
if (!Module || !Module->getASTFile() ||
|
|
|
|
FileMgr->getFile(ModuleFileName) != Module->getASTFile()) {
|
|
|
|
// Error out if Module does not refer to the file in the prebuilt
|
|
|
|
// module path.
|
|
|
|
getDiagnostics().Report(ModuleNameLoc, diag::err_module_prebuilt)
|
|
|
|
<< ModuleName;
|
|
|
|
ModuleBuildFailed = true;
|
|
|
|
KnownModules[Path[0].first] = nullptr;
|
|
|
|
return ModuleLoadResult();
|
|
|
|
}
|
|
|
|
}
|
2011-11-30 12:03:44 +08:00
|
|
|
break;
|
2016-08-19 01:42:15 +08:00
|
|
|
}
|
2011-08-27 07:56:07 +08:00
|
|
|
|
2013-09-17 08:51:29 +08:00
|
|
|
case ASTReader::OutOfDate:
|
2013-03-19 08:28:20 +08:00
|
|
|
case ASTReader::Missing: {
|
2016-08-19 01:42:15 +08:00
|
|
|
if (LoadFromPrebuiltModulePath) {
|
|
|
|
// We can't rebuild the module without a module map. Since ReadAST
|
|
|
|
// already produces diagnostics for these two cases, we simply
|
|
|
|
// error out here.
|
|
|
|
ModuleBuildFailed = true;
|
|
|
|
KnownModules[Path[0].first] = nullptr;
|
|
|
|
return ModuleLoadResult();
|
|
|
|
}
|
|
|
|
|
2013-09-17 08:51:29 +08:00
|
|
|
// The module file is missing or out-of-date. Build it.
|
2014-01-23 07:19:39 +08:00
|
|
|
assert(Module && "missing module file");
|
2013-03-19 08:28:20 +08:00
|
|
|
// Check whether there is a cycle in the module graph.
|
|
|
|
ModuleBuildStack ModPath = getSourceManager().getModuleBuildStack();
|
|
|
|
ModuleBuildStack::iterator Pos = ModPath.begin(), PosEnd = ModPath.end();
|
|
|
|
for (; Pos != PosEnd; ++Pos) {
|
|
|
|
if (Pos->first == ModuleName)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Pos != PosEnd) {
|
|
|
|
SmallString<256> CyclePath;
|
|
|
|
for (; Pos != PosEnd; ++Pos) {
|
|
|
|
CyclePath += Pos->first;
|
|
|
|
CyclePath += " -> ";
|
|
|
|
}
|
|
|
|
CyclePath += ModuleName;
|
|
|
|
|
|
|
|
getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle)
|
|
|
|
<< ModuleName << CyclePath;
|
|
|
|
return ModuleLoadResult();
|
|
|
|
}
|
2012-11-30 07:55:25 +08:00
|
|
|
|
|
|
|
// Check whether we have already attempted to build this module (but
|
|
|
|
// failed).
|
|
|
|
if (getPreprocessorOpts().FailedModules &&
|
|
|
|
getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) {
|
|
|
|
getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built)
|
|
|
|
<< ModuleName
|
|
|
|
<< SourceRange(ImportLoc, ModuleNameLoc);
|
2013-01-25 08:45:27 +08:00
|
|
|
ModuleBuildFailed = true;
|
2012-11-30 07:55:25 +08:00
|
|
|
return ModuleLoadResult();
|
|
|
|
}
|
|
|
|
|
2014-06-18 06:35:27 +08:00
|
|
|
// Try to compile and then load the module.
|
|
|
|
if (!compileAndLoadModule(*this, ImportLoc, ModuleNameLoc, Module,
|
|
|
|
ModuleFileName)) {
|
2014-09-27 06:42:23 +08:00
|
|
|
assert(getDiagnostics().hasErrorOccurred() &&
|
|
|
|
"undiagnosed error in compileAndLoadModule");
|
2013-01-10 10:04:18 +08:00
|
|
|
if (getPreprocessorOpts().FailedModules)
|
|
|
|
getPreprocessorOpts().FailedModules->addFailed(ModuleName);
|
2014-05-22 12:46:25 +08:00
|
|
|
KnownModules[Path[0].first] = nullptr;
|
2013-01-25 08:45:27 +08:00
|
|
|
ModuleBuildFailed = true;
|
2012-11-30 07:55:25 +08:00
|
|
|
return ModuleLoadResult();
|
2012-11-08 01:46:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Okay, we've rebuilt and now loaded the module.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-10-23 06:50:17 +08:00
|
|
|
case ASTReader::ConfigurationMismatch:
|
2016-08-19 01:42:15 +08:00
|
|
|
if (LoadFromPrebuiltModulePath)
|
|
|
|
getDiagnostics().Report(SourceLocation(),
|
|
|
|
diag::warn_module_config_mismatch)
|
|
|
|
<< ModuleFileName;
|
|
|
|
// Fall through to error out.
|
|
|
|
case ASTReader::VersionMismatch:
|
2012-10-23 06:50:17 +08:00
|
|
|
case ASTReader::HadErrors:
|
2013-05-24 13:44:08 +08:00
|
|
|
ModuleLoader::HadFatalFailure = true;
|
2015-08-09 16:48:41 +08:00
|
|
|
// FIXME: The ASTReader will already have complained, but can we shoehorn
|
2011-11-30 12:03:44 +08:00
|
|
|
// that diagnostic information into a more useful form?
|
2014-05-22 12:46:25 +08:00
|
|
|
KnownModules[Path[0].first] = nullptr;
|
2012-11-30 07:55:25 +08:00
|
|
|
return ModuleLoadResult();
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-11-30 12:03:44 +08:00
|
|
|
case ASTReader::Failure:
|
2013-05-24 13:44:08 +08:00
|
|
|
ModuleLoader::HadFatalFailure = true;
|
2011-12-01 01:33:56 +08:00
|
|
|
// Already complained, but note now that we failed.
|
2014-05-22 12:46:25 +08:00
|
|
|
KnownModules[Path[0].first] = nullptr;
|
2013-01-25 08:45:27 +08:00
|
|
|
ModuleBuildFailed = true;
|
2012-11-30 07:55:25 +08:00
|
|
|
return ModuleLoadResult();
|
2011-11-30 12:03:44 +08:00
|
|
|
}
|
2012-09-29 09:06:04 +08:00
|
|
|
|
2011-12-01 01:33:56 +08:00
|
|
|
// Cache the result of this top-level module lookup for later.
|
|
|
|
Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
|
2011-08-27 07:56:07 +08:00
|
|
|
}
|
2011-11-30 12:03:44 +08:00
|
|
|
|
2011-12-01 01:33:56 +08:00
|
|
|
// If we never found the module, fail.
|
|
|
|
if (!Module)
|
2012-11-30 07:55:25 +08:00
|
|
|
return ModuleLoadResult();
|
2011-12-01 01:33:56 +08:00
|
|
|
|
2011-11-30 12:03:44 +08:00
|
|
|
// Verify that the rest of the module path actually corresponds to
|
|
|
|
// a submodule.
|
2011-12-01 01:33:56 +08:00
|
|
|
if (Path.size() > 1) {
|
2011-11-30 12:03:44 +08:00
|
|
|
for (unsigned I = 1, N = Path.size(); I != N; ++I) {
|
|
|
|
StringRef Name = Path[I].first->getName();
|
2012-01-05 07:32:19 +08:00
|
|
|
clang::Module *Sub = Module->findSubmodule(Name);
|
2011-11-30 12:03:44 +08:00
|
|
|
|
2012-01-05 07:32:19 +08:00
|
|
|
if (!Sub) {
|
2011-11-30 12:03:44 +08:00
|
|
|
// Attempt to perform typo correction to find a module name that works.
|
2013-01-13 03:30:44 +08:00
|
|
|
SmallVector<StringRef, 2> Best;
|
2011-11-30 12:03:44 +08:00
|
|
|
unsigned BestEditDistance = (std::numeric_limits<unsigned>::max)();
|
|
|
|
|
2012-01-05 07:32:19 +08:00
|
|
|
for (clang::Module::submodule_iterator J = Module->submodule_begin(),
|
|
|
|
JEnd = Module->submodule_end();
|
2011-12-01 03:41:21 +08:00
|
|
|
J != JEnd; ++J) {
|
2012-01-05 07:32:19 +08:00
|
|
|
unsigned ED = Name.edit_distance((*J)->Name,
|
2011-11-30 12:03:44 +08:00
|
|
|
/*AllowReplacements=*/true,
|
|
|
|
BestEditDistance);
|
|
|
|
if (ED <= BestEditDistance) {
|
2012-01-05 07:32:19 +08:00
|
|
|
if (ED < BestEditDistance) {
|
2011-11-30 12:03:44 +08:00
|
|
|
Best.clear();
|
2012-01-05 07:32:19 +08:00
|
|
|
BestEditDistance = ED;
|
|
|
|
}
|
|
|
|
|
|
|
|
Best.push_back((*J)->Name);
|
2011-11-30 12:03:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If there was a clear winner, user it.
|
|
|
|
if (Best.size() == 1) {
|
|
|
|
getDiagnostics().Report(Path[I].second,
|
|
|
|
diag::err_no_submodule_suggest)
|
2011-12-01 01:33:56 +08:00
|
|
|
<< Path[I].first << Module->getFullModuleName() << Best[0]
|
2011-11-30 12:03:44 +08:00
|
|
|
<< SourceRange(Path[0].second, Path[I-1].second)
|
|
|
|
<< FixItHint::CreateReplacement(SourceRange(Path[I].second),
|
|
|
|
Best[0]);
|
2012-01-05 07:32:19 +08:00
|
|
|
|
|
|
|
Sub = Module->findSubmodule(Best[0]);
|
2011-11-30 12:03:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-05 07:32:19 +08:00
|
|
|
if (!Sub) {
|
2011-11-30 12:03:44 +08:00
|
|
|
// No submodule by this name. Complain, and don't look for further
|
|
|
|
// submodules.
|
|
|
|
getDiagnostics().Report(Path[I].second, diag::err_no_submodule)
|
2011-12-01 01:33:56 +08:00
|
|
|
<< Path[I].first << Module->getFullModuleName()
|
2011-11-30 12:03:44 +08:00
|
|
|
<< SourceRange(Path[0].second, Path[I-1].second);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-01-05 07:32:19 +08:00
|
|
|
Module = Sub;
|
2011-11-30 12:03:44 +08:00
|
|
|
}
|
|
|
|
}
|
2014-07-23 23:30:23 +08:00
|
|
|
|
2011-12-09 01:01:29 +08:00
|
|
|
// Make the named module visible, if it's not already part of the module
|
|
|
|
// we are parsing.
|
2011-12-20 08:28:52 +08:00
|
|
|
if (ModuleName != getLangOpts().CurrentModule) {
|
|
|
|
if (!Module->IsFromModuleFile) {
|
|
|
|
// We have an umbrella header or directory that doesn't actually include
|
|
|
|
// all of the headers within the directory it covers. Complain about
|
|
|
|
// this missing submodule and recover by forgetting that we ever saw
|
|
|
|
// this submodule.
|
|
|
|
// FIXME: Should we detect this at module load time? It seems fairly
|
|
|
|
// expensive (and rare).
|
|
|
|
getDiagnostics().Report(ImportLoc, diag::warn_missing_submodule)
|
|
|
|
<< Module->getFullModuleName()
|
|
|
|
<< SourceRange(Path.front().second, Path.back().second);
|
2014-05-22 12:46:25 +08:00
|
|
|
|
|
|
|
return ModuleLoadResult(nullptr, true);
|
2011-12-20 08:28:52 +08:00
|
|
|
}
|
2011-12-31 12:05:44 +08:00
|
|
|
|
|
|
|
// Check whether this module is available.
|
2013-10-29 06:18:19 +08:00
|
|
|
clang::Module::Requirement Requirement;
|
2014-12-02 08:08:08 +08:00
|
|
|
clang::Module::UnresolvedHeaderDirective MissingHeader;
|
2013-12-17 18:31:37 +08:00
|
|
|
if (!Module->isAvailable(getLangOpts(), getTarget(), Requirement,
|
|
|
|
MissingHeader)) {
|
|
|
|
if (MissingHeader.FileNameLoc.isValid()) {
|
|
|
|
getDiagnostics().Report(MissingHeader.FileNameLoc,
|
|
|
|
diag::err_module_header_missing)
|
|
|
|
<< MissingHeader.IsUmbrella << MissingHeader.FileName;
|
|
|
|
} else {
|
|
|
|
getDiagnostics().Report(ImportLoc, diag::err_module_unavailable)
|
|
|
|
<< Module->getFullModuleName()
|
|
|
|
<< Requirement.second << Requirement.first
|
|
|
|
<< SourceRange(Path.front().second, Path.back().second);
|
|
|
|
}
|
2011-12-31 12:05:44 +08:00
|
|
|
LastModuleImportLoc = ImportLoc;
|
2012-11-30 07:55:25 +08:00
|
|
|
LastModuleImportResult = ModuleLoadResult();
|
|
|
|
return ModuleLoadResult();
|
2011-12-31 12:05:44 +08:00
|
|
|
}
|
|
|
|
|
2015-05-01 09:53:09 +08:00
|
|
|
ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc);
|
2011-12-20 08:28:52 +08:00
|
|
|
}
|
2013-03-20 08:22:05 +08:00
|
|
|
|
|
|
|
// Check for any configuration macros that have changed.
|
|
|
|
clang::Module *TopModule = Module->getTopLevelModule();
|
|
|
|
for (unsigned I = 0, N = TopModule->ConfigMacros.size(); I != N; ++I) {
|
|
|
|
checkConfigMacro(getPreprocessor(), TopModule->ConfigMacros[I],
|
|
|
|
Module, ImportLoc);
|
|
|
|
}
|
|
|
|
|
2011-11-30 12:26:53 +08:00
|
|
|
LastModuleImportLoc = ImportLoc;
|
2012-11-30 07:55:25 +08:00
|
|
|
LastModuleImportResult = ModuleLoadResult(Module, false);
|
|
|
|
return LastModuleImportResult;
|
2011-08-27 07:56:07 +08:00
|
|
|
}
|
2013-01-12 09:29:50 +08:00
|
|
|
|
|
|
|
void CompilerInstance::makeModuleVisible(Module *Mod,
|
2013-02-02 00:36:12 +08:00
|
|
|
Module::NameVisibilityKind Visibility,
|
2015-05-01 09:53:09 +08:00
|
|
|
SourceLocation ImportLoc) {
|
2015-05-16 04:05:43 +08:00
|
|
|
if (!ModuleManager)
|
|
|
|
createModuleManager();
|
|
|
|
if (!ModuleManager)
|
|
|
|
return;
|
|
|
|
|
2015-05-01 09:53:09 +08:00
|
|
|
ModuleManager->makeModuleVisible(Mod, Visibility, ImportLoc);
|
2013-01-12 09:29:50 +08:00
|
|
|
}
|
|
|
|
|
2014-04-23 20:57:01 +08:00
|
|
|
GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(
|
|
|
|
SourceLocation TriggerLoc) {
|
2015-08-15 08:34:15 +08:00
|
|
|
if (getPreprocessor().getHeaderSearchInfo().getModuleCachePath().empty())
|
|
|
|
return nullptr;
|
2014-04-23 20:57:01 +08:00
|
|
|
if (!ModuleManager)
|
|
|
|
createModuleManager();
|
|
|
|
// Can't do anything if we don't have the module manager.
|
|
|
|
if (!ModuleManager)
|
2014-05-22 12:46:25 +08:00
|
|
|
return nullptr;
|
2014-04-23 20:57:01 +08:00
|
|
|
// Get an existing global index. This loads it if not already
|
|
|
|
// loaded.
|
|
|
|
ModuleManager->loadGlobalIndex();
|
|
|
|
GlobalModuleIndex *GlobalIndex = ModuleManager->getGlobalIndex();
|
|
|
|
// If the global index doesn't exist, create it.
|
|
|
|
if (!GlobalIndex && shouldBuildGlobalModuleIndex() && hasFileManager() &&
|
|
|
|
hasPreprocessor()) {
|
|
|
|
llvm::sys::fs::create_directories(
|
|
|
|
getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
|
|
|
|
GlobalModuleIndex::writeIndex(
|
2015-07-17 09:19:54 +08:00
|
|
|
getFileManager(), getPCHContainerReader(),
|
2015-06-21 02:53:08 +08:00
|
|
|
getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
|
2014-04-23 20:57:01 +08:00
|
|
|
ModuleManager->resetForReload();
|
|
|
|
ModuleManager->loadGlobalIndex();
|
|
|
|
GlobalIndex = ModuleManager->getGlobalIndex();
|
|
|
|
}
|
|
|
|
// For finding modules needing to be imported for fixit messages,
|
|
|
|
// we need to make the global index cover all modules, so we do that here.
|
|
|
|
if (!HaveFullGlobalModuleIndex && GlobalIndex && !buildingModule()) {
|
|
|
|
ModuleMap &MMap = getPreprocessor().getHeaderSearchInfo().getModuleMap();
|
|
|
|
bool RecreateIndex = false;
|
|
|
|
for (ModuleMap::module_iterator I = MMap.module_begin(),
|
|
|
|
E = MMap.module_end(); I != E; ++I) {
|
|
|
|
Module *TheModule = I->second;
|
|
|
|
const FileEntry *Entry = TheModule->getASTFile();
|
|
|
|
if (!Entry) {
|
|
|
|
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
|
|
|
|
Path.push_back(std::make_pair(
|
2015-08-11 08:03:28 +08:00
|
|
|
getPreprocessor().getIdentifierInfo(TheModule->Name), TriggerLoc));
|
2014-04-23 20:57:01 +08:00
|
|
|
std::reverse(Path.begin(), Path.end());
|
2015-08-11 08:03:28 +08:00
|
|
|
// Load a module as hidden. This also adds it to the global index.
|
|
|
|
loadModule(TheModule->DefinitionLoc, Path, Module::Hidden, false);
|
2014-04-23 20:57:01 +08:00
|
|
|
RecreateIndex = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (RecreateIndex) {
|
|
|
|
GlobalModuleIndex::writeIndex(
|
2015-07-17 09:19:54 +08:00
|
|
|
getFileManager(), getPCHContainerReader(),
|
2015-06-21 02:53:08 +08:00
|
|
|
getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
|
2014-04-23 20:57:01 +08:00
|
|
|
ModuleManager->resetForReload();
|
|
|
|
ModuleManager->loadGlobalIndex();
|
|
|
|
GlobalIndex = ModuleManager->getGlobalIndex();
|
|
|
|
}
|
|
|
|
HaveFullGlobalModuleIndex = true;
|
|
|
|
}
|
|
|
|
return GlobalIndex;
|
|
|
|
}
|
2014-04-24 03:04:32 +08:00
|
|
|
|
|
|
|
// Check global module index for missing imports.
|
|
|
|
bool
|
|
|
|
CompilerInstance::lookupMissingImports(StringRef Name,
|
|
|
|
SourceLocation TriggerLoc) {
|
|
|
|
// Look for the symbol in non-imported modules, but only if an error
|
|
|
|
// actually occurred.
|
|
|
|
if (!buildingModule()) {
|
|
|
|
// Load global module index, or retrieve a previously loaded one.
|
|
|
|
GlobalModuleIndex *GlobalIndex = loadGlobalModuleIndex(
|
|
|
|
TriggerLoc);
|
|
|
|
|
|
|
|
// Only if we have a global index.
|
|
|
|
if (GlobalIndex) {
|
|
|
|
GlobalModuleIndex::HitSet FoundModules;
|
|
|
|
|
|
|
|
// Find the modules that reference the identifier.
|
|
|
|
// Note that this only finds top-level modules.
|
|
|
|
// We'll let diagnoseTypo find the actual declaration module.
|
|
|
|
if (GlobalIndex->lookupIdentifier(Name, FoundModules))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
Provide a BuryPointer for unique_ptrs.
In theory, it'd be nice if we could move to a case where all buried
pointers were buried via unique_ptr to demonstrate that the program had
finished with the value (that we could really have cleanly deallocated
it) but instead chose to bury it.
I think the main reason that's not possible right now is the various
IntrusiveRefCntPtrs in the Frontend, sharing ownership for a variety of
compiler bits (see the various similar
"CompilerInstance::releaseAndLeak*" functions). I have yet to figure out
their correct ownership semantics - but perhaps, even if the
intrusiveness can be removed, the shared ownership may yet remain and
that would lead to a non-unique burying as is there today. (though we
could model that a little better - by passing in a shared_ptr, etc -
rather than needing the two step that's currently used in those other
releaseAndLeak* functions)
This might be a bit more robust if BuryPointer took the boolean:
BuryPointer(bool, unique_ptr<T>)
and the choice to bury was made internally - that way, even when
DisableFree was not set, the unique_ptr would still be null in the
caller and there'd be no chance of accidentally having a different
codepath where the value is used after burial in !DisableFree, but it
becomes null only in DisableFree, etc...
llvm-svn: 216742
2014-08-30 00:53:14 +08:00
|
|
|
void CompilerInstance::resetAndLeakSema() { BuryPointer(takeSema()); }
|
2016-11-17 02:15:26 +08:00
|
|
|
|
|
|
|
void CompilerInstance::setExternalSemaSource(
|
|
|
|
IntrusiveRefCntPtr<ExternalSemaSource> ESS) {
|
|
|
|
ExternalSemaSrc = std::move(ESS);
|
|
|
|
}
|