2009-11-13 11:51:44 +08:00
|
|
|
//===--- CompilerInstance.cpp ---------------------------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2009-11-13 11:51:44 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#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"
|
2017-06-20 07:09:36 +08:00
|
|
|
#include "clang/Basic/CharInfo.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"
|
2019-08-05 21:59:26 +08:00
|
|
|
#include "clang/Basic/LangStandard.h"
|
2009-11-13 12:12:06 +08:00
|
|
|
#include "clang/Basic/SourceManager.h"
|
2018-07-04 05:34:13 +08:00
|
|
|
#include "clang/Basic/Stack.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/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"
|
2019-03-10 01:33:56 +08:00
|
|
|
#include "clang/Serialization/InMemoryModuleCache.h"
|
2010-03-31 01:33:59 +08:00
|
|
|
#include "llvm/ADT/Statistic.h"
|
2018-11-18 02:04:13 +08:00
|
|
|
#include "llvm/Support/BuryPointer.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"
|
2019-03-30 16:42:48 +08:00
|
|
|
#include "llvm/Support/TimeProfiler.h"
|
2012-12-04 17:13:33 +08:00
|
|
|
#include "llvm/Support/Timer.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
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,
|
2019-03-10 01:33:56 +08:00
|
|
|
InMemoryModuleCache *SharedModuleCache)
|
|
|
|
: ModuleLoader(/* BuildingModule = */ SharedModuleCache),
|
Reapply "Modules: Cache PCMs in memory and avoid a use-after-free"
This reverts commit r298185, effectively reapplying r298165, after fixing the
new unit tests (PR32338). The memory buffer generator doesn't null-terminate
the MemoryBuffer it creates; this version of the commit informs getMemBuffer
about that to avoid the assert.
Original commit message follows:
----
Clang's internal build system for implicit modules uses lock files to
ensure that after a process writes a PCM it will read the same one back
in (without contention from other -cc1 commands). Since PCMs are read
from disk repeatedly while invalidating, building, and importing, the
lock is not released quickly. Furthermore, the LockFileManager is not
robust in every environment. Other -cc1 commands can stall until
timeout (after about eight minutes).
This commit changes the lock file from being necessary for correctness
to a (possibly dubious) performance hack. The remaining benefit is to
reduce duplicate work in competing -cc1 commands which depend on the
same module. Follow-up commits will change the internal build system to
continue after a timeout, and reduce the timeout. Perhaps we should
reconsider blocking at all.
This also fixes a use-after-free, when one part of a compilation
validates a PCM and starts using it, and another tries to swap out the
PCM for something new.
The PCMCache is a new type called MemoryBufferCache, which saves memory
buffers based on their filename. Its ownership is shared by the
CompilerInstance and ModuleManager.
- The ModuleManager stores PCMs there that it loads from disk, never
touching the disk if the cache is hot.
- When modules fail to validate, they're removed from the cache.
- When a CompilerInstance is spawned to build a new module, each
already-loaded PCM is assumed to be valid, and is frozen to avoid
the use-after-free.
- Any newly-built module is written directly to the cache to avoid the
round-trip to the filesystem, making lock files unnecessary for
correctness.
Original patch by Manman Ren; most testcases by Adrian Prantl!
llvm-svn: 298278
2017-03-21 01:58:26 +08:00
|
|
|
Invocation(new CompilerInvocation()),
|
2019-03-10 01:33:56 +08:00
|
|
|
ModuleCache(SharedModuleCache ? SharedModuleCache
|
|
|
|
: new InMemoryModuleCache),
|
Modules: Invalidate out-of-date PCMs as they're discovered
Leverage the InMemoryModuleCache to invalidate a module the first time
it fails to import (and to lock a module as soon as it's built or
imported successfully). For implicit module builds, this optimizes
importing deep graphs where the leaf module is out-of-date; see example
near the end of the commit message.
Previously the cache finalized ("locked in") all modules imported so far
when starting a new module build. This was sufficient to prevent
loading two versions of the same module, but was somewhat arbitrary and
hard to reason about.
Now the cache explicitly tracks module state, where each module must be
one of:
- Unknown: module not in the cache (yet).
- Tentative: module in the cache, but not yet fully imported.
- ToBuild: module found on disk could not be imported; need to build.
- Final: module in the cache has been successfully built or imported.
Preventing repeated failed imports avoids variation in builds based on
shifting filesystem state. Now it's guaranteed that a module is loaded
from disk exactly once. It now seems safe to remove
FileManager::invalidateCache, but I'm leaving that for a later commit.
The new, precise logic uncovered a pre-existing problem in the cache:
the map key is the module filename, and different contexts use different
filenames for the same PCM file. (In particular, the test
Modules/relative-import-path.c does not build without this commit.
r223577 started using a relative path to describe a module's base
directory when importing it within another module. As a result, the
module cache sees an absolute path when (a) building the module or
importing it at the top-level, and a relative path when (b) importing
the module underneath another one.)
The "obvious" fix is to resolve paths using FileManager::getVirtualFile
and change the map key for the cache to a FileEntry, but some contexts
(particularly related to ASTUnit) have a shorter lifetime for their
FileManager than the InMemoryModuleCache. This is worth pursuing
further in a later commit; perhaps by tying together the FileManager and
InMemoryModuleCache lifetime, or moving the in-memory PCM storage into a
VFS layer.
For now, use the PCM's base directory as-written for constructing the
filename to check the ModuleCache.
Example
=======
To understand the build optimization, first consider the build of a
module graph TU -> A -> B -> C -> D with an empty cache:
TU builds A'
A' builds B'
B' builds C'
C' builds D'
imports D'
B' imports C'
imports D'
A' imports B'
imports C'
imports D'
TU imports A'
imports B'
imports C'
imports D'
If we build TU again, where A, B, C, and D are in the cache and D is
out-of-date, we would previously get this build:
TU imports A
imports B
imports C
imports D (out-of-date)
TU builds A'
A' imports B
imports C
imports D (out-of-date)
builds B'
B' imports C
imports D (out-of-date)
builds C'
C' imports D (out-of-date)
builds D'
imports D'
B' imports C'
imports D'
A' imports B'
imports C'
imports D'
TU imports A'
imports B'
imports C'
imports D'
After this commit, we'll immediateley invalidate A, B, C, and D when we
first observe that D is out-of-date, giving this build:
TU imports A
imports B
imports C
imports D (out-of-date)
TU builds A' // The same graph as an empty cache.
A' builds B'
B' builds C'
C' builds D'
imports D'
B' imports C'
imports D'
A' imports B'
imports C'
imports D'
TU imports A'
imports B'
imports C'
imports D'
The new build matches what we'd naively expect, pretty closely matching
the original build with the empty cache.
rdar://problem/48545366
llvm-svn: 355778
2019-03-10 01:44:01 +08:00
|
|
|
ThePCHContainerOperations(std::move(PCHContainerOps)) {}
|
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
|
|
|
}
|
|
|
|
|
2017-01-07 03:49:01 +08:00
|
|
|
void CompilerInstance::setInvocation(
|
|
|
|
std::shared_ptr<CompilerInvocation> Value) {
|
|
|
|
Invocation = std::move(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 ||
|
2019-11-22 10:25:03 +08:00
|
|
|
(TheASTReader && TheASTReader->isGlobalIndexUnavailable() &&
|
2013-03-23 05:26:48 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2019-10-22 03:04:56 +08:00
|
|
|
void CompilerInstance::setVerboseOutputStream(raw_ostream &Value) {
|
|
|
|
OwnedVerboseOutputStream.release();
|
|
|
|
VerboseOutputStream = &Value;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CompilerInstance::setVerboseOutputStream(std::unique_ptr<raw_ostream> Value) {
|
|
|
|
OwnedVerboseOutputStream.swap(Value);
|
|
|
|
VerboseOutputStream = OwnedVerboseOutputStream.get();
|
|
|
|
}
|
|
|
|
|
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;
|
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
|
|
|
}
|
|
|
|
|
2017-01-06 03:48:07 +08:00
|
|
|
void CompilerInstance::setPreprocessor(std::shared_ptr<Preprocessor> Value) {
|
|
|
|
PP = std::move(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);
|
|
|
|
}
|
|
|
|
|
2019-11-22 10:25:03 +08:00
|
|
|
IntrusiveRefCntPtr<ASTReader> CompilerInstance::getASTReader() const {
|
|
|
|
return TheASTReader;
|
2014-02-27 12:11:59 +08:00
|
|
|
}
|
|
|
|
void CompilerInstance::setModuleManager(IntrusiveRefCntPtr<ASTReader> Reader) {
|
2019-03-10 01:33:56 +08:00
|
|
|
assert(ModuleCache.get() == &Reader->getModuleManager().getModuleCache() &&
|
Reapply "Modules: Cache PCMs in memory and avoid a use-after-free"
This reverts commit r298185, effectively reapplying r298165, after fixing the
new unit tests (PR32338). The memory buffer generator doesn't null-terminate
the MemoryBuffer it creates; this version of the commit informs getMemBuffer
about that to avoid the assert.
Original commit message follows:
----
Clang's internal build system for implicit modules uses lock files to
ensure that after a process writes a PCM it will read the same one back
in (without contention from other -cc1 commands). Since PCMs are read
from disk repeatedly while invalidating, building, and importing, the
lock is not released quickly. Furthermore, the LockFileManager is not
robust in every environment. Other -cc1 commands can stall until
timeout (after about eight minutes).
This commit changes the lock file from being necessary for correctness
to a (possibly dubious) performance hack. The remaining benefit is to
reduce duplicate work in competing -cc1 commands which depend on the
same module. Follow-up commits will change the internal build system to
continue after a timeout, and reduce the timeout. Perhaps we should
reconsider blocking at all.
This also fixes a use-after-free, when one part of a compilation
validates a PCM and starts using it, and another tries to swap out the
PCM for something new.
The PCMCache is a new type called MemoryBufferCache, which saves memory
buffers based on their filename. Its ownership is shared by the
CompilerInstance and ModuleManager.
- The ModuleManager stores PCMs there that it loads from disk, never
touching the disk if the cache is hot.
- When modules fail to validate, they're removed from the cache.
- When a CompilerInstance is spawned to build a new module, each
already-loaded PCM is assumed to be valid, and is frozen to avoid
the use-after-free.
- Any newly-built module is written directly to the cache to avoid the
round-trip to the filesystem, making lock files unnecessary for
correctness.
Original patch by Manman Ren; most testcases by Adrian Prantl!
llvm-svn: 298278
2017-03-21 01:58:26 +08:00
|
|
|
"Expected ASTReader to use the same PCM cache");
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader = 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
|
|
|
}
|
|
|
|
|
2016-12-11 12:27:28 +08:00
|
|
|
static void collectHeaderMaps(const HeaderSearch &HS,
|
|
|
|
std::shared_ptr<ModuleDependencyCollector> MDC) {
|
|
|
|
SmallVector<std::string, 4> HeaderMapFileNames;
|
|
|
|
HS.getHeaderMapFileNames(HeaderMapFileNames);
|
|
|
|
for (auto &Name : HeaderMapFileNames)
|
|
|
|
MDC->addFile(Name);
|
|
|
|
}
|
|
|
|
|
2016-12-13 03:28:25 +08:00
|
|
|
static void collectIncludePCH(CompilerInstance &CI,
|
|
|
|
std::shared_ptr<ModuleDependencyCollector> MDC) {
|
|
|
|
const PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
|
|
|
|
if (PPOpts.ImplicitPCHInclude.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
|
|
|
|
FileManager &FileMgr = CI.getFileManager();
|
2019-08-02 05:31:56 +08:00
|
|
|
auto PCHDir = FileMgr.getDirectory(PCHInclude);
|
2016-12-13 03:28:25 +08:00
|
|
|
if (!PCHDir) {
|
|
|
|
MDC->addFile(PCHInclude);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::error_code EC;
|
|
|
|
SmallString<128> DirNative;
|
2019-08-02 05:31:56 +08:00
|
|
|
llvm::sys::path::native((*PCHDir)->getName(), DirNative);
|
2019-03-27 06:32:06 +08:00
|
|
|
llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
|
2016-12-13 03:28:25 +08:00
|
|
|
SimpleASTReaderListener Validator(CI.getPreprocessor());
|
2018-10-10 21:27:25 +08:00
|
|
|
for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
|
2016-12-13 03:28:25 +08:00
|
|
|
Dir != DirEnd && !EC; Dir.increment(EC)) {
|
|
|
|
// Check whether this is an AST file. ASTReader::isAcceptableASTFile is not
|
|
|
|
// used here since we're not interested in validating the PCH at this time,
|
|
|
|
// but only to check whether this is a file containing an AST.
|
|
|
|
if (!ASTReader::readASTFileControlBlock(
|
2018-09-14 20:47:38 +08:00
|
|
|
Dir->path(), FileMgr, CI.getPCHContainerReader(),
|
2016-12-13 03:28:25 +08:00
|
|
|
/*FindModuleFileExtensions=*/false, Validator,
|
|
|
|
/*ValidateDiagnosticOptions=*/false))
|
2018-09-14 20:47:38 +08:00
|
|
|
MDC->addFile(Dir->path());
|
2016-12-13 03:28:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-22 15:06:03 +08:00
|
|
|
static void collectVFSEntries(CompilerInstance &CI,
|
|
|
|
std::shared_ptr<ModuleDependencyCollector> MDC) {
|
|
|
|
if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Collect all VFS found.
|
2018-10-10 21:27:25 +08:00
|
|
|
SmallVector<llvm::vfs::YAMLVFSEntry, 16> VFSEntries;
|
2016-12-22 15:06:03 +08:00
|
|
|
for (const std::string &VFSFile : CI.getHeaderSearchOpts().VFSOverlayFiles) {
|
|
|
|
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
|
|
|
|
llvm::MemoryBuffer::getFile(VFSFile);
|
|
|
|
if (!Buffer)
|
|
|
|
return;
|
2018-10-10 21:27:25 +08:00
|
|
|
llvm::vfs::collectVFSFromYAML(std::move(Buffer.get()),
|
|
|
|
/*DiagHandler*/ nullptr, VFSFile, VFSEntries);
|
2016-12-22 15:06:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (auto &E : VFSEntries)
|
|
|
|
MDC->addFile(E.VPath, E.RPath);
|
|
|
|
}
|
|
|
|
|
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.
|
2019-08-15 07:04:18 +08:00
|
|
|
auto FileOS = std::make_unique<llvm::raw_fd_ostream>(
|
2014-08-26 02:17:04 +08:00
|
|
|
DiagOpts->DiagnosticLogFile, EC,
|
2019-08-05 13:43:48 +08:00
|
|
|
llvm::sys::fs::OF_Append | llvm::sys::fs::OF_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.
|
2019-08-15 07:04:18 +08:00
|
|
|
auto Logger = std::make_unique<LogDiagnosticPrinter>(*OS, DiagOpts,
|
2014-09-16 01:50:10 +08:00
|
|
|
std::move(StreamOwner));
|
2011-04-08 02:59:02 +08:00
|
|
|
if (CodeGenOpts)
|
|
|
|
Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags);
|
2019-06-11 07:32:42 +08:00
|
|
|
if (Diags.ownsClient()) {
|
|
|
|
Diags.setClient(
|
|
|
|
new ChainedDiagnosticConsumer(Diags.takeClient(), std::move(Logger)));
|
|
|
|
} else {
|
|
|
|
Diags.setClient(
|
|
|
|
new ChainedDiagnosticConsumer(Diags.getClient(), 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);
|
2018-07-31 03:24:48 +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
|
|
|
|
|
2019-03-27 06:18:52 +08:00
|
|
|
FileManager *CompilerInstance::createFileManager(
|
|
|
|
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
|
|
|
|
if (!VFS)
|
2019-03-27 06:32:06 +08:00
|
|
|
VFS = FileMgr ? &FileMgr->getVirtualFileSystem()
|
2019-03-27 06:18:52 +08:00
|
|
|
: createVFSFromCompilerInvocation(getInvocation(),
|
|
|
|
getDiagnostics());
|
|
|
|
assert(VFS && "FileManager has no VFS?");
|
|
|
|
FileMgr = new FileManager(getFileSystemOpts(), std::move(VFS));
|
2017-09-13 00:54:53 +08:00
|
|
|
return FileMgr.get();
|
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.
|
2019-08-02 05:31:56 +08:00
|
|
|
auto 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 =
|
2019-08-02 05:31:56 +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.
|
2019-08-02 05:31:56 +08:00
|
|
|
SourceMgr.overrideFileContents(FromFile, *ToFile);
|
2014-07-07 14:05:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
2018-11-05 20:46:02 +08:00
|
|
|
// The module manager holds a reference to the old preprocessor (if any).
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader.reset();
|
2018-11-05 20:46:02 +08:00
|
|
|
|
2009-11-13 13:52:11 +08:00
|
|
|
// Create the Preprocessor.
|
2017-01-06 09:04:46 +08:00
|
|
|
HeaderSearch *HeaderInfo =
|
|
|
|
new HeaderSearch(getHeaderSearchOptsPtr(), getSourceManager(),
|
|
|
|
getDiagnostics(), getLangOpts(), &getTarget());
|
2019-03-10 01:33:56 +08:00
|
|
|
PP = std::make_shared<Preprocessor>(Invocation->getPreprocessorOptsPtr(),
|
|
|
|
getDiagnostics(), getLangOpts(),
|
|
|
|
getSourceManager(), *HeaderInfo, *this,
|
|
|
|
/*IdentifierInfoLookup=*/nullptr,
|
|
|
|
/*OwnsHeaderSearch=*/true, TUKind);
|
2017-10-07 07:09:55 +08:00
|
|
|
getTarget().adjust(getLangOpts());
|
2015-09-23 01:23:22 +08:00
|
|
|
PP->Initialize(getTarget(), getAuxTarget());
|
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
|
|
|
|
2016-11-18 08:41:27 +08:00
|
|
|
// Initialize the header search object. In CUDA compilations, we use the aux
|
|
|
|
// triple (the host triple) to initialize our header search, since we need to
|
|
|
|
// find the host headers in order to compile the CUDA code.
|
|
|
|
const llvm::Triple *HeaderSearchTriple = &PP->getTargetInfo().getTriple();
|
|
|
|
if (PP->getTargetInfo().getTriple().getOS() == llvm::Triple::CUDA &&
|
|
|
|
PP->getAuxTargetInfo())
|
|
|
|
HeaderSearchTriple = &PP->getAuxTargetInfo()->getTriple();
|
|
|
|
|
2014-07-07 14:05:00 +08:00
|
|
|
ApplyHeaderSearchOptions(PP->getHeaderSearchInfo(), getHeaderSearchOpts(),
|
2016-11-18 08:41:27 +08:00
|
|
|
PP->getLangOpts(), *HeaderSearchTriple);
|
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())
|
2019-06-20 01:07:36 +08:00
|
|
|
addDependencyCollector(std::make_shared<DependencyFileGenerator>(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
|
|
|
}
|
|
|
|
|
2016-12-11 12:27:28 +08:00
|
|
|
// If there is a module dep collector, register with other dep collectors
|
|
|
|
// and also (a) collect header maps and (b) TODO: input vfs overlay files.
|
|
|
|
if (ModuleDepCollector) {
|
2016-03-30 07:47:40 +08:00
|
|
|
addDependencyCollector(ModuleDepCollector);
|
2016-12-11 12:27:28 +08:00
|
|
|
collectHeaderMaps(PP->getHeaderSearchInfo(), ModuleDepCollector);
|
2016-12-13 03:28:25 +08:00
|
|
|
collectIncludePCH(*this, ModuleDepCollector);
|
2016-12-22 15:06:03 +08:00
|
|
|
collectVFSEntries(*this, ModuleDepCollector);
|
2016-12-11 12:27:28 +08:00
|
|
|
}
|
2016-03-30 07:47:40 +08:00
|
|
|
|
|
|
|
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
|
|
|
|
2018-05-04 23:58:31 +08:00
|
|
|
if (DepOpts.ShowIncludesDest != ShowIncludesDestination::None) {
|
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());
|
2020-01-29 03:23:46 +08:00
|
|
|
return std::string(SpecificModuleCache.str());
|
2015-02-20 04:12:20 +08:00
|
|
|
}
|
|
|
|
|
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;
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader = createPCHExternalASTSource(
|
2014-05-08 12:26:47 +08:00
|
|
|
Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation,
|
2019-03-10 01:33:56 +08:00
|
|
|
AllowPCHWithCompilerErrors, getPreprocessor(), getModuleCache(),
|
|
|
|
getASTContext(), getPCHContainerReader(),
|
2019-06-20 01:07:36 +08:00
|
|
|
getFrontendOpts().ModuleFileExtensions, DependencyCollectors,
|
|
|
|
DeserializationListener, OwnDeserializationListener, Preamble,
|
|
|
|
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,
|
2019-03-10 01:33:56 +08:00
|
|
|
bool AllowPCHWithCompilerErrors, Preprocessor &PP,
|
|
|
|
InMemoryModuleCache &ModuleCache, ASTContext &Context,
|
2015-07-17 09:19:54 +08:00
|
|
|
const PCHContainerReader &PCHContainerRdr,
|
2017-01-06 02:23:18 +08:00
|
|
|
ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
|
[PCH] Attach instance's dependency collectors to PCH external AST sources.
Summary:
When a PCH is included via -include-pch, clang should treat the
current TU as dependent on the sourcefile that the PCH was generated from.
This is currently _partly_ accomplished by InitializePreprocessor calling
AddImplicitIncludePCH to synthesize an implicit #include of the sourcefile,
into the preprocessor's Predefines buffer.
For FrontendActions such as PreprocessOnlyAction (which is, curiously, what the
driver winds up running one of in response to a plain clang -M) this is
sufficient: the preprocessor cranks over its Predefines and emits a dependency
reference to the initial sourcefile.
For other FrontendActions (for example -emit-obj or -fsyntax-only) the
Predefines buffer is reset to the suggested predefines buffer from the PCH, so
the dependency edge is lost. The result is that clang emits a .d file in those
cases that lacks a reference to the .h file responsible for the input (and in
Swift's case, our .swiftdeps file winds up not including a reference to the
source file for a PCH bridging header.)
This patch fixes the problem by taking a different tack: ignoring the
Predefines buffer (which seems a bit like a hack anyways) and directly
attaching the CompilerInstance's DependencyCollectors (and legacy
DependencyFileGenerator) to the ASTReader for the external AST.
This approach is similar to the one chosen in earlier consultation with Bruno
and Ben, and I think it's the least-bad solution, given several options.
Reviewers: bruno, benlangmuir, doug.gregor
Reviewed By: bruno, doug.gregor
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D31378
llvm-svn: 299009
2017-03-30 01:33:09 +08:00
|
|
|
ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,
|
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(
|
2019-03-10 01:33:56 +08:00
|
|
|
PP, ModuleCache, &Context, PCHContainerRdr, Extensions,
|
2015-11-04 02:33:07 +08:00
|
|
|
Sysroot.empty() ? "" : Sysroot.data(), DisablePCHValidation,
|
|
|
|
AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false,
|
Reapply: [Modules][PCH] Hash input files content
Summary:
When files often get touched during builds, the mtime based validation
leads to different problems in implicit modules builds, even when the
content doesn't actually change:
- Modules only: module invalidation due to out of date files. Usually causing rebuild traffic.
- Modules + PCH: build failures because clang cannot rebuild a module if it comes from building a PCH.
- PCH: build failures because clang cannot rebuild a PCH in case one of the input headers has different mtime.
This patch proposes hashing the content of input files (headers and
module maps), which is performed during serialization time. When looking
at input files for validation, clang only computes the hash in case
there's a mtime mismatch.
I've tested a couple of different hash algorithms availble in LLVM in
face of building modules+pch for `#import <Cocoa/Cocoa.h>`:
- `hash_code`: performace diff within the noise, total module cache increased by 0.07%.
- `SHA1`: 5% slowdown. Haven't done real size measurements, but it'd be BLOCK_ID+20 bytes per input file, instead of BLOCK_ID+8 bytes from `hash_code`.
- `MD5`: 3% slowdown. Like above, but BLOCK_ID+16 bytes per input file.
Given the numbers above, the patch uses `hash_code`. The patch also
improves invalidation error msgs to point out which type of problem the
user is facing: "mtime", "size" or "content".
rdar://problem/29320105
Reviewers: dexonsmith, arphaman, rsmith, aprantl
Subscribers: jkorous, cfe-commits, ributzka
Tags: #clang
Differential Revision: https://reviews.llvm.org/D67249
> llvm-svn: 374841
llvm-svn: 374895
2019-10-15 22:23:55 +08:00
|
|
|
HSOpts.ModulesValidateSystemHeaders, HSOpts.ValidateASTInputFilesContent,
|
|
|
|
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);
|
[PCH] Attach instance's dependency collectors to PCH external AST sources.
Summary:
When a PCH is included via -include-pch, clang should treat the
current TU as dependent on the sourcefile that the PCH was generated from.
This is currently _partly_ accomplished by InitializePreprocessor calling
AddImplicitIncludePCH to synthesize an implicit #include of the sourcefile,
into the preprocessor's Predefines buffer.
For FrontendActions such as PreprocessOnlyAction (which is, curiously, what the
driver winds up running one of in response to a plain clang -M) this is
sufficient: the preprocessor cranks over its Predefines and emits a dependency
reference to the initial sourcefile.
For other FrontendActions (for example -emit-obj or -fsyntax-only) the
Predefines buffer is reset to the suggested predefines buffer from the PCH, so
the dependency edge is lost. The result is that clang emits a .d file in those
cases that lacks a reference to the .h file responsible for the input (and in
Swift's case, our .swiftdeps file winds up not including a reference to the
source file for a PCH bridging header.)
This patch fixes the problem by taking a different tack: ignoring the
Predefines buffer (which seems a bit like a hack anyways) and directly
attaching the CompilerInstance's DependencyCollectors (and legacy
DependencyFileGenerator) to the ASTReader for the external AST.
This approach is similar to the one chosen in earlier consultation with Bruno
and Ben, and I think it's the least-bad solution, given several options.
Reviewers: bruno, benlangmuir, doug.gregor
Reviewed By: bruno, doug.gregor
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D31378
llvm-svn: 299009
2017-03-30 01:33:09 +08:00
|
|
|
|
|
|
|
for (auto &Listener : DependencyCollectors)
|
|
|
|
Listener->attachToASTReader(*Reader);
|
|
|
|
|
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.
|
2019-08-02 05:31:56 +08:00
|
|
|
auto 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.
|
2019-08-02 05:31:56 +08:00
|
|
|
PP.SetCodeCompletionPoint(*Entry, Line, Column);
|
2010-08-05 00:47:14 +08:00
|
|
|
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-11-13 17:36:05 +08:00
|
|
|
}
|
|
|
|
|
2009-11-29 17:57:35 +08:00
|
|
|
void CompilerInstance::createFrontendTimer() {
|
2016-11-19 03:43:25 +08:00
|
|
|
FrontendTimerGroup.reset(
|
|
|
|
new llvm::TimerGroup("frontend", "Clang front-end time report"));
|
2015-07-14 08:26:00 +08:00
|
|
|
FrontendTimer.reset(
|
2016-11-19 03:43:25 +08:00
|
|
|
new llvm::Timer("frontend", "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();
|
2017-06-10 05:24:02 +08:00
|
|
|
if (DeleteBuiltModules) {
|
|
|
|
for (auto &Module : BuiltModules)
|
|
|
|
llvm::sys::fs::remove(Module.second);
|
|
|
|
BuiltModules.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,
|
2019-12-19 20:23:13 +08:00
|
|
|
getFrontendOpts().UseTemporary);
|
2009-11-14 02:32:08 +08:00
|
|
|
}
|
|
|
|
|
2016-07-15 08:55:40 +08:00
|
|
|
std::unique_ptr<raw_pwrite_stream> CompilerInstance::createNullOutputFile() {
|
2019-08-15 07:04:18 +08:00
|
|
|
return std::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()) {
|
2020-01-29 03:23:46 +08:00
|
|
|
OutFile = std::string(OutputPath);
|
2009-11-14 02:32:08 +08:00
|
|
|
} 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);
|
2020-01-29 03:23:46 +08:00
|
|
|
OutFile = std::string(Path.str());
|
2009-11-14 02:32:08 +08:00
|
|
|
} 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.
|
2017-08-09 00:21:23 +08:00
|
|
|
// Insert -%%%%%%%% before the extension (if any), and because some tools
|
|
|
|
// (noticeable, clang's own GlobalModuleIndex.cpp) glob for build
|
|
|
|
// artifacts, also append .tmp.
|
|
|
|
StringRef OutputExtension = llvm::sys::path::extension(OutFile);
|
|
|
|
SmallString<128> TempPath =
|
|
|
|
StringRef(OutFile).drop_back(OutputExtension.size());
|
2013-06-28 02:26:26 +08:00
|
|
|
TempPath += "-%%%%%%%%";
|
2017-08-09 00:21:23 +08:00
|
|
|
TempPath += OutputExtension;
|
|
|
|
TempPath += ".tmp";
|
2013-06-28 02:26:26 +08:00
|
|
|
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));
|
2020-01-29 03:23:46 +08:00
|
|
|
OSFile = TempFile = std::string(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,
|
2019-08-05 13:43:48 +08:00
|
|
|
(Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_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);
|
|
|
|
|
2019-08-15 07:04:18 +08:00
|
|
|
auto B = std::make_unique<llvm::buffer_ostream>(*OS);
|
2015-04-14 23:15:49 +08:00
|
|
|
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) {
|
2017-06-29 10:19:42 +08:00
|
|
|
SrcMgr::CharacteristicKind Kind =
|
|
|
|
Input.getKind().getFormat() == InputKind::ModuleMap
|
|
|
|
? Input.isSystem() ? SrcMgr::C_System_ModuleMap
|
|
|
|
: SrcMgr::C_User_ModuleMap
|
|
|
|
: 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()) {
|
2017-09-09 09:14:04 +08:00
|
|
|
SourceMgr.setMainFileID(SourceMgr.createFileID(SourceManager::Unowned,
|
|
|
|
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 != "-") {
|
Introduce FileEntryRef and use it when handling includes to report correct dependencies
when the FileManager is reused across invocations
This commit introduces a parallel API to FileManager's getFile: getFileEntryRef, which returns
a reference to the FileEntry, and the name that was used to access the file. In the case of
a VFS with 'use-external-names', the FileEntyRef contains the external name of the file,
not the filename that was used to access it.
The new API is adopted only in the HeaderSearch and Preprocessor for include file lookup, so that the
accessed path can be propagated to SourceManager's FileInfo. SourceManager's FileInfo now can report this accessed path, using
the new getName method. This API is then adopted in the dependency collector, which now correctly reports dependencies when a file
is included both using a symlink and a real path in the case when the FileManager is reused across multiple Preprocessor invocations.
Note that this patch does not fix all dependency collector issues, as the same problem is still present in other cases when dependencies
are obtained using FileSkipped, InclusionDirective, and HasInclude. This will be fixed in follow-up commits.
Differential Revision: https://reviews.llvm.org/D65907
llvm-svn: 369680
2019-08-23 02:15:50 +08:00
|
|
|
auto FileOrErr = FileMgr.getFileRef(InputFile, /*OpenFile=*/true);
|
2019-08-02 05:31:56 +08:00
|
|
|
if (!FileOrErr) {
|
2019-08-27 02:29:51 +08:00
|
|
|
// FIXME: include the error in the diagnostic.
|
|
|
|
consumeError(FileOrErr.takeError());
|
2009-11-14 15:53:04 +08:00
|
|
|
Diags.Report(diag::err_fe_error_reading) << InputFile;
|
|
|
|
return false;
|
|
|
|
}
|
Introduce FileEntryRef and use it when handling includes to report correct dependencies
when the FileManager is reused across invocations
This commit introduces a parallel API to FileManager's getFile: getFileEntryRef, which returns
a reference to the FileEntry, and the name that was used to access the file. In the case of
a VFS with 'use-external-names', the FileEntyRef contains the external name of the file,
not the filename that was used to access it.
The new API is adopted only in the HeaderSearch and Preprocessor for include file lookup, so that the
accessed path can be propagated to SourceManager's FileInfo. SourceManager's FileInfo now can report this accessed path, using
the new getName method. This API is then adopted in the dependency collector, which now correctly reports dependencies when a file
is included both using a symlink and a real path in the case when the FileManager is reused across multiple Preprocessor invocations.
Note that this patch does not fix all dependency collector issues, as the same problem is still present in other cases when dependencies
are obtained using FileSkipped, InclusionDirective, and HasInclude. This will be fixed in follow-up commits.
Differential Revision: https://reviews.llvm.org/D65907
llvm-svn: 369680
2019-08-23 02:15:50 +08:00
|
|
|
FileEntryRef File = *FileOrErr;
|
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.
|
Introduce FileEntryRef and use it when handling includes to report correct dependencies
when the FileManager is reused across invocations
This commit introduces a parallel API to FileManager's getFile: getFileEntryRef, which returns
a reference to the FileEntry, and the name that was used to access the file. In the case of
a VFS with 'use-external-names', the FileEntyRef contains the external name of the file,
not the filename that was used to access it.
The new API is adopted only in the HeaderSearch and Preprocessor for include file lookup, so that the
accessed path can be propagated to SourceManager's FileInfo. SourceManager's FileInfo now can report this accessed path, using
the new getName method. This API is then adopted in the dependency collector, which now correctly reports dependencies when a file
is included both using a symlink and a real path in the case when the FileManager is reused across multiple Preprocessor invocations.
Note that this patch does not fix all dependency collector issues, as the same problem is still present in other cases when dependencies
are obtained using FileSkipped, InclusionDirective, and HasInclude. This will be fixed in follow-up commits.
Differential Revision: https://reviews.llvm.org/D65907
llvm-svn: 369680
2019-08-23 02:15:50 +08:00
|
|
|
if (File.getFileEntry().isNamedPipe()) {
|
|
|
|
auto MB =
|
|
|
|
FileMgr.getBufferForFile(&File.getFileEntry(), /*isVolatile=*/true);
|
2014-10-27 06:44:13 +08:00
|
|
|
if (MB) {
|
2013-08-12 21:46:52 +08:00
|
|
|
// Create a new virtual file that will have the correct size.
|
Introduce FileEntryRef and use it when handling includes to report correct dependencies
when the FileManager is reused across invocations
This commit introduces a parallel API to FileManager's getFile: getFileEntryRef, which returns
a reference to the FileEntry, and the name that was used to access the file. In the case of
a VFS with 'use-external-names', the FileEntyRef contains the external name of the file,
not the filename that was used to access it.
The new API is adopted only in the HeaderSearch and Preprocessor for include file lookup, so that the
accessed path can be propagated to SourceManager's FileInfo. SourceManager's FileInfo now can report this accessed path, using
the new getName method. This API is then adopted in the dependency collector, which now correctly reports dependencies when a file
is included both using a symlink and a real path in the case when the FileManager is reused across multiple Preprocessor invocations.
Note that this patch does not fix all dependency collector issues, as the same problem is still present in other cases when dependencies
are obtained using FileSkipped, InclusionDirective, and HasInclude. This will be fixed in follow-up commits.
Differential Revision: https://reviews.llvm.org/D65907
llvm-svn: 369680
2019-08-23 02:15:50 +08:00
|
|
|
const FileEntry *FE =
|
|
|
|
FileMgr.getVirtualFile(InputFile, (*MB)->getBufferSize(), 0);
|
|
|
|
SourceMgr.overrideFileContents(FE, std::move(*MB));
|
|
|
|
SourceMgr.setMainFileID(
|
|
|
|
SourceMgr.createFileID(FE, SourceLocation(), Kind));
|
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;
|
|
|
|
}
|
Introduce FileEntryRef and use it when handling includes to report correct dependencies
when the FileManager is reused across invocations
This commit introduces a parallel API to FileManager's getFile: getFileEntryRef, which returns
a reference to the FileEntry, and the name that was used to access the file. In the case of
a VFS with 'use-external-names', the FileEntyRef contains the external name of the file,
not the filename that was used to access it.
The new API is adopted only in the HeaderSearch and Preprocessor for include file lookup, so that the
accessed path can be propagated to SourceManager's FileInfo. SourceManager's FileInfo now can report this accessed path, using
the new getName method. This API is then adopted in the dependency collector, which now correctly reports dependencies when a file
is included both using a symlink and a real path in the case when the FileManager is reused across multiple Preprocessor invocations.
Note that this patch does not fix all dependency collector issues, as the same problem is still present in other cases when dependencies
are obtained using FileSkipped, InclusionDirective, and HasInclude. This will be fixed in follow-up commits.
Differential Revision: https://reviews.llvm.org/D65907
llvm-svn: 369680
2019-08-23 02:15:50 +08:00
|
|
|
} else {
|
|
|
|
SourceMgr.setMainFileID(
|
|
|
|
SourceMgr.createFileID(File, SourceLocation(), Kind));
|
2012-11-06 06:53:33 +08:00
|
|
|
}
|
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'!");
|
|
|
|
|
Improve behavior in the case of stack exhaustion.
Summary:
Clang performs various recursive operations (such as template instantiation),
and may use non-trivial amounts of stack space in each recursive step (for
instance, due to recursive AST walks). While we try to keep the stack space
used by such steps to a minimum and we have explicit limits on the number of
such steps we perform, it's impractical to guarantee that we won't blow out the
stack on deeply recursive template instantiations on complex ASTs, even with
only a moderately high instantiation depth limit.
The user experience in these cases is generally terrible: we crash with
no hint of what went wrong. Under this patch, we attempt to do better:
* Detect when the stack is nearly exhausted, and produce a warning with a
nice template instantiation backtrace, telling the user that we might
run slowly or crash.
* For cases where we're forced to trigger recursive template
instantiation in arbitrarily-deeply-nested contexts, check whether
we're nearly out of stack space and allocate a new stack (by spawning
a new thread) after producing the warning.
Reviewers: rnk, aaron.ballman
Subscribers: mgorny, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D66361
llvm-svn: 369940
2019-08-27 02:18:07 +08:00
|
|
|
// Mark this point as the bottom of the stack if we don't have somewhere
|
|
|
|
// better. We generally expect frontend actions to be invoked with (nearly)
|
|
|
|
// DesiredStackSpace available.
|
|
|
|
noteBottomOfStack();
|
|
|
|
|
2019-10-22 03:04:56 +08:00
|
|
|
raw_ostream &OS = getVerboseOutputStream();
|
2010-01-13 08:48:06 +08:00
|
|
|
|
2018-09-15 09:21:15 +08:00
|
|
|
if (!Act.PrepareToExecute(*this))
|
|
|
|
return false;
|
|
|
|
|
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;
|
|
|
|
|
2019-12-10 21:52:58 +08:00
|
|
|
// Create TargetInfo for the other side of CUDA/OpenMP/SYCL compilation.
|
|
|
|
if ((getLangOpts().CUDA || getLangOpts().OpenMPIsDevice ||
|
|
|
|
getLangOpts().SYCLIsDevice) &&
|
[OpenMP] Add support for auxiliary triple specification
Summary: Device offloading requires the specification of an additional flag containing the triple of the //other// architecture the code is being compiled on if such an architecture exists. If compiling for the host, the auxiliary triple flag will contain the triple describing the device and vice versa.
Reviewers: arpith-jacob, sfantao, caomhin, carlo.bertolli, ABataev, Hahnfeld, jlebar, hfinkel, tstellar
Reviewed By: Hahnfeld
Subscribers: rengolin, cfe-commits
Differential Revision: https://reviews.llvm.org/D29339
llvm-svn: 306689
2017-06-29 23:49:03 +08:00
|
|
|
!getFrontendOpts().AuxTriple.empty()) {
|
2016-04-30 07:05:19 +08:00
|
|
|
auto TO = std::make_shared<TargetOptions>();
|
2018-08-09 06:23:57 +08:00
|
|
|
TO->Triple = llvm::Triple::normalize(getFrontendOpts().AuxTriple);
|
[hip] Properly populate macros based on host processor.
Summary:
- The device compilation needs to have a consistent source code compared
to the corresponding host compilation. If macros based on the
host-specific target processor is not properly populated, the device
compilation may fail due to the inconsistent source after the
preprocessor. So far, only the host triple is used to build the
macros. If a detailed host CPU target or certain features are
specified, macros derived from them won't be populated properly, e.g.
`__SSE3__` won't be added unless `+sse3` feature is present. On
Windows compilation compatible with MSVC, that missing macros result
in that intrinsics are not included and cause device compilation
failure on the host-side source.
- This patch addresses this issue by introducing two `cc1` options,
i.e., `-aux-target-cpu` and `-aux-target-feature`. If a specific host
CPU target or certain features are specified, the compiler driver will
append them during the construction of the offline compilation
actions. Then, the toolchain in `cc1` phase will populate macros
accordingly.
- An internal option `--gpu-use-aux-triple-only` is added to fall back
the original behavior to help diagnosing potential issues from the new
behavior.
Reviewers: tra, yaxunl
Subscribers: cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73942
2020-02-04 04:35:18 +08:00
|
|
|
if (getFrontendOpts().AuxTargetCPU)
|
|
|
|
TO->CPU = getFrontendOpts().AuxTargetCPU.getValue();
|
|
|
|
if (getFrontendOpts().AuxTargetFeatures)
|
|
|
|
TO->FeaturesAsWritten = getFrontendOpts().AuxTargetFeatures.getValue();
|
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());
|
|
|
|
|
2019-01-30 20:26:54 +08:00
|
|
|
if (auto *Aux = getAuxTarget())
|
|
|
|
getTarget().setAuxTarget(Aux);
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
// rewriter project will change target built-in bool type from its default.
|
2012-04-17 05:03:30 +08:00
|
|
|
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)) {
|
2019-06-27 03:50:12 +08:00
|
|
|
if (llvm::Error Err = Act.Execute()) {
|
|
|
|
consumeError(std::move(Err)); // FIXME this drops errors on the floor.
|
|
|
|
}
|
2010-01-13 08:48:06 +08:00
|
|
|
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");
|
2017-09-08 02:37:16 +08:00
|
|
|
if (NumWarnings || NumErrors) {
|
|
|
|
OS << " generated";
|
|
|
|
if (getLangOpts().CUDA) {
|
|
|
|
if (!getLangOpts().CUDAIsDevice) {
|
|
|
|
OS << " when compiling for host";
|
|
|
|
} else {
|
|
|
|
OS << " when compiling for " << getTargetOpts().CPU;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
OS << ".\n";
|
|
|
|
}
|
2010-04-08 02:47:42 +08:00
|
|
|
}
|
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;
|
2019-08-15 07:04:18 +08:00
|
|
|
auto StatS = std::make_unique<llvm::raw_fd_ostream>(
|
2019-08-05 13:43:48 +08:00
|
|
|
StatsFile, EC, llvm::sys::fs::OF_Text);
|
2016-09-27 02:53:34 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Determine the appropriate source input kind based on language
|
2011-09-13 07:31:24 +08:00
|
|
|
/// options.
|
2019-08-05 21:59:26 +08:00
|
|
|
static Language getLanguageFromOptions(const LangOptions &LangOpts) {
|
2011-09-13 07:31:24 +08:00
|
|
|
if (LangOpts.OpenCL)
|
2019-08-05 21:59:26 +08:00
|
|
|
return Language::OpenCL;
|
2011-09-13 07:31:24 +08:00
|
|
|
if (LangOpts.CUDA)
|
2019-08-05 21:59:26 +08:00
|
|
|
return Language::CUDA;
|
2018-10-31 04:31:30 +08:00
|
|
|
if (LangOpts.ObjC)
|
2019-08-05 21:59:26 +08:00
|
|
|
return LangOpts.CPlusPlus ? Language::ObjCXX : Language::ObjC;
|
|
|
|
return LangOpts.CPlusPlus ? Language::CXX : Language::C;
|
2011-09-13 07:31:24 +08:00
|
|
|
}
|
|
|
|
|
2018-07-31 03:24:48 +08:00
|
|
|
/// 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.
|
2017-06-10 03:22:32 +08:00
|
|
|
static bool
|
|
|
|
compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
|
|
|
|
StringRef ModuleName, FrontendInputFile Input,
|
|
|
|
StringRef OriginalModuleMapFile, StringRef ModuleFileName,
|
|
|
|
llvm::function_ref<void(CompilerInstance &)> PreBuildStep =
|
|
|
|
[](CompilerInstance &) {},
|
|
|
|
llvm::function_ref<void(CompilerInstance &)> PostBuildStep =
|
|
|
|
[](CompilerInstance &) {}) {
|
2019-03-30 16:42:48 +08:00
|
|
|
llvm::TimeTraceScope TimeScope("Module Compile", ModuleName);
|
|
|
|
|
2011-09-13 07:31:24 +08:00
|
|
|
// Construct a compiler invocation for creating this module.
|
2017-01-07 03:49:01 +08:00
|
|
|
auto Invocation =
|
|
|
|
std::make_shared<CompilerInvocation>(ImportingInstance.getInvocation());
|
2011-10-08 19:31:46 +08:00
|
|
|
|
2011-11-30 05:59:16 +08:00
|
|
|
PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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.
|
2017-03-14 02:45:08 +08:00
|
|
|
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
|
|
|
|
2018-03-21 06:36:39 +08:00
|
|
|
// If the original compiler invocation had -fmodule-name, pass it through.
|
|
|
|
Invocation->getLangOpts()->ModuleName =
|
|
|
|
ImportingInstance.getInvocation().getLangOpts()->ModuleName;
|
|
|
|
|
2011-11-16 03:35:01 +08:00
|
|
|
// Note the name of the module we're building.
|
2020-01-29 03:23:46 +08:00
|
|
|
Invocation->getLangOpts()->CurrentModule = std::string(ModuleName);
|
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)
|
2017-01-06 03:11:31 +08:00
|
|
|
ImportingPPOpts.FailedModules =
|
|
|
|
std::make_shared<PreprocessorOptions::FailedModulesSet>();
|
2012-11-30 07:55:25 +08:00
|
|
|
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;
|
2020-01-29 03:23:46 +08:00
|
|
|
FrontendOpts.OriginalModuleMap = std::string(OriginalModuleMapFile);
|
2017-03-14 02:45:08 +08:00
|
|
|
// Force implicitly-built modules to hash the content of the module file.
|
|
|
|
HSOpts.ModulesHashContent = true;
|
2017-06-10 03:22:32 +08:00
|
|
|
FrontendOpts.Inputs = {Input};
|
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;
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-11-30 05:59:16 +08:00
|
|
|
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!");
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-09-13 07:31:24 +08:00
|
|
|
// Construct a compiler instance that will be used to actually create the
|
2019-03-10 01:33:56 +08:00
|
|
|
// module. Since we're sharing an in-memory module cache,
|
Reapply "Modules: Cache PCMs in memory and avoid a use-after-free"
This reverts commit r298185, effectively reapplying r298165, after fixing the
new unit tests (PR32338). The memory buffer generator doesn't null-terminate
the MemoryBuffer it creates; this version of the commit informs getMemBuffer
about that to avoid the assert.
Original commit message follows:
----
Clang's internal build system for implicit modules uses lock files to
ensure that after a process writes a PCM it will read the same one back
in (without contention from other -cc1 commands). Since PCMs are read
from disk repeatedly while invalidating, building, and importing, the
lock is not released quickly. Furthermore, the LockFileManager is not
robust in every environment. Other -cc1 commands can stall until
timeout (after about eight minutes).
This commit changes the lock file from being necessary for correctness
to a (possibly dubious) performance hack. The remaining benefit is to
reduce duplicate work in competing -cc1 commands which depend on the
same module. Follow-up commits will change the internal build system to
continue after a timeout, and reduce the timeout. Perhaps we should
reconsider blocking at all.
This also fixes a use-after-free, when one part of a compilation
validates a PCM and starts using it, and another tries to swap out the
PCM for something new.
The PCMCache is a new type called MemoryBufferCache, which saves memory
buffers based on their filename. Its ownership is shared by the
CompilerInstance and ModuleManager.
- The ModuleManager stores PCMs there that it loads from disk, never
touching the disk if the cache is hot.
- When modules fail to validate, they're removed from the cache.
- When a CompilerInstance is spawned to build a new module, each
already-loaded PCM is assumed to be valid, and is frozen to avoid
the use-after-free.
- Any newly-built module is written directly to the cache to avoid the
round-trip to the filesystem, making lock files unnecessary for
correctness.
Original patch by Manman Ren; most testcases by Adrian Prantl!
llvm-svn: 298278
2017-03-21 01:58:26 +08:00
|
|
|
// CompilerInstance::CompilerInstance is responsible for finalizing the
|
|
|
|
// buffers to prevent use-after-frees.
|
2015-06-21 02:53:08 +08:00
|
|
|
CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(),
|
2019-03-10 01:33:56 +08:00
|
|
|
&ImportingInstance.getModuleCache());
|
2017-01-07 03:49:01 +08:00
|
|
|
auto &Inv = *Invocation;
|
|
|
|
Instance.setInvocation(std::move(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
|
|
|
|
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());
|
2017-06-10 03:22:32 +08:00
|
|
|
SourceMgr.pushModuleBuildStack(ModuleName,
|
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());
|
2017-01-07 03:49:01 +08:00
|
|
|
Inv.getDependencyOutputOpts() = DependencyOutputOptions();
|
2014-06-20 03:36:03 +08:00
|
|
|
|
2014-10-14 10:08:30 +08:00
|
|
|
ImportingInstance.getDiagnostics().Report(ImportLoc,
|
|
|
|
diag::remark_module_build)
|
2017-06-10 03:22:32 +08:00
|
|
|
<< ModuleName << ModuleFileName;
|
|
|
|
|
|
|
|
PreBuildStep(Instance);
|
2014-10-14 10:08:30 +08:00
|
|
|
|
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.
|
|
|
|
llvm::CrashRecoveryContext CRC;
|
2017-04-28 09:49:42 +08:00
|
|
|
CRC.RunSafelyOnThread(
|
|
|
|
[&]() {
|
|
|
|
GenerateModuleFromModuleMapAction Action;
|
|
|
|
Instance.ExecuteAction(Action);
|
|
|
|
},
|
2018-07-04 05:34:13 +08:00
|
|
|
DesiredStackSize);
|
2013-05-04 06:58:43 +08:00
|
|
|
|
2017-06-10 03:22:32 +08:00
|
|
|
PostBuildStep(Instance);
|
|
|
|
|
2014-10-14 10:08:30 +08:00
|
|
|
ImportingInstance.getDiagnostics().Report(ImportLoc,
|
|
|
|
diag::remark_module_build_done)
|
2017-06-10 03:22:32 +08:00
|
|
|
<< ModuleName;
|
2014-10-14 10:08:30 +08:00
|
|
|
|
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
|
|
|
|
2017-06-10 03:22:32 +08:00
|
|
|
return !Instance.getDiagnostics().hasErrorOccurred();
|
|
|
|
}
|
|
|
|
|
2018-05-02 10:25:03 +08:00
|
|
|
static const FileEntry *getPublicModuleMap(const FileEntry *File,
|
|
|
|
FileManager &FileMgr) {
|
|
|
|
StringRef Filename = llvm::sys::path::filename(File->getName());
|
|
|
|
SmallString<128> PublicFilename(File->getDir()->getName());
|
|
|
|
if (Filename == "module_private.map")
|
|
|
|
llvm::sys::path::append(PublicFilename, "module.map");
|
|
|
|
else if (Filename == "module.private.modulemap")
|
|
|
|
llvm::sys::path::append(PublicFilename, "module.modulemap");
|
|
|
|
else
|
|
|
|
return nullptr;
|
2019-08-02 05:31:56 +08:00
|
|
|
if (auto FE = FileMgr.getFile(PublicFilename))
|
|
|
|
return *FE;
|
|
|
|
return nullptr;
|
2018-05-02 10:25:03 +08:00
|
|
|
}
|
|
|
|
|
clang/Modules: Refactor CompilerInstance::loadModule, NFC
Refactor the logic on CompilerInstance::loadModule and a couple of
surrounding methods in order to clarify what's going on.
- Rename ModuleLoader::loadModuleFromSource to compileModuleFromSource
and fix its documentation, since it never loads a module. It just
creates/compiles one.
- Rename one of the overloads of compileModuleImpl to compileModule,
making it more obvious which one calls the other.
- Rename compileAndLoadModule to compileModuleAndReadAST. This
clarifies the relationship between this helper and its caller,
CompilerInstance::loadModule (the old name implied the opposite
relationship). It also (correctly) indicates that more needs to be
done to load the module than this function is responsible for.
- Split findOrCompileModuleAndReadAST out of loadModule. Besides
reducing nesting for this code thanks to early returns and the like,
this refactor clarifies the logic in loadModule, particularly around
calls to ModuleMap::cacheModuleLoad and
ModuleMap::getCachedModuleLoad. findOrCompileModuleAndReadAST also
breaks early if the initial ReadAST call returns Missing or OutOfDate,
allowing the last ditch call to compileModuleAndReadAST to come at the
end of the function body.
- Additionally split out selectModuleSource, clarifying the logic
due to early returns.
- Add ModuleLoadResult::isNormal and OtherUncachedFailure, so that
loadModule knows whether to cache the result.
OtherUncachedFailure was added to keep this patch NFC, but there's
a chance that these cases were uncached by accident, through
copy/paste/modify failures. These should be audited as a
follow-up (maybe we can eliminate this case).
- Do *not* lift the setting of `ModuleLoadFailed = true` to
loadModule because there isn't a clear pattern for when it's set.
This should be reconsidered in a follow-up, in case it would be
correct to set `ModuleLoadFailed` whenever no module is returned
and the result is either Normal or OtherUncachedFailure.
- Add some header documentation where it was missing, and fix it where
it was wrong.
This should have no functionality change.
https://reviews.llvm.org/D70556
2019-11-22 02:39:55 +08:00
|
|
|
/// Compile a module file for the given module in a separate compiler instance,
|
|
|
|
/// using the options provided by the importing compiler instance. Returns true
|
|
|
|
/// if the module was built without errors.
|
|
|
|
static bool compileModule(CompilerInstance &ImportingInstance,
|
|
|
|
SourceLocation ImportLoc, Module *Module,
|
|
|
|
StringRef ModuleFileName) {
|
2017-06-10 03:22:32 +08:00
|
|
|
InputKind IK(getLanguageFromOptions(ImportingInstance.getLangOpts()),
|
|
|
|
InputKind::ModuleMap);
|
|
|
|
|
|
|
|
// Get or create the module map that we'll use to build this module.
|
2018-07-31 03:24:48 +08:00
|
|
|
ModuleMap &ModMap
|
2017-06-10 03:22:32 +08:00
|
|
|
= ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
|
|
|
|
bool Result;
|
|
|
|
if (const FileEntry *ModuleMapFile =
|
|
|
|
ModMap.getContainingModuleMapFile(Module)) {
|
2018-05-02 10:25:03 +08:00
|
|
|
// Canonicalize compilation to start with the public module map. This is
|
|
|
|
// vital for submodules declarations in the private module maps to be
|
|
|
|
// correctly parsed when depending on a top level module in the public one.
|
|
|
|
if (const FileEntry *PublicMMFile = getPublicModuleMap(
|
|
|
|
ModuleMapFile, ImportingInstance.getFileManager()))
|
|
|
|
ModuleMapFile = PublicMMFile;
|
|
|
|
|
2017-06-10 03:22:32 +08:00
|
|
|
// Use the module map where this module resides.
|
|
|
|
Result = compileModuleImpl(
|
|
|
|
ImportingInstance, ImportLoc, Module->getTopLevelModuleName(),
|
|
|
|
FrontendInputFile(ModuleMapFile->getName(), IK, +Module->IsSystem),
|
|
|
|
ModMap.getModuleMapFileForUniquing(Module)->getName(),
|
|
|
|
ModuleFileName);
|
|
|
|
} else {
|
|
|
|
// FIXME: We only need to fake up an input file here as a way of
|
|
|
|
// transporting the module's directory to the module map parser. We should
|
|
|
|
// be able to do that more directly, and parse from a memory buffer without
|
|
|
|
// inventing this file.
|
|
|
|
SmallString<128> FakeModuleMapFile(Module->Directory->getName());
|
|
|
|
llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map");
|
|
|
|
|
|
|
|
std::string InferredModuleMapContent;
|
|
|
|
llvm::raw_string_ostream OS(InferredModuleMapContent);
|
|
|
|
Module->print(OS);
|
|
|
|
OS.flush();
|
|
|
|
|
|
|
|
Result = compileModuleImpl(
|
|
|
|
ImportingInstance, ImportLoc, Module->getTopLevelModuleName(),
|
|
|
|
FrontendInputFile(FakeModuleMapFile, IK, +Module->IsSystem),
|
|
|
|
ModMap.getModuleMapFileForUniquing(Module)->getName(),
|
|
|
|
ModuleFileName,
|
|
|
|
[&](CompilerInstance &Instance) {
|
|
|
|
std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
|
|
|
|
llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);
|
|
|
|
ModuleMapFile = Instance.getFileManager().getVirtualFile(
|
|
|
|
FakeModuleMapFile, InferredModuleMapContent.size(), 0);
|
|
|
|
Instance.getSourceManager().overrideFileContents(
|
|
|
|
ModuleMapFile, std::move(ModuleMapBuffer));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2017-06-10 03:22:32 +08:00
|
|
|
return Result;
|
2011-10-08 19:31:46 +08:00
|
|
|
}
|
2011-09-13 07:31:24 +08:00
|
|
|
|
clang/Modules: Refactor CompilerInstance::loadModule, NFC
Refactor the logic on CompilerInstance::loadModule and a couple of
surrounding methods in order to clarify what's going on.
- Rename ModuleLoader::loadModuleFromSource to compileModuleFromSource
and fix its documentation, since it never loads a module. It just
creates/compiles one.
- Rename one of the overloads of compileModuleImpl to compileModule,
making it more obvious which one calls the other.
- Rename compileAndLoadModule to compileModuleAndReadAST. This
clarifies the relationship between this helper and its caller,
CompilerInstance::loadModule (the old name implied the opposite
relationship). It also (correctly) indicates that more needs to be
done to load the module than this function is responsible for.
- Split findOrCompileModuleAndReadAST out of loadModule. Besides
reducing nesting for this code thanks to early returns and the like,
this refactor clarifies the logic in loadModule, particularly around
calls to ModuleMap::cacheModuleLoad and
ModuleMap::getCachedModuleLoad. findOrCompileModuleAndReadAST also
breaks early if the initial ReadAST call returns Missing or OutOfDate,
allowing the last ditch call to compileModuleAndReadAST to come at the
end of the function body.
- Additionally split out selectModuleSource, clarifying the logic
due to early returns.
- Add ModuleLoadResult::isNormal and OtherUncachedFailure, so that
loadModule knows whether to cache the result.
OtherUncachedFailure was added to keep this patch NFC, but there's
a chance that these cases were uncached by accident, through
copy/paste/modify failures. These should be audited as a
follow-up (maybe we can eliminate this case).
- Do *not* lift the setting of `ModuleLoadFailed = true` to
loadModule because there isn't a clear pattern for when it's set.
This should be reconsidered in a follow-up, in case it would be
correct to set `ModuleLoadFailed` whenever no module is returned
and the result is either Normal or OtherUncachedFailure.
- Add some header documentation where it was missing, and fix it where
it was wrong.
This should have no functionality change.
https://reviews.llvm.org/D70556
2019-11-22 02:39:55 +08:00
|
|
|
/// Compile a module in a separate compiler instance and read the AST,
|
|
|
|
/// returning true if the module compiles without errors.
|
|
|
|
///
|
|
|
|
/// Uses a lock file manager and exponential backoff to reduce the chances that
|
|
|
|
/// multiple instances will compete to create the same module. On timeout,
|
|
|
|
/// deletes the lock file in order to avoid deadlock from crashing processes or
|
|
|
|
/// bugs in the lock file manager.
|
|
|
|
static bool compileModuleAndReadAST(CompilerInstance &ImportingInstance,
|
|
|
|
SourceLocation ImportLoc,
|
|
|
|
SourceLocation ModuleNameLoc,
|
|
|
|
Module *Module, 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:
|
2019-03-10 01:33:56 +08:00
|
|
|
// ModuleCache takes care of correctness and locks are only necessary for
|
2017-03-18 08:26:18 +08:00
|
|
|
// performance. Fallback to building the module in case of any lock
|
|
|
|
// related errors.
|
|
|
|
Diags.Report(ModuleNameLoc, diag::remark_module_lock_failure)
|
2016-06-04 09:13:22 +08:00
|
|
|
<< Module->Name << Locked.getErrorMessage();
|
2017-03-18 08:26:18 +08:00
|
|
|
// Clear out any potential leftover.
|
|
|
|
Locked.unsafeRemoveLockFile();
|
Fix clang -Wimplicit-fallthrough warnings across llvm, NFC
This patch should not introduce any behavior changes. It consists of
mostly one of two changes:
1. Replacing fall through comments with the LLVM_FALLTHROUGH macro
2. Inserting 'break' before falling through into a case block consisting
of only 'break'.
We were already using this warning with GCC, but its warning behaves
slightly differently. In this patch, the following differences are
relevant:
1. GCC recognizes comments that say "fall through" as annotations, clang
doesn't
2. GCC doesn't warn on "case N: foo(); default: break;", clang does
3. GCC doesn't warn when the case contains a switch, but falls through
the outer case.
I will enable the warning separately in a follow-up patch so that it can
be cleanly reverted if necessary.
Reviewers: alexfh, rsmith, lattner, rtrieu, EricWF, bollu
Differential Revision: https://reviews.llvm.org/D53950
llvm-svn: 345882
2018-11-02 03:54:45 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
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.
|
clang/Modules: Refactor CompilerInstance::loadModule, NFC
Refactor the logic on CompilerInstance::loadModule and a couple of
surrounding methods in order to clarify what's going on.
- Rename ModuleLoader::loadModuleFromSource to compileModuleFromSource
and fix its documentation, since it never loads a module. It just
creates/compiles one.
- Rename one of the overloads of compileModuleImpl to compileModule,
making it more obvious which one calls the other.
- Rename compileAndLoadModule to compileModuleAndReadAST. This
clarifies the relationship between this helper and its caller,
CompilerInstance::loadModule (the old name implied the opposite
relationship). It also (correctly) indicates that more needs to be
done to load the module than this function is responsible for.
- Split findOrCompileModuleAndReadAST out of loadModule. Besides
reducing nesting for this code thanks to early returns and the like,
this refactor clarifies the logic in loadModule, particularly around
calls to ModuleMap::cacheModuleLoad and
ModuleMap::getCachedModuleLoad. findOrCompileModuleAndReadAST also
breaks early if the initial ReadAST call returns Missing or OutOfDate,
allowing the last ditch call to compileModuleAndReadAST to come at the
end of the function body.
- Additionally split out selectModuleSource, clarifying the logic
due to early returns.
- Add ModuleLoadResult::isNormal and OtherUncachedFailure, so that
loadModule knows whether to cache the result.
OtherUncachedFailure was added to keep this patch NFC, but there's
a chance that these cases were uncached by accident, through
copy/paste/modify failures. These should be audited as a
follow-up (maybe we can eliminate this case).
- Do *not* lift the setting of `ModuleLoadFailed = true` to
loadModule because there isn't a clear pattern for when it's set.
This should be reconsidered in a follow-up, in case it would be
correct to set `ModuleLoadFailed` whenever no module is returned
and the result is either Normal or OtherUncachedFailure.
- Add some header documentation where it was missing, and fix it where
it was wrong.
This should have no functionality change.
https://reviews.llvm.org/D70556
2019-11-22 02:39:55 +08:00
|
|
|
if (!compileModule(ImportingInstance, ModuleNameLoc, Module,
|
|
|
|
ModuleFileName)) {
|
2014-07-20 00:29:28 +08:00
|
|
|
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:
|
2019-03-10 01:33:56 +08:00
|
|
|
// Since ModuleCache takes care of correctness, we try waiting for
|
|
|
|
// another process to complete the build so clang does not do it done
|
|
|
|
// twice. If case of timeout, build it ourselves.
|
2017-03-18 08:26:18 +08:00
|
|
|
Diags.Report(ModuleNameLoc, diag::remark_module_lock_timeout)
|
2015-02-10 04:35:13 +08:00
|
|
|
<< Module->Name;
|
2018-04-06 23:14:32 +08:00
|
|
|
// Clear the lock file so that future invocations can make progress.
|
2015-02-10 04:35:13 +08:00
|
|
|
Locked.unsafeRemoveLockFile();
|
2017-03-18 08:26:18 +08:00
|
|
|
continue;
|
2015-02-10 04:35:13 +08:00
|
|
|
}
|
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 =
|
2019-11-22 10:25:03 +08:00
|
|
|
ImportingInstance.getASTReader()->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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Diagnose differences between the current definition of the given
|
2013-03-20 08:22:05 +08:00
|
|
|
/// 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();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2013-03-20 08:22:05 +08:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Write a new timestamp file with the given path.
|
2013-03-26 05:19:16 +08:00
|
|
|
static void writeTimestampFile(StringRef TimestampFile) {
|
2014-08-26 02:17:04 +08:00
|
|
|
std::error_code EC;
|
2019-08-05 13:43:48 +08:00
|
|
|
llvm::raw_fd_ostream Out(TimestampFile.str(), EC, llvm::sys::fs::OF_None);
|
2013-03-26 05:19:16 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Prune the module cache of modules that haven't been accessed in
|
2013-03-26 05:19:16 +08:00
|
|
|
/// a long time.
|
|
|
|
static void pruneModuleCache(const HeaderSearchOptions &HSOpts) {
|
2019-10-17 03:12:34 +08:00
|
|
|
llvm::sys::fs::file_status StatBuf;
|
2013-03-26 05:19:16 +08:00
|
|
|
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.
|
2019-10-17 03:12:34 +08:00
|
|
|
if (std::error_code EC = llvm::sys::fs::status(TimestampFile, StatBuf)) {
|
2013-03-26 05:19:16 +08:00
|
|
|
// If the timestamp file wasn't there, create one now.
|
2019-10-17 03:12:34 +08:00
|
|
|
if (EC == std::errc::no_such_file_or_directory) {
|
2013-03-26 05:19:16 +08:00
|
|
|
writeTimestampFile(TimestampFile);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check whether the time stamp is older than our pruning interval.
|
|
|
|
// If not, do nothing.
|
2019-10-17 03:12:34 +08:00
|
|
|
time_t TimeStampModTime =
|
|
|
|
llvm::sys::toTimeT(StatBuf.getLastModificationTime());
|
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.
|
2019-10-17 03:12:34 +08:00
|
|
|
if (llvm::sys::fs::status(File->path(), StatBuf))
|
2013-03-26 05:19:16 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
// If the file has been used recently enough, leave it there.
|
2019-10-17 03:12:34 +08:00
|
|
|
time_t FileAccessTime = llvm::sys::toTimeT(StatBuf.getLastAccessedTime());
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-22 10:25:03 +08:00
|
|
|
void CompilerInstance::createASTReader() {
|
|
|
|
if (TheASTReader)
|
2019-11-20 10:10:04 +08:00
|
|
|
return;
|
2014-04-23 20:57:01 +08:00
|
|
|
|
2019-11-20 10:10:04 +08:00
|
|
|
if (!hasASTContext())
|
|
|
|
createASTContext();
|
|
|
|
|
|
|
|
// If we're implicitly building modules but not currently recursively
|
|
|
|
// building a module, check whether we need to prune the module cache.
|
|
|
|
if (getSourceManager().getModuleBuildStack().empty() &&
|
|
|
|
!getPreprocessor().getHeaderSearchInfo().getModuleCachePath().empty() &&
|
|
|
|
getHeaderSearchOpts().ModuleCachePruneInterval > 0 &&
|
|
|
|
getHeaderSearchOpts().ModuleCachePruneAfter > 0) {
|
|
|
|
pruneModuleCache(getHeaderSearchOpts());
|
|
|
|
}
|
|
|
|
|
|
|
|
HeaderSearchOptions &HSOpts = getHeaderSearchOpts();
|
|
|
|
std::string Sysroot = HSOpts.Sysroot;
|
|
|
|
const PreprocessorOptions &PPOpts = getPreprocessorOpts();
|
|
|
|
std::unique_ptr<llvm::Timer> ReadTimer;
|
|
|
|
if (FrontendTimerGroup)
|
|
|
|
ReadTimer = std::make_unique<llvm::Timer>("reading_modules",
|
|
|
|
"Reading modules",
|
|
|
|
*FrontendTimerGroup);
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader = new ASTReader(
|
2019-11-20 10:10:04 +08:00
|
|
|
getPreprocessor(), getModuleCache(), &getASTContext(),
|
|
|
|
getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions,
|
|
|
|
Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation,
|
|
|
|
/*AllowASTWithCompilerErrors=*/false,
|
2019-11-22 10:25:03 +08:00
|
|
|
/*AllowConfigurationMismatch=*/false, HSOpts.ModulesValidateSystemHeaders,
|
2019-11-20 10:10:04 +08:00
|
|
|
HSOpts.ValidateASTInputFilesContent,
|
|
|
|
getFrontendOpts().UseGlobalModuleIndex, std::move(ReadTimer));
|
|
|
|
if (hasASTConsumer()) {
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader->setDeserializationListener(
|
|
|
|
getASTConsumer().GetASTDeserializationListener());
|
2019-11-20 10:10:04 +08:00
|
|
|
getASTContext().setASTMutationListener(
|
|
|
|
getASTConsumer().GetASTMutationListener());
|
2014-04-23 20:57:01 +08:00
|
|
|
}
|
2019-11-22 10:25:03 +08:00
|
|
|
getASTContext().setExternalSource(TheASTReader);
|
2019-11-20 10:10:04 +08:00
|
|
|
if (hasSema())
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader->InitializeSema(getSema());
|
2019-11-20 10:10:04 +08:00
|
|
|
if (hasASTConsumer())
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader->StartTranslationUnit(&getASTConsumer());
|
2019-11-20 10:10:04 +08:00
|
|
|
|
|
|
|
for (auto &Listener : DependencyCollectors)
|
2019-11-22 10:25:03 +08:00
|
|
|
Listener->attachToASTReader(*TheASTReader);
|
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)
|
2016-11-19 03:43:25 +08:00
|
|
|
Timer.init("preloading." + FileName.str(), "Preloading " + FileName.str(),
|
|
|
|
*FrontendTimerGroup);
|
2015-07-14 08:26:00 +08:00
|
|
|
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() {
|
2019-11-04 11:29:29 +08:00
|
|
|
ModuleMap &MM = CI.getPreprocessor().getHeaderSearchInfo().getModuleMap();
|
|
|
|
for (auto *II : LoadedModules)
|
|
|
|
MM.cacheModuleLoad(*II, MM.findModule(II->getName()));
|
2015-08-09 16:48:41 +08:00
|
|
|
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()
|
2016-12-06 08:40:17 +08:00
|
|
|
.findModule(II->getName())) {
|
2015-11-05 08:54:55 +08:00
|
|
|
M->HasIncompatibleModuleFile = true;
|
2016-12-06 08:40:17 +08:00
|
|
|
|
|
|
|
// Mark module as available if the only reason it was unavailable
|
|
|
|
// was missing headers.
|
|
|
|
SmallVector<Module *, 2> Stack;
|
|
|
|
Stack.push_back(M);
|
|
|
|
while (!Stack.empty()) {
|
|
|
|
Module *Current = Stack.pop_back_val();
|
|
|
|
if (Current->IsMissingRequirement) continue;
|
|
|
|
Current->IsAvailable = true;
|
|
|
|
Stack.insert(Stack.end(),
|
|
|
|
Current->submodule_begin(), Current->submodule_end());
|
|
|
|
}
|
|
|
|
}
|
2015-11-05 08:54:55 +08:00
|
|
|
}
|
|
|
|
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.
|
2019-11-22 10:25:03 +08:00
|
|
|
if (!TheASTReader)
|
|
|
|
createASTReader();
|
2015-03-18 09:42:29 +08:00
|
|
|
|
2018-05-25 04:03:51 +08:00
|
|
|
// If -Wmodule-file-config-mismatch is mapped as an error or worse, allow the
|
|
|
|
// ASTReader to diagnose it, since it can produce better errors that we can.
|
|
|
|
bool ConfigMismatchIsRecoverable =
|
|
|
|
getDiagnostics().getDiagnosticLevel(diag::warn_module_config_mismatch,
|
|
|
|
SourceLocation())
|
|
|
|
<= DiagnosticsEngine::Warning;
|
|
|
|
|
2019-08-15 07:04:18 +08:00
|
|
|
auto Listener = std::make_unique<ReadModuleNames>(*this);
|
2015-08-09 16:48:41 +08:00
|
|
|
auto &ListenerRef = *Listener;
|
2019-11-22 10:25:03 +08:00
|
|
|
ASTReader::ListenerScope ReadModuleNamesListener(*TheASTReader,
|
2015-08-09 16:48:41 +08:00
|
|
|
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.
|
2019-11-22 10:25:03 +08:00
|
|
|
switch (TheASTReader->ReadAST(
|
2018-05-25 04:03:51 +08:00
|
|
|
FileName, serialization::MK_ExplicitModule, SourceLocation(),
|
|
|
|
ConfigMismatchIsRecoverable ? ASTReader::ARR_ConfigurationMismatch : 0)) {
|
2015-10-17 07:20:19 +08:00
|
|
|
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
|
|
|
}
|
|
|
|
|
clang/Modules: Refactor CompilerInstance::loadModule, NFC
Refactor the logic on CompilerInstance::loadModule and a couple of
surrounding methods in order to clarify what's going on.
- Rename ModuleLoader::loadModuleFromSource to compileModuleFromSource
and fix its documentation, since it never loads a module. It just
creates/compiles one.
- Rename one of the overloads of compileModuleImpl to compileModule,
making it more obvious which one calls the other.
- Rename compileAndLoadModule to compileModuleAndReadAST. This
clarifies the relationship between this helper and its caller,
CompilerInstance::loadModule (the old name implied the opposite
relationship). It also (correctly) indicates that more needs to be
done to load the module than this function is responsible for.
- Split findOrCompileModuleAndReadAST out of loadModule. Besides
reducing nesting for this code thanks to early returns and the like,
this refactor clarifies the logic in loadModule, particularly around
calls to ModuleMap::cacheModuleLoad and
ModuleMap::getCachedModuleLoad. findOrCompileModuleAndReadAST also
breaks early if the initial ReadAST call returns Missing or OutOfDate,
allowing the last ditch call to compileModuleAndReadAST to come at the
end of the function body.
- Additionally split out selectModuleSource, clarifying the logic
due to early returns.
- Add ModuleLoadResult::isNormal and OtherUncachedFailure, so that
loadModule knows whether to cache the result.
OtherUncachedFailure was added to keep this patch NFC, but there's
a chance that these cases were uncached by accident, through
copy/paste/modify failures. These should be audited as a
follow-up (maybe we can eliminate this case).
- Do *not* lift the setting of `ModuleLoadFailed = true` to
loadModule because there isn't a clear pattern for when it's set.
This should be reconsidered in a follow-up, in case it would be
correct to set `ModuleLoadFailed` whenever no module is returned
and the result is either Normal or OtherUncachedFailure.
- Add some header documentation where it was missing, and fix it where
it was wrong.
This should have no functionality change.
https://reviews.llvm.org/D70556
2019-11-22 02:39:55 +08:00
|
|
|
namespace {
|
|
|
|
enum ModuleSource {
|
|
|
|
MS_ModuleNotFound,
|
|
|
|
MS_ModuleCache,
|
|
|
|
MS_PrebuiltModulePath,
|
|
|
|
MS_ModuleBuildPragma
|
|
|
|
};
|
|
|
|
} // end namespace
|
|
|
|
|
|
|
|
/// Select a source for loading the named module and compute the filename to
|
|
|
|
/// load it from.
|
|
|
|
static ModuleSource
|
|
|
|
selectModuleSource(Module *M, StringRef ModuleName, std::string &ModuleFilename,
|
|
|
|
const std::map<std::string, std::string> &BuiltModules,
|
|
|
|
HeaderSearch &HS) {
|
|
|
|
assert(ModuleFilename.empty() && "Already has a module source?");
|
|
|
|
|
|
|
|
// Check to see if the module has been built as part of this compilation
|
|
|
|
// via a module build pragma.
|
2020-01-29 03:23:46 +08:00
|
|
|
auto BuiltModuleIt = BuiltModules.find(std::string(ModuleName));
|
clang/Modules: Refactor CompilerInstance::loadModule, NFC
Refactor the logic on CompilerInstance::loadModule and a couple of
surrounding methods in order to clarify what's going on.
- Rename ModuleLoader::loadModuleFromSource to compileModuleFromSource
and fix its documentation, since it never loads a module. It just
creates/compiles one.
- Rename one of the overloads of compileModuleImpl to compileModule,
making it more obvious which one calls the other.
- Rename compileAndLoadModule to compileModuleAndReadAST. This
clarifies the relationship between this helper and its caller,
CompilerInstance::loadModule (the old name implied the opposite
relationship). It also (correctly) indicates that more needs to be
done to load the module than this function is responsible for.
- Split findOrCompileModuleAndReadAST out of loadModule. Besides
reducing nesting for this code thanks to early returns and the like,
this refactor clarifies the logic in loadModule, particularly around
calls to ModuleMap::cacheModuleLoad and
ModuleMap::getCachedModuleLoad. findOrCompileModuleAndReadAST also
breaks early if the initial ReadAST call returns Missing or OutOfDate,
allowing the last ditch call to compileModuleAndReadAST to come at the
end of the function body.
- Additionally split out selectModuleSource, clarifying the logic
due to early returns.
- Add ModuleLoadResult::isNormal and OtherUncachedFailure, so that
loadModule knows whether to cache the result.
OtherUncachedFailure was added to keep this patch NFC, but there's
a chance that these cases were uncached by accident, through
copy/paste/modify failures. These should be audited as a
follow-up (maybe we can eliminate this case).
- Do *not* lift the setting of `ModuleLoadFailed = true` to
loadModule because there isn't a clear pattern for when it's set.
This should be reconsidered in a follow-up, in case it would be
correct to set `ModuleLoadFailed` whenever no module is returned
and the result is either Normal or OtherUncachedFailure.
- Add some header documentation where it was missing, and fix it where
it was wrong.
This should have no functionality change.
https://reviews.llvm.org/D70556
2019-11-22 02:39:55 +08:00
|
|
|
if (BuiltModuleIt != BuiltModules.end()) {
|
|
|
|
ModuleFilename = BuiltModuleIt->second;
|
|
|
|
return MS_ModuleBuildPragma;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to load the module from the prebuilt module path.
|
|
|
|
const HeaderSearchOptions &HSOpts = HS.getHeaderSearchOpts();
|
|
|
|
if (!HSOpts.PrebuiltModuleFiles.empty() ||
|
|
|
|
!HSOpts.PrebuiltModulePaths.empty()) {
|
|
|
|
ModuleFilename = HS.getPrebuiltModuleFileName(ModuleName);
|
|
|
|
if (!ModuleFilename.empty())
|
|
|
|
return MS_PrebuiltModulePath;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to load the module from the module cache.
|
|
|
|
if (M) {
|
|
|
|
ModuleFilename = HS.getCachedModuleFileName(M);
|
|
|
|
return MS_ModuleCache;
|
|
|
|
}
|
|
|
|
|
|
|
|
return MS_ModuleNotFound;
|
|
|
|
}
|
|
|
|
|
|
|
|
ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
|
|
|
|
StringRef ModuleName, SourceLocation ImportLoc,
|
|
|
|
SourceLocation ModuleNameLoc, bool IsInclusionDirective) {
|
|
|
|
// Search for a module with the given name.
|
|
|
|
HeaderSearch &HS = PP->getHeaderSearchInfo();
|
|
|
|
Module *M = HS.lookupModule(ModuleName, true, !IsInclusionDirective);
|
|
|
|
|
|
|
|
// Select the source and filename for loading the named module.
|
|
|
|
std::string ModuleFilename;
|
|
|
|
ModuleSource Source =
|
|
|
|
selectModuleSource(M, ModuleName, ModuleFilename, BuiltModules, HS);
|
|
|
|
if (Source == MS_ModuleNotFound) {
|
|
|
|
// We can't find a module, error out here.
|
|
|
|
getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
|
|
|
|
<< ModuleName << SourceRange(ImportLoc, ModuleNameLoc);
|
|
|
|
ModuleBuildFailed = true;
|
|
|
|
// FIXME: Why is this not cached?
|
|
|
|
return ModuleLoadResult::OtherUncachedFailure;
|
|
|
|
}
|
|
|
|
if (ModuleFilename.empty()) {
|
|
|
|
if (M && M->HasIncompatibleModuleFile) {
|
|
|
|
// We tried and failed to load a module file for this module. Fall
|
|
|
|
// back to textual inclusion for its headers.
|
|
|
|
return ModuleLoadResult::ConfigMismatch;
|
|
|
|
}
|
|
|
|
|
|
|
|
getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled)
|
|
|
|
<< ModuleName;
|
|
|
|
ModuleBuildFailed = true;
|
|
|
|
// FIXME: Why is this not cached?
|
|
|
|
return ModuleLoadResult::OtherUncachedFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create an ASTReader on demand.
|
2019-11-22 10:25:03 +08:00
|
|
|
if (!getASTReader())
|
|
|
|
createASTReader();
|
clang/Modules: Refactor CompilerInstance::loadModule, NFC
Refactor the logic on CompilerInstance::loadModule and a couple of
surrounding methods in order to clarify what's going on.
- Rename ModuleLoader::loadModuleFromSource to compileModuleFromSource
and fix its documentation, since it never loads a module. It just
creates/compiles one.
- Rename one of the overloads of compileModuleImpl to compileModule,
making it more obvious which one calls the other.
- Rename compileAndLoadModule to compileModuleAndReadAST. This
clarifies the relationship between this helper and its caller,
CompilerInstance::loadModule (the old name implied the opposite
relationship). It also (correctly) indicates that more needs to be
done to load the module than this function is responsible for.
- Split findOrCompileModuleAndReadAST out of loadModule. Besides
reducing nesting for this code thanks to early returns and the like,
this refactor clarifies the logic in loadModule, particularly around
calls to ModuleMap::cacheModuleLoad and
ModuleMap::getCachedModuleLoad. findOrCompileModuleAndReadAST also
breaks early if the initial ReadAST call returns Missing or OutOfDate,
allowing the last ditch call to compileModuleAndReadAST to come at the
end of the function body.
- Additionally split out selectModuleSource, clarifying the logic
due to early returns.
- Add ModuleLoadResult::isNormal and OtherUncachedFailure, so that
loadModule knows whether to cache the result.
OtherUncachedFailure was added to keep this patch NFC, but there's
a chance that these cases were uncached by accident, through
copy/paste/modify failures. These should be audited as a
follow-up (maybe we can eliminate this case).
- Do *not* lift the setting of `ModuleLoadFailed = true` to
loadModule because there isn't a clear pattern for when it's set.
This should be reconsidered in a follow-up, in case it would be
correct to set `ModuleLoadFailed` whenever no module is returned
and the result is either Normal or OtherUncachedFailure.
- Add some header documentation where it was missing, and fix it where
it was wrong.
This should have no functionality change.
https://reviews.llvm.org/D70556
2019-11-22 02:39:55 +08:00
|
|
|
|
|
|
|
// Time how long it takes to load the module.
|
|
|
|
llvm::Timer Timer;
|
|
|
|
if (FrontendTimerGroup)
|
|
|
|
Timer.init("loading." + ModuleFilename, "Loading " + ModuleFilename,
|
|
|
|
*FrontendTimerGroup);
|
|
|
|
llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
|
|
|
|
llvm::TimeTraceScope TimeScope("Module Load", ModuleName);
|
|
|
|
|
|
|
|
// Try to load the module file. If we are not trying to load from the
|
|
|
|
// module cache, we don't know how to rebuild modules.
|
|
|
|
unsigned ARRFlags = Source == MS_ModuleCache
|
|
|
|
? ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing
|
|
|
|
: Source == MS_PrebuiltModulePath
|
|
|
|
? 0
|
|
|
|
: ASTReader::ARR_ConfigurationMismatch;
|
2019-11-22 10:25:03 +08:00
|
|
|
switch (getASTReader()->ReadAST(ModuleFilename,
|
|
|
|
Source == MS_PrebuiltModulePath
|
|
|
|
? serialization::MK_PrebuiltModule
|
|
|
|
: Source == MS_ModuleBuildPragma
|
|
|
|
? serialization::MK_ExplicitModule
|
|
|
|
: serialization::MK_ImplicitModule,
|
|
|
|
ImportLoc, ARRFlags)) {
|
clang/Modules: Refactor CompilerInstance::loadModule, NFC
Refactor the logic on CompilerInstance::loadModule and a couple of
surrounding methods in order to clarify what's going on.
- Rename ModuleLoader::loadModuleFromSource to compileModuleFromSource
and fix its documentation, since it never loads a module. It just
creates/compiles one.
- Rename one of the overloads of compileModuleImpl to compileModule,
making it more obvious which one calls the other.
- Rename compileAndLoadModule to compileModuleAndReadAST. This
clarifies the relationship between this helper and its caller,
CompilerInstance::loadModule (the old name implied the opposite
relationship). It also (correctly) indicates that more needs to be
done to load the module than this function is responsible for.
- Split findOrCompileModuleAndReadAST out of loadModule. Besides
reducing nesting for this code thanks to early returns and the like,
this refactor clarifies the logic in loadModule, particularly around
calls to ModuleMap::cacheModuleLoad and
ModuleMap::getCachedModuleLoad. findOrCompileModuleAndReadAST also
breaks early if the initial ReadAST call returns Missing or OutOfDate,
allowing the last ditch call to compileModuleAndReadAST to come at the
end of the function body.
- Additionally split out selectModuleSource, clarifying the logic
due to early returns.
- Add ModuleLoadResult::isNormal and OtherUncachedFailure, so that
loadModule knows whether to cache the result.
OtherUncachedFailure was added to keep this patch NFC, but there's
a chance that these cases were uncached by accident, through
copy/paste/modify failures. These should be audited as a
follow-up (maybe we can eliminate this case).
- Do *not* lift the setting of `ModuleLoadFailed = true` to
loadModule because there isn't a clear pattern for when it's set.
This should be reconsidered in a follow-up, in case it would be
correct to set `ModuleLoadFailed` whenever no module is returned
and the result is either Normal or OtherUncachedFailure.
- Add some header documentation where it was missing, and fix it where
it was wrong.
This should have no functionality change.
https://reviews.llvm.org/D70556
2019-11-22 02:39:55 +08:00
|
|
|
case ASTReader::Success: {
|
|
|
|
if (M)
|
|
|
|
return M;
|
|
|
|
assert(Source != MS_ModuleCache &&
|
|
|
|
"missing module, but file loaded from cache");
|
|
|
|
|
|
|
|
// A prebuilt module is indexed as a ModuleFile; the Module does not exist
|
|
|
|
// until the first call to ReadAST. Look it up now.
|
|
|
|
M = HS.lookupModule(ModuleName, true, !IsInclusionDirective);
|
|
|
|
|
|
|
|
// Check whether M refers to the file in the prebuilt module path.
|
|
|
|
if (M && M->getASTFile())
|
|
|
|
if (auto ModuleFile = FileMgr->getFile(ModuleFilename))
|
|
|
|
if (*ModuleFile == M->getASTFile())
|
|
|
|
return M;
|
|
|
|
|
|
|
|
ModuleBuildFailed = true;
|
|
|
|
getDiagnostics().Report(ModuleNameLoc, diag::err_module_prebuilt)
|
|
|
|
<< ModuleName;
|
|
|
|
return ModuleLoadResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
case ASTReader::OutOfDate:
|
|
|
|
case ASTReader::Missing:
|
|
|
|
// The most interesting case.
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ASTReader::ConfigurationMismatch:
|
|
|
|
if (Source == MS_PrebuiltModulePath)
|
|
|
|
// FIXME: We shouldn't be setting HadFatalFailure below if we only
|
|
|
|
// produce a warning here!
|
|
|
|
getDiagnostics().Report(SourceLocation(),
|
|
|
|
diag::warn_module_config_mismatch)
|
|
|
|
<< ModuleFilename;
|
|
|
|
// Fall through to error out.
|
|
|
|
LLVM_FALLTHROUGH;
|
|
|
|
case ASTReader::VersionMismatch:
|
|
|
|
case ASTReader::HadErrors:
|
|
|
|
// FIXME: Should this set ModuleBuildFailed = true?
|
|
|
|
ModuleLoader::HadFatalFailure = true;
|
|
|
|
// FIXME: The ASTReader will already have complained, but can we shoehorn
|
|
|
|
// that diagnostic information into a more useful form?
|
|
|
|
return ModuleLoadResult();
|
|
|
|
|
|
|
|
case ASTReader::Failure:
|
|
|
|
// FIXME: Should this set ModuleBuildFailed = true?
|
|
|
|
ModuleLoader::HadFatalFailure = true;
|
|
|
|
return ModuleLoadResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReadAST returned Missing or OutOfDate.
|
|
|
|
if (Source != MS_ModuleCache) {
|
|
|
|
// We don't know the desired configuration for this module and don't
|
|
|
|
// necessarily even have a module map. Since ReadAST already produces
|
|
|
|
// diagnostics for these two cases, we simply error out here.
|
|
|
|
ModuleBuildFailed = true;
|
|
|
|
return ModuleLoadResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
// The module file is missing or out-of-date. Build it.
|
|
|
|
assert(M && "missing module, but trying to compile for cache");
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
// FIXME: Should this set ModuleBuildFailed = true?
|
|
|
|
// FIXME: Why is this not cached?
|
|
|
|
return ModuleLoadResult::OtherUncachedFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
ModuleBuildFailed = true;
|
|
|
|
// FIXME: Why is this not cached?
|
|
|
|
return ModuleLoadResult::OtherUncachedFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Try to compile and then read the AST.
|
|
|
|
if (!compileModuleAndReadAST(*this, ImportLoc, ModuleNameLoc, M,
|
|
|
|
ModuleFilename)) {
|
|
|
|
assert(getDiagnostics().hasErrorOccurred() &&
|
|
|
|
"undiagnosed error in compileModuleAndReadAST");
|
|
|
|
if (getPreprocessorOpts().FailedModules)
|
|
|
|
getPreprocessorOpts().FailedModules->addFailed(ModuleName);
|
|
|
|
ModuleBuildFailed = true;
|
|
|
|
// FIXME: Why is this not cached?
|
|
|
|
return ModuleLoadResult::OtherUncachedFailure;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Okay, we've rebuilt and now loaded the module.
|
|
|
|
return M;
|
|
|
|
}
|
|
|
|
|
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.
|
2018-09-15 09:21:15 +08:00
|
|
|
StringRef ModuleName = Path[0].first->getName();
|
2013-10-19 06:48:20 +08:00
|
|
|
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)
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader->makeModuleVisible(LastModuleImportResult, Visibility,
|
|
|
|
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
|
|
|
|
2011-11-30 12:03:44 +08:00
|
|
|
// If we don't already have information on this module, load the module now.
|
2019-11-05 03:10:09 +08:00
|
|
|
Module *Module = nullptr;
|
2019-11-04 11:29:29 +08:00
|
|
|
ModuleMap &MM = getPreprocessor().getHeaderSearchInfo().getModuleMap();
|
2019-11-05 03:10:09 +08:00
|
|
|
if (auto MaybeModule = MM.getCachedModuleLoad(*Path[0].first)) {
|
|
|
|
// Use the cached result, which may be nullptr.
|
|
|
|
Module = *MaybeModule;
|
2016-02-20 06:25:36 +08:00
|
|
|
} else if (ModuleName == getLangOpts().CurrentModule) {
|
2018-07-19 07:21:19 +08:00
|
|
|
// This is the module we're building.
|
|
|
|
Module = PP->getHeaderSearchInfo().lookupModule(
|
|
|
|
ModuleName, /*AllowSearch*/ true,
|
|
|
|
/*AllowExtraModuleMapSearch*/ !IsInclusionDirective);
|
2017-08-31 14:26:43 +08:00
|
|
|
/// FIXME: perhaps we should (a) look for a module using the module name
|
|
|
|
// to file map (PrebuiltModuleFiles) and (b) diagnose if still not found?
|
|
|
|
//if (Module == nullptr) {
|
|
|
|
// getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
|
|
|
|
// << ModuleName;
|
|
|
|
// ModuleBuildFailed = true;
|
|
|
|
// return ModuleLoadResult();
|
|
|
|
//}
|
2019-11-04 11:29:29 +08:00
|
|
|
MM.cacheModuleLoad(*Path[0].first, Module);
|
2011-12-09 01:01:29 +08:00
|
|
|
} else {
|
clang/Modules: Refactor CompilerInstance::loadModule, NFC
Refactor the logic on CompilerInstance::loadModule and a couple of
surrounding methods in order to clarify what's going on.
- Rename ModuleLoader::loadModuleFromSource to compileModuleFromSource
and fix its documentation, since it never loads a module. It just
creates/compiles one.
- Rename one of the overloads of compileModuleImpl to compileModule,
making it more obvious which one calls the other.
- Rename compileAndLoadModule to compileModuleAndReadAST. This
clarifies the relationship between this helper and its caller,
CompilerInstance::loadModule (the old name implied the opposite
relationship). It also (correctly) indicates that more needs to be
done to load the module than this function is responsible for.
- Split findOrCompileModuleAndReadAST out of loadModule. Besides
reducing nesting for this code thanks to early returns and the like,
this refactor clarifies the logic in loadModule, particularly around
calls to ModuleMap::cacheModuleLoad and
ModuleMap::getCachedModuleLoad. findOrCompileModuleAndReadAST also
breaks early if the initial ReadAST call returns Missing or OutOfDate,
allowing the last ditch call to compileModuleAndReadAST to come at the
end of the function body.
- Additionally split out selectModuleSource, clarifying the logic
due to early returns.
- Add ModuleLoadResult::isNormal and OtherUncachedFailure, so that
loadModule knows whether to cache the result.
OtherUncachedFailure was added to keep this patch NFC, but there's
a chance that these cases were uncached by accident, through
copy/paste/modify failures. These should be audited as a
follow-up (maybe we can eliminate this case).
- Do *not* lift the setting of `ModuleLoadFailed = true` to
loadModule because there isn't a clear pattern for when it's set.
This should be reconsidered in a follow-up, in case it would be
correct to set `ModuleLoadFailed` whenever no module is returned
and the result is either Normal or OtherUncachedFailure.
- Add some header documentation where it was missing, and fix it where
it was wrong.
This should have no functionality change.
https://reviews.llvm.org/D70556
2019-11-22 02:39:55 +08:00
|
|
|
ModuleLoadResult Result = findOrCompileModuleAndReadAST(
|
|
|
|
ModuleName, ImportLoc, ModuleNameLoc, IsInclusionDirective);
|
|
|
|
// FIXME: Can we pull 'ModuleBuildFailed = true' out of the return
|
|
|
|
// sequences for findOrCompileModuleAndReadAST and do it here (as long as
|
|
|
|
// the result is not a config mismatch)? See FIXMEs there.
|
|
|
|
if (!Result.isNormal())
|
|
|
|
return Result;
|
|
|
|
Module = Result;
|
2019-11-04 11:29:29 +08:00
|
|
|
MM.cacheModuleLoad(*Path[0].first, Module);
|
clang/Modules: Refactor CompilerInstance::loadModule, NFC
Refactor the logic on CompilerInstance::loadModule and a couple of
surrounding methods in order to clarify what's going on.
- Rename ModuleLoader::loadModuleFromSource to compileModuleFromSource
and fix its documentation, since it never loads a module. It just
creates/compiles one.
- Rename one of the overloads of compileModuleImpl to compileModule,
making it more obvious which one calls the other.
- Rename compileAndLoadModule to compileModuleAndReadAST. This
clarifies the relationship between this helper and its caller,
CompilerInstance::loadModule (the old name implied the opposite
relationship). It also (correctly) indicates that more needs to be
done to load the module than this function is responsible for.
- Split findOrCompileModuleAndReadAST out of loadModule. Besides
reducing nesting for this code thanks to early returns and the like,
this refactor clarifies the logic in loadModule, particularly around
calls to ModuleMap::cacheModuleLoad and
ModuleMap::getCachedModuleLoad. findOrCompileModuleAndReadAST also
breaks early if the initial ReadAST call returns Missing or OutOfDate,
allowing the last ditch call to compileModuleAndReadAST to come at the
end of the function body.
- Additionally split out selectModuleSource, clarifying the logic
due to early returns.
- Add ModuleLoadResult::isNormal and OtherUncachedFailure, so that
loadModule knows whether to cache the result.
OtherUncachedFailure was added to keep this patch NFC, but there's
a chance that these cases were uncached by accident, through
copy/paste/modify failures. These should be audited as a
follow-up (maybe we can eliminate this case).
- Do *not* lift the setting of `ModuleLoadFailed = true` to
loadModule because there isn't a clear pattern for when it's set.
This should be reconsidered in a follow-up, in case it would be
correct to set `ModuleLoadFailed` whenever no module is returned
and the result is either Normal or OtherUncachedFailure.
- Add some header documentation where it was missing, and fix it where
it was wrong.
This should have no functionality change.
https://reviews.llvm.org/D70556
2019-11-22 02:39:55 +08:00
|
|
|
if (!Module)
|
|
|
|
return Module;
|
2011-08-27 07:56:07 +08:00
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
clang/Modules: Refactor CompilerInstance::loadModule, NFC
Refactor the logic on CompilerInstance::loadModule and a couple of
surrounding methods in order to clarify what's going on.
- Rename ModuleLoader::loadModuleFromSource to compileModuleFromSource
and fix its documentation, since it never loads a module. It just
creates/compiles one.
- Rename one of the overloads of compileModuleImpl to compileModule,
making it more obvious which one calls the other.
- Rename compileAndLoadModule to compileModuleAndReadAST. This
clarifies the relationship between this helper and its caller,
CompilerInstance::loadModule (the old name implied the opposite
relationship). It also (correctly) indicates that more needs to be
done to load the module than this function is responsible for.
- Split findOrCompileModuleAndReadAST out of loadModule. Besides
reducing nesting for this code thanks to early returns and the like,
this refactor clarifies the logic in loadModule, particularly around
calls to ModuleMap::cacheModuleLoad and
ModuleMap::getCachedModuleLoad. findOrCompileModuleAndReadAST also
breaks early if the initial ReadAST call returns Missing or OutOfDate,
allowing the last ditch call to compileModuleAndReadAST to come at the
end of the function body.
- Additionally split out selectModuleSource, clarifying the logic
due to early returns.
- Add ModuleLoadResult::isNormal and OtherUncachedFailure, so that
loadModule knows whether to cache the result.
OtherUncachedFailure was added to keep this patch NFC, but there's
a chance that these cases were uncached by accident, through
copy/paste/modify failures. These should be audited as a
follow-up (maybe we can eliminate this case).
- Do *not* lift the setting of `ModuleLoadFailed = true` to
loadModule because there isn't a clear pattern for when it's set.
This should be reconsidered in a follow-up, in case it would be
correct to set `ModuleLoadFailed` whenever no module is returned
and the result is either Normal or OtherUncachedFailure.
- Add some header documentation where it was missing, and fix it where
it was wrong.
This should have no functionality change.
https://reviews.llvm.org/D70556
2019-11-22 02:39:55 +08:00
|
|
|
// If we never found the module, fail. Otherwise, verify the module and link
|
|
|
|
// it up.
|
2011-12-01 01:33:56 +08:00
|
|
|
if (!Module)
|
2012-11-30 07:55:25 +08:00
|
|
|
return ModuleLoadResult();
|
2017-06-10 03:22:32 +08:00
|
|
|
|
2011-11-30 12:03:44 +08:00
|
|
|
// Verify that the rest of the module path actually corresponds to
|
|
|
|
// a submodule.
|
2017-12-22 13:04:43 +08:00
|
|
|
bool MapPrivateSubModToTopLevel = false;
|
2018-09-15 09:21:15 +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);
|
2018-02-13 07:43:21 +08:00
|
|
|
|
|
|
|
// If the user is requesting Foo.Private and it doesn't exist, try to
|
|
|
|
// match Foo_Private and emit a warning asking for the user to write
|
|
|
|
// @import Foo_Private instead. FIXME: remove this when existing clients
|
|
|
|
// migrate off of Foo.Private syntax.
|
|
|
|
if (!Sub && PP->getLangOpts().ImplicitModules && Name == "Private" &&
|
|
|
|
Module == Module->getTopLevelModule()) {
|
|
|
|
SmallString<128> PrivateModule(Module->Name);
|
|
|
|
PrivateModule.append("_Private");
|
|
|
|
|
|
|
|
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> PrivPath;
|
|
|
|
auto &II = PP->getIdentifierTable().get(
|
|
|
|
PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
|
|
|
|
PrivPath.push_back(std::make_pair(&II, Path[0].second));
|
|
|
|
|
2018-07-19 07:21:19 +08:00
|
|
|
if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, true,
|
|
|
|
!IsInclusionDirective))
|
2018-02-13 07:43:21 +08:00
|
|
|
Sub =
|
|
|
|
loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective);
|
|
|
|
if (Sub) {
|
|
|
|
MapPrivateSubModToTopLevel = true;
|
|
|
|
if (!getDiagnostics().isIgnored(
|
|
|
|
diag::warn_no_priv_submodule_use_toplevel, ImportLoc)) {
|
|
|
|
getDiagnostics().Report(Path[I].second,
|
|
|
|
diag::warn_no_priv_submodule_use_toplevel)
|
|
|
|
<< Path[I].first << Module->getFullModuleName() << PrivateModule
|
|
|
|
<< SourceRange(Path[0].second, Path[I].second)
|
|
|
|
<< FixItHint::CreateReplacement(SourceRange(Path[0].second),
|
|
|
|
PrivateModule);
|
|
|
|
getDiagnostics().Report(Sub->DefinitionLoc,
|
|
|
|
diag::note_private_top_level_defined);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-31 03:24:48 +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)();
|
2018-07-31 03:24:48 +08:00
|
|
|
|
|
|
|
for (clang::Module::submodule_iterator J = Module->submodule_begin(),
|
2012-01-05 07:32:19 +08:00
|
|
|
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;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-01-05 07:32:19 +08:00
|
|
|
Best.push_back((*J)->Name);
|
2011-11-30 12:03:44 +08:00
|
|
|
}
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2011-11-30 12:03:44 +08:00
|
|
|
// If there was a clear winner, user it.
|
|
|
|
if (Best.size() == 1) {
|
2018-07-31 03:24:48 +08:00
|
|
|
getDiagnostics().Report(Path[I].second,
|
2011-11-30 12:03:44 +08:00
|
|
|
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]);
|
2018-07-31 03:24:48 +08:00
|
|
|
|
2012-01-05 07:32:19 +08:00
|
|
|
Sub = Module->findSubmodule(Best[0]);
|
2011-11-30 12:03:44 +08:00
|
|
|
}
|
|
|
|
}
|
2017-12-22 13:04:43 +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;
|
|
|
|
}
|
2018-07-31 03:24:48 +08:00
|
|
|
|
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) {
|
2017-12-22 13:04:43 +08:00
|
|
|
if (!Module->IsFromModuleFile && !MapPrivateSubModToTopLevel) {
|
2011-12-20 08:28:52 +08:00
|
|
|
// 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
|
|
|
|
2016-12-06 08:40:17 +08:00
|
|
|
return ModuleLoadResult::MissingExpected;
|
2011-12-20 08:28:52 +08:00
|
|
|
}
|
2011-12-31 12:05:44 +08:00
|
|
|
|
|
|
|
// Check whether this module is available.
|
2017-06-06 02:57:56 +08:00
|
|
|
if (Preprocessor::checkModuleIsAvailable(getLangOpts(), getTarget(),
|
|
|
|
getDiagnostics(), Module)) {
|
|
|
|
getDiagnostics().Report(ImportLoc, diag::note_module_import_here)
|
|
|
|
<< 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
|
|
|
}
|
|
|
|
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader->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);
|
|
|
|
}
|
|
|
|
|
2018-04-17 03:42:32 +08:00
|
|
|
// Resolve any remaining module using export_as for this one.
|
|
|
|
getPreprocessor()
|
|
|
|
.getHeaderSearchInfo()
|
|
|
|
.getModuleMap()
|
|
|
|
.resolveLinkAsDependencies(TopModule);
|
|
|
|
|
2011-11-30 12:26:53 +08:00
|
|
|
LastModuleImportLoc = ImportLoc;
|
2016-12-06 08:40:17 +08:00
|
|
|
LastModuleImportResult = ModuleLoadResult(Module);
|
2012-11-30 07:55:25 +08:00
|
|
|
return LastModuleImportResult;
|
2011-08-27 07:56:07 +08:00
|
|
|
}
|
2013-01-12 09:29:50 +08:00
|
|
|
|
clang/Modules: Refactor CompilerInstance::loadModule, NFC
Refactor the logic on CompilerInstance::loadModule and a couple of
surrounding methods in order to clarify what's going on.
- Rename ModuleLoader::loadModuleFromSource to compileModuleFromSource
and fix its documentation, since it never loads a module. It just
creates/compiles one.
- Rename one of the overloads of compileModuleImpl to compileModule,
making it more obvious which one calls the other.
- Rename compileAndLoadModule to compileModuleAndReadAST. This
clarifies the relationship between this helper and its caller,
CompilerInstance::loadModule (the old name implied the opposite
relationship). It also (correctly) indicates that more needs to be
done to load the module than this function is responsible for.
- Split findOrCompileModuleAndReadAST out of loadModule. Besides
reducing nesting for this code thanks to early returns and the like,
this refactor clarifies the logic in loadModule, particularly around
calls to ModuleMap::cacheModuleLoad and
ModuleMap::getCachedModuleLoad. findOrCompileModuleAndReadAST also
breaks early if the initial ReadAST call returns Missing or OutOfDate,
allowing the last ditch call to compileModuleAndReadAST to come at the
end of the function body.
- Additionally split out selectModuleSource, clarifying the logic
due to early returns.
- Add ModuleLoadResult::isNormal and OtherUncachedFailure, so that
loadModule knows whether to cache the result.
OtherUncachedFailure was added to keep this patch NFC, but there's
a chance that these cases were uncached by accident, through
copy/paste/modify failures. These should be audited as a
follow-up (maybe we can eliminate this case).
- Do *not* lift the setting of `ModuleLoadFailed = true` to
loadModule because there isn't a clear pattern for when it's set.
This should be reconsidered in a follow-up, in case it would be
correct to set `ModuleLoadFailed` whenever no module is returned
and the result is either Normal or OtherUncachedFailure.
- Add some header documentation where it was missing, and fix it where
it was wrong.
This should have no functionality change.
https://reviews.llvm.org/D70556
2019-11-22 02:39:55 +08:00
|
|
|
void CompilerInstance::createModuleFromSource(SourceLocation ImportLoc,
|
|
|
|
StringRef ModuleName,
|
|
|
|
StringRef Source) {
|
2017-06-20 07:09:36 +08:00
|
|
|
// Avoid creating filenames with special characters.
|
|
|
|
SmallString<128> CleanModuleName(ModuleName);
|
|
|
|
for (auto &C : CleanModuleName)
|
|
|
|
if (!isAlphanumeric(C))
|
|
|
|
C = '_';
|
|
|
|
|
2017-06-10 03:22:32 +08:00
|
|
|
// FIXME: Using a randomized filename here means that our intermediate .pcm
|
|
|
|
// output is nondeterministic (as .pcm files refer to each other by name).
|
|
|
|
// Can this affect the output in any way?
|
|
|
|
SmallString<128> ModuleFileName;
|
|
|
|
if (std::error_code EC = llvm::sys::fs::createTemporaryFile(
|
2017-06-20 07:09:36 +08:00
|
|
|
CleanModuleName, "pcm", ModuleFileName)) {
|
2017-06-10 03:22:32 +08:00
|
|
|
getDiagnostics().Report(ImportLoc, diag::err_fe_unable_to_open_output)
|
|
|
|
<< ModuleFileName << EC.message();
|
|
|
|
return;
|
|
|
|
}
|
2017-06-20 07:09:36 +08:00
|
|
|
std::string ModuleMapFileName = (CleanModuleName + ".map").str();
|
2017-06-10 03:22:32 +08:00
|
|
|
|
|
|
|
FrontendInputFile Input(
|
|
|
|
ModuleMapFileName,
|
|
|
|
InputKind(getLanguageFromOptions(*Invocation->getLangOpts()),
|
|
|
|
InputKind::ModuleMap, /*Preprocessed*/true));
|
|
|
|
|
|
|
|
std::string NullTerminatedSource(Source.str());
|
|
|
|
|
|
|
|
auto PreBuildStep = [&](CompilerInstance &Other) {
|
|
|
|
// Create a virtual file containing our desired source.
|
|
|
|
// FIXME: We shouldn't need to do this.
|
|
|
|
const FileEntry *ModuleMapFile = Other.getFileManager().getVirtualFile(
|
|
|
|
ModuleMapFileName, NullTerminatedSource.size(), 0);
|
|
|
|
Other.getSourceManager().overrideFileContents(
|
|
|
|
ModuleMapFile,
|
|
|
|
llvm::MemoryBuffer::getMemBuffer(NullTerminatedSource.c_str()));
|
|
|
|
|
|
|
|
Other.BuiltModules = std::move(BuiltModules);
|
2017-06-10 05:24:02 +08:00
|
|
|
Other.DeleteBuiltModules = false;
|
2017-06-10 03:22:32 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
auto PostBuildStep = [this](CompilerInstance &Other) {
|
|
|
|
BuiltModules = std::move(Other.BuiltModules);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Build the module, inheriting any modules that we've built locally.
|
|
|
|
if (compileModuleImpl(*this, ImportLoc, ModuleName, Input, StringRef(),
|
|
|
|
ModuleFileName, PreBuildStep, PostBuildStep)) {
|
2020-01-29 03:23:46 +08:00
|
|
|
BuiltModules[std::string(ModuleName)] = std::string(ModuleFileName.str());
|
2017-06-10 03:22:32 +08:00
|
|
|
llvm::sys::RemoveFileOnSignal(ModuleFileName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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) {
|
2019-11-22 10:25:03 +08:00
|
|
|
if (!TheASTReader)
|
|
|
|
createASTReader();
|
|
|
|
if (!TheASTReader)
|
2015-05-16 04:05:43 +08:00
|
|
|
return;
|
|
|
|
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader->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;
|
2019-11-22 10:25:03 +08:00
|
|
|
if (!TheASTReader)
|
|
|
|
createASTReader();
|
2014-04-23 20:57:01 +08:00
|
|
|
// Can't do anything if we don't have the module manager.
|
2019-11-22 10:25:03 +08:00
|
|
|
if (!TheASTReader)
|
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.
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader->loadGlobalIndex();
|
|
|
|
GlobalModuleIndex *GlobalIndex = TheASTReader->getGlobalIndex();
|
2014-04-23 20:57:01 +08:00
|
|
|
// If the global index doesn't exist, create it.
|
|
|
|
if (!GlobalIndex && shouldBuildGlobalModuleIndex() && hasFileManager() &&
|
|
|
|
hasPreprocessor()) {
|
|
|
|
llvm::sys::fs::create_directories(
|
|
|
|
getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
|
2019-06-27 03:50:12 +08:00
|
|
|
if (llvm::Error Err = GlobalModuleIndex::writeIndex(
|
|
|
|
getFileManager(), getPCHContainerReader(),
|
|
|
|
getPreprocessor().getHeaderSearchInfo().getModuleCachePath())) {
|
|
|
|
// FIXME this drops the error on the floor. This code is only used for
|
|
|
|
// typo correction and drops more than just this one source of errors
|
|
|
|
// (such as the directory creation failure above). It should handle the
|
|
|
|
// error.
|
|
|
|
consumeError(std::move(Err));
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader->resetForReload();
|
|
|
|
TheASTReader->loadGlobalIndex();
|
|
|
|
GlobalIndex = TheASTReader->getGlobalIndex();
|
2014-04-23 20:57:01 +08:00
|
|
|
}
|
|
|
|
// 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) {
|
2019-06-27 03:50:12 +08:00
|
|
|
if (llvm::Error Err = GlobalModuleIndex::writeIndex(
|
|
|
|
getFileManager(), getPCHContainerReader(),
|
|
|
|
getPreprocessor().getHeaderSearchInfo().getModuleCachePath())) {
|
|
|
|
// FIXME As above, this drops the error on the floor.
|
|
|
|
consumeError(std::move(Err));
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-11-22 10:25:03 +08:00
|
|
|
TheASTReader->resetForReload();
|
|
|
|
TheASTReader->loadGlobalIndex();
|
|
|
|
GlobalIndex = TheASTReader->getGlobalIndex();
|
2014-04-23 20:57:01 +08:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2018-11-18 02:04:13 +08:00
|
|
|
void CompilerInstance::resetAndLeakSema() { llvm::BuryPointer(takeSema()); }
|
2016-11-17 02:15:26 +08:00
|
|
|
|
|
|
|
void CompilerInstance::setExternalSemaSource(
|
|
|
|
IntrusiveRefCntPtr<ExternalSemaSource> ESS) {
|
|
|
|
ExternalSemaSrc = std::move(ESS);
|
|
|
|
}
|