1636404a3SDaniel Dunbar //===--- CompilerInstance.cpp ---------------------------------------------===//
2636404a3SDaniel Dunbar //
3636404a3SDaniel Dunbar //                     The LLVM Compiler Infrastructure
4636404a3SDaniel Dunbar //
5636404a3SDaniel Dunbar // This file is distributed under the University of Illinois Open Source
6636404a3SDaniel Dunbar // License. See LICENSE.TXT for details.
7636404a3SDaniel Dunbar //
8636404a3SDaniel Dunbar //===----------------------------------------------------------------------===//
9636404a3SDaniel Dunbar 
10636404a3SDaniel Dunbar #include "clang/Frontend/CompilerInstance.h"
110e93f017SDouglas Gregor #include "clang/Sema/Sema.h"
1256d9c293SDaniel Dunbar #include "clang/AST/ASTConsumer.h"
13df3e30c4SDaniel Dunbar #include "clang/AST/ASTContext.h"
14636404a3SDaniel Dunbar #include "clang/Basic/Diagnostic.h"
15546a676aSDaniel Dunbar #include "clang/Basic/FileManager.h"
16546a676aSDaniel Dunbar #include "clang/Basic/SourceManager.h"
17636404a3SDaniel Dunbar #include "clang/Basic/TargetInfo.h"
184f2bc55dSDaniel Dunbar #include "clang/Basic/Version.h"
19aaa148fdSDaniel Dunbar #include "clang/Lex/HeaderSearch.h"
20aaa148fdSDaniel Dunbar #include "clang/Lex/Preprocessor.h"
21aaa148fdSDaniel Dunbar #include "clang/Lex/PTHManager.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"
262083c32fSDaniel Dunbar #include "clang/Frontend/LogDiagnosticPrinter.h"
274610ea2bSTed Kremenek #include "clang/Frontend/SerializedDiagnosticPrinter.h"
287d75afc5SDaniel Dunbar #include "clang/Frontend/TextDiagnosticPrinter.h"
2969609dceSDavid Blaikie #include "clang/Frontend/VerifyDiagnosticConsumer.h"
30aaa148fdSDaniel Dunbar #include "clang/Frontend/Utils.h"
31f5b13467SSebastian Redl #include "clang/Serialization/ASTReader.h"
32f7093b5aSDaniel Dunbar #include "clang/Sema/CodeCompleteConsumer.h"
33f6efe58dSMichael J. Spencer #include "llvm/Support/FileSystem.h"
34409e890fSDaniel Dunbar #include "llvm/Support/MemoryBuffer.h"
357d75afc5SDaniel Dunbar #include "llvm/Support/raw_ostream.h"
36171b780cSDouglas Gregor #include "llvm/ADT/Statistic.h"
375505dff8SKovarththanan Rajaratnam #include "llvm/Support/Timer.h"
388aaf4995SMichael J. Spencer #include "llvm/Support/Host.h"
398aaf4995SMichael J. Spencer #include "llvm/Support/Path.h"
408aaf4995SMichael J. Spencer #include "llvm/Support/Program.h"
418aaf4995SMichael J. Spencer #include "llvm/Support/Signals.h"
42f25faaafSMichael J. Spencer #include "llvm/Support/system_error.h"
4351e0b541SDouglas Gregor #include "llvm/Support/CrashRecoveryContext.h"
44321cdb85SDylan Noblesmith #include "llvm/Config/config.h"
4554a88810SDouglas Gregor 
4654a88810SDouglas Gregor // Support for FileLockManager
4754a88810SDouglas Gregor #include <fstream>
4854a88810SDouglas Gregor #include <sys/types.h>
4954a88810SDouglas Gregor #include <sys/stat.h>
5054a88810SDouglas Gregor 
51a04a46e8SDouglas Gregor #if LLVM_ON_WIN32
52a04a46e8SDouglas Gregor #include <windows.h>
53a04a46e8SDouglas Gregor #endif
5454a88810SDouglas Gregor #if LLVM_ON_UNIX
5554a88810SDouglas Gregor #include <unistd.h>
5654a88810SDouglas Gregor #endif
5754a88810SDouglas Gregor 
58636404a3SDaniel Dunbar using namespace clang;
59636404a3SDaniel Dunbar 
60e922d9bdSDaniel Dunbar CompilerInstance::CompilerInstance()
61925296b4SDouglas Gregor   : Invocation(new CompilerInvocation()), ModuleManager(0) {
62636404a3SDaniel Dunbar }
63636404a3SDaniel Dunbar 
64636404a3SDaniel Dunbar CompilerInstance::~CompilerInstance() {
65e922d9bdSDaniel Dunbar }
66e922d9bdSDaniel Dunbar 
6768242254SDaniel Dunbar void CompilerInstance::setInvocation(CompilerInvocation *Value) {
685e14d39aSTed Kremenek   Invocation = Value;
6968242254SDaniel Dunbar }
7068242254SDaniel Dunbar 
719c902b55SDavid Blaikie void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
727f95d26eSDouglas Gregor   Diagnostics = Value;
73e01dc86dSDaniel Dunbar }
74e01dc86dSDaniel Dunbar 
75e01dc86dSDaniel Dunbar void CompilerInstance::setTarget(TargetInfo *Value) {
765e14d39aSTed Kremenek   Target = Value;
77e01dc86dSDaniel Dunbar }
78e01dc86dSDaniel Dunbar 
79e01dc86dSDaniel Dunbar void CompilerInstance::setFileManager(FileManager *Value) {
805e14d39aSTed Kremenek   FileMgr = Value;
81e01dc86dSDaniel Dunbar }
82e01dc86dSDaniel Dunbar 
83e01dc86dSDaniel Dunbar void CompilerInstance::setSourceManager(SourceManager *Value) {
845e14d39aSTed Kremenek   SourceMgr = Value;
85e01dc86dSDaniel Dunbar }
86e01dc86dSDaniel Dunbar 
875e14d39aSTed Kremenek void CompilerInstance::setPreprocessor(Preprocessor *Value) { PP = Value; }
88e01dc86dSDaniel Dunbar 
895e14d39aSTed Kremenek void CompilerInstance::setASTContext(ASTContext *Value) { Context = Value; }
90e01dc86dSDaniel Dunbar 
910e93f017SDouglas Gregor void CompilerInstance::setSema(Sema *S) {
920e93f017SDouglas Gregor   TheSema.reset(S);
930e93f017SDouglas Gregor }
940e93f017SDouglas Gregor 
9556d9c293SDaniel Dunbar void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
9656d9c293SDaniel Dunbar   Consumer.reset(Value);
9756d9c293SDaniel Dunbar }
9856d9c293SDaniel Dunbar 
99e01dc86dSDaniel Dunbar void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
100e01dc86dSDaniel Dunbar   CompletionConsumer.reset(Value);
101e01dc86dSDaniel Dunbar }
102e01dc86dSDaniel Dunbar 
1037d75afc5SDaniel Dunbar // Diagnostics
1047d75afc5SDaniel Dunbar static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
10589c31490SAxel Naumann                               unsigned argc, const char* const *argv,
1069c902b55SDavid Blaikie                               DiagnosticsEngine &Diags) {
1077d75afc5SDaniel Dunbar   std::string ErrorInfo;
1080e62c1ccSChris Lattner   llvm::OwningPtr<raw_ostream> OS(
109eeed0cc3SKovarththanan Rajaratnam     new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo));
1107d75afc5SDaniel Dunbar   if (!ErrorInfo.empty()) {
1114a94ba56SKovarththanan Rajaratnam     Diags.Report(diag::err_fe_unable_to_open_logfile)
1124a94ba56SKovarththanan Rajaratnam                  << DiagOpts.DumpBuildInformation << ErrorInfo;
1137d75afc5SDaniel Dunbar     return;
1147d75afc5SDaniel Dunbar   }
1157d75afc5SDaniel Dunbar 
116520d1e6cSDaniel Dunbar   (*OS) << "clang -cc1 command line arguments: ";
1177d75afc5SDaniel Dunbar   for (unsigned i = 0; i != argc; ++i)
1187d75afc5SDaniel Dunbar     (*OS) << argv[i] << ' ';
1197d75afc5SDaniel Dunbar   (*OS) << '\n';
1207d75afc5SDaniel Dunbar 
1217d75afc5SDaniel Dunbar   // Chain in a diagnostic client which will log the diagnostics.
122e2eefaecSDavid Blaikie   DiagnosticConsumer *Logger =
123eeed0cc3SKovarththanan Rajaratnam     new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true);
1248b00dcb0SDavid Blaikie   Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger));
1257d75afc5SDaniel Dunbar }
1267d75afc5SDaniel Dunbar 
1272083c32fSDaniel Dunbar static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts,
1287b83306dSDaniel Dunbar                                const CodeGenOptions *CodeGenOpts,
1299c902b55SDavid Blaikie                                DiagnosticsEngine &Diags) {
1302083c32fSDaniel Dunbar   std::string ErrorInfo;
1312083c32fSDaniel Dunbar   bool OwnsStream = false;
1320e62c1ccSChris Lattner   raw_ostream *OS = &llvm::errs();
1332083c32fSDaniel Dunbar   if (DiagOpts.DiagnosticLogFile != "-") {
1342083c32fSDaniel Dunbar     // Create the output stream.
1352083c32fSDaniel Dunbar     llvm::raw_fd_ostream *FileOS(
1362083c32fSDaniel Dunbar       new llvm::raw_fd_ostream(DiagOpts.DiagnosticLogFile.c_str(),
13744d9ef78SDaniel Dunbar                                ErrorInfo, llvm::raw_fd_ostream::F_Append));
1382083c32fSDaniel Dunbar     if (!ErrorInfo.empty()) {
1392083c32fSDaniel Dunbar       Diags.Report(diag::warn_fe_cc_log_diagnostics_failure)
1402083c32fSDaniel Dunbar         << DiagOpts.DumpBuildInformation << ErrorInfo;
1412083c32fSDaniel Dunbar     } else {
1422083c32fSDaniel Dunbar       FileOS->SetUnbuffered();
1432083c32fSDaniel Dunbar       FileOS->SetUseAtomicWrites(true);
1442083c32fSDaniel Dunbar       OS = FileOS;
1452083c32fSDaniel Dunbar       OwnsStream = true;
1462083c32fSDaniel Dunbar     }
1472083c32fSDaniel Dunbar   }
1482083c32fSDaniel Dunbar 
1492083c32fSDaniel Dunbar   // Chain in the diagnostic client which will log the diagnostics.
1507b83306dSDaniel Dunbar   LogDiagnosticPrinter *Logger = new LogDiagnosticPrinter(*OS, DiagOpts,
1512083c32fSDaniel Dunbar                                                           OwnsStream);
1527b83306dSDaniel Dunbar   if (CodeGenOpts)
1537b83306dSDaniel Dunbar     Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags);
1548b00dcb0SDavid Blaikie   Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger));
1552083c32fSDaniel Dunbar }
1562083c32fSDaniel Dunbar 
1574610ea2bSTed Kremenek static void SetupSerializedDiagnostics(const DiagnosticOptions &DiagOpts,
1584610ea2bSTed Kremenek                                        DiagnosticsEngine &Diags,
1594610ea2bSTed Kremenek                                        StringRef OutputFile) {
1604610ea2bSTed Kremenek   std::string ErrorInfo;
1614610ea2bSTed Kremenek   llvm::OwningPtr<llvm::raw_fd_ostream> OS;
1624610ea2bSTed Kremenek   OS.reset(new llvm::raw_fd_ostream(OutputFile.str().c_str(), ErrorInfo,
1634610ea2bSTed Kremenek                                     llvm::raw_fd_ostream::F_Binary));
1644610ea2bSTed Kremenek 
1654610ea2bSTed Kremenek   if (!ErrorInfo.empty()) {
1664610ea2bSTed Kremenek     Diags.Report(diag::warn_fe_serialized_diag_failure)
1674610ea2bSTed Kremenek       << OutputFile << ErrorInfo;
1684610ea2bSTed Kremenek     return;
1694610ea2bSTed Kremenek   }
1704610ea2bSTed Kremenek 
1714610ea2bSTed Kremenek   DiagnosticConsumer *SerializedConsumer =
1724610ea2bSTed Kremenek     clang::serialized_diags::create(OS.take(), Diags);
1734610ea2bSTed Kremenek 
1744610ea2bSTed Kremenek 
1754610ea2bSTed Kremenek   Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(),
1764610ea2bSTed Kremenek                                                 SerializedConsumer));
1774610ea2bSTed Kremenek }
1784610ea2bSTed Kremenek 
17944c6ee77SDouglas Gregor void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv,
180e2eefaecSDavid Blaikie                                          DiagnosticConsumer *Client,
181d0e9e3a6SDouglas Gregor                                          bool ShouldOwnClient,
182d0e9e3a6SDouglas Gregor                                          bool ShouldCloneClient) {
1837b83306dSDaniel Dunbar   Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client,
184d0e9e3a6SDouglas Gregor                                   ShouldOwnClient, ShouldCloneClient,
185d0e9e3a6SDouglas Gregor                                   &getCodeGenOpts());
1867d75afc5SDaniel Dunbar }
1877d75afc5SDaniel Dunbar 
1889c902b55SDavid Blaikie llvm::IntrusiveRefCntPtr<DiagnosticsEngine>
1897f95d26eSDouglas Gregor CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
19044c6ee77SDouglas Gregor                                     int Argc, const char* const *Argv,
191e2eefaecSDavid Blaikie                                     DiagnosticConsumer *Client,
1922b9b4642SDouglas Gregor                                     bool ShouldOwnClient,
193d0e9e3a6SDouglas Gregor                                     bool ShouldCloneClient,
1947b83306dSDaniel Dunbar                                     const CodeGenOptions *CodeGenOpts) {
195d0040648SArgyrios Kyrtzidis   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
1969c902b55SDavid Blaikie   llvm::IntrusiveRefCntPtr<DiagnosticsEngine>
1979c902b55SDavid Blaikie       Diags(new DiagnosticsEngine(DiagID));
1981b39a2edSDaniel Dunbar 
1997d75afc5SDaniel Dunbar   // Create the diagnostic client for reporting errors or for
2007d75afc5SDaniel Dunbar   // implementing -verify.
201d0e9e3a6SDouglas Gregor   if (Client) {
202d0e9e3a6SDouglas Gregor     if (ShouldCloneClient)
203d0e9e3a6SDouglas Gregor       Diags->setClient(Client->clone(*Diags), ShouldOwnClient);
20444c6ee77SDouglas Gregor     else
205d0e9e3a6SDouglas Gregor       Diags->setClient(Client, ShouldOwnClient);
206d0e9e3a6SDouglas Gregor   } else
2072dd19f1dSDouglas Gregor     Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
20850ec0da0SDaniel Dunbar 
20950ec0da0SDaniel Dunbar   // Chain in -verify checker, if requested.
21050ec0da0SDaniel Dunbar   if (Opts.VerifyDiagnostics)
21169609dceSDavid Blaikie     Diags->setClient(new VerifyDiagnosticConsumer(*Diags));
2127d75afc5SDaniel Dunbar 
2132083c32fSDaniel Dunbar   // Chain in -diagnostic-log-file dumper, if requested.
2142083c32fSDaniel Dunbar   if (!Opts.DiagnosticLogFile.empty())
2157b83306dSDaniel Dunbar     SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags);
2162083c32fSDaniel Dunbar 
2177d75afc5SDaniel Dunbar   if (!Opts.DumpBuildInformation.empty())
2184a94ba56SKovarththanan Rajaratnam     SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
2197d75afc5SDaniel Dunbar 
2204610ea2bSTed Kremenek   if (!Opts.DiagnosticSerializationFile.empty())
2214610ea2bSTed Kremenek     SetupSerializedDiagnostics(Opts, *Diags,
2224610ea2bSTed Kremenek                                Opts.DiagnosticSerializationFile);
2234610ea2bSTed Kremenek 
2247d75afc5SDaniel Dunbar   // Configure our handling of diagnostics.
2259ff84d9cSKovarththanan Rajaratnam   ProcessWarningOptions(*Diags, Opts);
2267d75afc5SDaniel Dunbar 
2277f95d26eSDouglas Gregor   return Diags;
2287d75afc5SDaniel Dunbar }
2297d75afc5SDaniel Dunbar 
2307d75afc5SDaniel Dunbar // File Manager
2317d75afc5SDaniel Dunbar 
232546a676aSDaniel Dunbar void CompilerInstance::createFileManager() {
2335e14d39aSTed Kremenek   FileMgr = new FileManager(getFileSystemOpts());
234546a676aSDaniel Dunbar }
235546a676aSDaniel Dunbar 
2367d75afc5SDaniel Dunbar // Source Manager
2377d75afc5SDaniel Dunbar 
2385159f616SChris Lattner void CompilerInstance::createSourceManager(FileManager &FileMgr) {
2395e14d39aSTed Kremenek   SourceMgr = new SourceManager(getDiagnostics(), FileMgr);
240546a676aSDaniel Dunbar }
241aaa148fdSDaniel Dunbar 
2427d75afc5SDaniel Dunbar // Preprocessor
2437d75afc5SDaniel Dunbar 
244aaa148fdSDaniel Dunbar void CompilerInstance::createPreprocessor() {
24508142534SDouglas Gregor   const PreprocessorOptions &PPOpts = getPreprocessorOpts();
246aaa148fdSDaniel Dunbar 
247aaa148fdSDaniel Dunbar   // Create a PTH manager if we are using some form of a token cache.
248aaa148fdSDaniel Dunbar   PTHManager *PTHMgr = 0;
249d6ea9028SDaniel Dunbar   if (!PPOpts.TokenCache.empty())
25008142534SDouglas Gregor     PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics());
251aaa148fdSDaniel Dunbar 
252aaa148fdSDaniel Dunbar   // Create the Preprocessor.
253197ac203SDouglas Gregor   HeaderSearch *HeaderInfo = new HeaderSearch(getFileManager(),
254197ac203SDouglas Gregor                                               getDiagnostics());
25583297dfcSDouglas Gregor   PP = new Preprocessor(getDiagnostics(), getLangOpts(), &getTarget(),
25608142534SDouglas Gregor                         getSourceManager(), *HeaderInfo, *this, PTHMgr,
257aaa148fdSDaniel Dunbar                         /*OwnsHeaderSearch=*/true);
258aaa148fdSDaniel Dunbar 
259aaa148fdSDaniel Dunbar   // Note that this is different then passing PTHMgr to Preprocessor's ctor.
260aaa148fdSDaniel Dunbar   // That argument is used as the IdentifierInfoLookup argument to
261aaa148fdSDaniel Dunbar   // IdentifierTable's ctor.
262aaa148fdSDaniel Dunbar   if (PTHMgr) {
26308142534SDouglas Gregor     PTHMgr->setPreprocessor(&*PP);
264aaa148fdSDaniel Dunbar     PP->setPTHManager(PTHMgr);
265aaa148fdSDaniel Dunbar   }
266aaa148fdSDaniel Dunbar 
2677f6d60dcSDouglas Gregor   if (PPOpts.DetailedRecord)
268998caeadSDouglas Gregor     PP->createPreprocessingRecord(
269de81fc85SChandler Carruth                                   PPOpts.DetailedRecordIncludesNestedMacroExpansions);
2707f6d60dcSDouglas Gregor 
27108142534SDouglas Gregor   InitializePreprocessor(*PP, PPOpts, getHeaderSearchOpts(), getFrontendOpts());
272aaa148fdSDaniel Dunbar 
2731735f4e7SDouglas Gregor   // Set up the module path, including the hash for the
2741735f4e7SDouglas Gregor   // module-creation options.
2751735f4e7SDouglas Gregor   llvm::SmallString<256> SpecificModuleCache(
2761735f4e7SDouglas Gregor                            getHeaderSearchOpts().ModuleCachePath);
2771735f4e7SDouglas Gregor   if (!getHeaderSearchOpts().DisableModuleHash)
2781735f4e7SDouglas Gregor     llvm::sys::path::append(SpecificModuleCache,
2791735f4e7SDouglas Gregor                             getInvocation().getModuleHash());
28097eec24bSDouglas Gregor   PP->getHeaderSearchInfo().configureModules(SpecificModuleCache,
2817d106e42SDouglas Gregor                                              getLangOpts().CurrentModule);
2821735f4e7SDouglas Gregor 
283aaa148fdSDaniel Dunbar   // Handle generating dependencies, if requested.
28408142534SDouglas Gregor   const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
285aaa148fdSDaniel Dunbar   if (!DepOpts.OutputFile.empty())
286aaa148fdSDaniel Dunbar     AttachDependencyFileGen(*PP, DepOpts);
287aaa148fdSDaniel Dunbar 
28827734fdbSDaniel Dunbar   // Handle generating header include information, if requested.
28927734fdbSDaniel Dunbar   if (DepOpts.ShowHeaderIncludes)
29027734fdbSDaniel Dunbar     AttachHeaderIncludeGen(*PP);
2911af1d275SDaniel Dunbar   if (!DepOpts.HeaderIncludeOutputFile.empty()) {
2920e62c1ccSChris Lattner     StringRef OutputPath = DepOpts.HeaderIncludeOutputFile;
2931af1d275SDaniel Dunbar     if (OutputPath == "-")
2941af1d275SDaniel Dunbar       OutputPath = "";
295fe908a80SDaniel Dunbar     AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath,
296fe908a80SDaniel Dunbar                            /*ShowDepth=*/false);
2971af1d275SDaniel Dunbar   }
298aaa148fdSDaniel Dunbar }
299df3e30c4SDaniel Dunbar 
300df3e30c4SDaniel Dunbar // ASTContext
301df3e30c4SDaniel Dunbar 
302df3e30c4SDaniel Dunbar void CompilerInstance::createASTContext() {
303df3e30c4SDaniel Dunbar   Preprocessor &PP = getPreprocessor();
3045e14d39aSTed Kremenek   Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
305e8bbc121SDouglas Gregor                            &getTarget(), PP.getIdentifierTable(),
306df3e30c4SDaniel Dunbar                            PP.getSelectorTable(), PP.getBuiltinInfo(),
3075e14d39aSTed Kremenek                            /*size_reserve=*/ 0);
308df3e30c4SDaniel Dunbar }
309599313efSDaniel Dunbar 
310599313efSDaniel Dunbar // ExternalASTSource
311599313efSDaniel Dunbar 
3120e62c1ccSChris Lattner void CompilerInstance::createPCHExternalASTSource(StringRef Path,
31307a89a83SSebastian Redl                                                   bool DisablePCHValidation,
314606c4ac3SDouglas Gregor                                                   bool DisableStatCache,
31507a89a83SSebastian Redl                                                  void *DeserializationListener){
316599313efSDaniel Dunbar   llvm::OwningPtr<ExternalASTSource> Source;
317009e7f20SSebastian Redl   bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
318599313efSDaniel Dunbar   Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
319ce3a8293SDouglas Gregor                                           DisablePCHValidation,
320606c4ac3SDouglas Gregor                                           DisableStatCache,
32107a89a83SSebastian Redl                                           getPreprocessor(), getASTContext(),
322009e7f20SSebastian Redl                                           DeserializationListener,
323009e7f20SSebastian Redl                                           Preamble));
324925296b4SDouglas Gregor   ModuleManager = static_cast<ASTReader*>(Source.get());
325599313efSDaniel Dunbar   getASTContext().setExternalSource(Source);
326599313efSDaniel Dunbar }
327599313efSDaniel Dunbar 
328599313efSDaniel Dunbar ExternalASTSource *
3290e62c1ccSChris Lattner CompilerInstance::createPCHExternalASTSource(StringRef Path,
330599313efSDaniel Dunbar                                              const std::string &Sysroot,
331ce3a8293SDouglas Gregor                                              bool DisablePCHValidation,
332606c4ac3SDouglas Gregor                                              bool DisableStatCache,
333599313efSDaniel Dunbar                                              Preprocessor &PP,
33407a89a83SSebastian Redl                                              ASTContext &Context,
335009e7f20SSebastian Redl                                              void *DeserializationListener,
336009e7f20SSebastian Redl                                              bool Preamble) {
3372c499f65SSebastian Redl   llvm::OwningPtr<ASTReader> Reader;
3388835e03cSDouglas Gregor   Reader.reset(new ASTReader(PP, Context,
339c567ba26SDouglas Gregor                              Sysroot.empty() ? "" : Sysroot.c_str(),
340606c4ac3SDouglas Gregor                              DisablePCHValidation, DisableStatCache));
341599313efSDaniel Dunbar 
34207a89a83SSebastian Redl   Reader->setDeserializationListener(
3433e31c724SSebastian Redl             static_cast<ASTDeserializationListener *>(DeserializationListener));
344009e7f20SSebastian Redl   switch (Reader->ReadAST(Path,
345a6895d8aSDouglas Gregor                           Preamble ? serialization::MK_Preamble
346a6895d8aSDouglas Gregor                                    : serialization::MK_PCH)) {
3472c499f65SSebastian Redl   case ASTReader::Success:
348599313efSDaniel Dunbar     // Set the predefines buffer as suggested by the PCH reader. Typically, the
349599313efSDaniel Dunbar     // predefines buffer will be empty.
350599313efSDaniel Dunbar     PP.setPredefines(Reader->getSuggestedPredefines());
351599313efSDaniel Dunbar     return Reader.take();
352599313efSDaniel Dunbar 
3532c499f65SSebastian Redl   case ASTReader::Failure:
354599313efSDaniel Dunbar     // Unrecoverable failure: don't even try to process the input file.
355599313efSDaniel Dunbar     break;
356599313efSDaniel Dunbar 
3572c499f65SSebastian Redl   case ASTReader::IgnorePCH:
358599313efSDaniel Dunbar     // No suitable PCH file could be found. Return an error.
359599313efSDaniel Dunbar     break;
360599313efSDaniel Dunbar   }
361599313efSDaniel Dunbar 
362599313efSDaniel Dunbar   return 0;
363599313efSDaniel Dunbar }
364f7093b5aSDaniel Dunbar 
365f7093b5aSDaniel Dunbar // Code Completion
366f7093b5aSDaniel Dunbar 
3678e984da8SDouglas Gregor static bool EnableCodeCompletion(Preprocessor &PP,
3688e984da8SDouglas Gregor                                  const std::string &Filename,
3698e984da8SDouglas Gregor                                  unsigned Line,
3708e984da8SDouglas Gregor                                  unsigned Column) {
3718e984da8SDouglas Gregor   // Tell the source manager to chop off the given file at a specific
3728e984da8SDouglas Gregor   // line and column.
3735159f616SChris Lattner   const FileEntry *Entry = PP.getFileManager().getFile(Filename);
3748e984da8SDouglas Gregor   if (!Entry) {
3758e984da8SDouglas Gregor     PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
3768e984da8SDouglas Gregor       << Filename;
3778e984da8SDouglas Gregor     return true;
3788e984da8SDouglas Gregor   }
3798e984da8SDouglas Gregor 
3808e984da8SDouglas Gregor   // Truncate the named file at the given line/column.
3818e984da8SDouglas Gregor   PP.SetCodeCompletionPoint(Entry, Line, Column);
3828e984da8SDouglas Gregor   return false;
3838e984da8SDouglas Gregor }
3848e984da8SDouglas Gregor 
385f7093b5aSDaniel Dunbar void CompilerInstance::createCodeCompletionConsumer() {
386f7093b5aSDaniel Dunbar   const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
3878e984da8SDouglas Gregor   if (!CompletionConsumer) {
388f7093b5aSDaniel Dunbar     CompletionConsumer.reset(
389f7093b5aSDaniel Dunbar       createCodeCompletionConsumer(getPreprocessor(),
390f7093b5aSDaniel Dunbar                                    Loc.FileName, Loc.Line, Loc.Column,
391f7093b5aSDaniel Dunbar                                    getFrontendOpts().ShowMacrosInCodeCompletion,
392f64acca2SDouglas Gregor                              getFrontendOpts().ShowCodePatternsInCodeCompletion,
39339982197SDouglas Gregor                            getFrontendOpts().ShowGlobalSymbolsInCodeCompletion,
394f7093b5aSDaniel Dunbar                                    llvm::outs()));
39500a0cf70SDouglas Gregor     if (!CompletionConsumer)
39600a0cf70SDouglas Gregor       return;
3978e984da8SDouglas Gregor   } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName,
3988e984da8SDouglas Gregor                                   Loc.Line, Loc.Column)) {
3998e984da8SDouglas Gregor     CompletionConsumer.reset();
4008e984da8SDouglas Gregor     return;
4018e984da8SDouglas Gregor   }
402f09935f1SDouglas Gregor 
403f09935f1SDouglas Gregor   if (CompletionConsumer->isOutputBinary() &&
404f09935f1SDouglas Gregor       llvm::sys::Program::ChangeStdoutToBinary()) {
405f09935f1SDouglas Gregor     getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
406f09935f1SDouglas Gregor     CompletionConsumer.reset();
407f09935f1SDouglas Gregor   }
408f7093b5aSDaniel Dunbar }
409f7093b5aSDaniel Dunbar 
4105505dff8SKovarththanan Rajaratnam void CompilerInstance::createFrontendTimer() {
4115505dff8SKovarththanan Rajaratnam   FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
4125505dff8SKovarththanan Rajaratnam }
4135505dff8SKovarththanan Rajaratnam 
414f7093b5aSDaniel Dunbar CodeCompleteConsumer *
415f7093b5aSDaniel Dunbar CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
416f7093b5aSDaniel Dunbar                                                const std::string &Filename,
417f7093b5aSDaniel Dunbar                                                unsigned Line,
418f7093b5aSDaniel Dunbar                                                unsigned Column,
419f7093b5aSDaniel Dunbar                                                bool ShowMacros,
420f64acca2SDouglas Gregor                                                bool ShowCodePatterns,
42139982197SDouglas Gregor                                                bool ShowGlobals,
4220e62c1ccSChris Lattner                                                raw_ostream &OS) {
4238e984da8SDouglas Gregor   if (EnableCodeCompletion(PP, Filename, Line, Column))
424f7093b5aSDaniel Dunbar     return 0;
425f7093b5aSDaniel Dunbar 
426f7093b5aSDaniel Dunbar   // Set up the creation routine for code-completion.
42739982197SDouglas Gregor   return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns,
42839982197SDouglas Gregor                                           ShowGlobals, OS);
429f7093b5aSDaniel Dunbar }
430566eeb2dSDaniel Dunbar 
43169f74f80SDouglas Gregor void CompilerInstance::createSema(TranslationUnitKind TUKind,
4320e93f017SDouglas Gregor                                   CodeCompleteConsumer *CompletionConsumer) {
4330e93f017SDouglas Gregor   TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
43469f74f80SDouglas Gregor                          TUKind, CompletionConsumer));
4350e93f017SDouglas Gregor }
4360e93f017SDouglas Gregor 
437566eeb2dSDaniel Dunbar // Output Files
438566eeb2dSDaniel Dunbar 
439d0599970SArgyrios Kyrtzidis void CompilerInstance::addOutputFile(const OutputFile &OutFile) {
440d0599970SArgyrios Kyrtzidis   assert(OutFile.OS && "Attempt to add empty stream to output list!");
441d0599970SArgyrios Kyrtzidis   OutputFiles.push_back(OutFile);
442566eeb2dSDaniel Dunbar }
443566eeb2dSDaniel Dunbar 
4441c558cd7SKovarththanan Rajaratnam void CompilerInstance::clearOutputFiles(bool EraseFiles) {
445d0599970SArgyrios Kyrtzidis   for (std::list<OutputFile>::iterator
446566eeb2dSDaniel Dunbar          it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
447d0599970SArgyrios Kyrtzidis     delete it->OS;
448d0599970SArgyrios Kyrtzidis     if (!it->TempFilename.empty()) {
449b5c356a4SAnders Carlsson       if (EraseFiles) {
450b5c356a4SAnders Carlsson         bool existed;
451b5c356a4SAnders Carlsson         llvm::sys::fs::remove(it->TempFilename, existed);
452b5c356a4SAnders Carlsson       } else {
453b5c356a4SAnders Carlsson         llvm::SmallString<128> NewOutFile(it->Filename);
454b5c356a4SAnders Carlsson 
45571731d6bSArgyrios Kyrtzidis         // If '-working-directory' was passed, the output filename should be
45671731d6bSArgyrios Kyrtzidis         // relative to that.
4579ba8fb1eSAnders Carlsson         FileMgr->FixupRelativePath(NewOutFile);
458b5c356a4SAnders Carlsson         if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename,
459b5c356a4SAnders Carlsson                                                         NewOutFile.str())) {
460d0599970SArgyrios Kyrtzidis           getDiagnostics().Report(diag::err_fe_unable_to_rename_temp)
461b5c356a4SAnders Carlsson             << it->TempFilename << it->Filename << ec.message();
462b5c356a4SAnders Carlsson 
463b5c356a4SAnders Carlsson           bool existed;
464b5c356a4SAnders Carlsson           llvm::sys::fs::remove(it->TempFilename, existed);
465d0599970SArgyrios Kyrtzidis         }
466d0599970SArgyrios Kyrtzidis       }
467d0599970SArgyrios Kyrtzidis     } else if (!it->Filename.empty() && EraseFiles)
468d0599970SArgyrios Kyrtzidis       llvm::sys::Path(it->Filename).eraseFromDisk();
469d0599970SArgyrios Kyrtzidis 
470566eeb2dSDaniel Dunbar   }
471566eeb2dSDaniel Dunbar   OutputFiles.clear();
472566eeb2dSDaniel Dunbar }
473566eeb2dSDaniel Dunbar 
474420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *
475420b0f1bSDaniel Dunbar CompilerInstance::createDefaultOutputFile(bool Binary,
4760e62c1ccSChris Lattner                                           StringRef InFile,
4770e62c1ccSChris Lattner                                           StringRef Extension) {
478420b0f1bSDaniel Dunbar   return createOutputFile(getFrontendOpts().OutputFile, Binary,
479e326f9bbSDaniel Dunbar                           /*RemoveFileOnSignal=*/true, InFile, Extension);
480420b0f1bSDaniel Dunbar }
481420b0f1bSDaniel Dunbar 
482420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *
4830e62c1ccSChris Lattner CompilerInstance::createOutputFile(StringRef OutputPath,
484e326f9bbSDaniel Dunbar                                    bool Binary, bool RemoveFileOnSignal,
4850e62c1ccSChris Lattner                                    StringRef InFile,
48608a2bfd2SArgyrios Kyrtzidis                                    StringRef Extension,
48708a2bfd2SArgyrios Kyrtzidis                                    bool UseTemporary) {
488d0599970SArgyrios Kyrtzidis   std::string Error, OutputPathName, TempPathName;
489420b0f1bSDaniel Dunbar   llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
490e326f9bbSDaniel Dunbar                                               RemoveFileOnSignal,
491420b0f1bSDaniel Dunbar                                               InFile, Extension,
49208a2bfd2SArgyrios Kyrtzidis                                               UseTemporary,
493d0599970SArgyrios Kyrtzidis                                               &OutputPathName,
494d0599970SArgyrios Kyrtzidis                                               &TempPathName);
495420b0f1bSDaniel Dunbar   if (!OS) {
4967554699aSDaniel Dunbar     getDiagnostics().Report(diag::err_fe_unable_to_open_output)
4977554699aSDaniel Dunbar       << OutputPath << Error;
4987554699aSDaniel Dunbar     return 0;
499420b0f1bSDaniel Dunbar   }
500420b0f1bSDaniel Dunbar 
501420b0f1bSDaniel Dunbar   // Add the output file -- but don't try to remove "-", since this means we are
502420b0f1bSDaniel Dunbar   // using stdin.
503d0599970SArgyrios Kyrtzidis   addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "",
504d0599970SArgyrios Kyrtzidis                 TempPathName, OS));
505420b0f1bSDaniel Dunbar 
506420b0f1bSDaniel Dunbar   return OS;
507420b0f1bSDaniel Dunbar }
508420b0f1bSDaniel Dunbar 
509420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *
5100e62c1ccSChris Lattner CompilerInstance::createOutputFile(StringRef OutputPath,
511420b0f1bSDaniel Dunbar                                    std::string &Error,
512420b0f1bSDaniel Dunbar                                    bool Binary,
513e326f9bbSDaniel Dunbar                                    bool RemoveFileOnSignal,
5140e62c1ccSChris Lattner                                    StringRef InFile,
5150e62c1ccSChris Lattner                                    StringRef Extension,
51608a2bfd2SArgyrios Kyrtzidis                                    bool UseTemporary,
517d0599970SArgyrios Kyrtzidis                                    std::string *ResultPathName,
518d0599970SArgyrios Kyrtzidis                                    std::string *TempPathName) {
519d0599970SArgyrios Kyrtzidis   std::string OutFile, TempFile;
520420b0f1bSDaniel Dunbar   if (!OutputPath.empty()) {
521420b0f1bSDaniel Dunbar     OutFile = OutputPath;
522420b0f1bSDaniel Dunbar   } else if (InFile == "-") {
523420b0f1bSDaniel Dunbar     OutFile = "-";
524420b0f1bSDaniel Dunbar   } else if (!Extension.empty()) {
525420b0f1bSDaniel Dunbar     llvm::sys::Path Path(InFile);
526420b0f1bSDaniel Dunbar     Path.eraseSuffix();
527420b0f1bSDaniel Dunbar     Path.appendSuffix(Extension);
528420b0f1bSDaniel Dunbar     OutFile = Path.str();
529420b0f1bSDaniel Dunbar   } else {
530420b0f1bSDaniel Dunbar     OutFile = "-";
531420b0f1bSDaniel Dunbar   }
532420b0f1bSDaniel Dunbar 
53308a2bfd2SArgyrios Kyrtzidis   llvm::OwningPtr<llvm::raw_fd_ostream> OS;
53408a2bfd2SArgyrios Kyrtzidis   std::string OSFile;
53508a2bfd2SArgyrios Kyrtzidis 
53608a2bfd2SArgyrios Kyrtzidis   if (UseTemporary && OutFile != "-") {
537d0599970SArgyrios Kyrtzidis     llvm::sys::Path OutPath(OutFile);
538d0599970SArgyrios Kyrtzidis     // Only create the temporary if we can actually write to OutPath, otherwise
539d0599970SArgyrios Kyrtzidis     // we want to fail early.
540f6efe58dSMichael J. Spencer     bool Exists;
541f6efe58dSMichael J. Spencer     if ((llvm::sys::fs::exists(OutPath.str(), Exists) || !Exists) ||
542d0599970SArgyrios Kyrtzidis         (OutPath.isRegularFile() && OutPath.canWrite())) {
543d0599970SArgyrios Kyrtzidis       // Create a temporary file.
54408a2bfd2SArgyrios Kyrtzidis       llvm::SmallString<128> TempPath;
54508a2bfd2SArgyrios Kyrtzidis       TempPath = OutFile;
54608a2bfd2SArgyrios Kyrtzidis       TempPath += "-%%%%%%%%";
54708a2bfd2SArgyrios Kyrtzidis       int fd;
54808a2bfd2SArgyrios Kyrtzidis       if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath,
54908a2bfd2SArgyrios Kyrtzidis                                /*makeAbsolute=*/false) == llvm::errc::success) {
55008a2bfd2SArgyrios Kyrtzidis         OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
55108a2bfd2SArgyrios Kyrtzidis         OSFile = TempFile = TempPath.str();
55208a2bfd2SArgyrios Kyrtzidis       }
553d0599970SArgyrios Kyrtzidis     }
554d0599970SArgyrios Kyrtzidis   }
555d0599970SArgyrios Kyrtzidis 
55608a2bfd2SArgyrios Kyrtzidis   if (!OS) {
55708a2bfd2SArgyrios Kyrtzidis     OSFile = OutFile;
55808a2bfd2SArgyrios Kyrtzidis     OS.reset(
559d0599970SArgyrios Kyrtzidis       new llvm::raw_fd_ostream(OSFile.c_str(), Error,
5602eaef18eSDaniel Dunbar                                (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
5612eaef18eSDaniel Dunbar     if (!Error.empty())
562420b0f1bSDaniel Dunbar       return 0;
56308a2bfd2SArgyrios Kyrtzidis   }
564420b0f1bSDaniel Dunbar 
565d0599970SArgyrios Kyrtzidis   // Make sure the out stream file gets removed if we crash.
566e326f9bbSDaniel Dunbar   if (RemoveFileOnSignal)
567d0599970SArgyrios Kyrtzidis     llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile));
568d0599970SArgyrios Kyrtzidis 
569420b0f1bSDaniel Dunbar   if (ResultPathName)
570420b0f1bSDaniel Dunbar     *ResultPathName = OutFile;
571d0599970SArgyrios Kyrtzidis   if (TempPathName)
572d0599970SArgyrios Kyrtzidis     *TempPathName = TempFile;
573420b0f1bSDaniel Dunbar 
5742eaef18eSDaniel Dunbar   return OS.take();
575420b0f1bSDaniel Dunbar }
576409e890fSDaniel Dunbar 
577409e890fSDaniel Dunbar // Initialization Utilities
578409e890fSDaniel Dunbar 
5790e62c1ccSChris Lattner bool CompilerInstance::InitializeSourceManager(StringRef InputFile) {
580409e890fSDaniel Dunbar   return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
581409e890fSDaniel Dunbar                                  getSourceManager(), getFrontendOpts());
582409e890fSDaniel Dunbar }
583409e890fSDaniel Dunbar 
5840e62c1ccSChris Lattner bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
5859c902b55SDavid Blaikie                                                DiagnosticsEngine &Diags,
586409e890fSDaniel Dunbar                                                FileManager &FileMgr,
587409e890fSDaniel Dunbar                                                SourceManager &SourceMgr,
588409e890fSDaniel Dunbar                                                const FrontendOptions &Opts) {
5897c06d866SArgyrios Kyrtzidis   // Figure out where to get and map in the main file.
5907c06d866SArgyrios Kyrtzidis   if (InputFile != "-") {
5915159f616SChris Lattner     const FileEntry *File = FileMgr.getFile(InputFile);
59252765215SDan Gohman     if (!File) {
593409e890fSDaniel Dunbar       Diags.Report(diag::err_fe_error_reading) << InputFile;
594409e890fSDaniel Dunbar       return false;
595409e890fSDaniel Dunbar     }
59652765215SDan Gohman     SourceMgr.createMainFileID(File);
597409e890fSDaniel Dunbar   } else {
598d9da7a1fSMichael J. Spencer     llvm::OwningPtr<llvm::MemoryBuffer> SB;
599d9da7a1fSMichael J. Spencer     if (llvm::MemoryBuffer::getSTDIN(SB)) {
600f25faaafSMichael J. Spencer       // FIXME: Give ec.message() in this diag.
601409e890fSDaniel Dunbar       Diags.Report(diag::err_fe_error_reading_stdin);
602409e890fSDaniel Dunbar       return false;
603409e890fSDaniel Dunbar     }
6042f76cd75SDan Gohman     const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
6055159f616SChris Lattner                                                    SB->getBufferSize(), 0);
6062f76cd75SDan Gohman     SourceMgr.createMainFileID(File);
607d9da7a1fSMichael J. Spencer     SourceMgr.overrideFileContents(File, SB.take());
608409e890fSDaniel Dunbar   }
609409e890fSDaniel Dunbar 
61052765215SDan Gohman   assert(!SourceMgr.getMainFileID().isInvalid() &&
61152765215SDan Gohman          "Couldn't establish MainFileID!");
612409e890fSDaniel Dunbar   return true;
613409e890fSDaniel Dunbar }
6144f2bc55dSDaniel Dunbar 
6154f2bc55dSDaniel Dunbar // High-Level Operations
6164f2bc55dSDaniel Dunbar 
6174f2bc55dSDaniel Dunbar bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
6184f2bc55dSDaniel Dunbar   assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
6194f2bc55dSDaniel Dunbar   assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
6204f2bc55dSDaniel Dunbar   assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
6214f2bc55dSDaniel Dunbar 
6224f2bc55dSDaniel Dunbar   // FIXME: Take this as an argument, once all the APIs we used have moved to
6234f2bc55dSDaniel Dunbar   // taking it as an input instead of hard-coding llvm::errs.
6240e62c1ccSChris Lattner   raw_ostream &OS = llvm::errs();
6254f2bc55dSDaniel Dunbar 
6264f2bc55dSDaniel Dunbar   // Create the target instance.
6274f2bc55dSDaniel Dunbar   setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
6284f2bc55dSDaniel Dunbar   if (!hasTarget())
6294f2bc55dSDaniel Dunbar     return false;
6304f2bc55dSDaniel Dunbar 
6314f2bc55dSDaniel Dunbar   // Inform the target of the language options.
6324f2bc55dSDaniel Dunbar   //
6334f2bc55dSDaniel Dunbar   // FIXME: We shouldn't need to do this, the target should be immutable once
6344f2bc55dSDaniel Dunbar   // created. This complexity should be lifted elsewhere.
6354f2bc55dSDaniel Dunbar   getTarget().setForcedLangOptions(getLangOpts());
6364f2bc55dSDaniel Dunbar 
6374f2bc55dSDaniel Dunbar   // Validate/process some options.
6384f2bc55dSDaniel Dunbar   if (getHeaderSearchOpts().Verbose)
6394f2bc55dSDaniel Dunbar     OS << "clang -cc1 version " CLANG_VERSION_STRING
6404f2bc55dSDaniel Dunbar        << " based upon " << PACKAGE_STRING
6418188c8a1SSebastian Pop        << " default target " << llvm::sys::getDefaultTargetTriple() << "\n";
6424f2bc55dSDaniel Dunbar 
6434f2bc55dSDaniel Dunbar   if (getFrontendOpts().ShowTimers)
6444f2bc55dSDaniel Dunbar     createFrontendTimer();
6454f2bc55dSDaniel Dunbar 
646171b780cSDouglas Gregor   if (getFrontendOpts().ShowStats)
647171b780cSDouglas Gregor     llvm::EnableStatistics();
648171b780cSDouglas Gregor 
6494f2bc55dSDaniel Dunbar   for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
650ac42ec6fSDouglas Gregor     const std::string &InFile = getFrontendOpts().Inputs[i].second;
6514f2bc55dSDaniel Dunbar 
6524f2bc55dSDaniel Dunbar     // Reset the ID tables if we are reusing the SourceManager.
653aed46fcbSDaniel Dunbar     if (hasSourceManager())
6544f2bc55dSDaniel Dunbar       getSourceManager().clearIDTables();
6554f2bc55dSDaniel Dunbar 
656ac42ec6fSDouglas Gregor     if (Act.BeginSourceFile(*this, InFile, getFrontendOpts().Inputs[i].first)) {
6574f2bc55dSDaniel Dunbar       Act.Execute();
6584f2bc55dSDaniel Dunbar       Act.EndSourceFile();
6594f2bc55dSDaniel Dunbar     }
6604f2bc55dSDaniel Dunbar   }
6614f2bc55dSDaniel Dunbar 
662198cb4dfSChris Lattner   if (getDiagnosticOpts().ShowCarets) {
663c79346a5SArgyrios Kyrtzidis     // We can have multiple diagnostics sharing one diagnostic client.
664c79346a5SArgyrios Kyrtzidis     // Get the total number of warnings/errors from the client.
665c79346a5SArgyrios Kyrtzidis     unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings();
666c79346a5SArgyrios Kyrtzidis     unsigned NumErrors = getDiagnostics().getClient()->getNumErrors();
667198cb4dfSChris Lattner 
668198cb4dfSChris Lattner     if (NumWarnings)
669198cb4dfSChris Lattner       OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
670198cb4dfSChris Lattner     if (NumWarnings && NumErrors)
671198cb4dfSChris Lattner       OS << " and ";
672198cb4dfSChris Lattner     if (NumErrors)
673198cb4dfSChris Lattner       OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
674198cb4dfSChris Lattner     if (NumWarnings || NumErrors)
675198cb4dfSChris Lattner       OS << " generated.\n";
676198cb4dfSChris Lattner   }
6774f2bc55dSDaniel Dunbar 
678aed46fcbSDaniel Dunbar   if (getFrontendOpts().ShowStats && hasFileManager()) {
6794f2bc55dSDaniel Dunbar     getFileManager().PrintStats();
6804f2bc55dSDaniel Dunbar     OS << "\n";
6814f2bc55dSDaniel Dunbar   }
6824f2bc55dSDaniel Dunbar 
683bc467933SArgyrios Kyrtzidis   return !getDiagnostics().getClient()->getNumErrors();
6844f2bc55dSDaniel Dunbar }
6854f2bc55dSDaniel Dunbar 
686faeb1d46SDouglas Gregor /// \brief Determine the appropriate source input kind based on language
687faeb1d46SDouglas Gregor /// options.
688faeb1d46SDouglas Gregor static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) {
689faeb1d46SDouglas Gregor   if (LangOpts.OpenCL)
690faeb1d46SDouglas Gregor     return IK_OpenCL;
691faeb1d46SDouglas Gregor   if (LangOpts.CUDA)
692faeb1d46SDouglas Gregor     return IK_CUDA;
693faeb1d46SDouglas Gregor   if (LangOpts.ObjC1)
694faeb1d46SDouglas Gregor     return LangOpts.CPlusPlus? IK_ObjCXX : IK_ObjC;
695faeb1d46SDouglas Gregor   return LangOpts.CPlusPlus? IK_CXX : IK_C;
696faeb1d46SDouglas Gregor }
697faeb1d46SDouglas Gregor 
69851e0b541SDouglas Gregor namespace {
69951e0b541SDouglas Gregor   struct CompileModuleData {
70051e0b541SDouglas Gregor     CompilerInstance &Instance;
701ac42ec6fSDouglas Gregor     GeneratePCHAction &CreateModuleAction;
70251e0b541SDouglas Gregor   };
70351e0b541SDouglas Gregor }
70451e0b541SDouglas Gregor 
70551e0b541SDouglas Gregor /// \brief Helper function that executes the module-generating action under
70651e0b541SDouglas Gregor /// a crash recovery context.
70751e0b541SDouglas Gregor static void doCompileModule(void *UserData) {
70851e0b541SDouglas Gregor   CompileModuleData &Data = *reinterpret_cast<CompileModuleData *>(UserData);
70951e0b541SDouglas Gregor   Data.Instance.ExecuteAction(Data.CreateModuleAction);
71051e0b541SDouglas Gregor }
71151e0b541SDouglas Gregor 
71254a88810SDouglas Gregor namespace {
713*514b636aSDouglas Gregor   struct CompileModuleMapData {
714*514b636aSDouglas Gregor     CompilerInstance &Instance;
715*514b636aSDouglas Gregor     GenerateModuleAction &CreateModuleAction;
716*514b636aSDouglas Gregor   };
717*514b636aSDouglas Gregor }
718*514b636aSDouglas Gregor 
719*514b636aSDouglas Gregor /// \brief Helper function that executes the module-generating action under
720*514b636aSDouglas Gregor /// a crash recovery context.
721*514b636aSDouglas Gregor static void doCompileMapModule(void *UserData) {
722*514b636aSDouglas Gregor   CompileModuleMapData &Data
723*514b636aSDouglas Gregor     = *reinterpret_cast<CompileModuleMapData *>(UserData);
724*514b636aSDouglas Gregor   Data.Instance.ExecuteAction(Data.CreateModuleAction);
725*514b636aSDouglas Gregor }
726*514b636aSDouglas Gregor 
727*514b636aSDouglas Gregor namespace {
72854a88810SDouglas Gregor   /// \brief Class that manages the creation of a lock file to aid
72954a88810SDouglas Gregor   /// implicit coordination between different processes.
73054a88810SDouglas Gregor   ///
73154a88810SDouglas Gregor   /// The implicit coordination works by creating a ".lock" file alongside
73254a88810SDouglas Gregor   /// the file that we're coordinating for, using the atomicity of the file
73354a88810SDouglas Gregor   /// system to ensure that only a single process can create that ".lock" file.
73454a88810SDouglas Gregor   /// When the lock file is removed, the owning process has finished the
73554a88810SDouglas Gregor   /// operation.
73654a88810SDouglas Gregor   class LockFileManager {
73754a88810SDouglas Gregor   public:
73854a88810SDouglas Gregor     /// \brief Describes the state of a lock file.
73954a88810SDouglas Gregor     enum LockFileState {
74054a88810SDouglas Gregor       /// \brief The lock file has been created and is owned by this instance
74154a88810SDouglas Gregor       /// of the object.
74254a88810SDouglas Gregor       LFS_Owned,
74354a88810SDouglas Gregor       /// \brief The lock file already exists and is owned by some other
74454a88810SDouglas Gregor       /// instance.
74554a88810SDouglas Gregor       LFS_Shared,
74654a88810SDouglas Gregor       /// \brief An error occurred while trying to create or find the lock
74754a88810SDouglas Gregor       /// file.
74854a88810SDouglas Gregor       LFS_Error
74954a88810SDouglas Gregor     };
75054a88810SDouglas Gregor 
75154a88810SDouglas Gregor   private:
75254a88810SDouglas Gregor     llvm::SmallString<128> LockFileName;
75354a88810SDouglas Gregor     llvm::SmallString<128> UniqueLockFileName;
75454a88810SDouglas Gregor 
75554a88810SDouglas Gregor     llvm::Optional<std::pair<std::string, int> > Owner;
75654a88810SDouglas Gregor     llvm::Optional<llvm::error_code> Error;
75754a88810SDouglas Gregor 
75854a88810SDouglas Gregor     LockFileManager(const LockFileManager &);
75954a88810SDouglas Gregor     LockFileManager &operator=(const LockFileManager &);
76054a88810SDouglas Gregor 
76154a88810SDouglas Gregor     static llvm::Optional<std::pair<std::string, int> >
76254a88810SDouglas Gregor     readLockFile(StringRef LockFileName);
76354a88810SDouglas Gregor 
76454a88810SDouglas Gregor     static bool processStillExecuting(StringRef Hostname, int PID);
76554a88810SDouglas Gregor 
76654a88810SDouglas Gregor   public:
76754a88810SDouglas Gregor 
76854a88810SDouglas Gregor     LockFileManager(StringRef FileName);
76954a88810SDouglas Gregor     ~LockFileManager();
77054a88810SDouglas Gregor 
77154a88810SDouglas Gregor     /// \brief Determine the state of the lock file.
77254a88810SDouglas Gregor     LockFileState getState() const;
77354a88810SDouglas Gregor 
77454a88810SDouglas Gregor     operator LockFileState() const { return getState(); }
77554a88810SDouglas Gregor 
77654a88810SDouglas Gregor     /// \brief For a shared lock, wait until the owner releases the lock.
77754a88810SDouglas Gregor     void waitForUnlock();
77854a88810SDouglas Gregor   };
77954a88810SDouglas Gregor }
78054a88810SDouglas Gregor 
78154a88810SDouglas Gregor /// \brief Attempt to read the lock file with the given name, if it exists.
78254a88810SDouglas Gregor ///
78354a88810SDouglas Gregor /// \param LockFileName The name of the lock file to read.
78454a88810SDouglas Gregor ///
78554a88810SDouglas Gregor /// \returns The process ID of the process that owns this lock file
78654a88810SDouglas Gregor llvm::Optional<std::pair<std::string, int> >
78754a88810SDouglas Gregor LockFileManager::readLockFile(StringRef LockFileName) {
78854a88810SDouglas Gregor   // Check whether the lock file exists. If not, clearly there's nothing
78954a88810SDouglas Gregor   // to read, so we just return.
79054a88810SDouglas Gregor   bool Exists = false;
79154a88810SDouglas Gregor   if (llvm::sys::fs::exists(LockFileName, Exists) || !Exists)
79254a88810SDouglas Gregor     return llvm::Optional<std::pair<std::string, int> >();
79354a88810SDouglas Gregor 
79454a88810SDouglas Gregor   // Read the owning host and PID out of the lock file. If it appears that the
79554a88810SDouglas Gregor   // owning process is dead, the lock file is invalid.
79654a88810SDouglas Gregor   int PID = 0;
79754a88810SDouglas Gregor   std::string Hostname;
79854a88810SDouglas Gregor   std::ifstream Input(LockFileName.str().c_str());
79954a88810SDouglas Gregor   if (Input >> Hostname >> PID && PID > 0 &&
80054a88810SDouglas Gregor       processStillExecuting(Hostname, PID))
80154a88810SDouglas Gregor     return std::make_pair(Hostname, PID);
80254a88810SDouglas Gregor 
80354a88810SDouglas Gregor   // Delete the lock file. It's invalid anyway.
80454a88810SDouglas Gregor   bool Existed;
80554a88810SDouglas Gregor   llvm::sys::fs::remove(LockFileName, Existed);
80654a88810SDouglas Gregor   return llvm::Optional<std::pair<std::string, int> >();
80754a88810SDouglas Gregor }
80854a88810SDouglas Gregor 
80954a88810SDouglas Gregor bool LockFileManager::processStillExecuting(StringRef Hostname, int PID) {
81054a88810SDouglas Gregor #if LLVM_ON_UNIX
81154a88810SDouglas Gregor   char MyHostname[256];
81254a88810SDouglas Gregor   MyHostname[255] = 0;
81354a88810SDouglas Gregor   MyHostname[0] = 0;
81454a88810SDouglas Gregor   gethostname(MyHostname, 255);
81554a88810SDouglas Gregor   // Check whether the process is dead. If so, we're done.
81654a88810SDouglas Gregor   if (MyHostname == Hostname && getsid(PID) == -1 && errno == ESRCH)
81754a88810SDouglas Gregor     return false;
81854a88810SDouglas Gregor #endif
81954a88810SDouglas Gregor 
82054a88810SDouglas Gregor   return true;
82154a88810SDouglas Gregor }
82254a88810SDouglas Gregor 
82354a88810SDouglas Gregor LockFileManager::LockFileManager(StringRef FileName)
82454a88810SDouglas Gregor {
82554a88810SDouglas Gregor   LockFileName = FileName;
82654a88810SDouglas Gregor   LockFileName += ".lock";
82754a88810SDouglas Gregor 
82854a88810SDouglas Gregor   // If the lock file already exists, don't bother to try to create our own
82954a88810SDouglas Gregor   // lock file; it won't work anyway. Just figure out who owns this lock file.
83054a88810SDouglas Gregor   if ((Owner = readLockFile(LockFileName)))
83154a88810SDouglas Gregor     return;
83254a88810SDouglas Gregor 
83354a88810SDouglas Gregor   // Create a lock file that is unique to this instance.
83454a88810SDouglas Gregor   UniqueLockFileName = LockFileName;
83554a88810SDouglas Gregor   UniqueLockFileName += "-%%%%%%%%";
83654a88810SDouglas Gregor   int UniqueLockFileID;
83754a88810SDouglas Gregor   if (llvm::error_code EC
83854a88810SDouglas Gregor         = llvm::sys::fs::unique_file(UniqueLockFileName.str(),
83954a88810SDouglas Gregor                                      UniqueLockFileID,
84054a88810SDouglas Gregor                                      UniqueLockFileName,
84154a88810SDouglas Gregor                                      /*makeAbsolute=*/false)) {
84254a88810SDouglas Gregor     Error = EC;
84354a88810SDouglas Gregor     return;
84454a88810SDouglas Gregor   }
84554a88810SDouglas Gregor 
84654a88810SDouglas Gregor   // Write our process ID to our unique lock file.
84754a88810SDouglas Gregor   {
84854a88810SDouglas Gregor     llvm::raw_fd_ostream Out(UniqueLockFileID, /*shouldClose=*/true);
84954a88810SDouglas Gregor 
85054a88810SDouglas Gregor #if LLVM_ON_UNIX
85154a88810SDouglas Gregor     // FIXME: move getpid() call into LLVM
85254a88810SDouglas Gregor     char hostname[256];
85354a88810SDouglas Gregor     hostname[255] = 0;
85454a88810SDouglas Gregor     hostname[0] = 0;
85554a88810SDouglas Gregor     gethostname(hostname, 255);
85654a88810SDouglas Gregor     Out << hostname << ' ' << getpid();
85754a88810SDouglas Gregor #else
85854a88810SDouglas Gregor     Out << "localhost 1";
85954a88810SDouglas Gregor #endif
86054a88810SDouglas Gregor     Out.close();
86154a88810SDouglas Gregor 
86254a88810SDouglas Gregor     if (Out.has_error()) {
86354a88810SDouglas Gregor       // We failed to write out PID, so make up an excuse, remove the
86454a88810SDouglas Gregor       // unique lock file, and fail.
86554a88810SDouglas Gregor       Error = llvm::make_error_code(llvm::errc::no_space_on_device);
86654a88810SDouglas Gregor       bool Existed;
86754a88810SDouglas Gregor       llvm::sys::fs::remove(UniqueLockFileName.c_str(), Existed);
86854a88810SDouglas Gregor       return;
86954a88810SDouglas Gregor     }
87054a88810SDouglas Gregor   }
87154a88810SDouglas Gregor 
87254a88810SDouglas Gregor   // Create a hard link from the lock file name. If this succeeds, we're done.
87354a88810SDouglas Gregor   llvm::error_code EC
87454a88810SDouglas Gregor     = llvm::sys::fs::create_hard_link(UniqueLockFileName.str(),
87554a88810SDouglas Gregor                                       LockFileName.str());
87654a88810SDouglas Gregor   if (EC == llvm::errc::success)
87754a88810SDouglas Gregor     return;
87854a88810SDouglas Gregor 
87954a88810SDouglas Gregor   // Creating the hard link failed.
88054a88810SDouglas Gregor 
88154a88810SDouglas Gregor #ifdef LLVM_ON_UNIX
88254a88810SDouglas Gregor   // The creation of the hard link may appear to fail, but if stat'ing the
88354a88810SDouglas Gregor   // unique file returns a link count of 2, then we can still declare success.
88454a88810SDouglas Gregor   struct stat StatBuf;
88554a88810SDouglas Gregor   if (stat(UniqueLockFileName.c_str(), &StatBuf) == 0 &&
88654a88810SDouglas Gregor       StatBuf.st_nlink == 2)
88754a88810SDouglas Gregor     return;
88854a88810SDouglas Gregor #endif
88954a88810SDouglas Gregor 
89054a88810SDouglas Gregor   // Someone else managed to create the lock file first. Wipe out our unique
89154a88810SDouglas Gregor   // lock file (it's useless now) and read the process ID from the lock file.
89254a88810SDouglas Gregor   bool Existed;
89354a88810SDouglas Gregor   llvm::sys::fs::remove(UniqueLockFileName.str(), Existed);
89454a88810SDouglas Gregor   if ((Owner = readLockFile(LockFileName)))
89554a88810SDouglas Gregor     return;
89654a88810SDouglas Gregor 
89754a88810SDouglas Gregor   // There is a lock file that nobody owns; try to clean it up and report
89854a88810SDouglas Gregor   // an error.
89954a88810SDouglas Gregor   llvm::sys::fs::remove(LockFileName.str(), Existed);
90054a88810SDouglas Gregor   Error = EC;
90154a88810SDouglas Gregor }
90254a88810SDouglas Gregor 
90354a88810SDouglas Gregor LockFileManager::LockFileState LockFileManager::getState() const {
90454a88810SDouglas Gregor   if (Owner)
90554a88810SDouglas Gregor     return LFS_Shared;
90654a88810SDouglas Gregor 
90754a88810SDouglas Gregor   if (Error)
90854a88810SDouglas Gregor     return LFS_Error;
90954a88810SDouglas Gregor 
91054a88810SDouglas Gregor   return LFS_Owned;
91154a88810SDouglas Gregor }
91254a88810SDouglas Gregor 
91354a88810SDouglas Gregor LockFileManager::~LockFileManager() {
91454a88810SDouglas Gregor   if (getState() != LFS_Owned)
91554a88810SDouglas Gregor     return;
91654a88810SDouglas Gregor 
91754a88810SDouglas Gregor   // Since we own the lock, remove the lock file and our own unique lock file.
91854a88810SDouglas Gregor   bool Existed;
91954a88810SDouglas Gregor   llvm::sys::fs::remove(LockFileName.str(), Existed);
92054a88810SDouglas Gregor   llvm::sys::fs::remove(UniqueLockFileName.str(), Existed);
92154a88810SDouglas Gregor }
92254a88810SDouglas Gregor 
92354a88810SDouglas Gregor void LockFileManager::waitForUnlock() {
92454a88810SDouglas Gregor   if (getState() != LFS_Shared)
92554a88810SDouglas Gregor     return;
92654a88810SDouglas Gregor 
92710312ab1SDouglas Gregor #if LLVM_ON_WIN32
92810312ab1SDouglas Gregor   unsigned long Interval = 1;
92910312ab1SDouglas Gregor #else
93054a88810SDouglas Gregor   struct timespec Interval;
93154a88810SDouglas Gregor   Interval.tv_sec = 0;
93254a88810SDouglas Gregor   Interval.tv_nsec = 1000000;
93310312ab1SDouglas Gregor #endif
93454a88810SDouglas Gregor   // Don't wait more than an hour for the file to appear.
93554a88810SDouglas Gregor   const unsigned MaxSeconds = 3600;
93654a88810SDouglas Gregor   do {
93754a88810SDouglas Gregor     // Sleep for the designated interval, to allow the owning process time to
93854a88810SDouglas Gregor     // finish up and
93954a88810SDouglas Gregor     // FIXME: Should we hook in to system APIs to get a notification when the
94054a88810SDouglas Gregor     // lock file is deleted?
941a04a46e8SDouglas Gregor #if LLVM_ON_WIN32
942a04a46e8SDouglas Gregor     Sleep(Interval);
943a04a46e8SDouglas Gregor #else
94454a88810SDouglas Gregor     nanosleep(&Interval, NULL);
945a04a46e8SDouglas Gregor #endif
94654a88810SDouglas Gregor     // If the file no longer exists, we're done.
94754a88810SDouglas Gregor     bool Exists = false;
94854a88810SDouglas Gregor     if (!llvm::sys::fs::exists(LockFileName.str(), Exists) && !Exists)
94954a88810SDouglas Gregor       return;
95054a88810SDouglas Gregor 
95154a88810SDouglas Gregor     if (!processStillExecuting((*Owner).first, (*Owner).second))
95254a88810SDouglas Gregor       return;
95354a88810SDouglas Gregor 
95454a88810SDouglas Gregor     // Exponentially increase the time we wait for the lock to be removed.
95510312ab1SDouglas Gregor #if LLVM_ON_WIN32
95610312ab1SDouglas Gregor     Interval *= 2;
95710312ab1SDouglas Gregor #else
95854a88810SDouglas Gregor     Interval.tv_sec *= 2;
95954a88810SDouglas Gregor     Interval.tv_nsec *= 2;
96054a88810SDouglas Gregor     if (Interval.tv_nsec >= 1000000000) {
96154a88810SDouglas Gregor       ++Interval.tv_sec;
96254a88810SDouglas Gregor       Interval.tv_nsec -= 1000000000;
96354a88810SDouglas Gregor     }
96410312ab1SDouglas Gregor #endif
96510312ab1SDouglas Gregor   } while (
96610312ab1SDouglas Gregor #if LLVM_ON_WIN32
96710312ab1SDouglas Gregor            Interval < MaxSeconds * 1000
96810312ab1SDouglas Gregor #else
9690010bd96SNAKAMURA Takumi            Interval.tv_sec < (time_t)MaxSeconds
97010312ab1SDouglas Gregor #endif
97110312ab1SDouglas Gregor            );
97254a88810SDouglas Gregor 
97354a88810SDouglas Gregor   // Give up.
97454a88810SDouglas Gregor }
97554a88810SDouglas Gregor 
976*514b636aSDouglas Gregor /// \brief Compile a module file for the given module, using the options
977*514b636aSDouglas Gregor /// provided by the importing compiler instance.
978faeb1d46SDouglas Gregor static void compileModule(CompilerInstance &ImportingInstance,
9796dc57927SDouglas Gregor                           ModuleMap::Module *Module,
9806dc57927SDouglas Gregor                           StringRef ModuleFileName) {
98154a88810SDouglas Gregor   LockFileManager Locked(ModuleFileName);
98254a88810SDouglas Gregor   switch (Locked) {
98354a88810SDouglas Gregor   case LockFileManager::LFS_Error:
98454a88810SDouglas Gregor     return;
98554a88810SDouglas Gregor 
98654a88810SDouglas Gregor   case LockFileManager::LFS_Owned:
98754a88810SDouglas Gregor     // We're responsible for building the module ourselves. Do so below.
98854a88810SDouglas Gregor     break;
98954a88810SDouglas Gregor 
99054a88810SDouglas Gregor   case LockFileManager::LFS_Shared:
99154a88810SDouglas Gregor     // Someone else is responsible for building the module. Wait for them to
99254a88810SDouglas Gregor     // finish.
99354a88810SDouglas Gregor     Locked.waitForUnlock();
99454a88810SDouglas Gregor     break;
99554a88810SDouglas Gregor   }
99654a88810SDouglas Gregor 
997*514b636aSDouglas Gregor   ModuleMap &ModMap
998*514b636aSDouglas Gregor     = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
999*514b636aSDouglas Gregor 
1000faeb1d46SDouglas Gregor   // Construct a compiler invocation for creating this module.
1001faeb1d46SDouglas Gregor   llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation
1002faeb1d46SDouglas Gregor     (new CompilerInvocation(ImportingInstance.getInvocation()));
100344bf68d8SDouglas Gregor 
100444bf68d8SDouglas Gregor   // For any options that aren't intended to affect how a module is built,
100544bf68d8SDouglas Gregor   // reset them to their default values.
10068cf47df7STed Kremenek   Invocation->getLangOpts()->resetNonModularOptions();
1007f1312a82SDouglas Gregor   Invocation->getPreprocessorOpts().resetNonModularOptions();
100844bf68d8SDouglas Gregor 
10097d106e42SDouglas Gregor   // Note the name of the module we're building.
10106dc57927SDouglas Gregor   Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName();
10117d106e42SDouglas Gregor 
101244bf68d8SDouglas Gregor   // Note that this module is part of the module build path, so that we
101344bf68d8SDouglas Gregor   // can detect cycles in the module graph.
10146dc57927SDouglas Gregor   Invocation->getPreprocessorOpts().ModuleBuildPath
10156dc57927SDouglas Gregor     .push_back(Module->getTopLevelModuleName());
1016f1312a82SDouglas Gregor 
1017*514b636aSDouglas Gregor   if (const FileEntry *ModuleMapFile
1018*514b636aSDouglas Gregor                                   = ModMap.getContainingModuleMapFile(Module)) {
1019*514b636aSDouglas Gregor     // If there is a module map file, build the module using the module map.
1020*514b636aSDouglas Gregor     // Set up the inputs/outputs so that we build the module from its umbrella
1021*514b636aSDouglas Gregor     // header.
1022*514b636aSDouglas Gregor     FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
1023*514b636aSDouglas Gregor     FrontendOpts.OutputFile = ModuleFileName.str();
1024*514b636aSDouglas Gregor     FrontendOpts.DisableFree = false;
1025*514b636aSDouglas Gregor     FrontendOpts.Inputs.clear();
1026*514b636aSDouglas Gregor     FrontendOpts.Inputs.push_back(
1027*514b636aSDouglas Gregor       std::make_pair(getSourceInputKindFromOptions(*Invocation->getLangOpts()),
1028*514b636aSDouglas Gregor                      ModuleMapFile->getName()));
1029*514b636aSDouglas Gregor 
1030*514b636aSDouglas Gregor     Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
1031*514b636aSDouglas Gregor 
1032*514b636aSDouglas Gregor 
1033*514b636aSDouglas Gregor     assert(ImportingInstance.getInvocation().getModuleHash() ==
1034*514b636aSDouglas Gregor            Invocation->getModuleHash() && "Module hash mismatch!");
1035*514b636aSDouglas Gregor 
1036*514b636aSDouglas Gregor     // Construct a compiler instance that will be used to actually create the
1037*514b636aSDouglas Gregor     // module.
1038*514b636aSDouglas Gregor     CompilerInstance Instance;
1039*514b636aSDouglas Gregor     Instance.setInvocation(&*Invocation);
1040*514b636aSDouglas Gregor     Instance.createDiagnostics(/*argc=*/0, /*argv=*/0,
1041*514b636aSDouglas Gregor                                &ImportingInstance.getDiagnosticClient(),
1042*514b636aSDouglas Gregor                                /*ShouldOwnClient=*/true,
1043*514b636aSDouglas Gregor                                /*ShouldCloneClient=*/true);
1044*514b636aSDouglas Gregor 
1045*514b636aSDouglas Gregor     // Construct a module-generating action.
1046*514b636aSDouglas Gregor     GenerateModuleAction CreateModuleAction;
1047*514b636aSDouglas Gregor 
1048*514b636aSDouglas Gregor     // Execute the action to actually build the module in-place. Use a separate
1049*514b636aSDouglas Gregor     // thread so that we get a stack large enough.
1050*514b636aSDouglas Gregor     const unsigned ThreadStackSize = 8 << 20;
1051*514b636aSDouglas Gregor     llvm::CrashRecoveryContext CRC;
1052*514b636aSDouglas Gregor     CompileModuleMapData Data = { Instance, CreateModuleAction };
1053*514b636aSDouglas Gregor     CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize);
1054*514b636aSDouglas Gregor     return;
1055*514b636aSDouglas Gregor   }
1056*514b636aSDouglas Gregor 
1057*514b636aSDouglas Gregor   // FIXME: Temporary fallback: generate the module from the umbrella header.
1058*514b636aSDouglas Gregor   // This is currently used when we infer a module map from a framework.
1059*514b636aSDouglas Gregor   assert(Module->UmbrellaHeader && "Inferred module map needs umbrella header");
1060*514b636aSDouglas Gregor 
106144bf68d8SDouglas Gregor   // Set up the inputs/outputs so that we build the module from its umbrella
106244bf68d8SDouglas Gregor   // header.
1063faeb1d46SDouglas Gregor   FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
10641735f4e7SDouglas Gregor   FrontendOpts.OutputFile = ModuleFileName.str();
1065faeb1d46SDouglas Gregor   FrontendOpts.DisableFree = false;
1066faeb1d46SDouglas Gregor   FrontendOpts.Inputs.clear();
1067faeb1d46SDouglas Gregor   FrontendOpts.Inputs.push_back(
10688cf47df7STed Kremenek     std::make_pair(getSourceInputKindFromOptions(*Invocation->getLangOpts()),
10696dc57927SDouglas Gregor                                            Module->UmbrellaHeader->getName()));
10702b9b4642SDouglas Gregor 
10712b9b4642SDouglas Gregor   Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
10722b9b4642SDouglas Gregor 
1073dff0e892SDouglas Gregor 
10743728ea75SDouglas Gregor   assert(ImportingInstance.getInvocation().getModuleHash() ==
10753728ea75SDouglas Gregor            Invocation->getModuleHash() && "Module hash mismatch!");
1076faeb1d46SDouglas Gregor 
1077faeb1d46SDouglas Gregor   // Construct a compiler instance that will be used to actually create the
1078faeb1d46SDouglas Gregor   // module.
1079faeb1d46SDouglas Gregor   CompilerInstance Instance;
1080faeb1d46SDouglas Gregor   Instance.setInvocation(&*Invocation);
10812b9b4642SDouglas Gregor   Instance.createDiagnostics(/*argc=*/0, /*argv=*/0,
10822b9b4642SDouglas Gregor                              &ImportingInstance.getDiagnosticClient(),
1083d0e9e3a6SDouglas Gregor                              /*ShouldOwnClient=*/true,
1084d0e9e3a6SDouglas Gregor                              /*ShouldCloneClient=*/true);
1085faeb1d46SDouglas Gregor 
1086faeb1d46SDouglas Gregor   // Construct a module-generating action.
1087ac42ec6fSDouglas Gregor   GeneratePCHAction CreateModuleAction(true);
1088faeb1d46SDouglas Gregor 
108951e0b541SDouglas Gregor   // Execute the action to actually build the module in-place. Use a separate
109051e0b541SDouglas Gregor   // thread so that we get a stack large enough.
109151e0b541SDouglas Gregor   const unsigned ThreadStackSize = 8 << 20;
109251e0b541SDouglas Gregor   llvm::CrashRecoveryContext CRC;
109351e0b541SDouglas Gregor   CompileModuleData Data = { Instance, CreateModuleAction };
109451e0b541SDouglas Gregor   CRC.RunSafelyOnThread(&doCompileModule, &Data, ThreadStackSize);
1095faeb1d46SDouglas Gregor }
1096faeb1d46SDouglas Gregor 
109708142534SDouglas Gregor ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
109808142534SDouglas Gregor                                        IdentifierInfo &ModuleName,
109908142534SDouglas Gregor                                        SourceLocation ModuleNameLoc) {
110008142534SDouglas Gregor   // Determine what file we're searching from.
110108142534SDouglas Gregor   SourceManager &SourceMgr = getSourceManager();
110208142534SDouglas Gregor   SourceLocation ExpandedImportLoc = SourceMgr.getExpansionLoc(ImportLoc);
110308142534SDouglas Gregor   const FileEntry *CurFile
110408142534SDouglas Gregor     = SourceMgr.getFileEntryForID(SourceMgr.getFileID(ExpandedImportLoc));
110508142534SDouglas Gregor   if (!CurFile)
110608142534SDouglas Gregor     CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
110708142534SDouglas Gregor 
110808142534SDouglas Gregor   // Search for a module with the given name.
1109ca295457SDouglas Gregor   ModuleMap::Module *Module = 0;
11101735f4e7SDouglas Gregor   std::string ModuleFileName;
111108142534SDouglas Gregor   const FileEntry *ModuleFile
1112ca295457SDouglas Gregor     = PP->getHeaderSearchInfo().lookupModule(ModuleName.getName(), Module,
1113ca295457SDouglas Gregor                                              &ModuleFileName);
1114faeb1d46SDouglas Gregor 
1115faeb1d46SDouglas Gregor   bool BuildingModule = false;
11166dc57927SDouglas Gregor   if (!ModuleFile && Module) {
11176dc57927SDouglas Gregor     // The module is not cached, but we have a module map from which we can
11186dc57927SDouglas Gregor     // build the module.
1119dff0e892SDouglas Gregor 
1120dff0e892SDouglas Gregor     // Check whether there is a cycle in the module graph.
1121dff0e892SDouglas Gregor     SmallVectorImpl<std::string> &ModuleBuildPath
1122dff0e892SDouglas Gregor       = getPreprocessorOpts().ModuleBuildPath;
1123dff0e892SDouglas Gregor     SmallVectorImpl<std::string>::iterator Pos
1124dff0e892SDouglas Gregor       = std::find(ModuleBuildPath.begin(), ModuleBuildPath.end(),
1125dff0e892SDouglas Gregor                   ModuleName.getName());
1126dff0e892SDouglas Gregor     if (Pos != ModuleBuildPath.end()) {
1127dff0e892SDouglas Gregor       llvm::SmallString<256> CyclePath;
1128dff0e892SDouglas Gregor       for (; Pos != ModuleBuildPath.end(); ++Pos) {
1129dff0e892SDouglas Gregor         CyclePath += *Pos;
1130dff0e892SDouglas Gregor         CyclePath += " -> ";
1131dff0e892SDouglas Gregor       }
1132dff0e892SDouglas Gregor       CyclePath += ModuleName.getName();
1133dff0e892SDouglas Gregor 
1134dff0e892SDouglas Gregor       getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle)
1135dff0e892SDouglas Gregor         << ModuleName.getName() << CyclePath;
1136dff0e892SDouglas Gregor       return 0;
1137dff0e892SDouglas Gregor     }
1138dff0e892SDouglas Gregor 
113944e688d4SDouglas Gregor     getDiagnostics().Report(ModuleNameLoc, diag::warn_module_build)
114044e688d4SDouglas Gregor       << ModuleName.getName();
1141faeb1d46SDouglas Gregor     BuildingModule = true;
11426dc57927SDouglas Gregor     compileModule(*this, Module, ModuleFileName);
1143ca295457SDouglas Gregor     ModuleFile = FileMgr->getFile(ModuleFileName);
1144faeb1d46SDouglas Gregor   }
1145faeb1d46SDouglas Gregor 
114608142534SDouglas Gregor   if (!ModuleFile) {
1147faeb1d46SDouglas Gregor     getDiagnostics().Report(ModuleNameLoc,
1148faeb1d46SDouglas Gregor                             BuildingModule? diag::err_module_not_built
1149faeb1d46SDouglas Gregor                                           : diag::err_module_not_found)
115008142534SDouglas Gregor       << ModuleName.getName()
115108142534SDouglas Gregor       << SourceRange(ImportLoc, ModuleNameLoc);
115208142534SDouglas Gregor     return 0;
115308142534SDouglas Gregor   }
115408142534SDouglas Gregor 
115508142534SDouglas Gregor   // If we don't already have an ASTReader, create one now.
115608142534SDouglas Gregor   if (!ModuleManager) {
115721931efcSDouglas Gregor     if (!hasASTContext())
115821931efcSDouglas Gregor       createASTContext();
115921931efcSDouglas Gregor 
116008142534SDouglas Gregor     std::string Sysroot = getHeaderSearchOpts().Sysroot;
116108142534SDouglas Gregor     const PreprocessorOptions &PPOpts = getPreprocessorOpts();
11628835e03cSDouglas Gregor     ModuleManager = new ASTReader(getPreprocessor(), *Context,
116308142534SDouglas Gregor                                   Sysroot.empty() ? "" : Sysroot.c_str(),
116408142534SDouglas Gregor                                   PPOpts.DisablePCHValidation,
116508142534SDouglas Gregor                                   PPOpts.DisableStatCache);
116621931efcSDouglas Gregor     if (hasASTConsumer()) {
116708142534SDouglas Gregor       ModuleManager->setDeserializationListener(
116808142534SDouglas Gregor         getASTConsumer().GetASTDeserializationListener());
116908142534SDouglas Gregor       getASTContext().setASTMutationListener(
117008142534SDouglas Gregor         getASTConsumer().GetASTMutationListener());
117121931efcSDouglas Gregor     }
117208142534SDouglas Gregor     llvm::OwningPtr<ExternalASTSource> Source;
117308142534SDouglas Gregor     Source.reset(ModuleManager);
117408142534SDouglas Gregor     getASTContext().setExternalSource(Source);
117521931efcSDouglas Gregor     if (hasSema())
117608142534SDouglas Gregor       ModuleManager->InitializeSema(getSema());
11776137d32cSDouglas Gregor     if (hasASTConsumer())
11786137d32cSDouglas Gregor       ModuleManager->StartTranslationUnit(&getASTConsumer());
117908142534SDouglas Gregor   }
118008142534SDouglas Gregor 
118108142534SDouglas Gregor   // Try to load the module we found.
118208142534SDouglas Gregor   switch (ModuleManager->ReadAST(ModuleFile->getName(),
118308142534SDouglas Gregor                                  serialization::MK_Module)) {
118408142534SDouglas Gregor   case ASTReader::Success:
118508142534SDouglas Gregor     break;
118608142534SDouglas Gregor 
118708142534SDouglas Gregor   case ASTReader::IgnorePCH:
118808142534SDouglas Gregor     // FIXME: The ASTReader will already have complained, but can we showhorn
118908142534SDouglas Gregor     // that diagnostic information into a more useful form?
119008142534SDouglas Gregor     return 0;
119108142534SDouglas Gregor 
119208142534SDouglas Gregor   case ASTReader::Failure:
119308142534SDouglas Gregor     // Already complained.
119408142534SDouglas Gregor     return 0;
119508142534SDouglas Gregor   }
119608142534SDouglas Gregor 
119708142534SDouglas Gregor   // FIXME: The module file's FileEntry makes a poor key indeed!
119808142534SDouglas Gregor   return (ModuleKey)ModuleFile;
119908142534SDouglas Gregor }
12004f2bc55dSDaniel Dunbar 
1201