1636404a3SDaniel Dunbar //===--- CompilerInstance.cpp ---------------------------------------------===//
2636404a3SDaniel Dunbar //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6636404a3SDaniel Dunbar //
7636404a3SDaniel Dunbar //===----------------------------------------------------------------------===//
8636404a3SDaniel Dunbar
9636404a3SDaniel Dunbar #include "clang/Frontend/CompilerInstance.h"
1056d9c293SDaniel Dunbar #include "clang/AST/ASTConsumer.h"
11df3e30c4SDaniel Dunbar #include "clang/AST/ASTContext.h"
12bcfc7d02SDouglas Gregor #include "clang/AST/Decl.h"
139565c75bSRichard Smith #include "clang/Basic/CharInfo.h"
14636404a3SDaniel Dunbar #include "clang/Basic/Diagnostic.h"
15546a676aSDaniel Dunbar #include "clang/Basic/FileManager.h"
1609d890d7SRainer Orth #include "clang/Basic/LangStandard.h"
17546a676aSDaniel Dunbar #include "clang/Basic/SourceManager.h"
180a7b297dSRichard Smith #include "clang/Basic/Stack.h"
19636404a3SDaniel Dunbar #include "clang/Basic/TargetInfo.h"
204f2bc55dSDaniel Dunbar #include "clang/Basic/Version.h"
21f988d006SAlp Toker #include "clang/Config/config.h"
228b00dcb0SDavid Blaikie #include "clang/Frontend/ChainedDiagnosticConsumer.h"
234f2bc55dSDaniel Dunbar #include "clang/Frontend/FrontendAction.h"
24faeb1d46SDouglas Gregor #include "clang/Frontend/FrontendActions.h"
25f7093b5aSDaniel Dunbar #include "clang/Frontend/FrontendDiagnostic.h"
26f4f9ad0fSVassil Vassilev #include "clang/Frontend/FrontendPluginRegistry.h"
272083c32fSDaniel Dunbar #include "clang/Frontend/LogDiagnosticPrinter.h"
284610ea2bSTed Kremenek #include "clang/Frontend/SerializedDiagnosticPrinter.h"
297d75afc5SDaniel Dunbar #include "clang/Frontend/TextDiagnosticPrinter.h"
30aaa148fdSDaniel Dunbar #include "clang/Frontend/Utils.h"
313a02247dSChandler Carruth #include "clang/Frontend/VerifyDiagnosticConsumer.h"
323a02247dSChandler Carruth #include "clang/Lex/HeaderSearch.h"
333a02247dSChandler Carruth #include "clang/Lex/Preprocessor.h"
349670f847SMehdi Amini #include "clang/Lex/PreprocessorOptions.h"
35f7093b5aSDaniel Dunbar #include "clang/Sema/CodeCompleteConsumer.h"
363a02247dSChandler Carruth #include "clang/Sema/Sema.h"
373a02247dSChandler Carruth #include "clang/Serialization/ASTReader.h"
382255f2ceSJohn Thompson #include "clang/Serialization/GlobalModuleIndex.h"
398bef5cd4SDuncan P. N. Exon Smith #include "clang/Serialization/InMemoryModuleCache.h"
4076cb4cd0SJan Svoboda #include "llvm/ADT/ScopeExit.h"
41171b780cSDouglas Gregor #include "llvm/ADT/Statistic.h"
429941da41SDavid Blaikie #include "llvm/Support/BuryPointer.h"
433a02247dSChandler Carruth #include "llvm/Support/CrashRecoveryContext.h"
4471de0b61SRafael Espindola #include "llvm/Support/Errc.h"
453a02247dSChandler Carruth #include "llvm/Support/FileSystem.h"
468aaf4995SMichael J. Spencer #include "llvm/Support/Host.h"
47e212489fSDouglas Gregor #include "llvm/Support/LockFileManager.h"
483a02247dSChandler Carruth #include "llvm/Support/MemoryBuffer.h"
498aaf4995SMichael J. Spencer #include "llvm/Support/Path.h"
508aaf4995SMichael J. Spencer #include "llvm/Support/Program.h"
518aaf4995SMichael J. Spencer #include "llvm/Support/Signals.h"
52d880de2dSAnton Afanasyev #include "llvm/Support/TimeProfiler.h"
533a02247dSChandler Carruth #include "llvm/Support/Timer.h"
543a02247dSChandler Carruth #include "llvm/Support/raw_ostream.h"
5537da327cSDouglas Gregor #include <time.h>
56cfeacf56SBenjamin Kramer #include <utility>
5754a88810SDouglas Gregor
58636404a3SDaniel Dunbar using namespace clang;
59636404a3SDaniel Dunbar
CompilerInstance(std::shared_ptr<PCHContainerOperations> PCHContainerOps,InMemoryModuleCache * SharedModuleCache)60bb165fb0SAdrian Prantl CompilerInstance::CompilerInstance(
61bb165fb0SAdrian Prantl std::shared_ptr<PCHContainerOperations> PCHContainerOps,
628bef5cd4SDuncan P. N. Exon Smith InMemoryModuleCache *SharedModuleCache)
638bef5cd4SDuncan P. N. Exon Smith : ModuleLoader(/* BuildingModule = */ SharedModuleCache),
64030d7d6dSDuncan P. N. Exon Smith Invocation(new CompilerInvocation()),
658bef5cd4SDuncan P. N. Exon Smith ModuleCache(SharedModuleCache ? SharedModuleCache
668bef5cd4SDuncan P. N. Exon Smith : new InMemoryModuleCache),
670a2be46cSDuncan P. N. Exon Smith ThePCHContainerOperations(std::move(PCHContainerOps)) {}
68636404a3SDaniel Dunbar
~CompilerInstance()69636404a3SDaniel Dunbar CompilerInstance::~CompilerInstance() {
703c717b45SBenjamin Kramer assert(OutputFiles.empty() && "Still output files in flight?");
71e922d9bdSDaniel Dunbar }
72e922d9bdSDaniel Dunbar
setInvocation(std::shared_ptr<CompilerInvocation> Value)73ea4395ebSDavid Blaikie void CompilerInstance::setInvocation(
74ea4395ebSDavid Blaikie std::shared_ptr<CompilerInvocation> Value) {
75ea4395ebSDavid Blaikie Invocation = std::move(Value);
7668242254SDaniel Dunbar }
7768242254SDaniel Dunbar
shouldBuildGlobalModuleIndex() const78c1bbec85SDouglas Gregor bool CompilerInstance::shouldBuildGlobalModuleIndex() const {
79e060e57bSDouglas Gregor return (BuildGlobalModuleIndex ||
8020d51b2fSDuncan P. N. Exon Smith (TheASTReader && TheASTReader->isGlobalIndexUnavailable() &&
8111ef0b77SDouglas Gregor getFrontendOpts().GenerateGlobalModuleIndex)) &&
8223e9146fSDuncan P. N. Exon Smith !DisableGeneratingGlobalModuleIndex;
83c1bbec85SDouglas Gregor }
84c1bbec85SDouglas Gregor
setDiagnostics(DiagnosticsEngine * Value)859c902b55SDavid Blaikie void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
867f95d26eSDouglas Gregor Diagnostics = Value;
87e01dc86dSDaniel Dunbar }
88e01dc86dSDaniel Dunbar
setVerboseOutputStream(raw_ostream & Value)8987cb734cSScott Linder void CompilerInstance::setVerboseOutputStream(raw_ostream &Value) {
908afabff6SDuncan P. N. Exon Smith OwnedVerboseOutputStream.reset();
9187cb734cSScott Linder VerboseOutputStream = &Value;
9287cb734cSScott Linder }
9387cb734cSScott Linder
setVerboseOutputStream(std::unique_ptr<raw_ostream> Value)9487cb734cSScott Linder void CompilerInstance::setVerboseOutputStream(std::unique_ptr<raw_ostream> Value) {
9587cb734cSScott Linder OwnedVerboseOutputStream.swap(Value);
9687cb734cSScott Linder VerboseOutputStream = OwnedVerboseOutputStream.get();
9787cb734cSScott Linder }
9887cb734cSScott Linder
setTarget(TargetInfo * Value)99b5bc923aSArtem Belevich void CompilerInstance::setTarget(TargetInfo *Value) { Target = Value; }
setAuxTarget(TargetInfo * Value)100b5bc923aSArtem Belevich void CompilerInstance::setAuxTarget(TargetInfo *Value) { AuxTarget = Value; }
101e01dc86dSDaniel Dunbar
createTarget()102d412dbe3SYu-Hsun Chiang bool CompilerInstance::createTarget() {
103d412dbe3SYu-Hsun Chiang // Create the target instance.
104d412dbe3SYu-Hsun Chiang setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(),
105d412dbe3SYu-Hsun Chiang getInvocation().TargetOpts));
106d412dbe3SYu-Hsun Chiang if (!hasTarget())
107d412dbe3SYu-Hsun Chiang return false;
108d412dbe3SYu-Hsun Chiang
109fc1117dfSoToToT // Check whether AuxTarget exists, if not, then create TargetInfo for the
110fc1117dfSoToToT // other side of CUDA/OpenMP/SYCL compilation.
111fc1117dfSoToToT if (!getAuxTarget() &&
112fc1117dfSoToToT (getLangOpts().CUDA || getLangOpts().OpenMPIsDevice ||
113d412dbe3SYu-Hsun Chiang getLangOpts().SYCLIsDevice) &&
114d412dbe3SYu-Hsun Chiang !getFrontendOpts().AuxTriple.empty()) {
115d412dbe3SYu-Hsun Chiang auto TO = std::make_shared<TargetOptions>();
116d412dbe3SYu-Hsun Chiang TO->Triple = llvm::Triple::normalize(getFrontendOpts().AuxTriple);
117d412dbe3SYu-Hsun Chiang if (getFrontendOpts().AuxTargetCPU)
118*cb2c8f69SKazu Hirata TO->CPU = getFrontendOpts().AuxTargetCPU.value();
119d412dbe3SYu-Hsun Chiang if (getFrontendOpts().AuxTargetFeatures)
120*cb2c8f69SKazu Hirata TO->FeaturesAsWritten = getFrontendOpts().AuxTargetFeatures.value();
121d412dbe3SYu-Hsun Chiang TO->HostTriple = getTarget().getTriple().str();
122d412dbe3SYu-Hsun Chiang setAuxTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), TO));
123d412dbe3SYu-Hsun Chiang }
124d412dbe3SYu-Hsun Chiang
125d412dbe3SYu-Hsun Chiang if (!getTarget().hasStrictFP() && !getLangOpts().ExpStrictFP) {
126706e89dbSSerge Pavlov if (getLangOpts().RoundingMath) {
127d412dbe3SYu-Hsun Chiang getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_rounding);
128706e89dbSSerge Pavlov getLangOpts().RoundingMath = false;
129d412dbe3SYu-Hsun Chiang }
130706e89dbSSerge Pavlov auto FPExc = getLangOpts().getFPExceptionMode();
131706e89dbSSerge Pavlov if (FPExc != LangOptions::FPE_Default && FPExc != LangOptions::FPE_Ignore) {
132d412dbe3SYu-Hsun Chiang getDiagnostics().Report(diag::warn_fe_backend_unsupported_fp_exceptions);
133d412dbe3SYu-Hsun Chiang getLangOpts().setFPExceptionMode(LangOptions::FPE_Ignore);
134d412dbe3SYu-Hsun Chiang }
135d412dbe3SYu-Hsun Chiang // FIXME: can we disable FEnvAccess?
136d412dbe3SYu-Hsun Chiang }
137d412dbe3SYu-Hsun Chiang
138f0efc007SAnton Zabaznov // We should do it here because target knows nothing about
139f0efc007SAnton Zabaznov // language options when it's being created.
14082690578SAnton Zabaznov if (getLangOpts().OpenCL &&
14182690578SAnton Zabaznov !getTarget().validateOpenCLTarget(getLangOpts(), getDiagnostics()))
14282690578SAnton Zabaznov return false;
143f0efc007SAnton Zabaznov
144d412dbe3SYu-Hsun Chiang // Inform the target of the language options.
145d412dbe3SYu-Hsun Chiang // FIXME: We shouldn't need to do this, the target should be immutable once
146d412dbe3SYu-Hsun Chiang // created. This complexity should be lifted elsewhere.
147aaba3718SMelanie Blower getTarget().adjust(getDiagnostics(), getLangOpts());
148d412dbe3SYu-Hsun Chiang
149d412dbe3SYu-Hsun Chiang // Adjust target options based on codegen options.
150d412dbe3SYu-Hsun Chiang getTarget().adjustTargetOptions(getCodeGenOpts(), getTargetOpts());
151d412dbe3SYu-Hsun Chiang
152d412dbe3SYu-Hsun Chiang if (auto *Aux = getAuxTarget())
153d412dbe3SYu-Hsun Chiang getTarget().setAuxTarget(Aux);
154d412dbe3SYu-Hsun Chiang
155d412dbe3SYu-Hsun Chiang return true;
156d412dbe3SYu-Hsun Chiang }
157d412dbe3SYu-Hsun Chiang
getVirtualFileSystem() const158e08464fbSReid Kleckner llvm::vfs::FileSystem &CompilerInstance::getVirtualFileSystem() const {
159e08464fbSReid Kleckner return getFileManager().getVirtualFileSystem();
160e08464fbSReid Kleckner }
161e08464fbSReid Kleckner
setFileManager(FileManager * Value)162e01dc86dSDaniel Dunbar void CompilerInstance::setFileManager(FileManager *Value) {
1635e14d39aSTed Kremenek FileMgr = Value;
164e01dc86dSDaniel Dunbar }
165e01dc86dSDaniel Dunbar
setSourceManager(SourceManager * Value)166e01dc86dSDaniel Dunbar void CompilerInstance::setSourceManager(SourceManager *Value) {
1675e14d39aSTed Kremenek SourceMgr = Value;
168e01dc86dSDaniel Dunbar }
169e01dc86dSDaniel Dunbar
setPreprocessor(std::shared_ptr<Preprocessor> Value)17041565463SDavid Blaikie void CompilerInstance::setPreprocessor(std::shared_ptr<Preprocessor> Value) {
17141565463SDavid Blaikie PP = std::move(Value);
17241565463SDavid Blaikie }
173e01dc86dSDaniel Dunbar
setASTContext(ASTContext * Value)174293534b1SRichard Smith void CompilerInstance::setASTContext(ASTContext *Value) {
175293534b1SRichard Smith Context = Value;
176293534b1SRichard Smith
177293534b1SRichard Smith if (Context && Consumer)
178293534b1SRichard Smith getASTConsumer().Initialize(getASTContext());
179293534b1SRichard Smith }
180e01dc86dSDaniel Dunbar
setSema(Sema * S)1810e93f017SDouglas Gregor void CompilerInstance::setSema(Sema *S) {
1820e93f017SDouglas Gregor TheSema.reset(S);
1830e93f017SDouglas Gregor }
1840e93f017SDouglas Gregor
setASTConsumer(std::unique_ptr<ASTConsumer> Value)1856beb6aa8SDavid Blaikie void CompilerInstance::setASTConsumer(std::unique_ptr<ASTConsumer> Value) {
1866beb6aa8SDavid Blaikie Consumer = std::move(Value);
187293534b1SRichard Smith
188293534b1SRichard Smith if (Context && Consumer)
189293534b1SRichard Smith getASTConsumer().Initialize(getASTContext());
19056d9c293SDaniel Dunbar }
19156d9c293SDaniel Dunbar
setCodeCompletionConsumer(CodeCompleteConsumer * Value)192e01dc86dSDaniel Dunbar void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
193e01dc86dSDaniel Dunbar CompletionConsumer.reset(Value);
194e01dc86dSDaniel Dunbar }
195e01dc86dSDaniel Dunbar
takeSema()1966153581aSDavid Blaikie std::unique_ptr<Sema> CompilerInstance::takeSema() {
1976153581aSDavid Blaikie return std::move(TheSema);
1986153581aSDavid Blaikie }
1996153581aSDavid Blaikie
getASTReader() const20020d51b2fSDuncan P. N. Exon Smith IntrusiveRefCntPtr<ASTReader> CompilerInstance::getASTReader() const {
20120d51b2fSDuncan P. N. Exon Smith return TheASTReader;
2021b7ed91eSArgyrios Kyrtzidis }
setASTReader(IntrusiveRefCntPtr<ASTReader> Reader)203a6c86989SVolodymyr Sapsai void CompilerInstance::setASTReader(IntrusiveRefCntPtr<ASTReader> Reader) {
2048bef5cd4SDuncan P. N. Exon Smith assert(ModuleCache.get() == &Reader->getModuleManager().getModuleCache() &&
205030d7d6dSDuncan P. N. Exon Smith "Expected ASTReader to use the same PCM cache");
20620d51b2fSDuncan P. N. Exon Smith TheASTReader = std::move(Reader);
2071b7ed91eSArgyrios Kyrtzidis }
2081b7ed91eSArgyrios Kyrtzidis
20986d1259cSJustin Bogner std::shared_ptr<ModuleDependencyCollector>
getModuleDepCollector() const21086d1259cSJustin Bogner CompilerInstance::getModuleDepCollector() const {
21186d1259cSJustin Bogner return ModuleDepCollector;
21286d1259cSJustin Bogner }
21386d1259cSJustin Bogner
setModuleDepCollector(std::shared_ptr<ModuleDependencyCollector> Collector)21486d1259cSJustin Bogner void CompilerInstance::setModuleDepCollector(
21586d1259cSJustin Bogner std::shared_ptr<ModuleDependencyCollector> Collector) {
216d6da1a09SBenjamin Kramer ModuleDepCollector = std::move(Collector);
21786d1259cSJustin Bogner }
21886d1259cSJustin Bogner
collectHeaderMaps(const HeaderSearch & HS,std::shared_ptr<ModuleDependencyCollector> MDC)219181225b8SBruno Cardoso Lopes static void collectHeaderMaps(const HeaderSearch &HS,
220181225b8SBruno Cardoso Lopes std::shared_ptr<ModuleDependencyCollector> MDC) {
221181225b8SBruno Cardoso Lopes SmallVector<std::string, 4> HeaderMapFileNames;
222181225b8SBruno Cardoso Lopes HS.getHeaderMapFileNames(HeaderMapFileNames);
223181225b8SBruno Cardoso Lopes for (auto &Name : HeaderMapFileNames)
224181225b8SBruno Cardoso Lopes MDC->addFile(Name);
225181225b8SBruno Cardoso Lopes }
226181225b8SBruno Cardoso Lopes
collectIncludePCH(CompilerInstance & CI,std::shared_ptr<ModuleDependencyCollector> MDC)2277aff2bb3SBruno Cardoso Lopes static void collectIncludePCH(CompilerInstance &CI,
2287aff2bb3SBruno Cardoso Lopes std::shared_ptr<ModuleDependencyCollector> MDC) {
2297aff2bb3SBruno Cardoso Lopes const PreprocessorOptions &PPOpts = CI.getPreprocessorOpts();
2307aff2bb3SBruno Cardoso Lopes if (PPOpts.ImplicitPCHInclude.empty())
2317aff2bb3SBruno Cardoso Lopes return;
2327aff2bb3SBruno Cardoso Lopes
2337aff2bb3SBruno Cardoso Lopes StringRef PCHInclude = PPOpts.ImplicitPCHInclude;
2347aff2bb3SBruno Cardoso Lopes FileManager &FileMgr = CI.getFileManager();
23599b4874aSJan Svoboda auto PCHDir = FileMgr.getOptionalDirectoryRef(PCHInclude);
2367aff2bb3SBruno Cardoso Lopes if (!PCHDir) {
2377aff2bb3SBruno Cardoso Lopes MDC->addFile(PCHInclude);
2387aff2bb3SBruno Cardoso Lopes return;
2397aff2bb3SBruno Cardoso Lopes }
2407aff2bb3SBruno Cardoso Lopes
2417aff2bb3SBruno Cardoso Lopes std::error_code EC;
2427aff2bb3SBruno Cardoso Lopes SmallString<128> DirNative;
24399b4874aSJan Svoboda llvm::sys::path::native(PCHDir->getName(), DirNative);
244db8a7422SDuncan P. N. Exon Smith llvm::vfs::FileSystem &FS = FileMgr.getVirtualFileSystem();
2457aff2bb3SBruno Cardoso Lopes SimpleASTReaderListener Validator(CI.getPreprocessor());
246fc51490bSJonas Devlieghere for (llvm::vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd;
2477aff2bb3SBruno Cardoso Lopes Dir != DirEnd && !EC; Dir.increment(EC)) {
2487aff2bb3SBruno Cardoso Lopes // Check whether this is an AST file. ASTReader::isAcceptableASTFile is not
2497aff2bb3SBruno Cardoso Lopes // used here since we're not interested in validating the PCH at this time,
2507aff2bb3SBruno Cardoso Lopes // but only to check whether this is a file containing an AST.
2517aff2bb3SBruno Cardoso Lopes if (!ASTReader::readASTFileControlBlock(
2520ae00567SSam McCall Dir->path(), FileMgr, CI.getPCHContainerReader(),
2537aff2bb3SBruno Cardoso Lopes /*FindModuleFileExtensions=*/false, Validator,
2547aff2bb3SBruno Cardoso Lopes /*ValidateDiagnosticOptions=*/false))
2550ae00567SSam McCall MDC->addFile(Dir->path());
2567aff2bb3SBruno Cardoso Lopes }
2577aff2bb3SBruno Cardoso Lopes }
2587aff2bb3SBruno Cardoso Lopes
collectVFSEntries(CompilerInstance & CI,std::shared_ptr<ModuleDependencyCollector> MDC)25982ec4fdeSBruno Cardoso Lopes static void collectVFSEntries(CompilerInstance &CI,
26082ec4fdeSBruno Cardoso Lopes std::shared_ptr<ModuleDependencyCollector> MDC) {
26182ec4fdeSBruno Cardoso Lopes if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty())
26282ec4fdeSBruno Cardoso Lopes return;
26382ec4fdeSBruno Cardoso Lopes
26482ec4fdeSBruno Cardoso Lopes // Collect all VFS found.
265fc51490bSJonas Devlieghere SmallVector<llvm::vfs::YAMLVFSEntry, 16> VFSEntries;
26682ec4fdeSBruno Cardoso Lopes for (const std::string &VFSFile : CI.getHeaderSearchOpts().VFSOverlayFiles) {
26782ec4fdeSBruno Cardoso Lopes llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer =
26882ec4fdeSBruno Cardoso Lopes llvm::MemoryBuffer::getFile(VFSFile);
26982ec4fdeSBruno Cardoso Lopes if (!Buffer)
27082ec4fdeSBruno Cardoso Lopes return;
271fc51490bSJonas Devlieghere llvm::vfs::collectVFSFromYAML(std::move(Buffer.get()),
272fc51490bSJonas Devlieghere /*DiagHandler*/ nullptr, VFSFile, VFSEntries);
27382ec4fdeSBruno Cardoso Lopes }
27482ec4fdeSBruno Cardoso Lopes
27582ec4fdeSBruno Cardoso Lopes for (auto &E : VFSEntries)
27682ec4fdeSBruno Cardoso Lopes MDC->addFile(E.VPath, E.RPath);
27782ec4fdeSBruno Cardoso Lopes }
27882ec4fdeSBruno Cardoso Lopes
2797d75afc5SDaniel Dunbar // Diagnostics
SetUpDiagnosticLog(DiagnosticOptions * DiagOpts,const CodeGenOptions * CodeGenOpts,DiagnosticsEngine & Diags)280811db4eaSDouglas Gregor static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts,
2817b83306dSDaniel Dunbar const CodeGenOptions *CodeGenOpts,
2829c902b55SDavid Blaikie DiagnosticsEngine &Diags) {
283dae941a6SRafael Espindola std::error_code EC;
28411f8a943SDavid Blaikie std::unique_ptr<raw_ostream> StreamOwner;
2850e62c1ccSChris Lattner raw_ostream *OS = &llvm::errs();
286811db4eaSDouglas Gregor if (DiagOpts->DiagnosticLogFile != "-") {
2872083c32fSDaniel Dunbar // Create the output stream.
2882b3d49b6SJonas Devlieghere auto FileOS = std::make_unique<llvm::raw_fd_ostream>(
289dae941a6SRafael Espindola DiagOpts->DiagnosticLogFile, EC,
29082b3e28eSAbhina Sreeskantharajan llvm::sys::fs::OF_Append | llvm::sys::fs::OF_TextWithCRLF);
291dae941a6SRafael Espindola if (EC) {
2922083c32fSDaniel Dunbar Diags.Report(diag::warn_fe_cc_log_diagnostics_failure)
293dae941a6SRafael Espindola << DiagOpts->DiagnosticLogFile << EC.message();
2942083c32fSDaniel Dunbar } else {
2952083c32fSDaniel Dunbar FileOS->SetUnbuffered();
29611f8a943SDavid Blaikie OS = FileOS.get();
29711f8a943SDavid Blaikie StreamOwner = std::move(FileOS);
2982083c32fSDaniel Dunbar }
2992083c32fSDaniel Dunbar }
3002083c32fSDaniel Dunbar
3012083c32fSDaniel Dunbar // Chain in the diagnostic client which will log the diagnostics.
3022b3d49b6SJonas Devlieghere auto Logger = std::make_unique<LogDiagnosticPrinter>(*OS, DiagOpts,
3037ee25502SDavid Blaikie std::move(StreamOwner));
3047b83306dSDaniel Dunbar if (CodeGenOpts)
3057b83306dSDaniel Dunbar Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags);
30688377d8dSAlex Lorenz if (Diags.ownsClient()) {
30741c247a6SAlexander Kornienko Diags.setClient(
30841c247a6SAlexander Kornienko new ChainedDiagnosticConsumer(Diags.takeClient(), std::move(Logger)));
30988377d8dSAlex Lorenz } else {
31088377d8dSAlex Lorenz Diags.setClient(
31188377d8dSAlex Lorenz new ChainedDiagnosticConsumer(Diags.getClient(), std::move(Logger)));
31288377d8dSAlex Lorenz }
3132083c32fSDaniel Dunbar }
3142083c32fSDaniel Dunbar
SetupSerializedDiagnostics(DiagnosticOptions * DiagOpts,DiagnosticsEngine & Diags,StringRef OutputFile)315811db4eaSDouglas Gregor static void SetupSerializedDiagnostics(DiagnosticOptions *DiagOpts,
3164610ea2bSTed Kremenek DiagnosticsEngine &Diags,
3174610ea2bSTed Kremenek StringRef OutputFile) {
3187ee25502SDavid Blaikie auto SerializedConsumer =
3195a6a2fcdSJustin Bogner clang::serialized_diags::create(OutputFile, DiagOpts);
3204610ea2bSTed Kremenek
321254b7dbaSAlexander Kornienko if (Diags.ownsClient()) {
3227ee25502SDavid Blaikie Diags.setClient(new ChainedDiagnosticConsumer(
32341c247a6SAlexander Kornienko Diags.takeClient(), std::move(SerializedConsumer)));
324254b7dbaSAlexander Kornienko } else {
325254b7dbaSAlexander Kornienko Diags.setClient(new ChainedDiagnosticConsumer(
3264c0ef379SAlexander Kornienko Diags.getClient(), std::move(SerializedConsumer)));
327254b7dbaSAlexander Kornienko }
3284610ea2bSTed Kremenek }
3294610ea2bSTed Kremenek
createDiagnostics(DiagnosticConsumer * Client,bool ShouldOwnClient)330f1b49e23SSean Silva void CompilerInstance::createDiagnostics(DiagnosticConsumer *Client,
33130071ceaSDouglas Gregor bool ShouldOwnClient) {
332f1b49e23SSean Silva Diagnostics = createDiagnostics(&getDiagnosticOpts(), Client,
33330071ceaSDouglas Gregor ShouldOwnClient, &getCodeGenOpts());
3347d75afc5SDaniel Dunbar }
3357d75afc5SDaniel Dunbar
336c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticsEngine>
createDiagnostics(DiagnosticOptions * Opts,DiagnosticConsumer * Client,bool ShouldOwnClient,const CodeGenOptions * CodeGenOpts)337811db4eaSDouglas Gregor CompilerInstance::createDiagnostics(DiagnosticOptions *Opts,
338e2eefaecSDavid Blaikie DiagnosticConsumer *Client,
3392b9b4642SDouglas Gregor bool ShouldOwnClient,
3407b83306dSDaniel Dunbar const CodeGenOptions *CodeGenOpts) {
341c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
342c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticsEngine>
343811db4eaSDouglas Gregor Diags(new DiagnosticsEngine(DiagID, Opts));
3441b39a2edSDaniel Dunbar
3457d75afc5SDaniel Dunbar // Create the diagnostic client for reporting errors or for
3467d75afc5SDaniel Dunbar // implementing -verify.
347d0e9e3a6SDouglas Gregor if (Client) {
348d0e9e3a6SDouglas Gregor Diags->setClient(Client, ShouldOwnClient);
349d0e9e3a6SDouglas Gregor } else
3502dd19f1dSDouglas Gregor Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
35150ec0da0SDaniel Dunbar
35250ec0da0SDaniel Dunbar // Chain in -verify checker, if requested.
353811db4eaSDouglas Gregor if (Opts->VerifyDiagnostics)
35469609dceSDavid Blaikie Diags->setClient(new VerifyDiagnosticConsumer(*Diags));
3557d75afc5SDaniel Dunbar
3562083c32fSDaniel Dunbar // Chain in -diagnostic-log-file dumper, if requested.
357811db4eaSDouglas Gregor if (!Opts->DiagnosticLogFile.empty())
3587b83306dSDaniel Dunbar SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags);
3592083c32fSDaniel Dunbar
360811db4eaSDouglas Gregor if (!Opts->DiagnosticSerializationFile.empty())
3614610ea2bSTed Kremenek SetupSerializedDiagnostics(Opts, *Diags,
362811db4eaSDouglas Gregor Opts->DiagnosticSerializationFile);
3634610ea2bSTed Kremenek
3647d75afc5SDaniel Dunbar // Configure our handling of diagnostics.
365811db4eaSDouglas Gregor ProcessWarningOptions(*Diags, *Opts);
3667d75afc5SDaniel Dunbar
3677f95d26eSDouglas Gregor return Diags;
3687d75afc5SDaniel Dunbar }
3697d75afc5SDaniel Dunbar
3707d75afc5SDaniel Dunbar // File Manager
3717d75afc5SDaniel Dunbar
createFileManager(IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS)3721da7eac8SDuncan P. N. Exon Smith FileManager *CompilerInstance::createFileManager(
3731da7eac8SDuncan P. N. Exon Smith IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
3741da7eac8SDuncan P. N. Exon Smith if (!VFS)
375db8a7422SDuncan P. N. Exon Smith VFS = FileMgr ? &FileMgr->getVirtualFileSystem()
3761da7eac8SDuncan P. N. Exon Smith : createVFSFromCompilerInvocation(getInvocation(),
3771da7eac8SDuncan P. N. Exon Smith getDiagnostics());
3781da7eac8SDuncan P. N. Exon Smith assert(VFS && "FileManager has no VFS?");
3791da7eac8SDuncan P. N. Exon Smith FileMgr = new FileManager(getFileSystemOpts(), std::move(VFS));
380abc3d04eSRaphael Isemann return FileMgr.get();
381546a676aSDaniel Dunbar }
382546a676aSDaniel Dunbar
3837d75afc5SDaniel Dunbar // Source Manager
3847d75afc5SDaniel Dunbar
createSourceManager(FileManager & FileMgr)3855159f616SChris Lattner void CompilerInstance::createSourceManager(FileManager &FileMgr) {
3865e14d39aSTed Kremenek SourceMgr = new SourceManager(getDiagnostics(), FileMgr);
387546a676aSDaniel Dunbar }
388aaa148fdSDaniel Dunbar
389c358000eSAlp Toker // Initialize the remapping of files to alternative contents, e.g.,
390c358000eSAlp Toker // those specified through other files.
InitializeFileRemapping(DiagnosticsEngine & Diags,SourceManager & SourceMgr,FileManager & FileMgr,const PreprocessorOptions & InitOpts)391c358000eSAlp Toker static void InitializeFileRemapping(DiagnosticsEngine &Diags,
392c358000eSAlp Toker SourceManager &SourceMgr,
393c358000eSAlp Toker FileManager &FileMgr,
394c358000eSAlp Toker const PreprocessorOptions &InitOpts) {
395c358000eSAlp Toker // Remap files in the source manager (with buffers).
3961b070d25SAlp Toker for (const auto &RB : InitOpts.RemappedFileBuffers) {
397c358000eSAlp Toker // Create the file entry for the file that we're mapping from.
398c358000eSAlp Toker const FileEntry *FromFile =
3991b070d25SAlp Toker FileMgr.getVirtualFile(RB.first, RB.second->getBufferSize(), 0);
400c358000eSAlp Toker if (!FromFile) {
4011b070d25SAlp Toker Diags.Report(diag::err_fe_remap_missing_from_file) << RB.first;
402c358000eSAlp Toker if (!InitOpts.RetainRemappedFileBuffers)
4031b070d25SAlp Toker delete RB.second;
404c358000eSAlp Toker continue;
405c358000eSAlp Toker }
406c358000eSAlp Toker
40729631451SDuncan P. N. Exon Smith // Override the contents of the "from" file with the contents of the
40829631451SDuncan P. N. Exon Smith // "to" file. If the caller owns the buffers, then pass a MemoryBufferRef;
40929631451SDuncan P. N. Exon Smith // otherwise, pass as a std::unique_ptr<MemoryBuffer> to transfer ownership
41029631451SDuncan P. N. Exon Smith // to the SourceManager.
41129631451SDuncan P. N. Exon Smith if (InitOpts.RetainRemappedFileBuffers)
41229631451SDuncan P. N. Exon Smith SourceMgr.overrideFileContents(FromFile, RB.second->getMemBufferRef());
41329631451SDuncan P. N. Exon Smith else
41429631451SDuncan P. N. Exon Smith SourceMgr.overrideFileContents(
41529631451SDuncan P. N. Exon Smith FromFile, std::unique_ptr<llvm::MemoryBuffer>(
41629631451SDuncan P. N. Exon Smith const_cast<llvm::MemoryBuffer *>(RB.second)));
417c358000eSAlp Toker }
418c358000eSAlp Toker
419c358000eSAlp Toker // Remap files in the source manager (with other files).
4201b070d25SAlp Toker for (const auto &RF : InitOpts.RemappedFiles) {
421c358000eSAlp Toker // Find the file that we're mapping to.
4228d323d15SHarlan Haskins auto ToFile = FileMgr.getFile(RF.second);
423c358000eSAlp Toker if (!ToFile) {
4241b070d25SAlp Toker Diags.Report(diag::err_fe_remap_missing_to_file) << RF.first << RF.second;
425c358000eSAlp Toker continue;
426c358000eSAlp Toker }
427c358000eSAlp Toker
428c358000eSAlp Toker // Create the file entry for the file that we're mapping from.
429c358000eSAlp Toker const FileEntry *FromFile =
4308d323d15SHarlan Haskins FileMgr.getVirtualFile(RF.first, (*ToFile)->getSize(), 0);
431c358000eSAlp Toker if (!FromFile) {
4321b070d25SAlp Toker Diags.Report(diag::err_fe_remap_missing_from_file) << RF.first;
433c358000eSAlp Toker continue;
434c358000eSAlp Toker }
435c358000eSAlp Toker
436c358000eSAlp Toker // Override the contents of the "from" file with the contents of
437c358000eSAlp Toker // the "to" file.
4388d323d15SHarlan Haskins SourceMgr.overrideFileContents(FromFile, *ToFile);
439c358000eSAlp Toker }
440c358000eSAlp Toker
441c358000eSAlp Toker SourceMgr.setOverridenFilesKeepOriginalName(
442c358000eSAlp Toker InitOpts.RemappedFilesKeepOriginalName);
443c358000eSAlp Toker }
444c358000eSAlp Toker
4457d75afc5SDaniel Dunbar // Preprocessor
4467d75afc5SDaniel Dunbar
createPreprocessor(TranslationUnitKind TUKind)447e1974dcdSArgyrios Kyrtzidis void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) {
44808142534SDouglas Gregor const PreprocessorOptions &PPOpts = getPreprocessorOpts();
449aaa148fdSDaniel Dunbar
450a6c86989SVolodymyr Sapsai // The AST reader holds a reference to the old preprocessor (if any).
45120d51b2fSDuncan P. N. Exon Smith TheASTReader.reset();
4525904c41eSBenjamin Kramer
453aaa148fdSDaniel Dunbar // Create the Preprocessor.
4549c28cb3fSDavid Blaikie HeaderSearch *HeaderInfo =
4559c28cb3fSDavid Blaikie new HeaderSearch(getHeaderSearchOptsPtr(), getSourceManager(),
4569c28cb3fSDavid Blaikie getDiagnostics(), getLangOpts(), &getTarget());
4578bef5cd4SDuncan P. N. Exon Smith PP = std::make_shared<Preprocessor>(Invocation->getPreprocessorOptsPtr(),
4588bef5cd4SDuncan P. N. Exon Smith getDiagnostics(), getLangOpts(),
4598bef5cd4SDuncan P. N. Exon Smith getSourceManager(), *HeaderInfo, *this,
4600a6b5b65SErich Keane /*IdentifierInfoLookup=*/nullptr,
4619663780eSAlp Toker /*OwnsHeaderSearch=*/true, TUKind);
462aaba3718SMelanie Blower getTarget().adjust(getDiagnostics(), getLangOpts());
463b5bc923aSArtem Belevich PP->Initialize(getTarget(), getAuxTarget());
464aaa148fdSDaniel Dunbar
4657f6d60dcSDouglas Gregor if (PPOpts.DetailedRecord)
466f3d587eaSArgyrios Kyrtzidis PP->createPreprocessingRecord();
4677f6d60dcSDouglas Gregor
468c358000eSAlp Toker // Apply remappings to the source manager.
469c358000eSAlp Toker InitializeFileRemapping(PP->getDiagnostics(), PP->getSourceManager(),
470c358000eSAlp Toker PP->getFileManager(), PPOpts);
471c358000eSAlp Toker
472c358000eSAlp Toker // Predefine macros and configure the preprocessor.
473fb2398d0SAdrian Prantl InitializePreprocessor(*PP, PPOpts, getPCHContainerReader(),
474bb165fb0SAdrian Prantl getFrontendOpts());
475c358000eSAlp Toker
476f91086b0SJustin Lebar // Initialize the header search object. In CUDA compilations, we use the aux
477f91086b0SJustin Lebar // triple (the host triple) to initialize our header search, since we need to
478f91086b0SJustin Lebar // find the host headers in order to compile the CUDA code.
479f91086b0SJustin Lebar const llvm::Triple *HeaderSearchTriple = &PP->getTargetInfo().getTriple();
480f91086b0SJustin Lebar if (PP->getTargetInfo().getTriple().getOS() == llvm::Triple::CUDA &&
481f91086b0SJustin Lebar PP->getAuxTargetInfo())
482f91086b0SJustin Lebar HeaderSearchTriple = &PP->getAuxTargetInfo()->getTriple();
483f91086b0SJustin Lebar
484c358000eSAlp Toker ApplyHeaderSearchOptions(PP->getHeaderSearchInfo(), getHeaderSearchOpts(),
485f91086b0SJustin Lebar PP->getLangOpts(), *HeaderSearchTriple);
486aaa148fdSDaniel Dunbar
48717441589SJordan Rose PP->setPreprocessedOutput(getPreprocessorOutputOpts().ShowCPP);
48817441589SJordan Rose
48958c586e7SAlexandre Rames if (PP->getLangOpts().Modules && PP->getLangOpts().ImplicitModules) {
49058c586e7SAlexandre Rames std::string ModuleHash = getInvocation().getModuleHash();
49158c586e7SAlexandre Rames PP->getHeaderSearchInfo().setModuleHash(ModuleHash);
49258c586e7SAlexandre Rames PP->getHeaderSearchInfo().setModuleCachePath(
49358c586e7SAlexandre Rames getSpecificModuleCachePath(ModuleHash));
49458c586e7SAlexandre Rames }
4951735f4e7SDouglas Gregor
496aaa148fdSDaniel Dunbar // Handle generating dependencies, if requested.
49708142534SDouglas Gregor const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
498aaa148fdSDaniel Dunbar if (!DepOpts.OutputFile.empty())
4998d9eb7acSAlex Lorenz addDependencyCollector(std::make_shared<DependencyFileGenerator>(DepOpts));
5002e129659SDouglas Gregor if (!DepOpts.DOTOutputFile.empty())
5012e129659SDouglas Gregor AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile,
50283d46be3SDouglas Gregor getHeaderSearchOpts().Sysroot);
50383d46be3SDouglas Gregor
50486d1259cSJustin Bogner // If we don't have a collector, but we are collecting module dependencies,
50586d1259cSJustin Bogner // then we're the top level compiler instance and need to create one.
506b1631d91SBruno Cardoso Lopes if (!ModuleDepCollector && !DepOpts.ModuleDependencyOutputDir.empty()) {
50786d1259cSJustin Bogner ModuleDepCollector = std::make_shared<ModuleDependencyCollector>(
50886d1259cSJustin Bogner DepOpts.ModuleDependencyOutputDir);
509b1631d91SBruno Cardoso Lopes }
510b1631d91SBruno Cardoso Lopes
511181225b8SBruno Cardoso Lopes // If there is a module dep collector, register with other dep collectors
512181225b8SBruno Cardoso Lopes // and also (a) collect header maps and (b) TODO: input vfs overlay files.
513181225b8SBruno Cardoso Lopes if (ModuleDepCollector) {
514b1631d91SBruno Cardoso Lopes addDependencyCollector(ModuleDepCollector);
515181225b8SBruno Cardoso Lopes collectHeaderMaps(PP->getHeaderSearchInfo(), ModuleDepCollector);
5167aff2bb3SBruno Cardoso Lopes collectIncludePCH(*this, ModuleDepCollector);
51782ec4fdeSBruno Cardoso Lopes collectVFSEntries(*this, ModuleDepCollector);
518181225b8SBruno Cardoso Lopes }
519b1631d91SBruno Cardoso Lopes
520b1631d91SBruno Cardoso Lopes for (auto &Listener : DependencyCollectors)
521b1631d91SBruno Cardoso Lopes Listener->attachToPreprocessor(*PP);
522aaa148fdSDaniel Dunbar
52327734fdbSDaniel Dunbar // Handle generating header include information, if requested.
52427734fdbSDaniel Dunbar if (DepOpts.ShowHeaderIncludes)
525f54146c1SNico Weber AttachHeaderIncludeGen(*PP, DepOpts);
5261af1d275SDaniel Dunbar if (!DepOpts.HeaderIncludeOutputFile.empty()) {
5270e62c1ccSChris Lattner StringRef OutputPath = DepOpts.HeaderIncludeOutputFile;
5281af1d275SDaniel Dunbar if (OutputPath == "-")
5291af1d275SDaniel Dunbar OutputPath = "";
530f54146c1SNico Weber AttachHeaderIncludeGen(*PP, DepOpts,
5311193f2cbSIvan Krasin /*ShowAllHeaders=*/true, OutputPath,
532fe908a80SDaniel Dunbar /*ShowDepth=*/false);
5330fd6207dSHans Wennborg }
5340fd6207dSHans Wennborg
535425f48d4SErich Keane if (DepOpts.ShowIncludesDest != ShowIncludesDestination::None) {
536f54146c1SNico Weber AttachHeaderIncludeGen(*PP, DepOpts,
537149d9522SNico Weber /*ShowAllHeaders=*/true, /*OutputPath=*/"",
5380fd6207dSHans Wennborg /*ShowDepth=*/true, /*MSStyle=*/true);
5391af1d275SDaniel Dunbar }
540aaa148fdSDaniel Dunbar }
541df3e30c4SDaniel Dunbar
getSpecificModuleCachePath(StringRef ModuleHash)54258c586e7SAlexandre Rames std::string CompilerInstance::getSpecificModuleCachePath(StringRef ModuleHash) {
54358c586e7SAlexandre Rames // Set up the module path, including the hash for the module-creation options.
544d520a250SRichard Smith SmallString<256> SpecificModuleCache(getHeaderSearchOpts().ModuleCachePath);
545d520a250SRichard Smith if (!SpecificModuleCache.empty() && !getHeaderSearchOpts().DisableModuleHash)
54658c586e7SAlexandre Rames llvm::sys::path::append(SpecificModuleCache, ModuleHash);
547adcd0268SBenjamin Kramer return std::string(SpecificModuleCache.str());
548bd0b651bSArgyrios Kyrtzidis }
549bd0b651bSArgyrios Kyrtzidis
550df3e30c4SDaniel Dunbar // ASTContext
551df3e30c4SDaniel Dunbar
createASTContext()552df3e30c4SDaniel Dunbar void CompilerInstance::createASTContext() {
553df3e30c4SDaniel Dunbar Preprocessor &PP = getPreprocessor();
554293534b1SRichard Smith auto *Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
55508043437SAlp Toker PP.getIdentifierTable(), PP.getSelectorTable(),
55611b47c10SVassil Vassilev PP.getBuiltinInfo(), PP.TUKind);
557b5bc923aSArtem Belevich Context->InitBuiltinTypes(getTarget(), getAuxTarget());
558293534b1SRichard Smith setASTContext(Context);
559df3e30c4SDaniel Dunbar }
560599313efSDaniel Dunbar
561599313efSDaniel Dunbar // ExternalASTSource
562599313efSDaniel Dunbar
563aae776a5SJan Svoboda namespace {
564aae776a5SJan Svoboda // Helper to recursively read the module names for all modules we're adding.
565aae776a5SJan Svoboda // We mark these as known and redirect any attempt to load that module to
566aae776a5SJan Svoboda // the files we were handed.
567aae776a5SJan Svoboda struct ReadModuleNames : ASTReaderListener {
56808c8016cSJan Svoboda Preprocessor &PP;
569a2d805c0SJan Svoboda llvm::SmallVector<std::string, 8> LoadedModules;
570aae776a5SJan Svoboda
ReadModuleNames__anon95e63fe90111::ReadModuleNames57108c8016cSJan Svoboda ReadModuleNames(Preprocessor &PP) : PP(PP) {}
572aae776a5SJan Svoboda
ReadModuleName__anon95e63fe90111::ReadModuleNames573aae776a5SJan Svoboda void ReadModuleName(StringRef ModuleName) override {
574a2d805c0SJan Svoboda // Keep the module name as a string for now. It's not safe to create a new
575a2d805c0SJan Svoboda // IdentifierInfo from an ASTReader callback.
576a2d805c0SJan Svoboda LoadedModules.push_back(ModuleName.str());
577aae776a5SJan Svoboda }
578aae776a5SJan Svoboda
registerAll__anon95e63fe90111::ReadModuleNames579aae776a5SJan Svoboda void registerAll() {
58008c8016cSJan Svoboda ModuleMap &MM = PP.getHeaderSearchInfo().getModuleMap();
581a2d805c0SJan Svoboda for (const std::string &LoadedModule : LoadedModules)
582a2d805c0SJan Svoboda MM.cacheModuleLoad(*PP.getIdentifierInfo(LoadedModule),
583a2d805c0SJan Svoboda MM.findModule(LoadedModule));
584aae776a5SJan Svoboda LoadedModules.clear();
585aae776a5SJan Svoboda }
586aae776a5SJan Svoboda
markAllUnavailable__anon95e63fe90111::ReadModuleNames587aae776a5SJan Svoboda void markAllUnavailable() {
588a2d805c0SJan Svoboda for (const std::string &LoadedModule : LoadedModules) {
58908c8016cSJan Svoboda if (Module *M = PP.getHeaderSearchInfo().getModuleMap().findModule(
590a2d805c0SJan Svoboda LoadedModule)) {
591aae776a5SJan Svoboda M->HasIncompatibleModuleFile = true;
592aae776a5SJan Svoboda
593aae776a5SJan Svoboda // Mark module as available if the only reason it was unavailable
594aae776a5SJan Svoboda // was missing headers.
595aae776a5SJan Svoboda SmallVector<Module *, 2> Stack;
596aae776a5SJan Svoboda Stack.push_back(M);
597aae776a5SJan Svoboda while (!Stack.empty()) {
598aae776a5SJan Svoboda Module *Current = Stack.pop_back_val();
599aae776a5SJan Svoboda if (Current->IsUnimportable) continue;
600aae776a5SJan Svoboda Current->IsAvailable = true;
601aae776a5SJan Svoboda Stack.insert(Stack.end(),
602aae776a5SJan Svoboda Current->submodule_begin(), Current->submodule_end());
603aae776a5SJan Svoboda }
604aae776a5SJan Svoboda }
605aae776a5SJan Svoboda }
606aae776a5SJan Svoboda LoadedModules.clear();
607aae776a5SJan Svoboda }
608aae776a5SJan Svoboda };
609aae776a5SJan Svoboda } // namespace
610aae776a5SJan Svoboda
createPCHExternalASTSource(StringRef Path,DisableValidationForModuleKind DisableValidation,bool AllowPCHWithCompilerErrors,void * DeserializationListener,bool OwnDeserializationListener)611824285ecSNico Weber void CompilerInstance::createPCHExternalASTSource(
612b0e89906SArgyrios Kyrtzidis StringRef Path, DisableValidationForModuleKind DisableValidation,
613b0e89906SArgyrios Kyrtzidis bool AllowPCHWithCompilerErrors, void *DeserializationListener,
614b0e89906SArgyrios Kyrtzidis bool OwnDeserializationListener) {
615009e7f20SSebastian Redl bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
61620d51b2fSDuncan P. N. Exon Smith TheASTReader = createPCHExternalASTSource(
617b0e89906SArgyrios Kyrtzidis Path, getHeaderSearchOpts().Sysroot, DisableValidation,
6188bef5cd4SDuncan P. N. Exon Smith AllowPCHWithCompilerErrors, getPreprocessor(), getModuleCache(),
6198bef5cd4SDuncan P. N. Exon Smith getASTContext(), getPCHContainerReader(),
6208d9eb7acSAlex Lorenz getFrontendOpts().ModuleFileExtensions, DependencyCollectors,
6218d9eb7acSAlex Lorenz DeserializationListener, OwnDeserializationListener, Preamble,
6228d9eb7acSAlex Lorenz getFrontendOpts().UseGlobalModuleIndex);
623599313efSDaniel Dunbar }
624599313efSDaniel Dunbar
createPCHExternalASTSource(StringRef Path,StringRef Sysroot,DisableValidationForModuleKind DisableValidation,bool AllowPCHWithCompilerErrors,Preprocessor & PP,InMemoryModuleCache & ModuleCache,ASTContext & Context,const PCHContainerReader & PCHContainerRdr,ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,void * DeserializationListener,bool OwnDeserializationListener,bool Preamble,bool UseGlobalModuleIndex)6254eca9b93SRichard Smith IntrusiveRefCntPtr<ASTReader> CompilerInstance::createPCHExternalASTSource(
626b0e89906SArgyrios Kyrtzidis StringRef Path, StringRef Sysroot,
627b0e89906SArgyrios Kyrtzidis DisableValidationForModuleKind DisableValidation,
6288bef5cd4SDuncan P. N. Exon Smith bool AllowPCHWithCompilerErrors, Preprocessor &PP,
6298bef5cd4SDuncan P. N. Exon Smith InMemoryModuleCache &ModuleCache, ASTContext &Context,
630fb2398d0SAdrian Prantl const PCHContainerReader &PCHContainerRdr,
63161137e1aSDavid Blaikie ArrayRef<std::shared_ptr<ModuleFileExtension>> Extensions,
632ce539b54SGraydon Hoare ArrayRef<std::shared_ptr<DependencyCollector>> DependencyCollectors,
633824285ecSNico Weber void *DeserializationListener, bool OwnDeserializationListener,
634824285ecSNico Weber bool Preamble, bool UseGlobalModuleIndex) {
635dcf73861SBen Langmuir HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts();
636dcf73861SBen Langmuir
637bb165fb0SAdrian Prantl IntrusiveRefCntPtr<ASTReader> Reader(new ASTReader(
6388bef5cd4SDuncan P. N. Exon Smith PP, ModuleCache, &Context, PCHContainerRdr, Extensions,
639b0e89906SArgyrios Kyrtzidis Sysroot.empty() ? "" : Sysroot.data(), DisableValidation,
6406623e1f1SDouglas Gregor AllowPCHWithCompilerErrors, /*AllowConfigurationMismatch*/ false,
6411731fc88SBruno Cardoso Lopes HSOpts.ModulesValidateSystemHeaders, HSOpts.ValidateASTInputFilesContent,
6421731fc88SBruno Cardoso Lopes UseGlobalModuleIndex));
6434eca9b93SRichard Smith
6444eca9b93SRichard Smith // We need the external source to be set up before we read the AST, because
6454eca9b93SRichard Smith // eagerly-deserialized declarations may use it.
6464eca9b93SRichard Smith Context.setExternalSource(Reader.get());
647599313efSDaniel Dunbar
64807a89a83SSebastian Redl Reader->setDeserializationListener(
649824285ecSNico Weber static_cast<ASTDeserializationListener *>(DeserializationListener),
650824285ecSNico Weber /*TakeOwnership=*/OwnDeserializationListener);
651ce539b54SGraydon Hoare
652ce539b54SGraydon Hoare for (auto &Listener : DependencyCollectors)
653ce539b54SGraydon Hoare Listener->attachToASTReader(*Reader);
654ce539b54SGraydon Hoare
65508c8016cSJan Svoboda auto Listener = std::make_unique<ReadModuleNames>(PP);
65608c8016cSJan Svoboda auto &ListenerRef = *Listener;
65708c8016cSJan Svoboda ASTReader::ListenerScope ReadModuleNamesListener(*Reader,
65808c8016cSJan Svoboda std::move(Listener));
65908c8016cSJan Svoboda
660009e7f20SSebastian Redl switch (Reader->ReadAST(Path,
661a6895d8aSDouglas Gregor Preamble ? serialization::MK_Preamble
6624b29c16eSDouglas Gregor : serialization::MK_PCH,
6632ec29367SArgyrios Kyrtzidis SourceLocation(),
6643d4417c7SBen Langmuir ASTReader::ARR_None)) {
6652c499f65SSebastian Redl case ASTReader::Success:
666599313efSDaniel Dunbar // Set the predefines buffer as suggested by the PCH reader. Typically, the
667599313efSDaniel Dunbar // predefines buffer will be empty.
668599313efSDaniel Dunbar PP.setPredefines(Reader->getSuggestedPredefines());
66908c8016cSJan Svoboda ListenerRef.registerAll();
6704eca9b93SRichard Smith return Reader;
671599313efSDaniel Dunbar
6722c499f65SSebastian Redl case ASTReader::Failure:
673599313efSDaniel Dunbar // Unrecoverable failure: don't even try to process the input file.
674599313efSDaniel Dunbar break;
675599313efSDaniel Dunbar
6767029ce1aSDouglas Gregor case ASTReader::Missing:
677c9ad5fb6SDouglas Gregor case ASTReader::OutOfDate:
678c9ad5fb6SDouglas Gregor case ASTReader::VersionMismatch:
679c9ad5fb6SDouglas Gregor case ASTReader::ConfigurationMismatch:
680c9ad5fb6SDouglas Gregor case ASTReader::HadErrors:
681599313efSDaniel Dunbar // No suitable PCH file could be found. Return an error.
682599313efSDaniel Dunbar break;
683599313efSDaniel Dunbar }
684599313efSDaniel Dunbar
68508c8016cSJan Svoboda ListenerRef.markAllUnavailable();
6864eca9b93SRichard Smith Context.setExternalSource(nullptr);
68749a2790fSCraig Topper return nullptr;
688599313efSDaniel Dunbar }
689f7093b5aSDaniel Dunbar
690f7093b5aSDaniel Dunbar // Code Completion
691f7093b5aSDaniel Dunbar
EnableCodeCompletion(Preprocessor & PP,StringRef Filename,unsigned Line,unsigned Column)6928e984da8SDouglas Gregor static bool EnableCodeCompletion(Preprocessor &PP,
6930772c423SBenjamin Kramer StringRef Filename,
6948e984da8SDouglas Gregor unsigned Line,
6958e984da8SDouglas Gregor unsigned Column) {
6968e984da8SDouglas Gregor // Tell the source manager to chop off the given file at a specific
6978e984da8SDouglas Gregor // line and column.
6988d323d15SHarlan Haskins auto Entry = PP.getFileManager().getFile(Filename);
6998e984da8SDouglas Gregor if (!Entry) {
7008e984da8SDouglas Gregor PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
7018e984da8SDouglas Gregor << Filename;
7028e984da8SDouglas Gregor return true;
7038e984da8SDouglas Gregor }
7048e984da8SDouglas Gregor
7058e984da8SDouglas Gregor // Truncate the named file at the given line/column.
7068d323d15SHarlan Haskins PP.SetCodeCompletionPoint(*Entry, Line, Column);
7078e984da8SDouglas Gregor return false;
7088e984da8SDouglas Gregor }
7098e984da8SDouglas Gregor
createCodeCompletionConsumer()710f7093b5aSDaniel Dunbar void CompilerInstance::createCodeCompletionConsumer() {
711f7093b5aSDaniel Dunbar const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
7128e984da8SDouglas Gregor if (!CompletionConsumer) {
713d3d3e252SYuki Okushi setCodeCompletionConsumer(createCodeCompletionConsumer(
714d3d3e252SYuki Okushi getPreprocessor(), Loc.FileName, Loc.Line, Loc.Column,
715d3d3e252SYuki Okushi getFrontendOpts().CodeCompleteOpts, llvm::outs()));
71600a0cf70SDouglas Gregor return;
7178e984da8SDouglas Gregor } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName,
7188e984da8SDouglas Gregor Loc.Line, Loc.Column)) {
71949a2790fSCraig Topper setCodeCompletionConsumer(nullptr);
7208e984da8SDouglas Gregor return;
7218e984da8SDouglas Gregor }
722f7093b5aSDaniel Dunbar }
723f7093b5aSDaniel Dunbar
createFrontendTimer()7245505dff8SKovarththanan Rajaratnam void CompilerInstance::createFrontendTimer() {
725ae032b6cSMatthias Braun FrontendTimerGroup.reset(
726ae032b6cSMatthias Braun new llvm::TimerGroup("frontend", "Clang front-end time report"));
727ce18a187SRichard Smith FrontendTimer.reset(
728ae032b6cSMatthias Braun new llvm::Timer("frontend", "Clang front-end timer",
729ae032b6cSMatthias Braun *FrontendTimerGroup));
7305505dff8SKovarththanan Rajaratnam }
7315505dff8SKovarththanan Rajaratnam
732f7093b5aSDaniel Dunbar CodeCompleteConsumer *
createCodeCompletionConsumer(Preprocessor & PP,StringRef Filename,unsigned Line,unsigned Column,const CodeCompleteOptions & Opts,raw_ostream & OS)733f7093b5aSDaniel Dunbar CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
7345b816061SYaron Keren StringRef Filename,
735f7093b5aSDaniel Dunbar unsigned Line,
736f7093b5aSDaniel Dunbar unsigned Column,
7373292d06aSDmitri Gribenko const CodeCompleteOptions &Opts,
7380e62c1ccSChris Lattner raw_ostream &OS) {
7398e984da8SDouglas Gregor if (EnableCodeCompletion(PP, Filename, Line, Column))
74049a2790fSCraig Topper return nullptr;
741f7093b5aSDaniel Dunbar
742f7093b5aSDaniel Dunbar // Set up the creation routine for code-completion.
7433292d06aSDmitri Gribenko return new PrintingCodeCompleteConsumer(Opts, OS);
744f7093b5aSDaniel Dunbar }
745566eeb2dSDaniel Dunbar
createSema(TranslationUnitKind TUKind,CodeCompleteConsumer * CompletionConsumer)74669f74f80SDouglas Gregor void CompilerInstance::createSema(TranslationUnitKind TUKind,
7470e93f017SDouglas Gregor CodeCompleteConsumer *CompletionConsumer) {
7480e93f017SDouglas Gregor TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
74969f74f80SDouglas Gregor TUKind, CompletionConsumer));
7507de9969bSBenjamin Kramer // Attach the external sema source if there is any.
7517de9969bSBenjamin Kramer if (ExternalSemaSrc) {
7527de9969bSBenjamin Kramer TheSema->addExternalSource(ExternalSemaSrc.get());
7537de9969bSBenjamin Kramer ExternalSemaSrc->InitializeSema(*TheSema);
7547de9969bSBenjamin Kramer }
7550e93f017SDouglas Gregor }
7560e93f017SDouglas Gregor
757566eeb2dSDaniel Dunbar // Output Files
758566eeb2dSDaniel Dunbar
clearOutputFiles(bool EraseFiles)7591c558cd7SKovarththanan Rajaratnam void CompilerInstance::clearOutputFiles(bool EraseFiles) {
76067a84ec8SBen Langmuir // The ASTConsumer can own streams that write to the output files.
76167a84ec8SBen Langmuir assert(!hasASTConsumer() && "ASTConsumer should be reset");
7629d070b2fSAmy Huang // Ignore errors that occur when trying to discard the temp file.
7630aa128e2SReid Kleckner for (OutputFile &OF : OutputFiles) {
764b5c356a4SAnders Carlsson if (EraseFiles) {
7659d070b2fSAmy Huang if (OF.File)
7669d070b2fSAmy Huang consumeError(OF.File->discard());
7678e464dd7SDuncan P. N. Exon Smith if (!OF.Filename.empty())
7688e464dd7SDuncan P. N. Exon Smith llvm::sys::fs::remove(OF.Filename);
7698e464dd7SDuncan P. N. Exon Smith continue;
7708e464dd7SDuncan P. N. Exon Smith }
7718e464dd7SDuncan P. N. Exon Smith
7729d070b2fSAmy Huang if (!OF.File)
7738e464dd7SDuncan P. N. Exon Smith continue;
774b5c356a4SAnders Carlsson
7759d070b2fSAmy Huang if (OF.File->TmpName.empty()) {
7769d070b2fSAmy Huang consumeError(OF.File->discard());
7779d070b2fSAmy Huang continue;
7789d070b2fSAmy Huang }
7799d070b2fSAmy Huang
78071731d6bSArgyrios Kyrtzidis // If '-working-directory' was passed, the output filename should be
78171731d6bSArgyrios Kyrtzidis // relative to that.
7828e464dd7SDuncan P. N. Exon Smith SmallString<128> NewOutFile(OF.Filename);
7839ba8fb1eSAnders Carlsson FileMgr->FixupRelativePath(NewOutFile);
7847daa1821SAmy Huang
7859d070b2fSAmy Huang llvm::Error E = OF.File->keep(NewOutFile);
7869d070b2fSAmy Huang if (!E)
7879d070b2fSAmy Huang continue;
7889d070b2fSAmy Huang
7899d070b2fSAmy Huang getDiagnostics().Report(diag::err_unable_to_rename_temp)
7909d070b2fSAmy Huang << OF.File->TmpName << OF.Filename << std::move(E);
7919d070b2fSAmy Huang
7929d070b2fSAmy Huang llvm::sys::fs::remove(OF.File->TmpName);
793d0599970SArgyrios Kyrtzidis }
794566eeb2dSDaniel Dunbar OutputFiles.clear();
79586a3ef5bSRichard Smith if (DeleteBuiltModules) {
7965d2ed489SRichard Smith for (auto &Module : BuiltModules)
7975d2ed489SRichard Smith llvm::sys::fs::remove(Module.second);
79886a3ef5bSRichard Smith BuiltModules.clear();
79986a3ef5bSRichard Smith }
800566eeb2dSDaniel Dunbar }
801566eeb2dSDaniel Dunbar
createDefaultOutputFile(bool Binary,StringRef InFile,StringRef Extension,bool RemoveFileOnSignal,bool CreateMissingDirectories,bool ForceUseTemporary)80205d0f1a8SZachary Henkel std::unique_ptr<raw_pwrite_stream> CompilerInstance::createDefaultOutputFile(
80305d0f1a8SZachary Henkel bool Binary, StringRef InFile, StringRef Extension, bool RemoveFileOnSignal,
80405d0f1a8SZachary Henkel bool CreateMissingDirectories, bool ForceUseTemporary) {
805ad7aaa47SDuncan P. N. Exon Smith StringRef OutputPath = getFrontendOpts().OutputFile;
806ad7aaa47SDuncan P. N. Exon Smith Optional<SmallString<128>> PathStorage;
807ad7aaa47SDuncan P. N. Exon Smith if (OutputPath.empty()) {
808ad7aaa47SDuncan P. N. Exon Smith if (InFile == "-" || Extension.empty()) {
809ad7aaa47SDuncan P. N. Exon Smith OutputPath = "-";
810ad7aaa47SDuncan P. N. Exon Smith } else {
811ad7aaa47SDuncan P. N. Exon Smith PathStorage.emplace(InFile);
812ad7aaa47SDuncan P. N. Exon Smith llvm::sys::path::replace_extension(*PathStorage, Extension);
813ad7aaa47SDuncan P. N. Exon Smith OutputPath = *PathStorage;
814ad7aaa47SDuncan P. N. Exon Smith }
815ad7aaa47SDuncan P. N. Exon Smith }
816ad7aaa47SDuncan P. N. Exon Smith
817ad7aaa47SDuncan P. N. Exon Smith return createOutputFile(OutputPath, Binary, RemoveFileOnSignal,
81805d0f1a8SZachary Henkel getFrontendOpts().UseTemporary || ForceUseTemporary,
819ad7aaa47SDuncan P. N. Exon Smith CreateMissingDirectories);
820420b0f1bSDaniel Dunbar }
821420b0f1bSDaniel Dunbar
createNullOutputFile()82203f8907fSPeter Collingbourne std::unique_ptr<raw_pwrite_stream> CompilerInstance::createNullOutputFile() {
8232b3d49b6SJonas Devlieghere return std::make_unique<llvm::raw_null_ostream>();
824ea04672cSAlp Toker }
825ea04672cSAlp Toker
82603f8907fSPeter Collingbourne std::unique_ptr<raw_pwrite_stream>
createOutputFile(StringRef OutputPath,bool Binary,bool RemoveFileOnSignal,bool UseTemporary,bool CreateMissingDirectories)8272f16bc10SRafael Espindola CompilerInstance::createOutputFile(StringRef OutputPath, bool Binary,
828ad7aaa47SDuncan P. N. Exon Smith bool RemoveFileOnSignal, bool UseTemporary,
829b9c62c07SDaniel Dunbar bool CreateMissingDirectories) {
830ad7aaa47SDuncan P. N. Exon Smith Expected<std::unique_ptr<raw_pwrite_stream>> OS =
831ad7aaa47SDuncan P. N. Exon Smith createOutputFileImpl(OutputPath, Binary, RemoveFileOnSignal, UseTemporary,
832ad7aaa47SDuncan P. N. Exon Smith CreateMissingDirectories);
833ad7aaa47SDuncan P. N. Exon Smith if (OS)
834ad7aaa47SDuncan P. N. Exon Smith return std::move(*OS);
835ad7aaa47SDuncan P. N. Exon Smith getDiagnostics().Report(diag::err_fe_unable_to_open_output)
836ad7aaa47SDuncan P. N. Exon Smith << OutputPath << errorToErrorCode(OS.takeError()).message();
83749a2790fSCraig Topper return nullptr;
838420b0f1bSDaniel Dunbar }
839420b0f1bSDaniel Dunbar
840ad7aaa47SDuncan P. N. Exon Smith Expected<std::unique_ptr<llvm::raw_pwrite_stream>>
createOutputFileImpl(StringRef OutputPath,bool Binary,bool RemoveFileOnSignal,bool UseTemporary,bool CreateMissingDirectories)841ad7aaa47SDuncan P. N. Exon Smith CompilerInstance::createOutputFileImpl(StringRef OutputPath, bool Binary,
842ad7aaa47SDuncan P. N. Exon Smith bool RemoveFileOnSignal,
843ad7aaa47SDuncan P. N. Exon Smith bool UseTemporary,
844ad7aaa47SDuncan P. N. Exon Smith bool CreateMissingDirectories) {
845b9c62c07SDaniel Dunbar assert((!CreateMissingDirectories || UseTemporary) &&
846b9c62c07SDaniel Dunbar "CreateMissingDirectories is only allowed when using temporary files");
847b9c62c07SDaniel Dunbar
848b8984329SAhmed Charles std::unique_ptr<llvm::raw_fd_ostream> OS;
849ad7aaa47SDuncan P. N. Exon Smith Optional<StringRef> OSFile;
85008a2bfd2SArgyrios Kyrtzidis
85173c23a71SRafael Espindola if (UseTemporary) {
852ad7aaa47SDuncan P. N. Exon Smith if (OutputPath == "-")
85373c23a71SRafael Espindola UseTemporary = false;
85473c23a71SRafael Espindola else {
85573c23a71SRafael Espindola llvm::sys::fs::file_status Status;
85673c23a71SRafael Espindola llvm::sys::fs::status(OutputPath, Status);
85773c23a71SRafael Espindola if (llvm::sys::fs::exists(Status)) {
85873c23a71SRafael Espindola // Fail early if we can't write to the final destination.
859ad7aaa47SDuncan P. N. Exon Smith if (!llvm::sys::fs::can_write(OutputPath))
860ad7aaa47SDuncan P. N. Exon Smith return llvm::errorCodeToError(
861ad7aaa47SDuncan P. N. Exon Smith make_error_code(llvm::errc::operation_not_permitted));
86273c23a71SRafael Espindola
86373c23a71SRafael Espindola // Don't use a temporary if the output is a special file. This handles
86473c23a71SRafael Espindola // things like '-o /dev/null'
86573c23a71SRafael Espindola if (!llvm::sys::fs::is_regular_file(Status))
86673c23a71SRafael Espindola UseTemporary = false;
86773c23a71SRafael Espindola }
86873c23a71SRafael Espindola }
86973c23a71SRafael Espindola }
87073c23a71SRafael Espindola
8719d070b2fSAmy Huang Optional<llvm::sys::fs::TempFile> Temp;
87273c23a71SRafael Espindola if (UseTemporary) {
873d0599970SArgyrios Kyrtzidis // Create a temporary file.
8742db47198SNico Weber // Insert -%%%%%%%% before the extension (if any), and because some tools
8752db47198SNico Weber // (noticeable, clang's own GlobalModuleIndex.cpp) glob for build
8762db47198SNico Weber // artifacts, also append .tmp.
877ad7aaa47SDuncan P. N. Exon Smith StringRef OutputExtension = llvm::sys::path::extension(OutputPath);
8782db47198SNico Weber SmallString<128> TempPath =
879ad7aaa47SDuncan P. N. Exon Smith StringRef(OutputPath).drop_back(OutputExtension.size());
88008a2bfd2SArgyrios Kyrtzidis TempPath += "-%%%%%%%%";
8812db47198SNico Weber TempPath += OutputExtension;
8822db47198SNico Weber TempPath += ".tmp";
8839d070b2fSAmy Huang Expected<llvm::sys::fs::TempFile> ExpectedFile =
8840e8506deSAbhina Sreeskantharajan llvm::sys::fs::TempFile::create(
8850e8506deSAbhina Sreeskantharajan TempPath, llvm::sys::fs::all_read | llvm::sys::fs::all_write,
8860e8506deSAbhina Sreeskantharajan Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_Text);
887157f34bdSRafael Espindola
8889d070b2fSAmy Huang llvm::Error E = handleErrors(
8899d070b2fSAmy Huang ExpectedFile.takeError(), [&](const llvm::ECError &E) -> llvm::Error {
8909d070b2fSAmy Huang std::error_code EC = E.convertToErrorCode();
891157f34bdSRafael Espindola if (CreateMissingDirectories &&
89271de0b61SRafael Espindola EC == llvm::errc::no_such_file_or_directory) {
893157f34bdSRafael Espindola StringRef Parent = llvm::sys::path::parent_path(OutputPath);
894157f34bdSRafael Espindola EC = llvm::sys::fs::create_directories(Parent);
895157f34bdSRafael Espindola if (!EC) {
8969d070b2fSAmy Huang ExpectedFile = llvm::sys::fs::TempFile::create(TempPath);
8979d070b2fSAmy Huang if (!ExpectedFile)
8989d070b2fSAmy Huang return llvm::errorCodeToError(
8999d070b2fSAmy Huang llvm::errc::no_such_file_or_directory);
90020797b12SAmy Huang }
90120797b12SAmy Huang }
9029d070b2fSAmy Huang return llvm::errorCodeToError(EC);
9039d070b2fSAmy Huang });
90420797b12SAmy Huang
9059d070b2fSAmy Huang if (E) {
9069d070b2fSAmy Huang consumeError(std::move(E));
9079d070b2fSAmy Huang } else {
9089d070b2fSAmy Huang Temp = std::move(ExpectedFile.get());
909cf11d958SAmy Huang OS.reset(new llvm::raw_fd_ostream(Temp->FD, /*shouldClose=*/false));
9109d070b2fSAmy Huang OSFile = Temp->TmpName;
91108a2bfd2SArgyrios Kyrtzidis }
91273c23a71SRafael Espindola // If we failed to create the temporary, fallback to writing to the file
91373c23a71SRafael Espindola // directly. This handles the corner case where we cannot write to the
91473c23a71SRafael Espindola // directory, but can write to the file.
915d0599970SArgyrios Kyrtzidis }
916d0599970SArgyrios Kyrtzidis
91708a2bfd2SArgyrios Kyrtzidis if (!OS) {
918ad7aaa47SDuncan P. N. Exon Smith OSFile = OutputPath;
919ad7aaa47SDuncan P. N. Exon Smith std::error_code EC;
92069f3528cSNAKAMURA Takumi OS.reset(new llvm::raw_fd_ostream(
921ad7aaa47SDuncan P. N. Exon Smith *OSFile, EC,
92282b3e28eSAbhina Sreeskantharajan (Binary ? llvm::sys::fs::OF_None : llvm::sys::fs::OF_TextWithCRLF)));
923ad7aaa47SDuncan P. N. Exon Smith if (EC)
924ad7aaa47SDuncan P. N. Exon Smith return llvm::errorCodeToError(EC);
92508a2bfd2SArgyrios Kyrtzidis }
926420b0f1bSDaniel Dunbar
927ad7aaa47SDuncan P. N. Exon Smith // Add the output file -- but don't try to remove "-", since this means we are
928ad7aaa47SDuncan P. N. Exon Smith // using stdin.
929ad7aaa47SDuncan P. N. Exon Smith OutputFiles.emplace_back(((OutputPath != "-") ? OutputPath : "").str(),
9309d070b2fSAmy Huang std::move(Temp));
931420b0f1bSDaniel Dunbar
9322f16bc10SRafael Espindola if (!Binary || OS->supportsSeeking())
9332f16bc10SRafael Espindola return std::move(OS);
9342f16bc10SRafael Espindola
9352f721476SDuncan P. N. Exon Smith return std::make_unique<llvm::buffer_unique_ostream>(std::move(OS));
936420b0f1bSDaniel Dunbar }
937409e890fSDaniel Dunbar
938409e890fSDaniel Dunbar // Initialization Utilities
939409e890fSDaniel Dunbar
InitializeSourceManager(const FrontendInputFile & Input)9401b3240b0SArgyrios Kyrtzidis bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input){
941ef875c22SAndrzej Warzynski return InitializeSourceManager(Input, getDiagnostics(), getFileManager(),
942ef875c22SAndrzej Warzynski getSourceManager());
943409e890fSDaniel Dunbar }
944409e890fSDaniel Dunbar
9452ca4be97SNico Weber // static
InitializeSourceManager(const FrontendInputFile & Input,DiagnosticsEngine & Diags,FileManager & FileMgr,SourceManager & SourceMgr)946ef875c22SAndrzej Warzynski bool CompilerInstance::InitializeSourceManager(const FrontendInputFile &Input,
947ef875c22SAndrzej Warzynski DiagnosticsEngine &Diags,
948ef875c22SAndrzej Warzynski FileManager &FileMgr,
949ef875c22SAndrzej Warzynski SourceManager &SourceMgr) {
950f3f84616SRichard Smith SrcMgr::CharacteristicKind Kind =
951f3f84616SRichard Smith Input.getKind().getFormat() == InputKind::ModuleMap
952f3f84616SRichard Smith ? Input.isSystem() ? SrcMgr::C_System_ModuleMap
953f3f84616SRichard Smith : SrcMgr::C_User_ModuleMap
954f3f84616SRichard Smith : Input.isSystem() ? SrcMgr::C_System : SrcMgr::C_User;
9551b3240b0SArgyrios Kyrtzidis
9566566e23eSArgyrios Kyrtzidis if (Input.isBuffer()) {
95751d1d585SDuncan P. N. Exon Smith SourceMgr.setMainFileID(SourceMgr.createFileID(Input.getBuffer(), Kind));
9588b563665SYaron Keren assert(SourceMgr.getMainFileID().isValid() &&
9596566e23eSArgyrios Kyrtzidis "Couldn't establish MainFileID!");
9606566e23eSArgyrios Kyrtzidis return true;
9616566e23eSArgyrios Kyrtzidis }
9626566e23eSArgyrios Kyrtzidis
9636566e23eSArgyrios Kyrtzidis StringRef InputFile = Input.getFile();
9646566e23eSArgyrios Kyrtzidis
9657c06d866SArgyrios Kyrtzidis // Figure out where to get and map in the main file.
9663ee43adfSDuncan P. N. Exon Smith auto FileOrErr = InputFile == "-"
9673ee43adfSDuncan P. N. Exon Smith ? FileMgr.getSTDIN()
9683ee43adfSDuncan P. N. Exon Smith : FileMgr.getFileRef(InputFile, /*OpenFile=*/true);
9698d323d15SHarlan Haskins if (!FileOrErr) {
9703ee43adfSDuncan P. N. Exon Smith // FIXME: include the error in the diagnostic even when it's not stdin.
9713ee43adfSDuncan P. N. Exon Smith auto EC = llvm::errorToErrorCode(FileOrErr.takeError());
9723ee43adfSDuncan P. N. Exon Smith if (InputFile != "-")
973409e890fSDaniel Dunbar Diags.Report(diag::err_fe_error_reading) << InputFile;
9743ee43adfSDuncan P. N. Exon Smith else
9753ee43adfSDuncan P. N. Exon Smith Diags.Report(diag::err_fe_error_reading_stdin) << EC.message();
976409e890fSDaniel Dunbar return false;
977409e890fSDaniel Dunbar }
978e2951f48SDaniel Dunbar
979b3463220SDuncan P. N. Exon Smith SourceMgr.setMainFileID(
980245218bbSDuncan P. N. Exon Smith SourceMgr.createFileID(*FileOrErr, SourceLocation(), Kind));
981409e890fSDaniel Dunbar
9828b563665SYaron Keren assert(SourceMgr.getMainFileID().isValid() &&
98352765215SDan Gohman "Couldn't establish MainFileID!");
984409e890fSDaniel Dunbar return true;
985409e890fSDaniel Dunbar }
9864f2bc55dSDaniel Dunbar
9874f2bc55dSDaniel Dunbar // High-Level Operations
9884f2bc55dSDaniel Dunbar
ExecuteAction(FrontendAction & Act)9894f2bc55dSDaniel Dunbar bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
9904f2bc55dSDaniel Dunbar assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
9914f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
9924f2bc55dSDaniel Dunbar assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
9934f2bc55dSDaniel Dunbar
99426a92d58SRichard Smith // Mark this point as the bottom of the stack if we don't have somewhere
99526a92d58SRichard Smith // better. We generally expect frontend actions to be invoked with (nearly)
99626a92d58SRichard Smith // DesiredStackSpace available.
99726a92d58SRichard Smith noteBottomOfStack();
99826a92d58SRichard Smith
99976cb4cd0SJan Svoboda auto FinishDiagnosticClient = llvm::make_scope_exit([&]() {
100076cb4cd0SJan Svoboda // Notify the diagnostic client that all files were processed.
100176cb4cd0SJan Svoboda getDiagnosticClient().finish();
100276cb4cd0SJan Svoboda });
100376cb4cd0SJan Svoboda
100487cb734cSScott Linder raw_ostream &OS = getVerboseOutputStream();
10054f2bc55dSDaniel Dunbar
1006d6509cf2SRichard Smith if (!Act.PrepareToExecute(*this))
1007d6509cf2SRichard Smith return false;
1008d6509cf2SRichard Smith
1009d412dbe3SYu-Hsun Chiang if (!createTarget())
10104f2bc55dSDaniel Dunbar return false;
10114f2bc55dSDaniel Dunbar
101229898f45SFariborz Jahanian // rewriter project will change target built-in bool type from its default.
101329898f45SFariborz Jahanian if (getFrontendOpts().ProgramAction == frontend::RewriteObjC)
101429898f45SFariborz Jahanian getTarget().noSignedCharForObjCBool();
101529898f45SFariborz Jahanian
10164f2bc55dSDaniel Dunbar // Validate/process some options.
10174f2bc55dSDaniel Dunbar if (getHeaderSearchOpts().Verbose)
10184f2bc55dSDaniel Dunbar OS << "clang -cc1 version " CLANG_VERSION_STRING
1019f988d006SAlp Toker << " based upon " << BACKEND_PACKAGE_STRING
10208188c8a1SSebastian Pop << " default target " << llvm::sys::getDefaultTargetTriple() << "\n";
10214f2bc55dSDaniel Dunbar
10221821265dSYuanfang Chen if (getCodeGenOpts().TimePasses)
10234f2bc55dSDaniel Dunbar createFrontendTimer();
10244f2bc55dSDaniel Dunbar
1025abb6eea1SMatthias Braun if (getFrontendOpts().ShowStats || !getFrontendOpts().StatsFile.empty())
1026ec1c5a20SMatthias Braun llvm::EnableStatistics(false);
1027171b780cSDouglas Gregor
10285b60ad68SVedant Kumar for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) {
1029eeccb30bSTed Kremenek // Reset the ID tables if we are reusing the SourceManager and parsing
1030eeccb30bSTed Kremenek // regular files.
1031eeccb30bSTed Kremenek if (hasSourceManager() && !Act.isModelParsingAction())
10324f2bc55dSDaniel Dunbar getSourceManager().clearIDTables();
10334f2bc55dSDaniel Dunbar
10345b60ad68SVedant Kumar if (Act.BeginSourceFile(*this, FIF)) {
10350e828958SJF Bastien if (llvm::Error Err = Act.Execute()) {
10360e828958SJF Bastien consumeError(std::move(Err)); // FIXME this drops errors on the floor.
10370e828958SJF Bastien }
10384f2bc55dSDaniel Dunbar Act.EndSourceFile();
10394f2bc55dSDaniel Dunbar }
10404f2bc55dSDaniel Dunbar }
10414f2bc55dSDaniel Dunbar
1042198cb4dfSChris Lattner if (getDiagnosticOpts().ShowCarets) {
1043c79346a5SArgyrios Kyrtzidis // We can have multiple diagnostics sharing one diagnostic client.
1044c79346a5SArgyrios Kyrtzidis // Get the total number of warnings/errors from the client.
1045c79346a5SArgyrios Kyrtzidis unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings();
1046c79346a5SArgyrios Kyrtzidis unsigned NumErrors = getDiagnostics().getClient()->getNumErrors();
1047198cb4dfSChris Lattner
1048198cb4dfSChris Lattner if (NumWarnings)
1049198cb4dfSChris Lattner OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
1050198cb4dfSChris Lattner if (NumWarnings && NumErrors)
1051198cb4dfSChris Lattner OS << " and ";
1052198cb4dfSChris Lattner if (NumErrors)
1053198cb4dfSChris Lattner OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
105478137ec8SJustin Lebar if (NumWarnings || NumErrors) {
105578137ec8SJustin Lebar OS << " generated";
105678137ec8SJustin Lebar if (getLangOpts().CUDA) {
105778137ec8SJustin Lebar if (!getLangOpts().CUDAIsDevice) {
105878137ec8SJustin Lebar OS << " when compiling for host";
105978137ec8SJustin Lebar } else {
106078137ec8SJustin Lebar OS << " when compiling for " << getTargetOpts().CPU;
106178137ec8SJustin Lebar }
106278137ec8SJustin Lebar }
106378137ec8SJustin Lebar OS << ".\n";
106478137ec8SJustin Lebar }
1065198cb4dfSChris Lattner }
10664f2bc55dSDaniel Dunbar
1067abb6eea1SMatthias Braun if (getFrontendOpts().ShowStats) {
1068abb6eea1SMatthias Braun if (hasFileManager()) {
10694f2bc55dSDaniel Dunbar getFileManager().PrintStats();
1070abb6eea1SMatthias Braun OS << '\n';
1071abb6eea1SMatthias Braun }
1072abb6eea1SMatthias Braun llvm::PrintStatistics(OS);
1073abb6eea1SMatthias Braun }
1074abb6eea1SMatthias Braun StringRef StatsFile = getFrontendOpts().StatsFile;
1075abb6eea1SMatthias Braun if (!StatsFile.empty()) {
1076abb6eea1SMatthias Braun std::error_code EC;
10772b3d49b6SJonas Devlieghere auto StatS = std::make_unique<llvm::raw_fd_ostream>(
107882b3e28eSAbhina Sreeskantharajan StatsFile, EC, llvm::sys::fs::OF_TextWithCRLF);
1079abb6eea1SMatthias Braun if (EC) {
1080abb6eea1SMatthias Braun getDiagnostics().Report(diag::warn_fe_unable_to_open_stats_file)
1081abb6eea1SMatthias Braun << StatsFile << EC.message();
1082abb6eea1SMatthias Braun } else {
1083abb6eea1SMatthias Braun llvm::PrintStatisticsJSON(*StatS);
1084abb6eea1SMatthias Braun }
10854f2bc55dSDaniel Dunbar }
10864f2bc55dSDaniel Dunbar
1087bc467933SArgyrios Kyrtzidis return !getDiagnostics().getClient()->getNumErrors();
10884f2bc55dSDaniel Dunbar }
10894f2bc55dSDaniel Dunbar
LoadRequestedPlugins()1090f4f9ad0fSVassil Vassilev void CompilerInstance::LoadRequestedPlugins() {
1091f4f9ad0fSVassil Vassilev // Load any requested plugins.
1092f4f9ad0fSVassil Vassilev for (const std::string &Path : getFrontendOpts().Plugins) {
1093f4f9ad0fSVassil Vassilev std::string Error;
1094f4f9ad0fSVassil Vassilev if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error))
1095f4f9ad0fSVassil Vassilev getDiagnostics().Report(diag::err_fe_unable_to_load_plugin)
1096f4f9ad0fSVassil Vassilev << Path << Error;
1097f4f9ad0fSVassil Vassilev }
1098f4f9ad0fSVassil Vassilev
1099f4f9ad0fSVassil Vassilev // Check if any of the loaded plugins replaces the main AST action
1100f4f9ad0fSVassil Vassilev for (const FrontendPluginRegistry::entry &Plugin :
1101f4f9ad0fSVassil Vassilev FrontendPluginRegistry::entries()) {
1102f4f9ad0fSVassil Vassilev std::unique_ptr<PluginASTAction> P(Plugin.instantiate());
1103f4f9ad0fSVassil Vassilev if (P->getActionType() == PluginASTAction::ReplaceAction) {
1104f4f9ad0fSVassil Vassilev getFrontendOpts().ProgramAction = clang::frontend::PluginAction;
1105f4f9ad0fSVassil Vassilev getFrontendOpts().ActionName = Plugin.getName().str();
1106f4f9ad0fSVassil Vassilev break;
1107f4f9ad0fSVassil Vassilev }
1108f4f9ad0fSVassil Vassilev }
1109f4f9ad0fSVassil Vassilev }
1110f4f9ad0fSVassil Vassilev
11119fc8faf9SAdrian Prantl /// Determine the appropriate source input kind based on language
1112faeb1d46SDouglas Gregor /// options.
getLanguageFromOptions(const LangOptions & LangOpts)111309d890d7SRainer Orth static Language getLanguageFromOptions(const LangOptions &LangOpts) {
1114faeb1d46SDouglas Gregor if (LangOpts.OpenCL)
111509d890d7SRainer Orth return Language::OpenCL;
1116faeb1d46SDouglas Gregor if (LangOpts.CUDA)
111709d890d7SRainer Orth return Language::CUDA;
1118fa98390bSErik Pilkington if (LangOpts.ObjC)
111909d890d7SRainer Orth return LangOpts.CPlusPlus ? Language::ObjCXX : Language::ObjC;
112009d890d7SRainer Orth return LangOpts.CPlusPlus ? Language::CXX : Language::C;
1121faeb1d46SDouglas Gregor }
1122faeb1d46SDouglas Gregor
11239fc8faf9SAdrian Prantl /// Compile a module file for the given module, using the options
1124b797d59fSBen Langmuir /// provided by the importing compiler instance. Returns true if the module
1125b797d59fSBen Langmuir /// was built without errors.
11265d2ed489SRichard Smith 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 &){})11275d2ed489SRichard Smith compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
11285d2ed489SRichard Smith StringRef ModuleName, FrontendInputFile Input,
11295d2ed489SRichard Smith StringRef OriginalModuleMapFile, StringRef ModuleFileName,
11305d2ed489SRichard Smith llvm::function_ref<void(CompilerInstance &)> PreBuildStep =
11315d2ed489SRichard Smith [](CompilerInstance &) {},
11325d2ed489SRichard Smith llvm::function_ref<void(CompilerInstance &)> PostBuildStep =
__anon95e63fe90502(CompilerInstance &) 11335d2ed489SRichard Smith [](CompilerInstance &) {}) {
1134d880de2dSAnton Afanasyev llvm::TimeTraceScope TimeScope("Module Compile", ModuleName);
1135d880de2dSAnton Afanasyev
1136766a08dfSBen Barham // Never compile a module that's already finalized - this would cause the
1137766a08dfSBen Barham // existing module to be freed, causing crashes if it is later referenced
1138766a08dfSBen Barham if (ImportingInstance.getModuleCache().isPCMFinal(ModuleFileName)) {
1139766a08dfSBen Barham ImportingInstance.getDiagnostics().Report(
1140766a08dfSBen Barham ImportLoc, diag::err_module_rebuild_finalized)
1141766a08dfSBen Barham << ModuleName;
1142766a08dfSBen Barham return false;
1143766a08dfSBen Barham }
1144766a08dfSBen Barham
1145faeb1d46SDouglas Gregor // Construct a compiler invocation for creating this module.
1146ea4395ebSDavid Blaikie auto Invocation =
1147ea4395ebSDavid Blaikie std::make_shared<CompilerInvocation>(ImportingInstance.getInvocation());
114844bf68d8SDouglas Gregor
1149f545f67dSDouglas Gregor PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
1150f545f67dSDouglas Gregor
115144bf68d8SDouglas Gregor // For any options that aren't intended to affect how a module is built,
115244bf68d8SDouglas Gregor // reset them to their default values.
11538cf47df7STed Kremenek Invocation->getLangOpts()->resetNonModularOptions();
1154f545f67dSDouglas Gregor PPOpts.resetNonModularOptions();
115544bf68d8SDouglas Gregor
11565dc3899cSDouglas Gregor // Remove any macro definitions that are explicitly ignored by the module.
11575dc3899cSDouglas Gregor // They aren't supposed to affect how the module is built anyway.
115860fa2888SDuncan P. N. Exon Smith HeaderSearchOptions &HSOpts = Invocation->getHeaderSearchOpts();
115976f0f1ccSKazu Hirata llvm::erase_if(PPOpts.Macros,
__anon95e63fe90602(const std::pair<std::string, bool> &def) 116076f0f1ccSKazu Hirata [&HSOpts](const std::pair<std::string, bool> &def) {
1161bbdd7640SBenjamin Kramer StringRef MacroDef = def.first;
116276f0f1ccSKazu Hirata return HSOpts.ModulesIgnoreMacros.contains(
116376f0f1ccSKazu Hirata llvm::CachedHashString(MacroDef.split('=').first));
1164d245f2e8SKazu Hirata });
11655dc3899cSDouglas Gregor
1166970b2819SBruno Cardoso Lopes // If the original compiler invocation had -fmodule-name, pass it through.
1167970b2819SBruno Cardoso Lopes Invocation->getLangOpts()->ModuleName =
1168970b2819SBruno Cardoso Lopes ImportingInstance.getInvocation().getLangOpts()->ModuleName;
1169970b2819SBruno Cardoso Lopes
11707d106e42SDouglas Gregor // Note the name of the module we're building.
1171adcd0268SBenjamin Kramer Invocation->getLangOpts()->CurrentModule = std::string(ModuleName);
11727d106e42SDouglas Gregor
11737a626570SDouglas Gregor // Make sure that the failed-module structure has been allocated in
11747a626570SDouglas Gregor // the importing instance, and propagate the pointer to the newly-created
11757a626570SDouglas Gregor // instance.
11767a626570SDouglas Gregor PreprocessorOptions &ImportingPPOpts
11777a626570SDouglas Gregor = ImportingInstance.getInvocation().getPreprocessorOpts();
11787a626570SDouglas Gregor if (!ImportingPPOpts.FailedModules)
1179f95113daSDavid Blaikie ImportingPPOpts.FailedModules =
1180f95113daSDavid Blaikie std::make_shared<PreprocessorOptions::FailedModulesSet>();
11817a626570SDouglas Gregor PPOpts.FailedModules = ImportingPPOpts.FailedModules;
11827a626570SDouglas Gregor
1183514b636aSDouglas Gregor // If there is a module map file, build the module using the module map.
1184514b636aSDouglas Gregor // Set up the inputs/outputs so that we build the module from its umbrella
1185514b636aSDouglas Gregor // header.
1186514b636aSDouglas Gregor FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
1187514b636aSDouglas Gregor FrontendOpts.OutputFile = ModuleFileName.str();
1188514b636aSDouglas Gregor FrontendOpts.DisableFree = false;
1189c1bbec85SDouglas Gregor FrontendOpts.GenerateGlobalModuleIndex = false;
1190e75ee0f0SRichard Smith FrontendOpts.BuildingImplicitModule = true;
1191adcd0268SBenjamin Kramer FrontendOpts.OriginalModuleMap = std::string(OriginalModuleMapFile);
119260fa2888SDuncan P. N. Exon Smith // Force implicitly-built modules to hash the content of the module file.
119360fa2888SDuncan P. N. Exon Smith HSOpts.ModulesHashContent = true;
11945d2ed489SRichard Smith FrontendOpts.Inputs = {Input};
1195f545f67dSDouglas Gregor
1196f545f67dSDouglas Gregor // Don't free the remapped file buffers; they are owned by our caller.
1197f545f67dSDouglas Gregor PPOpts.RetainRemappedFileBuffers = true;
1198514b636aSDouglas Gregor
1199514b636aSDouglas Gregor Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
1200514b636aSDouglas Gregor assert(ImportingInstance.getInvocation().getModuleHash() ==
1201514b636aSDouglas Gregor Invocation->getModuleHash() && "Module hash mismatch!");
1202514b636aSDouglas Gregor
1203514b636aSDouglas Gregor // Construct a compiler instance that will be used to actually create the
12048bef5cd4SDuncan P. N. Exon Smith // module. Since we're sharing an in-memory module cache,
1205030d7d6dSDuncan P. N. Exon Smith // CompilerInstance::CompilerInstance is responsible for finalizing the
1206030d7d6dSDuncan P. N. Exon Smith // buffers to prevent use-after-frees.
1207bb165fb0SAdrian Prantl CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(),
12088bef5cd4SDuncan P. N. Exon Smith &ImportingInstance.getModuleCache());
1209ea4395ebSDavid Blaikie auto &Inv = *Invocation;
1210ea4395ebSDavid Blaikie Instance.setInvocation(std::move(Invocation));
12116b930967SDouglas Gregor
12126b930967SDouglas Gregor Instance.createDiagnostics(new ForwardingDiagnosticConsumer(
12136b930967SDouglas Gregor ImportingInstance.getDiagnosticClient()),
121430071ceaSDouglas Gregor /*ShouldOwnClient=*/true);
1215514b636aSDouglas Gregor
121663365431SDouglas Gregor // Note that this module is part of the module build stack, so that we
1217af8f0263SDouglas Gregor // can detect cycles in the module graph.
1218d066d4c8SBen Langmuir Instance.setFileManager(&ImportingInstance.getFileManager());
1219af8f0263SDouglas Gregor Instance.createSourceManager(Instance.getFileManager());
1220af8f0263SDouglas Gregor SourceManager &SourceMgr = Instance.getSourceManager();
122163365431SDouglas Gregor SourceMgr.setModuleBuildStack(
122263365431SDouglas Gregor ImportingInstance.getSourceManager().getModuleBuildStack());
12235d2ed489SRichard Smith SourceMgr.pushModuleBuildStack(ModuleName,
1224af8f0263SDouglas Gregor FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager()));
1225af8f0263SDouglas Gregor
122686d1259cSJustin Bogner // If we're collecting module dependencies, we need to share a collector
122738c1e6d3SRichard Smith // between all of the module CompilerInstances. Other than that, we don't
122838c1e6d3SRichard Smith // want to produce any dependency output from the module build.
122986d1259cSJustin Bogner Instance.setModuleDepCollector(ImportingInstance.getModuleDepCollector());
1230ea4395ebSDavid Blaikie Inv.getDependencyOutputOpts() = DependencyOutputOptions();
123186d1259cSJustin Bogner
123299891da7SRichard Smith ImportingInstance.getDiagnostics().Report(ImportLoc,
123399891da7SRichard Smith diag::remark_module_build)
12345d2ed489SRichard Smith << ModuleName << ModuleFileName;
12355d2ed489SRichard Smith
12365d2ed489SRichard Smith PreBuildStep(Instance);
123799891da7SRichard Smith
1238514b636aSDouglas Gregor // Execute the action to actually build the module in-place. Use a separate
1239514b636aSDouglas Gregor // thread so that we get a stack large enough.
124067a84ec8SBen Langmuir bool Crashed = !llvm::CrashRecoveryContext().RunSafelyOnThread(
__anon95e63fe90702() 1241f74d9466SRichard Smith [&]() {
1242f74d9466SRichard Smith GenerateModuleFromModuleMapAction Action;
1243f74d9466SRichard Smith Instance.ExecuteAction(Action);
1244f74d9466SRichard Smith },
12450a7b297dSRichard Smith DesiredStackSize);
12466b930967SDouglas Gregor
12475d2ed489SRichard Smith PostBuildStep(Instance);
12485d2ed489SRichard Smith
124999891da7SRichard Smith ImportingInstance.getDiagnostics().Report(ImportLoc,
125099891da7SRichard Smith diag::remark_module_build_done)
12515d2ed489SRichard Smith << ModuleName;
125299891da7SRichard Smith
125367a84ec8SBen Langmuir if (Crashed) {
125467a84ec8SBen Langmuir // Clear the ASTConsumer if it hasn't been already, in case it owns streams
125567a84ec8SBen Langmuir // that must be closed before clearing output files.
125667a84ec8SBen Langmuir Instance.setSema(nullptr);
125767a84ec8SBen Langmuir Instance.setASTConsumer(nullptr);
125867a84ec8SBen Langmuir
125967a84ec8SBen Langmuir // Delete any remaining temporary files related to Instance.
126013afbf42SBenjamin Kramer Instance.clearOutputFiles(/*EraseFiles=*/true);
126167a84ec8SBen Langmuir }
12625e306b12SDouglas Gregor
1263a8cb39baSArgyrios Kyrtzidis // If \p AllowPCMWithCompilerErrors is set return 'success' even if errors
1264a8cb39baSArgyrios Kyrtzidis // occurred.
1265a8cb39baSArgyrios Kyrtzidis return !Instance.getDiagnostics().hasErrorOccurred() ||
1266a8cb39baSArgyrios Kyrtzidis Instance.getFrontendOpts().AllowPCMWithCompilerErrors;
12675d2ed489SRichard Smith }
12685d2ed489SRichard Smith
getPublicModuleMap(const FileEntry * File,FileManager & FileMgr)126922d97065SBruno Cardoso Lopes static const FileEntry *getPublicModuleMap(const FileEntry *File,
127022d97065SBruno Cardoso Lopes FileManager &FileMgr) {
127122d97065SBruno Cardoso Lopes StringRef Filename = llvm::sys::path::filename(File->getName());
127222d97065SBruno Cardoso Lopes SmallString<128> PublicFilename(File->getDir()->getName());
127322d97065SBruno Cardoso Lopes if (Filename == "module_private.map")
127422d97065SBruno Cardoso Lopes llvm::sys::path::append(PublicFilename, "module.map");
127522d97065SBruno Cardoso Lopes else if (Filename == "module.private.modulemap")
127622d97065SBruno Cardoso Lopes llvm::sys::path::append(PublicFilename, "module.modulemap");
127722d97065SBruno Cardoso Lopes else
127822d97065SBruno Cardoso Lopes return nullptr;
12798d323d15SHarlan Haskins if (auto FE = FileMgr.getFile(PublicFilename))
12808d323d15SHarlan Haskins return *FE;
12818d323d15SHarlan Haskins return nullptr;
128222d97065SBruno Cardoso Lopes }
128322d97065SBruno Cardoso Lopes
12845cca6223SDuncan P. N. Exon Smith /// Compile a module file for the given module in a separate compiler instance,
12855cca6223SDuncan P. N. Exon Smith /// using the options provided by the importing compiler instance. Returns true
12865cca6223SDuncan P. N. Exon Smith /// if the module was built without errors.
compileModule(CompilerInstance & ImportingInstance,SourceLocation ImportLoc,Module * Module,StringRef ModuleFileName)12875cca6223SDuncan P. N. Exon Smith static bool compileModule(CompilerInstance &ImportingInstance,
12885cca6223SDuncan P. N. Exon Smith SourceLocation ImportLoc, Module *Module,
12895d2ed489SRichard Smith StringRef ModuleFileName) {
12905d2ed489SRichard Smith InputKind IK(getLanguageFromOptions(ImportingInstance.getLangOpts()),
12915d2ed489SRichard Smith InputKind::ModuleMap);
12925d2ed489SRichard Smith
12935d2ed489SRichard Smith // Get or create the module map that we'll use to build this module.
12945d2ed489SRichard Smith ModuleMap &ModMap
12955d2ed489SRichard Smith = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
12965d2ed489SRichard Smith bool Result;
12975d2ed489SRichard Smith if (const FileEntry *ModuleMapFile =
12985d2ed489SRichard Smith ModMap.getContainingModuleMapFile(Module)) {
129922d97065SBruno Cardoso Lopes // Canonicalize compilation to start with the public module map. This is
130022d97065SBruno Cardoso Lopes // vital for submodules declarations in the private module maps to be
130122d97065SBruno Cardoso Lopes // correctly parsed when depending on a top level module in the public one.
130222d97065SBruno Cardoso Lopes if (const FileEntry *PublicMMFile = getPublicModuleMap(
130322d97065SBruno Cardoso Lopes ModuleMapFile, ImportingInstance.getFileManager()))
130422d97065SBruno Cardoso Lopes ModuleMapFile = PublicMMFile;
130522d97065SBruno Cardoso Lopes
13065d2ed489SRichard Smith // Use the module map where this module resides.
13075d2ed489SRichard Smith Result = compileModuleImpl(
13085d2ed489SRichard Smith ImportingInstance, ImportLoc, Module->getTopLevelModuleName(),
13095d2ed489SRichard Smith FrontendInputFile(ModuleMapFile->getName(), IK, +Module->IsSystem),
13105d2ed489SRichard Smith ModMap.getModuleMapFileForUniquing(Module)->getName(),
13115d2ed489SRichard Smith ModuleFileName);
13125d2ed489SRichard Smith } else {
13135d2ed489SRichard Smith // FIXME: We only need to fake up an input file here as a way of
13145d2ed489SRichard Smith // transporting the module's directory to the module map parser. We should
13155d2ed489SRichard Smith // be able to do that more directly, and parse from a memory buffer without
13165d2ed489SRichard Smith // inventing this file.
13175d2ed489SRichard Smith SmallString<128> FakeModuleMapFile(Module->Directory->getName());
13185d2ed489SRichard Smith llvm::sys::path::append(FakeModuleMapFile, "__inferred_module.map");
13195d2ed489SRichard Smith
13205d2ed489SRichard Smith std::string InferredModuleMapContent;
13215d2ed489SRichard Smith llvm::raw_string_ostream OS(InferredModuleMapContent);
13225d2ed489SRichard Smith Module->print(OS);
13235d2ed489SRichard Smith OS.flush();
13245d2ed489SRichard Smith
13255d2ed489SRichard Smith Result = compileModuleImpl(
13265d2ed489SRichard Smith ImportingInstance, ImportLoc, Module->getTopLevelModuleName(),
13275d2ed489SRichard Smith FrontendInputFile(FakeModuleMapFile, IK, +Module->IsSystem),
13285d2ed489SRichard Smith ModMap.getModuleMapFileForUniquing(Module)->getName(),
13295d2ed489SRichard Smith ModuleFileName,
13305d2ed489SRichard Smith [&](CompilerInstance &Instance) {
13315d2ed489SRichard Smith std::unique_ptr<llvm::MemoryBuffer> ModuleMapBuffer =
13325d2ed489SRichard Smith llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent);
13335d2ed489SRichard Smith ModuleMapFile = Instance.getFileManager().getVirtualFile(
13345d2ed489SRichard Smith FakeModuleMapFile, InferredModuleMapContent.size(), 0);
13355d2ed489SRichard Smith Instance.getSourceManager().overrideFileContents(
13365d2ed489SRichard Smith ModuleMapFile, std::move(ModuleMapBuffer));
13375d2ed489SRichard Smith });
13385d2ed489SRichard Smith }
13395d2ed489SRichard Smith
13405e306b12SDouglas Gregor // We've rebuilt a module. If we're allowed to generate or update the global
13415e306b12SDouglas Gregor // module index, record that fact in the importing compiler instance.
1342c1bbec85SDouglas Gregor if (ImportingInstance.getFrontendOpts().GenerateGlobalModuleIndex) {
13435e306b12SDouglas Gregor ImportingInstance.setBuildGlobalModuleIndex(true);
13445e306b12SDouglas Gregor }
1345b797d59fSBen Langmuir
13465d2ed489SRichard Smith return Result;
1347faeb1d46SDouglas Gregor }
1348faeb1d46SDouglas Gregor
1349c130300fSDuncan P. N. Exon Smith /// Read the AST right after compiling the module.
readASTAfterCompileModule(CompilerInstance & ImportingInstance,SourceLocation ImportLoc,SourceLocation ModuleNameLoc,Module * Module,StringRef ModuleFileName,bool * OutOfDate)1350c130300fSDuncan P. N. Exon Smith static bool readASTAfterCompileModule(CompilerInstance &ImportingInstance,
1351c130300fSDuncan P. N. Exon Smith SourceLocation ImportLoc,
1352c130300fSDuncan P. N. Exon Smith SourceLocation ModuleNameLoc,
1353c130300fSDuncan P. N. Exon Smith Module *Module, StringRef ModuleFileName,
1354c130300fSDuncan P. N. Exon Smith bool *OutOfDate) {
1355c130300fSDuncan P. N. Exon Smith DiagnosticsEngine &Diags = ImportingInstance.getDiagnostics();
1356c130300fSDuncan P. N. Exon Smith
1357c130300fSDuncan P. N. Exon Smith unsigned ModuleLoadCapabilities = ASTReader::ARR_Missing;
1358c130300fSDuncan P. N. Exon Smith if (OutOfDate)
1359c130300fSDuncan P. N. Exon Smith ModuleLoadCapabilities |= ASTReader::ARR_OutOfDate;
1360c130300fSDuncan P. N. Exon Smith
1361c130300fSDuncan P. N. Exon Smith // Try to read the module file, now that we've compiled it.
1362c130300fSDuncan P. N. Exon Smith ASTReader::ASTReadResult ReadResult =
1363c130300fSDuncan P. N. Exon Smith ImportingInstance.getASTReader()->ReadAST(
1364c130300fSDuncan P. N. Exon Smith ModuleFileName, serialization::MK_ImplicitModule, ImportLoc,
1365c130300fSDuncan P. N. Exon Smith ModuleLoadCapabilities);
1366c130300fSDuncan P. N. Exon Smith if (ReadResult == ASTReader::Success)
1367c130300fSDuncan P. N. Exon Smith return true;
1368c130300fSDuncan P. N. Exon Smith
1369c130300fSDuncan P. N. Exon Smith // The caller wants to handle out-of-date failures.
1370c130300fSDuncan P. N. Exon Smith if (OutOfDate && ReadResult == ASTReader::OutOfDate) {
1371c130300fSDuncan P. N. Exon Smith *OutOfDate = true;
1372c130300fSDuncan P. N. Exon Smith return false;
1373c130300fSDuncan P. N. Exon Smith }
1374c130300fSDuncan P. N. Exon Smith
1375c130300fSDuncan P. N. Exon Smith // The ASTReader didn't diagnose the error, so conservatively report it.
1376c130300fSDuncan P. N. Exon Smith if (ReadResult == ASTReader::Missing || !Diags.hasErrorOccurred())
1377c130300fSDuncan P. N. Exon Smith Diags.Report(ModuleNameLoc, diag::err_module_not_built)
1378c130300fSDuncan P. N. Exon Smith << Module->Name << SourceRange(ImportLoc, ModuleNameLoc);
1379c130300fSDuncan P. N. Exon Smith
1380c130300fSDuncan P. N. Exon Smith return false;
1381c130300fSDuncan P. N. Exon Smith }
1382c130300fSDuncan P. N. Exon Smith
13835cca6223SDuncan P. N. Exon Smith /// Compile a module in a separate compiler instance and read the AST,
13845cca6223SDuncan P. N. Exon Smith /// returning true if the module compiles without errors.
compileModuleAndReadASTImpl(CompilerInstance & ImportingInstance,SourceLocation ImportLoc,SourceLocation ModuleNameLoc,Module * Module,StringRef ModuleFileName)1385c130300fSDuncan P. N. Exon Smith static bool compileModuleAndReadASTImpl(CompilerInstance &ImportingInstance,
1386c130300fSDuncan P. N. Exon Smith SourceLocation ImportLoc,
1387c130300fSDuncan P. N. Exon Smith SourceLocation ModuleNameLoc,
1388c130300fSDuncan P. N. Exon Smith Module *Module,
1389c130300fSDuncan P. N. Exon Smith StringRef ModuleFileName) {
1390c130300fSDuncan P. N. Exon Smith if (!compileModule(ImportingInstance, ModuleNameLoc, Module,
1391c130300fSDuncan P. N. Exon Smith ModuleFileName)) {
1392c130300fSDuncan P. N. Exon Smith ImportingInstance.getDiagnostics().Report(ModuleNameLoc,
1393c130300fSDuncan P. N. Exon Smith diag::err_module_not_built)
1394c130300fSDuncan P. N. Exon Smith << Module->Name << SourceRange(ImportLoc, ModuleNameLoc);
1395c130300fSDuncan P. N. Exon Smith return false;
1396c130300fSDuncan P. N. Exon Smith }
1397c130300fSDuncan P. N. Exon Smith
1398c130300fSDuncan P. N. Exon Smith return readASTAfterCompileModule(ImportingInstance, ImportLoc, ModuleNameLoc,
1399c130300fSDuncan P. N. Exon Smith Module, ModuleFileName,
1400c130300fSDuncan P. N. Exon Smith /*OutOfDate=*/nullptr);
1401c130300fSDuncan P. N. Exon Smith }
1402c130300fSDuncan P. N. Exon Smith
1403c130300fSDuncan P. N. Exon Smith /// Compile a module in a separate compiler instance and read the AST,
1404c130300fSDuncan P. N. Exon Smith /// returning true if the module compiles without errors, using a lock manager
1405c130300fSDuncan P. N. Exon Smith /// to avoid building the same module in multiple compiler instances.
14065cca6223SDuncan P. N. Exon Smith ///
14075cca6223SDuncan P. N. Exon Smith /// Uses a lock file manager and exponential backoff to reduce the chances that
14085cca6223SDuncan P. N. Exon Smith /// multiple instances will compete to create the same module. On timeout,
14095cca6223SDuncan P. N. Exon Smith /// deletes the lock file in order to avoid deadlock from crashing processes or
14105cca6223SDuncan P. N. Exon Smith /// bugs in the lock file manager.
compileModuleAndReadASTBehindLock(CompilerInstance & ImportingInstance,SourceLocation ImportLoc,SourceLocation ModuleNameLoc,Module * Module,StringRef ModuleFileName)1411c130300fSDuncan P. N. Exon Smith static bool compileModuleAndReadASTBehindLock(
1412c130300fSDuncan P. N. Exon Smith CompilerInstance &ImportingInstance, SourceLocation ImportLoc,
1413c130300fSDuncan P. N. Exon Smith SourceLocation ModuleNameLoc, Module *Module, StringRef ModuleFileName) {
1414d213aab7SBen Langmuir DiagnosticsEngine &Diags = ImportingInstance.getDiagnostics();
1415d213aab7SBen Langmuir
1416b714f73dSDuncan P. N. Exon Smith Diags.Report(ModuleNameLoc, diag::remark_module_lock)
1417b714f73dSDuncan P. N. Exon Smith << ModuleFileName << Module->Name;
1418b714f73dSDuncan P. N. Exon Smith
14194382fe74SArgyrios Kyrtzidis // FIXME: have LockFileManager return an error_code so that we can
14204382fe74SArgyrios Kyrtzidis // avoid the mkdir when the directory already exists.
14214382fe74SArgyrios Kyrtzidis StringRef Dir = llvm::sys::path::parent_path(ModuleFileName);
14224382fe74SArgyrios Kyrtzidis llvm::sys::fs::create_directories(Dir);
14234382fe74SArgyrios Kyrtzidis
142440446663SKazu Hirata while (true) {
14254382fe74SArgyrios Kyrtzidis llvm::LockFileManager Locked(ModuleFileName);
14264382fe74SArgyrios Kyrtzidis switch (Locked) {
14274382fe74SArgyrios Kyrtzidis case llvm::LockFileManager::LFS_Error:
14288bef5cd4SDuncan P. N. Exon Smith // ModuleCache takes care of correctness and locks are only necessary for
14295a0af1fcSBruno Cardoso Lopes // performance. Fallback to building the module in case of any lock
14305a0af1fcSBruno Cardoso Lopes // related errors.
14315a0af1fcSBruno Cardoso Lopes Diags.Report(ModuleNameLoc, diag::remark_module_lock_failure)
14324a52222cSBruno Cardoso Lopes << Module->Name << Locked.getErrorMessage();
14335a0af1fcSBruno Cardoso Lopes // Clear out any potential leftover.
14345a0af1fcSBruno Cardoso Lopes Locked.unsafeRemoveLockFile();
14354dc0b1acSReid Kleckner LLVM_FALLTHROUGH;
14364382fe74SArgyrios Kyrtzidis case llvm::LockFileManager::LFS_Owned:
1437dbdc0368SBen Langmuir // We're responsible for building the module ourselves.
1438c130300fSDuncan P. N. Exon Smith return compileModuleAndReadASTImpl(ImportingInstance, ImportLoc,
1439c130300fSDuncan P. N. Exon Smith ModuleNameLoc, Module, ModuleFileName);
14404382fe74SArgyrios Kyrtzidis
14414382fe74SArgyrios Kyrtzidis case llvm::LockFileManager::LFS_Shared:
1442c130300fSDuncan P. N. Exon Smith break; // The interesting case.
1443c130300fSDuncan P. N. Exon Smith }
1444c130300fSDuncan P. N. Exon Smith
14454382fe74SArgyrios Kyrtzidis // Someone else is responsible for building the module. Wait for them to
14464382fe74SArgyrios Kyrtzidis // finish.
14471daf4801SBen Langmuir switch (Locked.waitForUnlock()) {
14481daf4801SBen Langmuir case llvm::LockFileManager::Res_Success:
1449c130300fSDuncan P. N. Exon Smith break; // The interesting case.
14501daf4801SBen Langmuir case llvm::LockFileManager::Res_OwnerDied:
14511daf4801SBen Langmuir continue; // try again to get the lock.
14521daf4801SBen Langmuir case llvm::LockFileManager::Res_Timeout:
14538bef5cd4SDuncan P. N. Exon Smith // Since ModuleCache takes care of correctness, we try waiting for
14548bef5cd4SDuncan P. N. Exon Smith // another process to complete the build so clang does not do it done
14558bef5cd4SDuncan P. N. Exon Smith // twice. If case of timeout, build it ourselves.
14565a0af1fcSBruno Cardoso Lopes Diags.Report(ModuleNameLoc, diag::remark_module_lock_timeout)
14571daf4801SBen Langmuir << Module->Name;
14582a8c18d9SAlexander Kornienko // Clear the lock file so that future invocations can make progress.
14591daf4801SBen Langmuir Locked.unsafeRemoveLockFile();
14605a0af1fcSBruno Cardoso Lopes continue;
14611daf4801SBen Langmuir }
14624382fe74SArgyrios Kyrtzidis
1463c130300fSDuncan P. N. Exon Smith // Read the module that was just written by someone else.
1464c130300fSDuncan P. N. Exon Smith bool OutOfDate = false;
1465c130300fSDuncan P. N. Exon Smith if (readASTAfterCompileModule(ImportingInstance, ImportLoc, ModuleNameLoc,
1466c130300fSDuncan P. N. Exon Smith Module, ModuleFileName, &OutOfDate))
1467c130300fSDuncan P. N. Exon Smith return true;
1468c130300fSDuncan P. N. Exon Smith if (!OutOfDate)
1469c130300fSDuncan P. N. Exon Smith return false;
1470dbdc0368SBen Langmuir
1471dbdc0368SBen Langmuir // The module may be out of date in the presence of file system races,
1472dbdc0368SBen Langmuir // or if one of its imports depends on header search paths that are not
1473dbdc0368SBen Langmuir // consistent with this ImportingInstance. Try again...
14744382fe74SArgyrios Kyrtzidis }
14754382fe74SArgyrios Kyrtzidis }
14764382fe74SArgyrios Kyrtzidis
1477b714f73dSDuncan P. N. Exon Smith /// Compile a module in a separate compiler instance and read the AST,
1478b714f73dSDuncan P. N. Exon Smith /// returning true if the module compiles without errors, potentially using a
1479b714f73dSDuncan P. N. Exon Smith /// lock manager to avoid building the same module in multiple compiler
1480b714f73dSDuncan P. N. Exon Smith /// instances.
compileModuleAndReadAST(CompilerInstance & ImportingInstance,SourceLocation ImportLoc,SourceLocation ModuleNameLoc,Module * Module,StringRef ModuleFileName)1481b714f73dSDuncan P. N. Exon Smith static bool compileModuleAndReadAST(CompilerInstance &ImportingInstance,
1482b714f73dSDuncan P. N. Exon Smith SourceLocation ImportLoc,
1483b714f73dSDuncan P. N. Exon Smith SourceLocation ModuleNameLoc,
1484b714f73dSDuncan P. N. Exon Smith Module *Module, StringRef ModuleFileName) {
1485b714f73dSDuncan P. N. Exon Smith return ImportingInstance.getInvocation()
1486b714f73dSDuncan P. N. Exon Smith .getFrontendOpts()
1487b714f73dSDuncan P. N. Exon Smith .BuildingImplicitModuleUsesLock
1488b714f73dSDuncan P. N. Exon Smith ? compileModuleAndReadASTBehindLock(ImportingInstance, ImportLoc,
1489b714f73dSDuncan P. N. Exon Smith ModuleNameLoc, Module,
1490b714f73dSDuncan P. N. Exon Smith ModuleFileName)
1491b714f73dSDuncan P. N. Exon Smith : compileModuleAndReadASTImpl(ImportingInstance, ImportLoc,
1492b714f73dSDuncan P. N. Exon Smith ModuleNameLoc, Module,
1493b714f73dSDuncan P. N. Exon Smith ModuleFileName);
1494b714f73dSDuncan P. N. Exon Smith }
1495b714f73dSDuncan P. N. Exon Smith
14969fc8faf9SAdrian Prantl /// Diagnose differences between the current definition of the given
149735b13eceSDouglas Gregor /// configuration macro and the definition provided on the command line.
checkConfigMacro(Preprocessor & PP,StringRef ConfigMacro,Module * Mod,SourceLocation ImportLoc)149835b13eceSDouglas Gregor static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
149935b13eceSDouglas Gregor Module *Mod, SourceLocation ImportLoc) {
150035b13eceSDouglas Gregor IdentifierInfo *Id = PP.getIdentifierInfo(ConfigMacro);
150135b13eceSDouglas Gregor SourceManager &SourceMgr = PP.getSourceManager();
150235b13eceSDouglas Gregor
150335b13eceSDouglas Gregor // If this identifier has never had a macro definition, then it could
150435b13eceSDouglas Gregor // not have changed.
150535b13eceSDouglas Gregor if (!Id->hadMacroDefinition())
150635b13eceSDouglas Gregor return;
150720e883e5SRichard Smith auto *LatestLocalMD = PP.getLocalMacroDirectiveHistory(Id);
150835b13eceSDouglas Gregor
150920e883e5SRichard Smith // Find the macro definition from the command line.
151020e883e5SRichard Smith MacroInfo *CmdLineDefinition = nullptr;
151120e883e5SRichard Smith for (auto *MD = LatestLocalMD; MD; MD = MD->getPrevious()) {
151235b13eceSDouglas Gregor // We only care about the predefines buffer.
151320e883e5SRichard Smith FileID FID = SourceMgr.getFileID(MD->getLocation());
151420e883e5SRichard Smith if (FID.isInvalid() || FID != PP.getPredefinesFileID())
151535b13eceSDouglas Gregor continue;
151620e883e5SRichard Smith if (auto *DMD = dyn_cast<DefMacroDirective>(MD))
151720e883e5SRichard Smith CmdLineDefinition = DMD->getMacroInfo();
151820e883e5SRichard Smith break;
151920e883e5SRichard Smith }
152035b13eceSDouglas Gregor
152120e883e5SRichard Smith auto *CurrentDefinition = PP.getMacroInfo(Id);
152220e883e5SRichard Smith if (CurrentDefinition == CmdLineDefinition) {
152320e883e5SRichard Smith // Macro matches. Nothing to do.
152420e883e5SRichard Smith } else if (!CurrentDefinition) {
152535b13eceSDouglas Gregor // This macro was defined on the command line, then #undef'd later.
152635b13eceSDouglas Gregor // Complain.
152735b13eceSDouglas Gregor PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
152835b13eceSDouglas Gregor << true << ConfigMacro << Mod->getFullModuleName();
152920e883e5SRichard Smith auto LatestDef = LatestLocalMD->getDefinition();
153020e883e5SRichard Smith assert(LatestDef.isUndefined() &&
153120e883e5SRichard Smith "predefined macro went away with no #undef?");
1532b6210dffSArgyrios Kyrtzidis PP.Diag(LatestDef.getUndefLocation(), diag::note_module_def_undef_here)
153335b13eceSDouglas Gregor << true;
153435b13eceSDouglas Gregor return;
153520e883e5SRichard Smith } else if (!CmdLineDefinition) {
153620e883e5SRichard Smith // There was no definition for this macro in the predefines buffer,
153720e883e5SRichard Smith // but there was a local definition. Complain.
153835b13eceSDouglas Gregor PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
153935b13eceSDouglas Gregor << false << ConfigMacro << Mod->getFullModuleName();
154020e883e5SRichard Smith PP.Diag(CurrentDefinition->getDefinitionLoc(),
154120e883e5SRichard Smith diag::note_module_def_undef_here)
154235b13eceSDouglas Gregor << false;
154320e883e5SRichard Smith } else if (!CurrentDefinition->isIdenticalTo(*CmdLineDefinition, PP,
154420e883e5SRichard Smith /*Syntactically=*/true)) {
154535b13eceSDouglas Gregor // The macro definitions differ.
154635b13eceSDouglas Gregor PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
154735b13eceSDouglas Gregor << false << ConfigMacro << Mod->getFullModuleName();
154820e883e5SRichard Smith PP.Diag(CurrentDefinition->getDefinitionLoc(),
154920e883e5SRichard Smith diag::note_module_def_undef_here)
155035b13eceSDouglas Gregor << false;
155135b13eceSDouglas Gregor }
155220e883e5SRichard Smith }
155335b13eceSDouglas Gregor
15549fc8faf9SAdrian Prantl /// Write a new timestamp file with the given path.
writeTimestampFile(StringRef TimestampFile)1555527b1c95SDouglas Gregor static void writeTimestampFile(StringRef TimestampFile) {
1556dae941a6SRafael Espindola std::error_code EC;
1557d9b948b6SFangrui Song llvm::raw_fd_ostream Out(TimestampFile.str(), EC, llvm::sys::fs::OF_None);
1558527b1c95SDouglas Gregor }
1559527b1c95SDouglas Gregor
15609fc8faf9SAdrian Prantl /// Prune the module cache of modules that haven't been accessed in
1561527b1c95SDouglas Gregor /// a long time.
pruneModuleCache(const HeaderSearchOptions & HSOpts)1562527b1c95SDouglas Gregor static void pruneModuleCache(const HeaderSearchOptions &HSOpts) {
1563930ada91SVolodymyr Sapsai llvm::sys::fs::file_status StatBuf;
1564527b1c95SDouglas Gregor llvm::SmallString<128> TimestampFile;
1565527b1c95SDouglas Gregor TimestampFile = HSOpts.ModuleCachePath;
15663938f0c7SRichard Smith assert(!TimestampFile.empty());
1567527b1c95SDouglas Gregor llvm::sys::path::append(TimestampFile, "modules.timestamp");
1568527b1c95SDouglas Gregor
1569527b1c95SDouglas Gregor // Try to stat() the timestamp file.
1570930ada91SVolodymyr Sapsai if (std::error_code EC = llvm::sys::fs::status(TimestampFile, StatBuf)) {
1571527b1c95SDouglas Gregor // If the timestamp file wasn't there, create one now.
1572930ada91SVolodymyr Sapsai if (EC == std::errc::no_such_file_or_directory) {
1573527b1c95SDouglas Gregor writeTimestampFile(TimestampFile);
1574527b1c95SDouglas Gregor }
1575527b1c95SDouglas Gregor return;
1576527b1c95SDouglas Gregor }
1577527b1c95SDouglas Gregor
1578527b1c95SDouglas Gregor // Check whether the time stamp is older than our pruning interval.
1579527b1c95SDouglas Gregor // If not, do nothing.
1580930ada91SVolodymyr Sapsai time_t TimeStampModTime =
1581930ada91SVolodymyr Sapsai llvm::sys::toTimeT(StatBuf.getLastModificationTime());
158249a2790fSCraig Topper time_t CurrentTime = time(nullptr);
1583dbcf5037SBenjamin Kramer if (CurrentTime - TimeStampModTime <= time_t(HSOpts.ModuleCachePruneInterval))
1584527b1c95SDouglas Gregor return;
1585527b1c95SDouglas Gregor
1586527b1c95SDouglas Gregor // Write a new timestamp file so that nobody else attempts to prune.
1587527b1c95SDouglas Gregor // There is a benign race condition here, if two Clang instances happen to
1588527b1c95SDouglas Gregor // notice at the same time that the timestamp is out-of-date.
1589527b1c95SDouglas Gregor writeTimestampFile(TimestampFile);
1590527b1c95SDouglas Gregor
1591527b1c95SDouglas Gregor // Walk the entire module cache, looking for unused module files and module
1592527b1c95SDouglas Gregor // indices.
1593c080917eSRafael Espindola std::error_code EC;
1594527b1c95SDouglas Gregor SmallString<128> ModuleCachePathNative;
1595527b1c95SDouglas Gregor llvm::sys::path::native(HSOpts.ModuleCachePath, ModuleCachePathNative);
159692e1b62dSYaron Keren for (llvm::sys::fs::directory_iterator Dir(ModuleCachePathNative, EC), DirEnd;
1597527b1c95SDouglas Gregor Dir != DirEnd && !EC; Dir.increment(EC)) {
1598527b1c95SDouglas Gregor // If we don't have a directory, there's nothing to look into.
1599a07f720aSRafael Espindola if (!llvm::sys::fs::is_directory(Dir->path()))
1600527b1c95SDouglas Gregor continue;
1601527b1c95SDouglas Gregor
1602527b1c95SDouglas Gregor // Walk all of the files within this directory.
1603527b1c95SDouglas Gregor for (llvm::sys::fs::directory_iterator File(Dir->path(), EC), FileEnd;
1604527b1c95SDouglas Gregor File != FileEnd && !EC; File.increment(EC)) {
1605527b1c95SDouglas Gregor // We only care about module and global module index files.
1606f430da4dSDmitri Gribenko StringRef Extension = llvm::sys::path::extension(File->path());
1607f430da4dSDmitri Gribenko if (Extension != ".pcm" && Extension != ".timestamp" &&
1608f430da4dSDmitri Gribenko llvm::sys::path::filename(File->path()) != "modules.idx")
1609527b1c95SDouglas Gregor continue;
1610527b1c95SDouglas Gregor
1611527b1c95SDouglas Gregor // Look at this file. If we can't stat it, there's nothing interesting
1612527b1c95SDouglas Gregor // there.
1613930ada91SVolodymyr Sapsai if (llvm::sys::fs::status(File->path(), StatBuf))
1614527b1c95SDouglas Gregor continue;
1615527b1c95SDouglas Gregor
1616527b1c95SDouglas Gregor // If the file has been used recently enough, leave it there.
1617930ada91SVolodymyr Sapsai time_t FileAccessTime = llvm::sys::toTimeT(StatBuf.getLastAccessedTime());
1618dbcf5037SBenjamin Kramer if (CurrentTime - FileAccessTime <=
1619dbcf5037SBenjamin Kramer time_t(HSOpts.ModuleCachePruneAfter)) {
1620527b1c95SDouglas Gregor continue;
1621527b1c95SDouglas Gregor }
1622527b1c95SDouglas Gregor
1623527b1c95SDouglas Gregor // Remove the file.
1624f430da4dSDmitri Gribenko llvm::sys::fs::remove(File->path());
1625f430da4dSDmitri Gribenko
1626f430da4dSDmitri Gribenko // Remove the timestamp file.
1627f430da4dSDmitri Gribenko std::string TimpestampFilename = File->path() + ".timestamp";
1628f430da4dSDmitri Gribenko llvm::sys::fs::remove(TimpestampFilename);
1629527b1c95SDouglas Gregor }
1630527b1c95SDouglas Gregor
1631527b1c95SDouglas Gregor // If we removed all of the files in the directory, remove the directory
1632527b1c95SDouglas Gregor // itself.
1633f430da4dSDmitri Gribenko if (llvm::sys::fs::directory_iterator(Dir->path(), EC) ==
1634f430da4dSDmitri Gribenko llvm::sys::fs::directory_iterator() && !EC)
16352a008784SRafael Espindola llvm::sys::fs::remove(Dir->path());
1636527b1c95SDouglas Gregor }
1637527b1c95SDouglas Gregor }
1638527b1c95SDouglas Gregor
createASTReader()163920d51b2fSDuncan P. N. Exon Smith void CompilerInstance::createASTReader() {
164020d51b2fSDuncan P. N. Exon Smith if (TheASTReader)
164187008317SDuncan P. N. Exon Smith return;
164287008317SDuncan P. N. Exon Smith
16432255f2ceSJohn Thompson if (!hasASTContext())
16442255f2ceSJohn Thompson createASTContext();
16452255f2ceSJohn Thompson
1646580dd296SChandler Carruth // If we're implicitly building modules but not currently recursively
1647580dd296SChandler Carruth // building a module, check whether we need to prune the module cache.
16483938f0c7SRichard Smith if (getSourceManager().getModuleBuildStack().empty() &&
16493938f0c7SRichard Smith !getPreprocessor().getHeaderSearchInfo().getModuleCachePath().empty() &&
16502255f2ceSJohn Thompson getHeaderSearchOpts().ModuleCachePruneInterval > 0 &&
16512255f2ceSJohn Thompson getHeaderSearchOpts().ModuleCachePruneAfter > 0) {
16522255f2ceSJohn Thompson pruneModuleCache(getHeaderSearchOpts());
16532255f2ceSJohn Thompson }
16542255f2ceSJohn Thompson
16552255f2ceSJohn Thompson HeaderSearchOptions &HSOpts = getHeaderSearchOpts();
16562255f2ceSJohn Thompson std::string Sysroot = HSOpts.Sysroot;
16572255f2ceSJohn Thompson const PreprocessorOptions &PPOpts = getPreprocessorOpts();
16585834996fSBen Barham const FrontendOptions &FEOpts = getFrontendOpts();
1659ce18a187SRichard Smith std::unique_ptr<llvm::Timer> ReadTimer;
16605834996fSBen Barham
1661ce18a187SRichard Smith if (FrontendTimerGroup)
16622b3d49b6SJonas Devlieghere ReadTimer = std::make_unique<llvm::Timer>("reading_modules",
1663ae032b6cSMatthias Braun "Reading modules",
1664ce18a187SRichard Smith *FrontendTimerGroup);
166520d51b2fSDuncan P. N. Exon Smith TheASTReader = new ASTReader(
16668bef5cd4SDuncan P. N. Exon Smith getPreprocessor(), getModuleCache(), &getASTContext(),
16678bef5cd4SDuncan P. N. Exon Smith getPCHContainerReader(), getFrontendOpts().ModuleFileExtensions,
1668b0e89906SArgyrios Kyrtzidis Sysroot.empty() ? "" : Sysroot.c_str(),
1669b0e89906SArgyrios Kyrtzidis PPOpts.DisablePCHOrModuleValidation,
16705834996fSBen Barham /*AllowASTWithCompilerErrors=*/FEOpts.AllowPCMWithCompilerErrors,
167120d51b2fSDuncan P. N. Exon Smith /*AllowConfigurationMismatch=*/false, HSOpts.ModulesValidateSystemHeaders,
16721731fc88SBruno Cardoso Lopes HSOpts.ValidateASTInputFilesContent,
16738bef5cd4SDuncan P. N. Exon Smith getFrontendOpts().UseGlobalModuleIndex, std::move(ReadTimer));
16742255f2ceSJohn Thompson if (hasASTConsumer()) {
167520d51b2fSDuncan P. N. Exon Smith TheASTReader->setDeserializationListener(
16762255f2ceSJohn Thompson getASTConsumer().GetASTDeserializationListener());
16772255f2ceSJohn Thompson getASTContext().setASTMutationListener(
16782255f2ceSJohn Thompson getASTConsumer().GetASTMutationListener());
16792255f2ceSJohn Thompson }
168020d51b2fSDuncan P. N. Exon Smith getASTContext().setExternalSource(TheASTReader);
16812255f2ceSJohn Thompson if (hasSema())
168220d51b2fSDuncan P. N. Exon Smith TheASTReader->InitializeSema(getSema());
1683293534b1SRichard Smith if (hasASTConsumer())
168420d51b2fSDuncan P. N. Exon Smith TheASTReader->StartTranslationUnit(&getASTConsumer());
168503f7e611SRichard Smith
168603f7e611SRichard Smith for (auto &Listener : DependencyCollectors)
168720d51b2fSDuncan P. N. Exon Smith Listener->attachToASTReader(*TheASTReader);
16882255f2ceSJohn Thompson }
16892255f2ceSJohn Thompson
loadModuleFile(StringRef FileName)1690d4b230b3SRichard Smith bool CompilerInstance::loadModuleFile(StringRef FileName) {
1691ce18a187SRichard Smith llvm::Timer Timer;
1692ce18a187SRichard Smith if (FrontendTimerGroup)
1693ae032b6cSMatthias Braun Timer.init("preloading." + FileName.str(), "Preloading " + FileName.str(),
1694ae032b6cSMatthias Braun *FrontendTimerGroup);
1695ce18a187SRichard Smith llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
1696ce18a187SRichard Smith
16977f330cdbSRichard Smith // If we don't already have an ASTReader, create one now.
169820d51b2fSDuncan P. N. Exon Smith if (!TheASTReader)
169920d51b2fSDuncan P. N. Exon Smith createASTReader();
17007f330cdbSRichard Smith
17017a985e1bSRichard Smith // If -Wmodule-file-config-mismatch is mapped as an error or worse, allow the
17027a985e1bSRichard Smith // ASTReader to diagnose it, since it can produce better errors that we can.
17037a985e1bSRichard Smith bool ConfigMismatchIsRecoverable =
17047a985e1bSRichard Smith getDiagnostics().getDiagnosticLevel(diag::warn_module_config_mismatch,
17057a985e1bSRichard Smith SourceLocation())
17067a985e1bSRichard Smith <= DiagnosticsEngine::Warning;
17077a985e1bSRichard Smith
170808c8016cSJan Svoboda auto Listener = std::make_unique<ReadModuleNames>(*PP);
17090f99d6a4SRichard Smith auto &ListenerRef = *Listener;
171020d51b2fSDuncan P. N. Exon Smith ASTReader::ListenerScope ReadModuleNamesListener(*TheASTReader,
17110f99d6a4SRichard Smith std::move(Listener));
17127f330cdbSRichard Smith
17130f99d6a4SRichard Smith // Try to load the module file.
171420d51b2fSDuncan P. N. Exon Smith switch (TheASTReader->ReadAST(
17157a985e1bSRichard Smith FileName, serialization::MK_ExplicitModule, SourceLocation(),
17167a985e1bSRichard Smith ConfigMismatchIsRecoverable ? ASTReader::ARR_ConfigurationMismatch : 0)) {
171795dc57a6SRichard Smith case ASTReader::Success:
17180f99d6a4SRichard Smith // We successfully loaded the module file; remember the set of provided
17190f99d6a4SRichard Smith // modules so that we don't try to load implicit modules for them.
17200f99d6a4SRichard Smith ListenerRef.registerAll();
1721d4b230b3SRichard Smith return true;
172295dc57a6SRichard Smith
172395dc57a6SRichard Smith case ASTReader::ConfigurationMismatch:
172495dc57a6SRichard Smith // Ignore unusable module files.
172595dc57a6SRichard Smith getDiagnostics().Report(SourceLocation(), diag::warn_module_config_mismatch)
172695dc57a6SRichard Smith << FileName;
17278a308ec2SRichard Smith // All modules provided by any files we tried and failed to load are now
17288a308ec2SRichard Smith // unavailable; includes of those modules should now be handled textually.
17298a308ec2SRichard Smith ListenerRef.markAllUnavailable();
173095dc57a6SRichard Smith return true;
173195dc57a6SRichard Smith
173295dc57a6SRichard Smith default:
173395dc57a6SRichard Smith return false;
173495dc57a6SRichard Smith }
1735e842a474SRichard Smith }
1736e842a474SRichard Smith
17375cca6223SDuncan P. N. Exon Smith namespace {
17385cca6223SDuncan P. N. Exon Smith enum ModuleSource {
17395cca6223SDuncan P. N. Exon Smith MS_ModuleNotFound,
17405cca6223SDuncan P. N. Exon Smith MS_ModuleCache,
17415cca6223SDuncan P. N. Exon Smith MS_PrebuiltModulePath,
17425cca6223SDuncan P. N. Exon Smith MS_ModuleBuildPragma
17435cca6223SDuncan P. N. Exon Smith };
17445cca6223SDuncan P. N. Exon Smith } // end namespace
17455cca6223SDuncan P. N. Exon Smith
17465cca6223SDuncan P. N. Exon Smith /// Select a source for loading the named module and compute the filename to
17475cca6223SDuncan P. N. Exon Smith /// load it from.
selectModuleSource(Module * M,StringRef ModuleName,std::string & ModuleFilename,const std::map<std::string,std::string,std::less<>> & BuiltModules,HeaderSearch & HS)1748ef83d46bSBenjamin Kramer static ModuleSource selectModuleSource(
1749ef83d46bSBenjamin Kramer Module *M, StringRef ModuleName, std::string &ModuleFilename,
1750ef83d46bSBenjamin Kramer const std::map<std::string, std::string, std::less<>> &BuiltModules,
17515cca6223SDuncan P. N. Exon Smith HeaderSearch &HS) {
17525cca6223SDuncan P. N. Exon Smith assert(ModuleFilename.empty() && "Already has a module source?");
17535cca6223SDuncan P. N. Exon Smith
17545cca6223SDuncan P. N. Exon Smith // Check to see if the module has been built as part of this compilation
17555cca6223SDuncan P. N. Exon Smith // via a module build pragma.
1756ef83d46bSBenjamin Kramer auto BuiltModuleIt = BuiltModules.find(ModuleName);
17575cca6223SDuncan P. N. Exon Smith if (BuiltModuleIt != BuiltModules.end()) {
17585cca6223SDuncan P. N. Exon Smith ModuleFilename = BuiltModuleIt->second;
17595cca6223SDuncan P. N. Exon Smith return MS_ModuleBuildPragma;
17605cca6223SDuncan P. N. Exon Smith }
17615cca6223SDuncan P. N. Exon Smith
17625cca6223SDuncan P. N. Exon Smith // Try to load the module from the prebuilt module path.
17635cca6223SDuncan P. N. Exon Smith const HeaderSearchOptions &HSOpts = HS.getHeaderSearchOpts();
17645cca6223SDuncan P. N. Exon Smith if (!HSOpts.PrebuiltModuleFiles.empty() ||
17655cca6223SDuncan P. N. Exon Smith !HSOpts.PrebuiltModulePaths.empty()) {
17665cca6223SDuncan P. N. Exon Smith ModuleFilename = HS.getPrebuiltModuleFileName(ModuleName);
176758c586e7SAlexandre Rames if (HSOpts.EnablePrebuiltImplicitModules && ModuleFilename.empty())
176858c586e7SAlexandre Rames ModuleFilename = HS.getPrebuiltImplicitModuleFileName(M);
17695cca6223SDuncan P. N. Exon Smith if (!ModuleFilename.empty())
17705cca6223SDuncan P. N. Exon Smith return MS_PrebuiltModulePath;
17715cca6223SDuncan P. N. Exon Smith }
17725cca6223SDuncan P. N. Exon Smith
17735cca6223SDuncan P. N. Exon Smith // Try to load the module from the module cache.
17745cca6223SDuncan P. N. Exon Smith if (M) {
17755cca6223SDuncan P. N. Exon Smith ModuleFilename = HS.getCachedModuleFileName(M);
17765cca6223SDuncan P. N. Exon Smith return MS_ModuleCache;
17775cca6223SDuncan P. N. Exon Smith }
17785cca6223SDuncan P. N. Exon Smith
17795cca6223SDuncan P. N. Exon Smith return MS_ModuleNotFound;
17805cca6223SDuncan P. N. Exon Smith }
17815cca6223SDuncan P. N. Exon Smith
findOrCompileModuleAndReadAST(StringRef ModuleName,SourceLocation ImportLoc,SourceLocation ModuleNameLoc,bool IsInclusionDirective)17825cca6223SDuncan P. N. Exon Smith ModuleLoadResult CompilerInstance::findOrCompileModuleAndReadAST(
17835cca6223SDuncan P. N. Exon Smith StringRef ModuleName, SourceLocation ImportLoc,
17845cca6223SDuncan P. N. Exon Smith SourceLocation ModuleNameLoc, bool IsInclusionDirective) {
17855cca6223SDuncan P. N. Exon Smith // Search for a module with the given name.
17865cca6223SDuncan P. N. Exon Smith HeaderSearch &HS = PP->getHeaderSearchInfo();
1787638c673aSJan Svoboda Module *M =
1788638c673aSJan Svoboda HS.lookupModule(ModuleName, ImportLoc, true, !IsInclusionDirective);
17895cca6223SDuncan P. N. Exon Smith
17905cca6223SDuncan P. N. Exon Smith // Select the source and filename for loading the named module.
17915cca6223SDuncan P. N. Exon Smith std::string ModuleFilename;
17925cca6223SDuncan P. N. Exon Smith ModuleSource Source =
17935cca6223SDuncan P. N. Exon Smith selectModuleSource(M, ModuleName, ModuleFilename, BuiltModules, HS);
17945cca6223SDuncan P. N. Exon Smith if (Source == MS_ModuleNotFound) {
17955cca6223SDuncan P. N. Exon Smith // We can't find a module, error out here.
17965cca6223SDuncan P. N. Exon Smith getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
17975cca6223SDuncan P. N. Exon Smith << ModuleName << SourceRange(ImportLoc, ModuleNameLoc);
17987c2afd58SDuncan P. N. Exon Smith return nullptr;
17995cca6223SDuncan P. N. Exon Smith }
18005cca6223SDuncan P. N. Exon Smith if (ModuleFilename.empty()) {
18015cca6223SDuncan P. N. Exon Smith if (M && M->HasIncompatibleModuleFile) {
18025cca6223SDuncan P. N. Exon Smith // We tried and failed to load a module file for this module. Fall
18035cca6223SDuncan P. N. Exon Smith // back to textual inclusion for its headers.
18045cca6223SDuncan P. N. Exon Smith return ModuleLoadResult::ConfigMismatch;
18055cca6223SDuncan P. N. Exon Smith }
18065cca6223SDuncan P. N. Exon Smith
18075cca6223SDuncan P. N. Exon Smith getDiagnostics().Report(ModuleNameLoc, diag::err_module_build_disabled)
18085cca6223SDuncan P. N. Exon Smith << ModuleName;
18097c2afd58SDuncan P. N. Exon Smith return nullptr;
18105cca6223SDuncan P. N. Exon Smith }
18115cca6223SDuncan P. N. Exon Smith
18125cca6223SDuncan P. N. Exon Smith // Create an ASTReader on demand.
181320d51b2fSDuncan P. N. Exon Smith if (!getASTReader())
181420d51b2fSDuncan P. N. Exon Smith createASTReader();
18155cca6223SDuncan P. N. Exon Smith
18165cca6223SDuncan P. N. Exon Smith // Time how long it takes to load the module.
18175cca6223SDuncan P. N. Exon Smith llvm::Timer Timer;
18185cca6223SDuncan P. N. Exon Smith if (FrontendTimerGroup)
18195cca6223SDuncan P. N. Exon Smith Timer.init("loading." + ModuleFilename, "Loading " + ModuleFilename,
18205cca6223SDuncan P. N. Exon Smith *FrontendTimerGroup);
18215cca6223SDuncan P. N. Exon Smith llvm::TimeRegion TimeLoading(FrontendTimerGroup ? &Timer : nullptr);
18225cca6223SDuncan P. N. Exon Smith llvm::TimeTraceScope TimeScope("Module Load", ModuleName);
18235cca6223SDuncan P. N. Exon Smith
18245cca6223SDuncan P. N. Exon Smith // Try to load the module file. If we are not trying to load from the
18255cca6223SDuncan P. N. Exon Smith // module cache, we don't know how to rebuild modules.
18265cca6223SDuncan P. N. Exon Smith unsigned ARRFlags = Source == MS_ModuleCache
1827a8cb39baSArgyrios Kyrtzidis ? ASTReader::ARR_OutOfDate | ASTReader::ARR_Missing |
1828a8cb39baSArgyrios Kyrtzidis ASTReader::ARR_TreatModuleWithErrorsAsOutOfDate
18295cca6223SDuncan P. N. Exon Smith : Source == MS_PrebuiltModulePath
18305cca6223SDuncan P. N. Exon Smith ? 0
18315cca6223SDuncan P. N. Exon Smith : ASTReader::ARR_ConfigurationMismatch;
183220d51b2fSDuncan P. N. Exon Smith switch (getASTReader()->ReadAST(ModuleFilename,
18335cca6223SDuncan P. N. Exon Smith Source == MS_PrebuiltModulePath
18345cca6223SDuncan P. N. Exon Smith ? serialization::MK_PrebuiltModule
183520d51b2fSDuncan P. N. Exon Smith : Source == MS_ModuleBuildPragma
183620d51b2fSDuncan P. N. Exon Smith ? serialization::MK_ExplicitModule
18375cca6223SDuncan P. N. Exon Smith : serialization::MK_ImplicitModule,
18385cca6223SDuncan P. N. Exon Smith ImportLoc, ARRFlags)) {
18395cca6223SDuncan P. N. Exon Smith case ASTReader::Success: {
18405cca6223SDuncan P. N. Exon Smith if (M)
18415cca6223SDuncan P. N. Exon Smith return M;
18425cca6223SDuncan P. N. Exon Smith assert(Source != MS_ModuleCache &&
18435cca6223SDuncan P. N. Exon Smith "missing module, but file loaded from cache");
18445cca6223SDuncan P. N. Exon Smith
18455cca6223SDuncan P. N. Exon Smith // A prebuilt module is indexed as a ModuleFile; the Module does not exist
18465cca6223SDuncan P. N. Exon Smith // until the first call to ReadAST. Look it up now.
1847638c673aSJan Svoboda M = HS.lookupModule(ModuleName, ImportLoc, true, !IsInclusionDirective);
18485cca6223SDuncan P. N. Exon Smith
18495cca6223SDuncan P. N. Exon Smith // Check whether M refers to the file in the prebuilt module path.
18505cca6223SDuncan P. N. Exon Smith if (M && M->getASTFile())
18515cca6223SDuncan P. N. Exon Smith if (auto ModuleFile = FileMgr->getFile(ModuleFilename))
18525cca6223SDuncan P. N. Exon Smith if (*ModuleFile == M->getASTFile())
18535cca6223SDuncan P. N. Exon Smith return M;
18545cca6223SDuncan P. N. Exon Smith
18555cca6223SDuncan P. N. Exon Smith getDiagnostics().Report(ModuleNameLoc, diag::err_module_prebuilt)
18565cca6223SDuncan P. N. Exon Smith << ModuleName;
18575cca6223SDuncan P. N. Exon Smith return ModuleLoadResult();
18585cca6223SDuncan P. N. Exon Smith }
18595cca6223SDuncan P. N. Exon Smith
18605cca6223SDuncan P. N. Exon Smith case ASTReader::OutOfDate:
18615cca6223SDuncan P. N. Exon Smith case ASTReader::Missing:
18625cca6223SDuncan P. N. Exon Smith // The most interesting case.
18635cca6223SDuncan P. N. Exon Smith break;
18645cca6223SDuncan P. N. Exon Smith
18655cca6223SDuncan P. N. Exon Smith case ASTReader::ConfigurationMismatch:
18665cca6223SDuncan P. N. Exon Smith if (Source == MS_PrebuiltModulePath)
18675cca6223SDuncan P. N. Exon Smith // FIXME: We shouldn't be setting HadFatalFailure below if we only
18685cca6223SDuncan P. N. Exon Smith // produce a warning here!
18695cca6223SDuncan P. N. Exon Smith getDiagnostics().Report(SourceLocation(),
18705cca6223SDuncan P. N. Exon Smith diag::warn_module_config_mismatch)
18715cca6223SDuncan P. N. Exon Smith << ModuleFilename;
18725cca6223SDuncan P. N. Exon Smith // Fall through to error out.
18735cca6223SDuncan P. N. Exon Smith LLVM_FALLTHROUGH;
18745cca6223SDuncan P. N. Exon Smith case ASTReader::VersionMismatch:
18755cca6223SDuncan P. N. Exon Smith case ASTReader::HadErrors:
18765cca6223SDuncan P. N. Exon Smith ModuleLoader::HadFatalFailure = true;
18775cca6223SDuncan P. N. Exon Smith // FIXME: The ASTReader will already have complained, but can we shoehorn
18785cca6223SDuncan P. N. Exon Smith // that diagnostic information into a more useful form?
18795cca6223SDuncan P. N. Exon Smith return ModuleLoadResult();
18805cca6223SDuncan P. N. Exon Smith
18815cca6223SDuncan P. N. Exon Smith case ASTReader::Failure:
18825cca6223SDuncan P. N. Exon Smith ModuleLoader::HadFatalFailure = true;
18835cca6223SDuncan P. N. Exon Smith return ModuleLoadResult();
18845cca6223SDuncan P. N. Exon Smith }
18855cca6223SDuncan P. N. Exon Smith
18865cca6223SDuncan P. N. Exon Smith // ReadAST returned Missing or OutOfDate.
18875cca6223SDuncan P. N. Exon Smith if (Source != MS_ModuleCache) {
18885cca6223SDuncan P. N. Exon Smith // We don't know the desired configuration for this module and don't
18895cca6223SDuncan P. N. Exon Smith // necessarily even have a module map. Since ReadAST already produces
18905cca6223SDuncan P. N. Exon Smith // diagnostics for these two cases, we simply error out here.
18915cca6223SDuncan P. N. Exon Smith return ModuleLoadResult();
18925cca6223SDuncan P. N. Exon Smith }
18935cca6223SDuncan P. N. Exon Smith
18945cca6223SDuncan P. N. Exon Smith // The module file is missing or out-of-date. Build it.
18955cca6223SDuncan P. N. Exon Smith assert(M && "missing module, but trying to compile for cache");
18965cca6223SDuncan P. N. Exon Smith
18975cca6223SDuncan P. N. Exon Smith // Check whether there is a cycle in the module graph.
18985cca6223SDuncan P. N. Exon Smith ModuleBuildStack ModPath = getSourceManager().getModuleBuildStack();
18995cca6223SDuncan P. N. Exon Smith ModuleBuildStack::iterator Pos = ModPath.begin(), PosEnd = ModPath.end();
19005cca6223SDuncan P. N. Exon Smith for (; Pos != PosEnd; ++Pos) {
19015cca6223SDuncan P. N. Exon Smith if (Pos->first == ModuleName)
19025cca6223SDuncan P. N. Exon Smith break;
19035cca6223SDuncan P. N. Exon Smith }
19045cca6223SDuncan P. N. Exon Smith
19055cca6223SDuncan P. N. Exon Smith if (Pos != PosEnd) {
19065cca6223SDuncan P. N. Exon Smith SmallString<256> CyclePath;
19075cca6223SDuncan P. N. Exon Smith for (; Pos != PosEnd; ++Pos) {
19085cca6223SDuncan P. N. Exon Smith CyclePath += Pos->first;
19095cca6223SDuncan P. N. Exon Smith CyclePath += " -> ";
19105cca6223SDuncan P. N. Exon Smith }
19115cca6223SDuncan P. N. Exon Smith CyclePath += ModuleName;
19125cca6223SDuncan P. N. Exon Smith
19135cca6223SDuncan P. N. Exon Smith getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle)
19145cca6223SDuncan P. N. Exon Smith << ModuleName << CyclePath;
19157c2afd58SDuncan P. N. Exon Smith return nullptr;
19165cca6223SDuncan P. N. Exon Smith }
19175cca6223SDuncan P. N. Exon Smith
19185cca6223SDuncan P. N. Exon Smith // Check whether we have already attempted to build this module (but
19195cca6223SDuncan P. N. Exon Smith // failed).
19205cca6223SDuncan P. N. Exon Smith if (getPreprocessorOpts().FailedModules &&
19215cca6223SDuncan P. N. Exon Smith getPreprocessorOpts().FailedModules->hasAlreadyFailed(ModuleName)) {
19225cca6223SDuncan P. N. Exon Smith getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_built)
19235cca6223SDuncan P. N. Exon Smith << ModuleName << SourceRange(ImportLoc, ModuleNameLoc);
19247c2afd58SDuncan P. N. Exon Smith return nullptr;
19255cca6223SDuncan P. N. Exon Smith }
19265cca6223SDuncan P. N. Exon Smith
19275cca6223SDuncan P. N. Exon Smith // Try to compile and then read the AST.
1928b714f73dSDuncan P. N. Exon Smith if (!compileModuleAndReadAST(*this, ImportLoc, ModuleNameLoc, M,
19295cca6223SDuncan P. N. Exon Smith ModuleFilename)) {
19305cca6223SDuncan P. N. Exon Smith assert(getDiagnostics().hasErrorOccurred() &&
19315cca6223SDuncan P. N. Exon Smith "undiagnosed error in compileModuleAndReadAST");
19325cca6223SDuncan P. N. Exon Smith if (getPreprocessorOpts().FailedModules)
19335cca6223SDuncan P. N. Exon Smith getPreprocessorOpts().FailedModules->addFailed(ModuleName);
19347c2afd58SDuncan P. N. Exon Smith return nullptr;
19355cca6223SDuncan P. N. Exon Smith }
19365cca6223SDuncan P. N. Exon Smith
19375cca6223SDuncan P. N. Exon Smith // Okay, we've rebuilt and now loaded the module.
19385cca6223SDuncan P. N. Exon Smith return M;
19395cca6223SDuncan P. N. Exon Smith }
19405cca6223SDuncan P. N. Exon Smith
1941e842a474SRichard Smith ModuleLoadResult
loadModule(SourceLocation ImportLoc,ModuleIdPath Path,Module::NameVisibilityKind Visibility,bool IsInclusionDirective)19427a626570SDouglas Gregor CompilerInstance::loadModule(SourceLocation ImportLoc,
1943ff2be53fSDouglas Gregor ModuleIdPath Path,
1944bcfc7d02SDouglas Gregor Module::NameVisibilityKind Visibility,
1945bcfc7d02SDouglas Gregor bool IsInclusionDirective) {
194692304e00SRichard Smith // Determine what file we're searching from.
1947d6509cf2SRichard Smith StringRef ModuleName = Path[0].first->getName();
194892304e00SRichard Smith SourceLocation ModuleNameLoc = Path[0].second;
194992304e00SRichard Smith
19501805b8a4SDouglas Gregor // If we've already handled this import, just return the cached result.
19511805b8a4SDouglas Gregor // This one-element cache is important to eliminate redundant diagnostics
19521805b8a4SDouglas Gregor // when both the preprocessor and parser see the same import declaration.
19538b563665SYaron Keren if (ImportLoc.isValid() && LastModuleImportLoc == ImportLoc) {
1954ff2be53fSDouglas Gregor // Make the named module visible.
19557e82e019SRichard Smith if (LastModuleImportResult && ModuleName != getLangOpts().CurrentModule)
195620d51b2fSDuncan P. N. Exon Smith TheASTReader->makeModuleVisible(LastModuleImportResult, Visibility,
1957a7e2cc68SRichard Smith ImportLoc);
195869021974SDouglas Gregor return LastModuleImportResult;
1959ff2be53fSDouglas Gregor }
19601805b8a4SDouglas Gregor
19615196bc6bSDouglas Gregor // If we don't already have information on this module, load the module now.
19628112a423SDuncan P. N. Exon Smith Module *Module = nullptr;
196331e14f41SDuncan P. N. Exon Smith ModuleMap &MM = getPreprocessor().getHeaderSearchInfo().getModuleMap();
19648112a423SDuncan P. N. Exon Smith if (auto MaybeModule = MM.getCachedModuleLoad(*Path[0].first)) {
19658112a423SDuncan P. N. Exon Smith // Use the cached result, which may be nullptr.
19668112a423SDuncan P. N. Exon Smith Module = *MaybeModule;
19677e82e019SRichard Smith } else if (ModuleName == getLangOpts().CurrentModule) {
19682537a364SDouglas Gregor // This is the module we're building.
196952431f39SBruno Cardoso Lopes Module = PP->getHeaderSearchInfo().lookupModule(
1970638c673aSJan Svoboda ModuleName, ImportLoc, /*AllowSearch*/ true,
197152431f39SBruno Cardoso Lopes /*AllowExtraModuleMapSearch*/ !IsInclusionDirective);
1972d30446fdSBoris Kolpackov /// FIXME: perhaps we should (a) look for a module using the module name
1973d30446fdSBoris Kolpackov // to file map (PrebuiltModuleFiles) and (b) diagnose if still not found?
1974d30446fdSBoris Kolpackov //if (Module == nullptr) {
1975d30446fdSBoris Kolpackov // getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
1976d30446fdSBoris Kolpackov // << ModuleName;
197723e9146fSDuncan P. N. Exon Smith // DisableGeneratingGlobalModuleIndex = true;
1978d30446fdSBoris Kolpackov // return ModuleLoadResult();
1979d30446fdSBoris Kolpackov //}
198031e14f41SDuncan P. N. Exon Smith MM.cacheModuleLoad(*Path[0].first, Module);
19812537a364SDouglas Gregor } else {
19825cca6223SDuncan P. N. Exon Smith ModuleLoadResult Result = findOrCompileModuleAndReadAST(
19835cca6223SDuncan P. N. Exon Smith ModuleName, ImportLoc, ModuleNameLoc, IsInclusionDirective);
19845cca6223SDuncan P. N. Exon Smith if (!Result.isNormal())
19855cca6223SDuncan P. N. Exon Smith return Result;
19867c57a9bdSDuncan P. N. Exon Smith if (!Result)
19877c57a9bdSDuncan P. N. Exon Smith DisableGeneratingGlobalModuleIndex = true;
19885cca6223SDuncan P. N. Exon Smith Module = Result;
198931e14f41SDuncan P. N. Exon Smith MM.cacheModuleLoad(*Path[0].first, Module);
199069021974SDouglas Gregor }
199169021974SDouglas Gregor
19925cca6223SDuncan P. N. Exon Smith // If we never found the module, fail. Otherwise, verify the module and link
19935cca6223SDuncan P. N. Exon Smith // it up.
199469021974SDouglas Gregor if (!Module)
19957a626570SDouglas Gregor return ModuleLoadResult();
199669021974SDouglas Gregor
19975196bc6bSDouglas Gregor // Verify that the rest of the module path actually corresponds to
19985196bc6bSDouglas Gregor // a submodule.
199984bc0a27SBruno Cardoso Lopes bool MapPrivateSubModToTopLevel = false;
20005196bc6bSDouglas Gregor for (unsigned I = 1, N = Path.size(); I != N; ++I) {
20015196bc6bSDouglas Gregor StringRef Name = Path[I].first->getName();
2002eb90e830SDouglas Gregor clang::Module *Sub = Module->findSubmodule(Name);
20035196bc6bSDouglas Gregor
20049284931eSBruno Cardoso Lopes // If the user is requesting Foo.Private and it doesn't exist, try to
20059284931eSBruno Cardoso Lopes // match Foo_Private and emit a warning asking for the user to write
20069284931eSBruno Cardoso Lopes // @import Foo_Private instead. FIXME: remove this when existing clients
20079284931eSBruno Cardoso Lopes // migrate off of Foo.Private syntax.
20089284931eSBruno Cardoso Lopes if (!Sub && PP->getLangOpts().ImplicitModules && Name == "Private" &&
20099284931eSBruno Cardoso Lopes Module == Module->getTopLevelModule()) {
20109284931eSBruno Cardoso Lopes SmallString<128> PrivateModule(Module->Name);
20119284931eSBruno Cardoso Lopes PrivateModule.append("_Private");
20129284931eSBruno Cardoso Lopes
20139284931eSBruno Cardoso Lopes SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> PrivPath;
20149284931eSBruno Cardoso Lopes auto &II = PP->getIdentifierTable().get(
20159284931eSBruno Cardoso Lopes PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID());
20169284931eSBruno Cardoso Lopes PrivPath.push_back(std::make_pair(&II, Path[0].second));
20179284931eSBruno Cardoso Lopes
2018ab6ef587SJan Svoboda if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, ImportLoc, true,
2019ab6ef587SJan Svoboda !IsInclusionDirective))
2020ab6ef587SJan Svoboda Sub = loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective);
20219284931eSBruno Cardoso Lopes if (Sub) {
20229284931eSBruno Cardoso Lopes MapPrivateSubModToTopLevel = true;
20239284931eSBruno Cardoso Lopes if (!getDiagnostics().isIgnored(
20249284931eSBruno Cardoso Lopes diag::warn_no_priv_submodule_use_toplevel, ImportLoc)) {
20259284931eSBruno Cardoso Lopes getDiagnostics().Report(Path[I].second,
20269284931eSBruno Cardoso Lopes diag::warn_no_priv_submodule_use_toplevel)
20279284931eSBruno Cardoso Lopes << Path[I].first << Module->getFullModuleName() << PrivateModule
20289284931eSBruno Cardoso Lopes << SourceRange(Path[0].second, Path[I].second)
20299284931eSBruno Cardoso Lopes << FixItHint::CreateReplacement(SourceRange(Path[0].second),
20309284931eSBruno Cardoso Lopes PrivateModule);
20319284931eSBruno Cardoso Lopes getDiagnostics().Report(Sub->DefinitionLoc,
20329284931eSBruno Cardoso Lopes diag::note_private_top_level_defined);
20339284931eSBruno Cardoso Lopes }
20349284931eSBruno Cardoso Lopes }
20359284931eSBruno Cardoso Lopes }
20369284931eSBruno Cardoso Lopes
2037eb90e830SDouglas Gregor if (!Sub) {
20385196bc6bSDouglas Gregor // Attempt to perform typo correction to find a module name that works.
2039f857950dSDmitri Gribenko SmallVector<StringRef, 2> Best;
20405196bc6bSDouglas Gregor unsigned BestEditDistance = (std::numeric_limits<unsigned>::max)();
20415196bc6bSDouglas Gregor
2042c57ca335SJan Svoboda for (class Module *SubModule : Module->submodules()) {
2043ab6ef587SJan Svoboda unsigned ED =
2044ab6ef587SJan Svoboda Name.edit_distance(SubModule->Name,
2045ab6ef587SJan Svoboda /*AllowReplacements=*/true, BestEditDistance);
20465196bc6bSDouglas Gregor if (ED <= BestEditDistance) {
2047eb90e830SDouglas Gregor if (ED < BestEditDistance) {
20485196bc6bSDouglas Gregor Best.clear();
2049eb90e830SDouglas Gregor BestEditDistance = ED;
2050eb90e830SDouglas Gregor }
2051eb90e830SDouglas Gregor
2052c57ca335SJan Svoboda Best.push_back(SubModule->Name);
20535196bc6bSDouglas Gregor }
20545196bc6bSDouglas Gregor }
20555196bc6bSDouglas Gregor
20565196bc6bSDouglas Gregor // If there was a clear winner, user it.
20575196bc6bSDouglas Gregor if (Best.size() == 1) {
2058ab6ef587SJan Svoboda getDiagnostics().Report(Path[I].second, diag::err_no_submodule_suggest)
205969021974SDouglas Gregor << Path[I].first << Module->getFullModuleName() << Best[0]
20605196bc6bSDouglas Gregor << SourceRange(Path[0].second, Path[I - 1].second)
20615196bc6bSDouglas Gregor << FixItHint::CreateReplacement(SourceRange(Path[I].second),
20625196bc6bSDouglas Gregor Best[0]);
2063eb90e830SDouglas Gregor
2064eb90e830SDouglas Gregor Sub = Module->findSubmodule(Best[0]);
20655196bc6bSDouglas Gregor }
20665196bc6bSDouglas Gregor }
20675196bc6bSDouglas Gregor
2068eb90e830SDouglas Gregor if (!Sub) {
20695196bc6bSDouglas Gregor // No submodule by this name. Complain, and don't look for further
20705196bc6bSDouglas Gregor // submodules.
20715196bc6bSDouglas Gregor getDiagnostics().Report(Path[I].second, diag::err_no_submodule)
207269021974SDouglas Gregor << Path[I].first << Module->getFullModuleName()
20735196bc6bSDouglas Gregor << SourceRange(Path[0].second, Path[I - 1].second);
20745196bc6bSDouglas Gregor break;
20755196bc6bSDouglas Gregor }
20765196bc6bSDouglas Gregor
2077eb90e830SDouglas Gregor Module = Sub;
20785196bc6bSDouglas Gregor }
20795196bc6bSDouglas Gregor
20802537a364SDouglas Gregor // Make the named module visible, if it's not already part of the module
20812537a364SDouglas Gregor // we are parsing.
208298a52db8SDouglas Gregor if (ModuleName != getLangOpts().CurrentModule) {
208384bc0a27SBruno Cardoso Lopes if (!Module->IsFromModuleFile && !MapPrivateSubModToTopLevel) {
208498a52db8SDouglas Gregor // We have an umbrella header or directory that doesn't actually include
208598a52db8SDouglas Gregor // all of the headers within the directory it covers. Complain about
208698a52db8SDouglas Gregor // this missing submodule and recover by forgetting that we ever saw
208798a52db8SDouglas Gregor // this submodule.
208898a52db8SDouglas Gregor // FIXME: Should we detect this at module load time? It seems fairly
208998a52db8SDouglas Gregor // expensive (and rare).
209098a52db8SDouglas Gregor getDiagnostics().Report(ImportLoc, diag::warn_missing_submodule)
209198a52db8SDouglas Gregor << Module->getFullModuleName()
209298a52db8SDouglas Gregor << SourceRange(Path.front().second, Path.back().second);
209398a52db8SDouglas Gregor
2094a114c46eSRichard Smith return ModuleLoadResult::MissingExpected;
209598a52db8SDouglas Gregor }
20961fb5c3a6SDouglas Gregor
20971fb5c3a6SDouglas Gregor // Check whether this module is available.
209827e5aa08SRichard Smith if (Preprocessor::checkModuleIsAvailable(getLangOpts(), getTarget(),
209927e5aa08SRichard Smith getDiagnostics(), Module)) {
210027e5aa08SRichard Smith getDiagnostics().Report(ImportLoc, diag::note_module_import_here)
21011fb5c3a6SDouglas Gregor << SourceRange(Path.front().second, Path.back().second);
21021fb5c3a6SDouglas Gregor LastModuleImportLoc = ImportLoc;
21037a626570SDouglas Gregor LastModuleImportResult = ModuleLoadResult();
21047a626570SDouglas Gregor return ModuleLoadResult();
21051fb5c3a6SDouglas Gregor }
21061fb5c3a6SDouglas Gregor
210720d51b2fSDuncan P. N. Exon Smith TheASTReader->makeModuleVisible(Module, Visibility, ImportLoc);
210898a52db8SDouglas Gregor }
21095196bc6bSDouglas Gregor
211035b13eceSDouglas Gregor // Check for any configuration macros that have changed.
211135b13eceSDouglas Gregor clang::Module *TopModule = Module->getTopLevelModule();
211235b13eceSDouglas Gregor for (unsigned I = 0, N = TopModule->ConfigMacros.size(); I != N; ++I) {
211335b13eceSDouglas Gregor checkConfigMacro(getPreprocessor(), TopModule->ConfigMacros[I],
211435b13eceSDouglas Gregor Module, ImportLoc);
211535b13eceSDouglas Gregor }
211635b13eceSDouglas Gregor
2117a3b5f71eSBruno Cardoso Lopes // Resolve any remaining module using export_as for this one.
2118a3b5f71eSBruno Cardoso Lopes getPreprocessor()
2119a3b5f71eSBruno Cardoso Lopes .getHeaderSearchInfo()
2120a3b5f71eSBruno Cardoso Lopes .getModuleMap()
2121a3b5f71eSBruno Cardoso Lopes .resolveLinkAsDependencies(TopModule);
2122a3b5f71eSBruno Cardoso Lopes
21231805b8a4SDouglas Gregor LastModuleImportLoc = ImportLoc;
2124a114c46eSRichard Smith LastModuleImportResult = ModuleLoadResult(Module);
21257a626570SDouglas Gregor return LastModuleImportResult;
212608142534SDouglas Gregor }
2127c147b0bcSDouglas Gregor
createModuleFromSource(SourceLocation ImportLoc,StringRef ModuleName,StringRef Source)21285cca6223SDuncan P. N. Exon Smith void CompilerInstance::createModuleFromSource(SourceLocation ImportLoc,
21295d2ed489SRichard Smith StringRef ModuleName,
21305d2ed489SRichard Smith StringRef Source) {
21319565c75bSRichard Smith // Avoid creating filenames with special characters.
21329565c75bSRichard Smith SmallString<128> CleanModuleName(ModuleName);
21339565c75bSRichard Smith for (auto &C : CleanModuleName)
21349565c75bSRichard Smith if (!isAlphanumeric(C))
21359565c75bSRichard Smith C = '_';
21369565c75bSRichard Smith
21375d2ed489SRichard Smith // FIXME: Using a randomized filename here means that our intermediate .pcm
21385d2ed489SRichard Smith // output is nondeterministic (as .pcm files refer to each other by name).
21395d2ed489SRichard Smith // Can this affect the output in any way?
21405d2ed489SRichard Smith SmallString<128> ModuleFileName;
21415d2ed489SRichard Smith if (std::error_code EC = llvm::sys::fs::createTemporaryFile(
21429565c75bSRichard Smith CleanModuleName, "pcm", ModuleFileName)) {
21435d2ed489SRichard Smith getDiagnostics().Report(ImportLoc, diag::err_fe_unable_to_open_output)
21445d2ed489SRichard Smith << ModuleFileName << EC.message();
21455d2ed489SRichard Smith return;
21465d2ed489SRichard Smith }
21479565c75bSRichard Smith std::string ModuleMapFileName = (CleanModuleName + ".map").str();
21485d2ed489SRichard Smith
21495d2ed489SRichard Smith FrontendInputFile Input(
21505d2ed489SRichard Smith ModuleMapFileName,
21515d2ed489SRichard Smith InputKind(getLanguageFromOptions(*Invocation->getLangOpts()),
21525d2ed489SRichard Smith InputKind::ModuleMap, /*Preprocessed*/true));
21535d2ed489SRichard Smith
21545d2ed489SRichard Smith std::string NullTerminatedSource(Source.str());
21555d2ed489SRichard Smith
21565d2ed489SRichard Smith auto PreBuildStep = [&](CompilerInstance &Other) {
21575d2ed489SRichard Smith // Create a virtual file containing our desired source.
21585d2ed489SRichard Smith // FIXME: We shouldn't need to do this.
21595d2ed489SRichard Smith const FileEntry *ModuleMapFile = Other.getFileManager().getVirtualFile(
21605d2ed489SRichard Smith ModuleMapFileName, NullTerminatedSource.size(), 0);
21615d2ed489SRichard Smith Other.getSourceManager().overrideFileContents(
2162b8debabbSKazu Hirata ModuleMapFile, llvm::MemoryBuffer::getMemBuffer(NullTerminatedSource));
21635d2ed489SRichard Smith
21645d2ed489SRichard Smith Other.BuiltModules = std::move(BuiltModules);
216586a3ef5bSRichard Smith Other.DeleteBuiltModules = false;
21665d2ed489SRichard Smith };
21675d2ed489SRichard Smith
21685d2ed489SRichard Smith auto PostBuildStep = [this](CompilerInstance &Other) {
21695d2ed489SRichard Smith BuiltModules = std::move(Other.BuiltModules);
21705d2ed489SRichard Smith };
21715d2ed489SRichard Smith
21725d2ed489SRichard Smith // Build the module, inheriting any modules that we've built locally.
21735d2ed489SRichard Smith if (compileModuleImpl(*this, ImportLoc, ModuleName, Input, StringRef(),
21745d2ed489SRichard Smith ModuleFileName, PreBuildStep, PostBuildStep)) {
2175adcd0268SBenjamin Kramer BuiltModules[std::string(ModuleName)] = std::string(ModuleFileName.str());
21765d2ed489SRichard Smith llvm::sys::RemoveFileOnSignal(ModuleFileName);
21775d2ed489SRichard Smith }
21785d2ed489SRichard Smith }
21795d2ed489SRichard Smith
makeModuleVisible(Module * Mod,Module::NameVisibilityKind Visibility,SourceLocation ImportLoc)2180c147b0bcSDouglas Gregor void CompilerInstance::makeModuleVisible(Module *Mod,
2181125df058SArgyrios Kyrtzidis Module::NameVisibilityKind Visibility,
2182a7e2cc68SRichard Smith SourceLocation ImportLoc) {
218320d51b2fSDuncan P. N. Exon Smith if (!TheASTReader)
218420d51b2fSDuncan P. N. Exon Smith createASTReader();
218520d51b2fSDuncan P. N. Exon Smith if (!TheASTReader)
218642413141SRichard Smith return;
218742413141SRichard Smith
218820d51b2fSDuncan P. N. Exon Smith TheASTReader->makeModuleVisible(Mod, Visibility, ImportLoc);
2189c147b0bcSDouglas Gregor }
2190c147b0bcSDouglas Gregor
loadGlobalModuleIndex(SourceLocation TriggerLoc)21912255f2ceSJohn Thompson GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex(
21922255f2ceSJohn Thompson SourceLocation TriggerLoc) {
21933938f0c7SRichard Smith if (getPreprocessor().getHeaderSearchInfo().getModuleCachePath().empty())
21943938f0c7SRichard Smith return nullptr;
219520d51b2fSDuncan P. N. Exon Smith if (!TheASTReader)
219620d51b2fSDuncan P. N. Exon Smith createASTReader();
21972255f2ceSJohn Thompson // Can't do anything if we don't have the module manager.
219820d51b2fSDuncan P. N. Exon Smith if (!TheASTReader)
219949a2790fSCraig Topper return nullptr;
22002255f2ceSJohn Thompson // Get an existing global index. This loads it if not already
22012255f2ceSJohn Thompson // loaded.
220220d51b2fSDuncan P. N. Exon Smith TheASTReader->loadGlobalIndex();
220320d51b2fSDuncan P. N. Exon Smith GlobalModuleIndex *GlobalIndex = TheASTReader->getGlobalIndex();
22042255f2ceSJohn Thompson // If the global index doesn't exist, create it.
22052255f2ceSJohn Thompson if (!GlobalIndex && shouldBuildGlobalModuleIndex() && hasFileManager() &&
22062255f2ceSJohn Thompson hasPreprocessor()) {
22072255f2ceSJohn Thompson llvm::sys::fs::create_directories(
22082255f2ceSJohn Thompson getPreprocessor().getHeaderSearchInfo().getModuleCachePath());
22090e828958SJF Bastien if (llvm::Error Err = GlobalModuleIndex::writeIndex(
2210fb2398d0SAdrian Prantl getFileManager(), getPCHContainerReader(),
22110e828958SJF Bastien getPreprocessor().getHeaderSearchInfo().getModuleCachePath())) {
22120e828958SJF Bastien // FIXME this drops the error on the floor. This code is only used for
22130e828958SJF Bastien // typo correction and drops more than just this one source of errors
22140e828958SJF Bastien // (such as the directory creation failure above). It should handle the
22150e828958SJF Bastien // error.
22160e828958SJF Bastien consumeError(std::move(Err));
22170e828958SJF Bastien return nullptr;
22180e828958SJF Bastien }
221920d51b2fSDuncan P. N. Exon Smith TheASTReader->resetForReload();
222020d51b2fSDuncan P. N. Exon Smith TheASTReader->loadGlobalIndex();
222120d51b2fSDuncan P. N. Exon Smith GlobalIndex = TheASTReader->getGlobalIndex();
22222255f2ceSJohn Thompson }
22232255f2ceSJohn Thompson // For finding modules needing to be imported for fixit messages,
22242255f2ceSJohn Thompson // we need to make the global index cover all modules, so we do that here.
22252255f2ceSJohn Thompson if (!HaveFullGlobalModuleIndex && GlobalIndex && !buildingModule()) {
22262255f2ceSJohn Thompson ModuleMap &MMap = getPreprocessor().getHeaderSearchInfo().getModuleMap();
22272255f2ceSJohn Thompson bool RecreateIndex = false;
22282255f2ceSJohn Thompson for (ModuleMap::module_iterator I = MMap.module_begin(),
22292255f2ceSJohn Thompson E = MMap.module_end(); I != E; ++I) {
22302255f2ceSJohn Thompson Module *TheModule = I->second;
22312255f2ceSJohn Thompson const FileEntry *Entry = TheModule->getASTFile();
22322255f2ceSJohn Thompson if (!Entry) {
22332255f2ceSJohn Thompson SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path;
22342255f2ceSJohn Thompson Path.push_back(std::make_pair(
22352255f2ceSJohn Thompson getPreprocessor().getIdentifierInfo(TheModule->Name), TriggerLoc));
22362255f2ceSJohn Thompson std::reverse(Path.begin(), Path.end());
22372255f2ceSJohn Thompson // Load a module as hidden. This also adds it to the global index.
2238629d8e6fSRichard Smith loadModule(TheModule->DefinitionLoc, Path, Module::Hidden, false);
22392255f2ceSJohn Thompson RecreateIndex = true;
22402255f2ceSJohn Thompson }
22412255f2ceSJohn Thompson }
22422255f2ceSJohn Thompson if (RecreateIndex) {
22430e828958SJF Bastien if (llvm::Error Err = GlobalModuleIndex::writeIndex(
2244fb2398d0SAdrian Prantl getFileManager(), getPCHContainerReader(),
22450e828958SJF Bastien getPreprocessor().getHeaderSearchInfo().getModuleCachePath())) {
22460e828958SJF Bastien // FIXME As above, this drops the error on the floor.
22470e828958SJF Bastien consumeError(std::move(Err));
22480e828958SJF Bastien return nullptr;
22490e828958SJF Bastien }
225020d51b2fSDuncan P. N. Exon Smith TheASTReader->resetForReload();
225120d51b2fSDuncan P. N. Exon Smith TheASTReader->loadGlobalIndex();
225220d51b2fSDuncan P. N. Exon Smith GlobalIndex = TheASTReader->getGlobalIndex();
22532255f2ceSJohn Thompson }
22542255f2ceSJohn Thompson HaveFullGlobalModuleIndex = true;
22552255f2ceSJohn Thompson }
22562255f2ceSJohn Thompson return GlobalIndex;
22572255f2ceSJohn Thompson }
22582d94bbb0SJohn Thompson
22592d94bbb0SJohn Thompson // Check global module index for missing imports.
22602d94bbb0SJohn Thompson bool
lookupMissingImports(StringRef Name,SourceLocation TriggerLoc)22612d94bbb0SJohn Thompson CompilerInstance::lookupMissingImports(StringRef Name,
22622d94bbb0SJohn Thompson SourceLocation TriggerLoc) {
22632d94bbb0SJohn Thompson // Look for the symbol in non-imported modules, but only if an error
22642d94bbb0SJohn Thompson // actually occurred.
22652d94bbb0SJohn Thompson if (!buildingModule()) {
22662d94bbb0SJohn Thompson // Load global module index, or retrieve a previously loaded one.
22672d94bbb0SJohn Thompson GlobalModuleIndex *GlobalIndex = loadGlobalModuleIndex(
22682d94bbb0SJohn Thompson TriggerLoc);
22692d94bbb0SJohn Thompson
22702d94bbb0SJohn Thompson // Only if we have a global index.
22712d94bbb0SJohn Thompson if (GlobalIndex) {
22722d94bbb0SJohn Thompson GlobalModuleIndex::HitSet FoundModules;
22732d94bbb0SJohn Thompson
22742d94bbb0SJohn Thompson // Find the modules that reference the identifier.
22752d94bbb0SJohn Thompson // Note that this only finds top-level modules.
22762d94bbb0SJohn Thompson // We'll let diagnoseTypo find the actual declaration module.
22772d94bbb0SJohn Thompson if (GlobalIndex->lookupIdentifier(Name, FoundModules))
22782d94bbb0SJohn Thompson return true;
22792d94bbb0SJohn Thompson }
22802d94bbb0SJohn Thompson }
22812d94bbb0SJohn Thompson
22822d94bbb0SJohn Thompson return false;
22832d94bbb0SJohn Thompson }
resetAndLeakSema()22849941da41SDavid Blaikie void CompilerInstance::resetAndLeakSema() { llvm::BuryPointer(takeSema()); }
22857de9969bSBenjamin Kramer
setExternalSemaSource(IntrusiveRefCntPtr<ExternalSemaSource> ESS)22867de9969bSBenjamin Kramer void CompilerInstance::setExternalSemaSource(
22877de9969bSBenjamin Kramer IntrusiveRefCntPtr<ExternalSemaSource> ESS) {
22887de9969bSBenjamin Kramer ExternalSemaSrc = std::move(ESS);
22897de9969bSBenjamin Kramer }
2290