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"
14bcfc7d02SDouglas Gregor #include "clang/AST/Decl.h"
15636404a3SDaniel Dunbar #include "clang/Basic/Diagnostic.h"
16546a676aSDaniel Dunbar #include "clang/Basic/FileManager.h"
17546a676aSDaniel Dunbar #include "clang/Basic/SourceManager.h"
18636404a3SDaniel Dunbar #include "clang/Basic/TargetInfo.h"
194f2bc55dSDaniel Dunbar #include "clang/Basic/Version.h"
20aaa148fdSDaniel Dunbar #include "clang/Lex/HeaderSearch.h"
21aaa148fdSDaniel Dunbar #include "clang/Lex/Preprocessor.h"
22aaa148fdSDaniel Dunbar #include "clang/Lex/PTHManager.h"
238b00dcb0SDavid Blaikie #include "clang/Frontend/ChainedDiagnosticConsumer.h"
244f2bc55dSDaniel Dunbar #include "clang/Frontend/FrontendAction.h"
25faeb1d46SDouglas Gregor #include "clang/Frontend/FrontendActions.h"
26f7093b5aSDaniel Dunbar #include "clang/Frontend/FrontendDiagnostic.h"
272083c32fSDaniel Dunbar #include "clang/Frontend/LogDiagnosticPrinter.h"
284610ea2bSTed Kremenek #include "clang/Frontend/SerializedDiagnosticPrinter.h"
297d75afc5SDaniel Dunbar #include "clang/Frontend/TextDiagnosticPrinter.h"
3069609dceSDavid Blaikie #include "clang/Frontend/VerifyDiagnosticConsumer.h"
31aaa148fdSDaniel Dunbar #include "clang/Frontend/Utils.h"
32f5b13467SSebastian Redl #include "clang/Serialization/ASTReader.h"
33f7093b5aSDaniel Dunbar #include "clang/Sema/CodeCompleteConsumer.h"
34f6efe58dSMichael J. Spencer #include "llvm/Support/FileSystem.h"
35409e890fSDaniel Dunbar #include "llvm/Support/MemoryBuffer.h"
367d75afc5SDaniel Dunbar #include "llvm/Support/raw_ostream.h"
37171b780cSDouglas Gregor #include "llvm/ADT/Statistic.h"
385505dff8SKovarththanan Rajaratnam #include "llvm/Support/Timer.h"
398aaf4995SMichael J. Spencer #include "llvm/Support/Host.h"
40e212489fSDouglas Gregor #include "llvm/Support/LockFileManager.h"
418aaf4995SMichael J. Spencer #include "llvm/Support/Path.h"
428aaf4995SMichael J. Spencer #include "llvm/Support/Program.h"
438aaf4995SMichael J. Spencer #include "llvm/Support/Signals.h"
44f25faaafSMichael J. Spencer #include "llvm/Support/system_error.h"
4551e0b541SDouglas Gregor #include "llvm/Support/CrashRecoveryContext.h"
46321cdb85SDylan Noblesmith #include "llvm/Config/config.h"
4754a88810SDouglas Gregor 
48636404a3SDaniel Dunbar using namespace clang;
49636404a3SDaniel Dunbar 
50e922d9bdSDaniel Dunbar CompilerInstance::CompilerInstance()
51925296b4SDouglas Gregor   : Invocation(new CompilerInvocation()), ModuleManager(0) {
52636404a3SDaniel Dunbar }
53636404a3SDaniel Dunbar 
54636404a3SDaniel Dunbar CompilerInstance::~CompilerInstance() {
55e922d9bdSDaniel Dunbar }
56e922d9bdSDaniel Dunbar 
5768242254SDaniel Dunbar void CompilerInstance::setInvocation(CompilerInvocation *Value) {
585e14d39aSTed Kremenek   Invocation = Value;
5968242254SDaniel Dunbar }
6068242254SDaniel Dunbar 
619c902b55SDavid Blaikie void CompilerInstance::setDiagnostics(DiagnosticsEngine *Value) {
627f95d26eSDouglas Gregor   Diagnostics = Value;
63e01dc86dSDaniel Dunbar }
64e01dc86dSDaniel Dunbar 
65e01dc86dSDaniel Dunbar void CompilerInstance::setTarget(TargetInfo *Value) {
665e14d39aSTed Kremenek   Target = Value;
67e01dc86dSDaniel Dunbar }
68e01dc86dSDaniel Dunbar 
69e01dc86dSDaniel Dunbar void CompilerInstance::setFileManager(FileManager *Value) {
705e14d39aSTed Kremenek   FileMgr = Value;
71e01dc86dSDaniel Dunbar }
72e01dc86dSDaniel Dunbar 
73e01dc86dSDaniel Dunbar void CompilerInstance::setSourceManager(SourceManager *Value) {
745e14d39aSTed Kremenek   SourceMgr = Value;
75e01dc86dSDaniel Dunbar }
76e01dc86dSDaniel Dunbar 
775e14d39aSTed Kremenek void CompilerInstance::setPreprocessor(Preprocessor *Value) { PP = Value; }
78e01dc86dSDaniel Dunbar 
795e14d39aSTed Kremenek void CompilerInstance::setASTContext(ASTContext *Value) { Context = Value; }
80e01dc86dSDaniel Dunbar 
810e93f017SDouglas Gregor void CompilerInstance::setSema(Sema *S) {
820e93f017SDouglas Gregor   TheSema.reset(S);
830e93f017SDouglas Gregor }
840e93f017SDouglas Gregor 
8556d9c293SDaniel Dunbar void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
8656d9c293SDaniel Dunbar   Consumer.reset(Value);
8756d9c293SDaniel Dunbar }
8856d9c293SDaniel Dunbar 
89e01dc86dSDaniel Dunbar void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
90e01dc86dSDaniel Dunbar   CompletionConsumer.reset(Value);
91e01dc86dSDaniel Dunbar }
92e01dc86dSDaniel Dunbar 
937d75afc5SDaniel Dunbar // Diagnostics
947d75afc5SDaniel Dunbar static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
9589c31490SAxel Naumann                               unsigned argc, const char* const *argv,
969c902b55SDavid Blaikie                               DiagnosticsEngine &Diags) {
977d75afc5SDaniel Dunbar   std::string ErrorInfo;
98e2778999SDylan Noblesmith   OwningPtr<raw_ostream> OS(
99eeed0cc3SKovarththanan Rajaratnam     new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo));
1007d75afc5SDaniel Dunbar   if (!ErrorInfo.empty()) {
1014a94ba56SKovarththanan Rajaratnam     Diags.Report(diag::err_fe_unable_to_open_logfile)
1024a94ba56SKovarththanan Rajaratnam                  << DiagOpts.DumpBuildInformation << ErrorInfo;
1037d75afc5SDaniel Dunbar     return;
1047d75afc5SDaniel Dunbar   }
1057d75afc5SDaniel Dunbar 
106520d1e6cSDaniel Dunbar   (*OS) << "clang -cc1 command line arguments: ";
1077d75afc5SDaniel Dunbar   for (unsigned i = 0; i != argc; ++i)
1087d75afc5SDaniel Dunbar     (*OS) << argv[i] << ' ';
1097d75afc5SDaniel Dunbar   (*OS) << '\n';
1107d75afc5SDaniel Dunbar 
1117d75afc5SDaniel Dunbar   // Chain in a diagnostic client which will log the diagnostics.
112e2eefaecSDavid Blaikie   DiagnosticConsumer *Logger =
113eeed0cc3SKovarththanan Rajaratnam     new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true);
1148b00dcb0SDavid Blaikie   Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger));
1157d75afc5SDaniel Dunbar }
1167d75afc5SDaniel Dunbar 
1172083c32fSDaniel Dunbar static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts,
1187b83306dSDaniel Dunbar                                const CodeGenOptions *CodeGenOpts,
1199c902b55SDavid Blaikie                                DiagnosticsEngine &Diags) {
1202083c32fSDaniel Dunbar   std::string ErrorInfo;
1212083c32fSDaniel Dunbar   bool OwnsStream = false;
1220e62c1ccSChris Lattner   raw_ostream *OS = &llvm::errs();
1232083c32fSDaniel Dunbar   if (DiagOpts.DiagnosticLogFile != "-") {
1242083c32fSDaniel Dunbar     // Create the output stream.
1252083c32fSDaniel Dunbar     llvm::raw_fd_ostream *FileOS(
1262083c32fSDaniel Dunbar       new llvm::raw_fd_ostream(DiagOpts.DiagnosticLogFile.c_str(),
12744d9ef78SDaniel Dunbar                                ErrorInfo, llvm::raw_fd_ostream::F_Append));
1282083c32fSDaniel Dunbar     if (!ErrorInfo.empty()) {
1292083c32fSDaniel Dunbar       Diags.Report(diag::warn_fe_cc_log_diagnostics_failure)
1302083c32fSDaniel Dunbar         << DiagOpts.DumpBuildInformation << ErrorInfo;
1312083c32fSDaniel Dunbar     } else {
1322083c32fSDaniel Dunbar       FileOS->SetUnbuffered();
1332083c32fSDaniel Dunbar       FileOS->SetUseAtomicWrites(true);
1342083c32fSDaniel Dunbar       OS = FileOS;
1352083c32fSDaniel Dunbar       OwnsStream = true;
1362083c32fSDaniel Dunbar     }
1372083c32fSDaniel Dunbar   }
1382083c32fSDaniel Dunbar 
1392083c32fSDaniel Dunbar   // Chain in the diagnostic client which will log the diagnostics.
1407b83306dSDaniel Dunbar   LogDiagnosticPrinter *Logger = new LogDiagnosticPrinter(*OS, DiagOpts,
1412083c32fSDaniel Dunbar                                                           OwnsStream);
1427b83306dSDaniel Dunbar   if (CodeGenOpts)
1437b83306dSDaniel Dunbar     Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags);
1448b00dcb0SDavid Blaikie   Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(), Logger));
1452083c32fSDaniel Dunbar }
1462083c32fSDaniel Dunbar 
1474610ea2bSTed Kremenek static void SetupSerializedDiagnostics(const DiagnosticOptions &DiagOpts,
1484610ea2bSTed Kremenek                                        DiagnosticsEngine &Diags,
1494610ea2bSTed Kremenek                                        StringRef OutputFile) {
1504610ea2bSTed Kremenek   std::string ErrorInfo;
151e2778999SDylan Noblesmith   OwningPtr<llvm::raw_fd_ostream> OS;
1524610ea2bSTed Kremenek   OS.reset(new llvm::raw_fd_ostream(OutputFile.str().c_str(), ErrorInfo,
1534610ea2bSTed Kremenek                                     llvm::raw_fd_ostream::F_Binary));
1544610ea2bSTed Kremenek 
1554610ea2bSTed Kremenek   if (!ErrorInfo.empty()) {
1564610ea2bSTed Kremenek     Diags.Report(diag::warn_fe_serialized_diag_failure)
1574610ea2bSTed Kremenek       << OutputFile << ErrorInfo;
1584610ea2bSTed Kremenek     return;
1594610ea2bSTed Kremenek   }
1604610ea2bSTed Kremenek 
1614610ea2bSTed Kremenek   DiagnosticConsumer *SerializedConsumer =
1624548e044STed Kremenek     clang::serialized_diags::create(OS.take(), DiagOpts);
1634610ea2bSTed Kremenek 
1644610ea2bSTed Kremenek 
1654610ea2bSTed Kremenek   Diags.setClient(new ChainedDiagnosticConsumer(Diags.takeClient(),
1664610ea2bSTed Kremenek                                                 SerializedConsumer));
1674610ea2bSTed Kremenek }
1684610ea2bSTed Kremenek 
16944c6ee77SDouglas Gregor void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv,
170e2eefaecSDavid Blaikie                                          DiagnosticConsumer *Client,
171d0e9e3a6SDouglas Gregor                                          bool ShouldOwnClient,
172d0e9e3a6SDouglas Gregor                                          bool ShouldCloneClient) {
1737b83306dSDaniel Dunbar   Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client,
174d0e9e3a6SDouglas Gregor                                   ShouldOwnClient, ShouldCloneClient,
175d0e9e3a6SDouglas Gregor                                   &getCodeGenOpts());
1767d75afc5SDaniel Dunbar }
1777d75afc5SDaniel Dunbar 
178c95d8192SDylan Noblesmith IntrusiveRefCntPtr<DiagnosticsEngine>
1797f95d26eSDouglas Gregor CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
18044c6ee77SDouglas Gregor                                     int Argc, const char* const *Argv,
181e2eefaecSDavid Blaikie                                     DiagnosticConsumer *Client,
1822b9b4642SDouglas Gregor                                     bool ShouldOwnClient,
183d0e9e3a6SDouglas Gregor                                     bool ShouldCloneClient,
1847b83306dSDaniel Dunbar                                     const CodeGenOptions *CodeGenOpts) {
185c95d8192SDylan Noblesmith   IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
186c95d8192SDylan Noblesmith   IntrusiveRefCntPtr<DiagnosticsEngine>
1879c902b55SDavid Blaikie       Diags(new DiagnosticsEngine(DiagID));
1881b39a2edSDaniel Dunbar 
1897d75afc5SDaniel Dunbar   // Create the diagnostic client for reporting errors or for
1907d75afc5SDaniel Dunbar   // implementing -verify.
191d0e9e3a6SDouglas Gregor   if (Client) {
192d0e9e3a6SDouglas Gregor     if (ShouldCloneClient)
193d0e9e3a6SDouglas Gregor       Diags->setClient(Client->clone(*Diags), ShouldOwnClient);
19444c6ee77SDouglas Gregor     else
195d0e9e3a6SDouglas Gregor       Diags->setClient(Client, ShouldOwnClient);
196d0e9e3a6SDouglas Gregor   } else
1972dd19f1dSDouglas Gregor     Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
19850ec0da0SDaniel Dunbar 
19950ec0da0SDaniel Dunbar   // Chain in -verify checker, if requested.
20050ec0da0SDaniel Dunbar   if (Opts.VerifyDiagnostics)
20169609dceSDavid Blaikie     Diags->setClient(new VerifyDiagnosticConsumer(*Diags));
2027d75afc5SDaniel Dunbar 
2032083c32fSDaniel Dunbar   // Chain in -diagnostic-log-file dumper, if requested.
2042083c32fSDaniel Dunbar   if (!Opts.DiagnosticLogFile.empty())
2057b83306dSDaniel Dunbar     SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags);
2062083c32fSDaniel Dunbar 
2077d75afc5SDaniel Dunbar   if (!Opts.DumpBuildInformation.empty())
2084a94ba56SKovarththanan Rajaratnam     SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
2097d75afc5SDaniel Dunbar 
2104610ea2bSTed Kremenek   if (!Opts.DiagnosticSerializationFile.empty())
2114610ea2bSTed Kremenek     SetupSerializedDiagnostics(Opts, *Diags,
2124610ea2bSTed Kremenek                                Opts.DiagnosticSerializationFile);
2134610ea2bSTed Kremenek 
2147d75afc5SDaniel Dunbar   // Configure our handling of diagnostics.
2159ff84d9cSKovarththanan Rajaratnam   ProcessWarningOptions(*Diags, Opts);
2167d75afc5SDaniel Dunbar 
2177f95d26eSDouglas Gregor   return Diags;
2187d75afc5SDaniel Dunbar }
2197d75afc5SDaniel Dunbar 
2207d75afc5SDaniel Dunbar // File Manager
2217d75afc5SDaniel Dunbar 
222546a676aSDaniel Dunbar void CompilerInstance::createFileManager() {
2235e14d39aSTed Kremenek   FileMgr = new FileManager(getFileSystemOpts());
224546a676aSDaniel Dunbar }
225546a676aSDaniel Dunbar 
2267d75afc5SDaniel Dunbar // Source Manager
2277d75afc5SDaniel Dunbar 
2285159f616SChris Lattner void CompilerInstance::createSourceManager(FileManager &FileMgr) {
2295e14d39aSTed Kremenek   SourceMgr = new SourceManager(getDiagnostics(), FileMgr);
230546a676aSDaniel Dunbar }
231aaa148fdSDaniel Dunbar 
2327d75afc5SDaniel Dunbar // Preprocessor
2337d75afc5SDaniel Dunbar 
234aaa148fdSDaniel Dunbar void CompilerInstance::createPreprocessor() {
23508142534SDouglas Gregor   const PreprocessorOptions &PPOpts = getPreprocessorOpts();
236aaa148fdSDaniel Dunbar 
237aaa148fdSDaniel Dunbar   // Create a PTH manager if we are using some form of a token cache.
238aaa148fdSDaniel Dunbar   PTHManager *PTHMgr = 0;
239d6ea9028SDaniel Dunbar   if (!PPOpts.TokenCache.empty())
24008142534SDouglas Gregor     PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics());
241aaa148fdSDaniel Dunbar 
242aaa148fdSDaniel Dunbar   // Create the Preprocessor.
243197ac203SDouglas Gregor   HeaderSearch *HeaderInfo = new HeaderSearch(getFileManager(),
2441fb5c3a6SDouglas Gregor                                               getDiagnostics(),
24589929282SDouglas Gregor                                               getLangOpts(),
24689929282SDouglas Gregor                                               &getTarget());
24783297dfcSDouglas Gregor   PP = new Preprocessor(getDiagnostics(), getLangOpts(), &getTarget(),
24808142534SDouglas Gregor                         getSourceManager(), *HeaderInfo, *this, PTHMgr,
249aaa148fdSDaniel Dunbar                         /*OwnsHeaderSearch=*/true);
250aaa148fdSDaniel Dunbar 
251aaa148fdSDaniel Dunbar   // Note that this is different then passing PTHMgr to Preprocessor's ctor.
252aaa148fdSDaniel Dunbar   // That argument is used as the IdentifierInfoLookup argument to
253aaa148fdSDaniel Dunbar   // IdentifierTable's ctor.
254aaa148fdSDaniel Dunbar   if (PTHMgr) {
25508142534SDouglas Gregor     PTHMgr->setPreprocessor(&*PP);
256aaa148fdSDaniel Dunbar     PP->setPTHManager(PTHMgr);
257aaa148fdSDaniel Dunbar   }
258aaa148fdSDaniel Dunbar 
2597f6d60dcSDouglas Gregor   if (PPOpts.DetailedRecord)
260*647dcd80SArgyrios Kyrtzidis     PP->createPreprocessingRecord(PPOpts.DetailedRecordConditionalDirectives);
2617f6d60dcSDouglas Gregor 
26208142534SDouglas Gregor   InitializePreprocessor(*PP, PPOpts, getHeaderSearchOpts(), getFrontendOpts());
263aaa148fdSDaniel Dunbar 
2641735f4e7SDouglas Gregor   // Set up the module path, including the hash for the
2651735f4e7SDouglas Gregor   // module-creation options.
2662c1dd271SDylan Noblesmith   SmallString<256> SpecificModuleCache(
2671735f4e7SDouglas Gregor                            getHeaderSearchOpts().ModuleCachePath);
2681735f4e7SDouglas Gregor   if (!getHeaderSearchOpts().DisableModuleHash)
2691735f4e7SDouglas Gregor     llvm::sys::path::append(SpecificModuleCache,
2701735f4e7SDouglas Gregor                             getInvocation().getModuleHash());
2712537a364SDouglas Gregor   PP->getHeaderSearchInfo().setModuleCachePath(SpecificModuleCache);
2721735f4e7SDouglas Gregor 
273aaa148fdSDaniel Dunbar   // Handle generating dependencies, if requested.
27408142534SDouglas Gregor   const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
275aaa148fdSDaniel Dunbar   if (!DepOpts.OutputFile.empty())
276aaa148fdSDaniel Dunbar     AttachDependencyFileGen(*PP, DepOpts);
2772e129659SDouglas Gregor   if (!DepOpts.DOTOutputFile.empty())
2782e129659SDouglas Gregor     AttachDependencyGraphGen(*PP, DepOpts.DOTOutputFile,
27983d46be3SDouglas Gregor                              getHeaderSearchOpts().Sysroot);
28083d46be3SDouglas Gregor 
281aaa148fdSDaniel Dunbar 
28227734fdbSDaniel Dunbar   // Handle generating header include information, if requested.
28327734fdbSDaniel Dunbar   if (DepOpts.ShowHeaderIncludes)
28427734fdbSDaniel Dunbar     AttachHeaderIncludeGen(*PP);
2851af1d275SDaniel Dunbar   if (!DepOpts.HeaderIncludeOutputFile.empty()) {
2860e62c1ccSChris Lattner     StringRef OutputPath = DepOpts.HeaderIncludeOutputFile;
2871af1d275SDaniel Dunbar     if (OutputPath == "-")
2881af1d275SDaniel Dunbar       OutputPath = "";
289fe908a80SDaniel Dunbar     AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath,
290fe908a80SDaniel Dunbar                            /*ShowDepth=*/false);
2911af1d275SDaniel Dunbar   }
292aaa148fdSDaniel Dunbar }
293df3e30c4SDaniel Dunbar 
294df3e30c4SDaniel Dunbar // ASTContext
295df3e30c4SDaniel Dunbar 
296df3e30c4SDaniel Dunbar void CompilerInstance::createASTContext() {
297df3e30c4SDaniel Dunbar   Preprocessor &PP = getPreprocessor();
2985e14d39aSTed Kremenek   Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
299e8bbc121SDouglas Gregor                            &getTarget(), PP.getIdentifierTable(),
300df3e30c4SDaniel Dunbar                            PP.getSelectorTable(), PP.getBuiltinInfo(),
3015e14d39aSTed Kremenek                            /*size_reserve=*/ 0);
302df3e30c4SDaniel Dunbar }
303599313efSDaniel Dunbar 
304599313efSDaniel Dunbar // ExternalASTSource
305599313efSDaniel Dunbar 
3060e62c1ccSChris Lattner void CompilerInstance::createPCHExternalASTSource(StringRef Path,
30707a89a83SSebastian Redl                                                   bool DisablePCHValidation,
308606c4ac3SDouglas Gregor                                                   bool DisableStatCache,
30907a89a83SSebastian Redl                                                  void *DeserializationListener){
310e2778999SDylan Noblesmith   OwningPtr<ExternalASTSource> Source;
311009e7f20SSebastian Redl   bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
312599313efSDaniel Dunbar   Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
313ce3a8293SDouglas Gregor                                           DisablePCHValidation,
314606c4ac3SDouglas Gregor                                           DisableStatCache,
31507a89a83SSebastian Redl                                           getPreprocessor(), getASTContext(),
316009e7f20SSebastian Redl                                           DeserializationListener,
317009e7f20SSebastian Redl                                           Preamble));
318925296b4SDouglas Gregor   ModuleManager = static_cast<ASTReader*>(Source.get());
319599313efSDaniel Dunbar   getASTContext().setExternalSource(Source);
320599313efSDaniel Dunbar }
321599313efSDaniel Dunbar 
322599313efSDaniel Dunbar ExternalASTSource *
3230e62c1ccSChris Lattner CompilerInstance::createPCHExternalASTSource(StringRef Path,
324599313efSDaniel Dunbar                                              const std::string &Sysroot,
325ce3a8293SDouglas Gregor                                              bool DisablePCHValidation,
326606c4ac3SDouglas Gregor                                              bool DisableStatCache,
327599313efSDaniel Dunbar                                              Preprocessor &PP,
32807a89a83SSebastian Redl                                              ASTContext &Context,
329009e7f20SSebastian Redl                                              void *DeserializationListener,
330009e7f20SSebastian Redl                                              bool Preamble) {
331e2778999SDylan Noblesmith   OwningPtr<ASTReader> Reader;
3328835e03cSDouglas Gregor   Reader.reset(new ASTReader(PP, Context,
333c567ba26SDouglas Gregor                              Sysroot.empty() ? "" : Sysroot.c_str(),
334606c4ac3SDouglas Gregor                              DisablePCHValidation, DisableStatCache));
335599313efSDaniel Dunbar 
33607a89a83SSebastian Redl   Reader->setDeserializationListener(
3373e31c724SSebastian Redl             static_cast<ASTDeserializationListener *>(DeserializationListener));
338009e7f20SSebastian Redl   switch (Reader->ReadAST(Path,
339a6895d8aSDouglas Gregor                           Preamble ? serialization::MK_Preamble
340a6895d8aSDouglas Gregor                                    : serialization::MK_PCH)) {
3412c499f65SSebastian Redl   case ASTReader::Success:
342599313efSDaniel Dunbar     // Set the predefines buffer as suggested by the PCH reader. Typically, the
343599313efSDaniel Dunbar     // predefines buffer will be empty.
344599313efSDaniel Dunbar     PP.setPredefines(Reader->getSuggestedPredefines());
345599313efSDaniel Dunbar     return Reader.take();
346599313efSDaniel Dunbar 
3472c499f65SSebastian Redl   case ASTReader::Failure:
348599313efSDaniel Dunbar     // Unrecoverable failure: don't even try to process the input file.
349599313efSDaniel Dunbar     break;
350599313efSDaniel Dunbar 
3512c499f65SSebastian Redl   case ASTReader::IgnorePCH:
352599313efSDaniel Dunbar     // No suitable PCH file could be found. Return an error.
353599313efSDaniel Dunbar     break;
354599313efSDaniel Dunbar   }
355599313efSDaniel Dunbar 
356599313efSDaniel Dunbar   return 0;
357599313efSDaniel Dunbar }
358f7093b5aSDaniel Dunbar 
359f7093b5aSDaniel Dunbar // Code Completion
360f7093b5aSDaniel Dunbar 
3618e984da8SDouglas Gregor static bool EnableCodeCompletion(Preprocessor &PP,
3628e984da8SDouglas Gregor                                  const std::string &Filename,
3638e984da8SDouglas Gregor                                  unsigned Line,
3648e984da8SDouglas Gregor                                  unsigned Column) {
3658e984da8SDouglas Gregor   // Tell the source manager to chop off the given file at a specific
3668e984da8SDouglas Gregor   // line and column.
3675159f616SChris Lattner   const FileEntry *Entry = PP.getFileManager().getFile(Filename);
3688e984da8SDouglas Gregor   if (!Entry) {
3698e984da8SDouglas Gregor     PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
3708e984da8SDouglas Gregor       << Filename;
3718e984da8SDouglas Gregor     return true;
3728e984da8SDouglas Gregor   }
3738e984da8SDouglas Gregor 
3748e984da8SDouglas Gregor   // Truncate the named file at the given line/column.
3758e984da8SDouglas Gregor   PP.SetCodeCompletionPoint(Entry, Line, Column);
3768e984da8SDouglas Gregor   return false;
3778e984da8SDouglas Gregor }
3788e984da8SDouglas Gregor 
379f7093b5aSDaniel Dunbar void CompilerInstance::createCodeCompletionConsumer() {
380f7093b5aSDaniel Dunbar   const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
3818e984da8SDouglas Gregor   if (!CompletionConsumer) {
382f7093b5aSDaniel Dunbar     CompletionConsumer.reset(
383f7093b5aSDaniel Dunbar       createCodeCompletionConsumer(getPreprocessor(),
384f7093b5aSDaniel Dunbar                                    Loc.FileName, Loc.Line, Loc.Column,
385f7093b5aSDaniel Dunbar                                    getFrontendOpts().ShowMacrosInCodeCompletion,
386f64acca2SDouglas Gregor                              getFrontendOpts().ShowCodePatternsInCodeCompletion,
38739982197SDouglas Gregor                            getFrontendOpts().ShowGlobalSymbolsInCodeCompletion,
388f7093b5aSDaniel Dunbar                                    llvm::outs()));
38900a0cf70SDouglas Gregor     if (!CompletionConsumer)
39000a0cf70SDouglas Gregor       return;
3918e984da8SDouglas Gregor   } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName,
3928e984da8SDouglas Gregor                                   Loc.Line, Loc.Column)) {
3938e984da8SDouglas Gregor     CompletionConsumer.reset();
3948e984da8SDouglas Gregor     return;
3958e984da8SDouglas Gregor   }
396f09935f1SDouglas Gregor 
397f09935f1SDouglas Gregor   if (CompletionConsumer->isOutputBinary() &&
398f09935f1SDouglas Gregor       llvm::sys::Program::ChangeStdoutToBinary()) {
399f09935f1SDouglas Gregor     getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
400f09935f1SDouglas Gregor     CompletionConsumer.reset();
401f09935f1SDouglas Gregor   }
402f7093b5aSDaniel Dunbar }
403f7093b5aSDaniel Dunbar 
4045505dff8SKovarththanan Rajaratnam void CompilerInstance::createFrontendTimer() {
4055505dff8SKovarththanan Rajaratnam   FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
4065505dff8SKovarththanan Rajaratnam }
4075505dff8SKovarththanan Rajaratnam 
408f7093b5aSDaniel Dunbar CodeCompleteConsumer *
409f7093b5aSDaniel Dunbar CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
410f7093b5aSDaniel Dunbar                                                const std::string &Filename,
411f7093b5aSDaniel Dunbar                                                unsigned Line,
412f7093b5aSDaniel Dunbar                                                unsigned Column,
413f7093b5aSDaniel Dunbar                                                bool ShowMacros,
414f64acca2SDouglas Gregor                                                bool ShowCodePatterns,
41539982197SDouglas Gregor                                                bool ShowGlobals,
4160e62c1ccSChris Lattner                                                raw_ostream &OS) {
4178e984da8SDouglas Gregor   if (EnableCodeCompletion(PP, Filename, Line, Column))
418f7093b5aSDaniel Dunbar     return 0;
419f7093b5aSDaniel Dunbar 
420f7093b5aSDaniel Dunbar   // Set up the creation routine for code-completion.
42139982197SDouglas Gregor   return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns,
42239982197SDouglas Gregor                                           ShowGlobals, OS);
423f7093b5aSDaniel Dunbar }
424566eeb2dSDaniel Dunbar 
42569f74f80SDouglas Gregor void CompilerInstance::createSema(TranslationUnitKind TUKind,
4260e93f017SDouglas Gregor                                   CodeCompleteConsumer *CompletionConsumer) {
4270e93f017SDouglas Gregor   TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
42869f74f80SDouglas Gregor                          TUKind, CompletionConsumer));
4290e93f017SDouglas Gregor }
4300e93f017SDouglas Gregor 
431566eeb2dSDaniel Dunbar // Output Files
432566eeb2dSDaniel Dunbar 
433d0599970SArgyrios Kyrtzidis void CompilerInstance::addOutputFile(const OutputFile &OutFile) {
434d0599970SArgyrios Kyrtzidis   assert(OutFile.OS && "Attempt to add empty stream to output list!");
435d0599970SArgyrios Kyrtzidis   OutputFiles.push_back(OutFile);
436566eeb2dSDaniel Dunbar }
437566eeb2dSDaniel Dunbar 
4381c558cd7SKovarththanan Rajaratnam void CompilerInstance::clearOutputFiles(bool EraseFiles) {
439d0599970SArgyrios Kyrtzidis   for (std::list<OutputFile>::iterator
440566eeb2dSDaniel Dunbar          it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
441d0599970SArgyrios Kyrtzidis     delete it->OS;
442d0599970SArgyrios Kyrtzidis     if (!it->TempFilename.empty()) {
443b5c356a4SAnders Carlsson       if (EraseFiles) {
444b5c356a4SAnders Carlsson         bool existed;
445b5c356a4SAnders Carlsson         llvm::sys::fs::remove(it->TempFilename, existed);
446b5c356a4SAnders Carlsson       } else {
4472c1dd271SDylan Noblesmith         SmallString<128> NewOutFile(it->Filename);
448b5c356a4SAnders Carlsson 
44971731d6bSArgyrios Kyrtzidis         // If '-working-directory' was passed, the output filename should be
45071731d6bSArgyrios Kyrtzidis         // relative to that.
4519ba8fb1eSAnders Carlsson         FileMgr->FixupRelativePath(NewOutFile);
452b5c356a4SAnders Carlsson         if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename,
453b5c356a4SAnders Carlsson                                                         NewOutFile.str())) {
454d0599970SArgyrios Kyrtzidis           getDiagnostics().Report(diag::err_fe_unable_to_rename_temp)
455b5c356a4SAnders Carlsson             << it->TempFilename << it->Filename << ec.message();
456b5c356a4SAnders Carlsson 
457b5c356a4SAnders Carlsson           bool existed;
458b5c356a4SAnders Carlsson           llvm::sys::fs::remove(it->TempFilename, existed);
459d0599970SArgyrios Kyrtzidis         }
460d0599970SArgyrios Kyrtzidis       }
461d0599970SArgyrios Kyrtzidis     } else if (!it->Filename.empty() && EraseFiles)
462d0599970SArgyrios Kyrtzidis       llvm::sys::Path(it->Filename).eraseFromDisk();
463d0599970SArgyrios Kyrtzidis 
464566eeb2dSDaniel Dunbar   }
465566eeb2dSDaniel Dunbar   OutputFiles.clear();
466566eeb2dSDaniel Dunbar }
467566eeb2dSDaniel Dunbar 
468420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *
469420b0f1bSDaniel Dunbar CompilerInstance::createDefaultOutputFile(bool Binary,
4700e62c1ccSChris Lattner                                           StringRef InFile,
4710e62c1ccSChris Lattner                                           StringRef Extension) {
472420b0f1bSDaniel Dunbar   return createOutputFile(getFrontendOpts().OutputFile, Binary,
473ae77b3dfSDaniel Dunbar                           /*RemoveFileOnSignal=*/true, InFile, Extension,
474ae77b3dfSDaniel Dunbar                           /*UseTemporary=*/true);
475420b0f1bSDaniel Dunbar }
476420b0f1bSDaniel Dunbar 
477420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *
4780e62c1ccSChris Lattner CompilerInstance::createOutputFile(StringRef OutputPath,
479e326f9bbSDaniel Dunbar                                    bool Binary, bool RemoveFileOnSignal,
4800e62c1ccSChris Lattner                                    StringRef InFile,
48108a2bfd2SArgyrios Kyrtzidis                                    StringRef Extension,
482b9c62c07SDaniel Dunbar                                    bool UseTemporary,
483b9c62c07SDaniel Dunbar                                    bool CreateMissingDirectories) {
484d0599970SArgyrios Kyrtzidis   std::string Error, OutputPathName, TempPathName;
485420b0f1bSDaniel Dunbar   llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
486e326f9bbSDaniel Dunbar                                               RemoveFileOnSignal,
487420b0f1bSDaniel Dunbar                                               InFile, Extension,
48808a2bfd2SArgyrios Kyrtzidis                                               UseTemporary,
489b9c62c07SDaniel Dunbar                                               CreateMissingDirectories,
490d0599970SArgyrios Kyrtzidis                                               &OutputPathName,
491d0599970SArgyrios Kyrtzidis                                               &TempPathName);
492420b0f1bSDaniel Dunbar   if (!OS) {
4937554699aSDaniel Dunbar     getDiagnostics().Report(diag::err_fe_unable_to_open_output)
4947554699aSDaniel Dunbar       << OutputPath << Error;
4957554699aSDaniel Dunbar     return 0;
496420b0f1bSDaniel Dunbar   }
497420b0f1bSDaniel Dunbar 
498420b0f1bSDaniel Dunbar   // Add the output file -- but don't try to remove "-", since this means we are
499420b0f1bSDaniel Dunbar   // using stdin.
500d0599970SArgyrios Kyrtzidis   addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "",
501d0599970SArgyrios Kyrtzidis                 TempPathName, OS));
502420b0f1bSDaniel Dunbar 
503420b0f1bSDaniel Dunbar   return OS;
504420b0f1bSDaniel Dunbar }
505420b0f1bSDaniel Dunbar 
506420b0f1bSDaniel Dunbar llvm::raw_fd_ostream *
5070e62c1ccSChris Lattner CompilerInstance::createOutputFile(StringRef OutputPath,
508420b0f1bSDaniel Dunbar                                    std::string &Error,
509420b0f1bSDaniel Dunbar                                    bool Binary,
510e326f9bbSDaniel Dunbar                                    bool RemoveFileOnSignal,
5110e62c1ccSChris Lattner                                    StringRef InFile,
5120e62c1ccSChris Lattner                                    StringRef Extension,
51308a2bfd2SArgyrios Kyrtzidis                                    bool UseTemporary,
514b9c62c07SDaniel Dunbar                                    bool CreateMissingDirectories,
515d0599970SArgyrios Kyrtzidis                                    std::string *ResultPathName,
516d0599970SArgyrios Kyrtzidis                                    std::string *TempPathName) {
517b9c62c07SDaniel Dunbar   assert((!CreateMissingDirectories || UseTemporary) &&
518b9c62c07SDaniel Dunbar          "CreateMissingDirectories is only allowed when using temporary files");
519b9c62c07SDaniel Dunbar 
520d0599970SArgyrios Kyrtzidis   std::string OutFile, TempFile;
521420b0f1bSDaniel Dunbar   if (!OutputPath.empty()) {
522420b0f1bSDaniel Dunbar     OutFile = OutputPath;
523420b0f1bSDaniel Dunbar   } else if (InFile == "-") {
524420b0f1bSDaniel Dunbar     OutFile = "-";
525420b0f1bSDaniel Dunbar   } else if (!Extension.empty()) {
526420b0f1bSDaniel Dunbar     llvm::sys::Path Path(InFile);
527420b0f1bSDaniel Dunbar     Path.eraseSuffix();
528420b0f1bSDaniel Dunbar     Path.appendSuffix(Extension);
529420b0f1bSDaniel Dunbar     OutFile = Path.str();
530420b0f1bSDaniel Dunbar   } else {
531420b0f1bSDaniel Dunbar     OutFile = "-";
532420b0f1bSDaniel Dunbar   }
533420b0f1bSDaniel Dunbar 
534e2778999SDylan Noblesmith   OwningPtr<llvm::raw_fd_ostream> OS;
53508a2bfd2SArgyrios Kyrtzidis   std::string OSFile;
53608a2bfd2SArgyrios Kyrtzidis 
53708a2bfd2SArgyrios Kyrtzidis   if (UseTemporary && OutFile != "-") {
538b9c62c07SDaniel Dunbar     // Only create the temporary if the parent directory exists (or create
539b9c62c07SDaniel Dunbar     // missing directories is true) and we can actually write to OutPath,
540b9c62c07SDaniel Dunbar     // otherwise we want to fail early.
541b9c62c07SDaniel Dunbar     SmallString<256> AbsPath(OutputPath);
542b9c62c07SDaniel Dunbar     llvm::sys::fs::make_absolute(AbsPath);
543b9c62c07SDaniel Dunbar     llvm::sys::Path OutPath(AbsPath);
544b9c62c07SDaniel Dunbar     bool ParentExists = false;
545b9c62c07SDaniel Dunbar     if (llvm::sys::fs::exists(llvm::sys::path::parent_path(AbsPath.str()),
546b9c62c07SDaniel Dunbar                               ParentExists))
547b9c62c07SDaniel Dunbar       ParentExists = false;
548f6efe58dSMichael J. Spencer     bool Exists;
549b9c62c07SDaniel Dunbar     if ((CreateMissingDirectories || ParentExists) &&
550b9c62c07SDaniel Dunbar         ((llvm::sys::fs::exists(AbsPath.str(), Exists) || !Exists) ||
551b9c62c07SDaniel Dunbar          (OutPath.isRegularFile() && OutPath.canWrite()))) {
552d0599970SArgyrios Kyrtzidis       // Create a temporary file.
5532c1dd271SDylan Noblesmith       SmallString<128> TempPath;
55408a2bfd2SArgyrios Kyrtzidis       TempPath = OutFile;
55508a2bfd2SArgyrios Kyrtzidis       TempPath += "-%%%%%%%%";
55608a2bfd2SArgyrios Kyrtzidis       int fd;
55708a2bfd2SArgyrios Kyrtzidis       if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath,
55808a2bfd2SArgyrios Kyrtzidis                                /*makeAbsolute=*/false) == llvm::errc::success) {
55908a2bfd2SArgyrios Kyrtzidis         OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
56008a2bfd2SArgyrios Kyrtzidis         OSFile = TempFile = TempPath.str();
56108a2bfd2SArgyrios Kyrtzidis       }
562d0599970SArgyrios Kyrtzidis     }
563d0599970SArgyrios Kyrtzidis   }
564d0599970SArgyrios Kyrtzidis 
56508a2bfd2SArgyrios Kyrtzidis   if (!OS) {
56608a2bfd2SArgyrios Kyrtzidis     OSFile = OutFile;
56708a2bfd2SArgyrios Kyrtzidis     OS.reset(
568d0599970SArgyrios Kyrtzidis       new llvm::raw_fd_ostream(OSFile.c_str(), Error,
5692eaef18eSDaniel Dunbar                                (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
5702eaef18eSDaniel Dunbar     if (!Error.empty())
571420b0f1bSDaniel Dunbar       return 0;
57208a2bfd2SArgyrios Kyrtzidis   }
573420b0f1bSDaniel Dunbar 
574d0599970SArgyrios Kyrtzidis   // Make sure the out stream file gets removed if we crash.
575e326f9bbSDaniel Dunbar   if (RemoveFileOnSignal)
576d0599970SArgyrios Kyrtzidis     llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile));
577d0599970SArgyrios Kyrtzidis 
578420b0f1bSDaniel Dunbar   if (ResultPathName)
579420b0f1bSDaniel Dunbar     *ResultPathName = OutFile;
580d0599970SArgyrios Kyrtzidis   if (TempPathName)
581d0599970SArgyrios Kyrtzidis     *TempPathName = TempFile;
582420b0f1bSDaniel Dunbar 
5832eaef18eSDaniel Dunbar   return OS.take();
584420b0f1bSDaniel Dunbar }
585409e890fSDaniel Dunbar 
586409e890fSDaniel Dunbar // Initialization Utilities
587409e890fSDaniel Dunbar 
588a686e1b0SDouglas Gregor bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
589a686e1b0SDouglas Gregor                                                SrcMgr::CharacteristicKind Kind){
590a686e1b0SDouglas Gregor   return InitializeSourceManager(InputFile, Kind, getDiagnostics(),
591a686e1b0SDouglas Gregor                                  getFileManager(), getSourceManager(),
592a686e1b0SDouglas Gregor                                  getFrontendOpts());
593409e890fSDaniel Dunbar }
594409e890fSDaniel Dunbar 
5950e62c1ccSChris Lattner bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
596a686e1b0SDouglas Gregor                                                SrcMgr::CharacteristicKind Kind,
5979c902b55SDavid Blaikie                                                DiagnosticsEngine &Diags,
598409e890fSDaniel Dunbar                                                FileManager &FileMgr,
599409e890fSDaniel Dunbar                                                SourceManager &SourceMgr,
600409e890fSDaniel Dunbar                                                const FrontendOptions &Opts) {
6017c06d866SArgyrios Kyrtzidis   // Figure out where to get and map in the main file.
6027c06d866SArgyrios Kyrtzidis   if (InputFile != "-") {
6035159f616SChris Lattner     const FileEntry *File = FileMgr.getFile(InputFile);
60452765215SDan Gohman     if (!File) {
605409e890fSDaniel Dunbar       Diags.Report(diag::err_fe_error_reading) << InputFile;
606409e890fSDaniel Dunbar       return false;
607409e890fSDaniel Dunbar     }
608a686e1b0SDouglas Gregor     SourceMgr.createMainFileID(File, Kind);
609409e890fSDaniel Dunbar   } else {
610e2778999SDylan Noblesmith     OwningPtr<llvm::MemoryBuffer> SB;
611d9da7a1fSMichael J. Spencer     if (llvm::MemoryBuffer::getSTDIN(SB)) {
612f25faaafSMichael J. Spencer       // FIXME: Give ec.message() in this diag.
613409e890fSDaniel Dunbar       Diags.Report(diag::err_fe_error_reading_stdin);
614409e890fSDaniel Dunbar       return false;
615409e890fSDaniel Dunbar     }
6162f76cd75SDan Gohman     const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
6175159f616SChris Lattner                                                    SB->getBufferSize(), 0);
618a686e1b0SDouglas Gregor     SourceMgr.createMainFileID(File, Kind);
619d9da7a1fSMichael J. Spencer     SourceMgr.overrideFileContents(File, SB.take());
620409e890fSDaniel Dunbar   }
621409e890fSDaniel Dunbar 
62252765215SDan Gohman   assert(!SourceMgr.getMainFileID().isInvalid() &&
62352765215SDan Gohman          "Couldn't establish MainFileID!");
624409e890fSDaniel Dunbar   return true;
625409e890fSDaniel Dunbar }
6264f2bc55dSDaniel Dunbar 
6274f2bc55dSDaniel Dunbar // High-Level Operations
6284f2bc55dSDaniel Dunbar 
6294f2bc55dSDaniel Dunbar bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
6304f2bc55dSDaniel Dunbar   assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
6314f2bc55dSDaniel Dunbar   assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
6324f2bc55dSDaniel Dunbar   assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
6334f2bc55dSDaniel Dunbar 
6344f2bc55dSDaniel Dunbar   // FIXME: Take this as an argument, once all the APIs we used have moved to
6354f2bc55dSDaniel Dunbar   // taking it as an input instead of hard-coding llvm::errs.
6360e62c1ccSChris Lattner   raw_ostream &OS = llvm::errs();
6374f2bc55dSDaniel Dunbar 
6384f2bc55dSDaniel Dunbar   // Create the target instance.
6394f2bc55dSDaniel Dunbar   setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
6404f2bc55dSDaniel Dunbar   if (!hasTarget())
6414f2bc55dSDaniel Dunbar     return false;
6424f2bc55dSDaniel Dunbar 
6434f2bc55dSDaniel Dunbar   // Inform the target of the language options.
6444f2bc55dSDaniel Dunbar   //
6454f2bc55dSDaniel Dunbar   // FIXME: We shouldn't need to do this, the target should be immutable once
6464f2bc55dSDaniel Dunbar   // created. This complexity should be lifted elsewhere.
6474f2bc55dSDaniel Dunbar   getTarget().setForcedLangOptions(getLangOpts());
6484f2bc55dSDaniel Dunbar 
6494f2bc55dSDaniel Dunbar   // Validate/process some options.
6504f2bc55dSDaniel Dunbar   if (getHeaderSearchOpts().Verbose)
6514f2bc55dSDaniel Dunbar     OS << "clang -cc1 version " CLANG_VERSION_STRING
6524f2bc55dSDaniel Dunbar        << " based upon " << PACKAGE_STRING
6538188c8a1SSebastian Pop        << " default target " << llvm::sys::getDefaultTargetTriple() << "\n";
6544f2bc55dSDaniel Dunbar 
6554f2bc55dSDaniel Dunbar   if (getFrontendOpts().ShowTimers)
6564f2bc55dSDaniel Dunbar     createFrontendTimer();
6574f2bc55dSDaniel Dunbar 
658171b780cSDouglas Gregor   if (getFrontendOpts().ShowStats)
659171b780cSDouglas Gregor     llvm::EnableStatistics();
660171b780cSDouglas Gregor 
6614f2bc55dSDaniel Dunbar   for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
6624f2bc55dSDaniel Dunbar     // Reset the ID tables if we are reusing the SourceManager.
663aed46fcbSDaniel Dunbar     if (hasSourceManager())
6644f2bc55dSDaniel Dunbar       getSourceManager().clearIDTables();
6654f2bc55dSDaniel Dunbar 
66632fbe312SDouglas Gregor     if (Act.BeginSourceFile(*this, getFrontendOpts().Inputs[i])) {
6674f2bc55dSDaniel Dunbar       Act.Execute();
6684f2bc55dSDaniel Dunbar       Act.EndSourceFile();
6694f2bc55dSDaniel Dunbar     }
6704f2bc55dSDaniel Dunbar   }
6714f2bc55dSDaniel Dunbar 
6727910d7b7SArgyrios Kyrtzidis   // Notify the diagnostic client that all files were processed.
6737910d7b7SArgyrios Kyrtzidis   getDiagnostics().getClient()->finish();
6747910d7b7SArgyrios Kyrtzidis 
675198cb4dfSChris Lattner   if (getDiagnosticOpts().ShowCarets) {
676c79346a5SArgyrios Kyrtzidis     // We can have multiple diagnostics sharing one diagnostic client.
677c79346a5SArgyrios Kyrtzidis     // Get the total number of warnings/errors from the client.
678c79346a5SArgyrios Kyrtzidis     unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings();
679c79346a5SArgyrios Kyrtzidis     unsigned NumErrors = getDiagnostics().getClient()->getNumErrors();
680198cb4dfSChris Lattner 
681198cb4dfSChris Lattner     if (NumWarnings)
682198cb4dfSChris Lattner       OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
683198cb4dfSChris Lattner     if (NumWarnings && NumErrors)
684198cb4dfSChris Lattner       OS << " and ";
685198cb4dfSChris Lattner     if (NumErrors)
686198cb4dfSChris Lattner       OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
687198cb4dfSChris Lattner     if (NumWarnings || NumErrors)
688198cb4dfSChris Lattner       OS << " generated.\n";
689198cb4dfSChris Lattner   }
6904f2bc55dSDaniel Dunbar 
691aed46fcbSDaniel Dunbar   if (getFrontendOpts().ShowStats && hasFileManager()) {
6924f2bc55dSDaniel Dunbar     getFileManager().PrintStats();
6934f2bc55dSDaniel Dunbar     OS << "\n";
6944f2bc55dSDaniel Dunbar   }
6954f2bc55dSDaniel Dunbar 
696bc467933SArgyrios Kyrtzidis   return !getDiagnostics().getClient()->getNumErrors();
6974f2bc55dSDaniel Dunbar }
6984f2bc55dSDaniel Dunbar 
699faeb1d46SDouglas Gregor /// \brief Determine the appropriate source input kind based on language
700faeb1d46SDouglas Gregor /// options.
701faeb1d46SDouglas Gregor static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) {
702faeb1d46SDouglas Gregor   if (LangOpts.OpenCL)
703faeb1d46SDouglas Gregor     return IK_OpenCL;
704faeb1d46SDouglas Gregor   if (LangOpts.CUDA)
705faeb1d46SDouglas Gregor     return IK_CUDA;
706faeb1d46SDouglas Gregor   if (LangOpts.ObjC1)
707faeb1d46SDouglas Gregor     return LangOpts.CPlusPlus? IK_ObjCXX : IK_ObjC;
708faeb1d46SDouglas Gregor   return LangOpts.CPlusPlus? IK_CXX : IK_C;
709faeb1d46SDouglas Gregor }
710faeb1d46SDouglas Gregor 
71151e0b541SDouglas Gregor namespace {
712514b636aSDouglas Gregor   struct CompileModuleMapData {
713514b636aSDouglas Gregor     CompilerInstance &Instance;
714514b636aSDouglas Gregor     GenerateModuleAction &CreateModuleAction;
715514b636aSDouglas Gregor   };
716514b636aSDouglas Gregor }
717514b636aSDouglas Gregor 
718514b636aSDouglas Gregor /// \brief Helper function that executes the module-generating action under
719514b636aSDouglas Gregor /// a crash recovery context.
720514b636aSDouglas Gregor static void doCompileMapModule(void *UserData) {
721514b636aSDouglas Gregor   CompileModuleMapData &Data
722514b636aSDouglas Gregor     = *reinterpret_cast<CompileModuleMapData *>(UserData);
723514b636aSDouglas Gregor   Data.Instance.ExecuteAction(Data.CreateModuleAction);
724514b636aSDouglas Gregor }
725514b636aSDouglas Gregor 
726514b636aSDouglas Gregor /// \brief Compile a module file for the given module, using the options
727514b636aSDouglas Gregor /// provided by the importing compiler instance.
728faeb1d46SDouglas Gregor static void compileModule(CompilerInstance &ImportingInstance,
729de3ef502SDouglas Gregor                           Module *Module,
7306dc57927SDouglas Gregor                           StringRef ModuleFileName) {
731e212489fSDouglas Gregor   llvm::LockFileManager Locked(ModuleFileName);
73254a88810SDouglas Gregor   switch (Locked) {
733e212489fSDouglas Gregor   case llvm::LockFileManager::LFS_Error:
73454a88810SDouglas Gregor     return;
73554a88810SDouglas Gregor 
736e212489fSDouglas Gregor   case llvm::LockFileManager::LFS_Owned:
73754a88810SDouglas Gregor     // We're responsible for building the module ourselves. Do so below.
73854a88810SDouglas Gregor     break;
73954a88810SDouglas Gregor 
740e212489fSDouglas Gregor   case llvm::LockFileManager::LFS_Shared:
74154a88810SDouglas Gregor     // Someone else is responsible for building the module. Wait for them to
74254a88810SDouglas Gregor     // finish.
74354a88810SDouglas Gregor     Locked.waitForUnlock();
74454a88810SDouglas Gregor     break;
74554a88810SDouglas Gregor   }
74654a88810SDouglas Gregor 
747514b636aSDouglas Gregor   ModuleMap &ModMap
748514b636aSDouglas Gregor     = ImportingInstance.getPreprocessor().getHeaderSearchInfo().getModuleMap();
749514b636aSDouglas Gregor 
750faeb1d46SDouglas Gregor   // Construct a compiler invocation for creating this module.
751c95d8192SDylan Noblesmith   IntrusiveRefCntPtr<CompilerInvocation> Invocation
752faeb1d46SDouglas Gregor     (new CompilerInvocation(ImportingInstance.getInvocation()));
75344bf68d8SDouglas Gregor 
754f545f67dSDouglas Gregor   PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
755f545f67dSDouglas Gregor 
75644bf68d8SDouglas Gregor   // For any options that aren't intended to affect how a module is built,
75744bf68d8SDouglas Gregor   // reset them to their default values.
7588cf47df7STed Kremenek   Invocation->getLangOpts()->resetNonModularOptions();
759f545f67dSDouglas Gregor   PPOpts.resetNonModularOptions();
76044bf68d8SDouglas Gregor 
7617d106e42SDouglas Gregor   // Note the name of the module we're building.
7626dc57927SDouglas Gregor   Invocation->getLangOpts()->CurrentModule = Module->getTopLevelModuleName();
7637d106e42SDouglas Gregor 
76444bf68d8SDouglas Gregor   // Note that this module is part of the module build path, so that we
76544bf68d8SDouglas Gregor   // can detect cycles in the module graph.
766f545f67dSDouglas Gregor   PPOpts.ModuleBuildPath.push_back(Module->getTopLevelModuleName());
767f1312a82SDouglas Gregor 
768514b636aSDouglas Gregor   // If there is a module map file, build the module using the module map.
769514b636aSDouglas Gregor   // Set up the inputs/outputs so that we build the module from its umbrella
770514b636aSDouglas Gregor   // header.
771514b636aSDouglas Gregor   FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
772514b636aSDouglas Gregor   FrontendOpts.OutputFile = ModuleFileName.str();
773514b636aSDouglas Gregor   FrontendOpts.DisableFree = false;
774514b636aSDouglas Gregor   FrontendOpts.Inputs.clear();
775f545f67dSDouglas Gregor   InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts());
776f545f67dSDouglas Gregor 
777f545f67dSDouglas Gregor   // Get or create the module map that we'll use to build this module.
7782c1dd271SDylan Noblesmith   SmallString<128> TempModuleMapFileName;
779f545f67dSDouglas Gregor   if (const FileEntry *ModuleMapFile
780f545f67dSDouglas Gregor                                   = ModMap.getContainingModuleMapFile(Module)) {
781f545f67dSDouglas Gregor     // Use the module map where this module resides.
78232fbe312SDouglas Gregor     FrontendOpts.Inputs.push_back(FrontendInputFile(ModuleMapFile->getName(),
78332fbe312SDouglas Gregor                                                     IK));
784f545f67dSDouglas Gregor   } else {
785f545f67dSDouglas Gregor     // Create a temporary module map file.
786f545f67dSDouglas Gregor     TempModuleMapFileName = Module->Name;
787f545f67dSDouglas Gregor     TempModuleMapFileName += "-%%%%%%%%.map";
788f545f67dSDouglas Gregor     int FD;
789f545f67dSDouglas Gregor     if (llvm::sys::fs::unique_file(TempModuleMapFileName.str(), FD,
790f545f67dSDouglas Gregor                                    TempModuleMapFileName,
79119f9f7bcSDouglas Gregor                                    /*makeAbsolute=*/true)
7922f554c4cSDouglas Gregor           != llvm::errc::success) {
793ee78d3e0SDouglas Gregor       ImportingInstance.getDiagnostics().Report(diag::err_module_map_temp_file)
794ee78d3e0SDouglas Gregor         << TempModuleMapFileName;
795f545f67dSDouglas Gregor       return;
7962f554c4cSDouglas Gregor     }
797f545f67dSDouglas Gregor     // Print the module map to this file.
798f545f67dSDouglas Gregor     llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true);
799f545f67dSDouglas Gregor     Module->print(OS);
800514b636aSDouglas Gregor     FrontendOpts.Inputs.push_back(
80132fbe312SDouglas Gregor       FrontendInputFile(TempModuleMapFileName.str().str(), IK));
802f545f67dSDouglas Gregor   }
803f545f67dSDouglas Gregor 
804f545f67dSDouglas Gregor   // Don't free the remapped file buffers; they are owned by our caller.
805f545f67dSDouglas Gregor   PPOpts.RetainRemappedFileBuffers = true;
806514b636aSDouglas Gregor 
807514b636aSDouglas Gregor   Invocation->getDiagnosticOpts().VerifyDiagnostics = 0;
808514b636aSDouglas Gregor   assert(ImportingInstance.getInvocation().getModuleHash() ==
809514b636aSDouglas Gregor          Invocation->getModuleHash() && "Module hash mismatch!");
810514b636aSDouglas Gregor 
811514b636aSDouglas Gregor   // Construct a compiler instance that will be used to actually create the
812514b636aSDouglas Gregor   // module.
813514b636aSDouglas Gregor   CompilerInstance Instance;
814514b636aSDouglas Gregor   Instance.setInvocation(&*Invocation);
815514b636aSDouglas Gregor   Instance.createDiagnostics(/*argc=*/0, /*argv=*/0,
816514b636aSDouglas Gregor                              &ImportingInstance.getDiagnosticClient(),
817514b636aSDouglas Gregor                              /*ShouldOwnClient=*/true,
818514b636aSDouglas Gregor                              /*ShouldCloneClient=*/true);
819514b636aSDouglas Gregor 
820514b636aSDouglas Gregor   // Construct a module-generating action.
821514b636aSDouglas Gregor   GenerateModuleAction CreateModuleAction;
822514b636aSDouglas Gregor 
823514b636aSDouglas Gregor   // Execute the action to actually build the module in-place. Use a separate
824514b636aSDouglas Gregor   // thread so that we get a stack large enough.
825514b636aSDouglas Gregor   const unsigned ThreadStackSize = 8 << 20;
826514b636aSDouglas Gregor   llvm::CrashRecoveryContext CRC;
827514b636aSDouglas Gregor   CompileModuleMapData Data = { Instance, CreateModuleAction };
828514b636aSDouglas Gregor   CRC.RunSafelyOnThread(&doCompileMapModule, &Data, ThreadStackSize);
829514b636aSDouglas Gregor 
830f545f67dSDouglas Gregor   // Delete the temporary module map file.
831f545f67dSDouglas Gregor   // FIXME: Even though we're executing under crash protection, it would still
832f545f67dSDouglas Gregor   // be nice to do this with RemoveFileOnSignal when we can. However, that
833f545f67dSDouglas Gregor   // doesn't make sense for all clients, so clean this up manually.
834f545f67dSDouglas Gregor   if (!TempModuleMapFileName.empty())
835f545f67dSDouglas Gregor     llvm::sys::Path(TempModuleMapFileName).eraseFromDisk();
836faeb1d46SDouglas Gregor }
837faeb1d46SDouglas Gregor 
838de3ef502SDouglas Gregor Module *CompilerInstance::loadModule(SourceLocation ImportLoc,
839ff2be53fSDouglas Gregor                                      ModuleIdPath Path,
840bcfc7d02SDouglas Gregor                                      Module::NameVisibilityKind Visibility,
841bcfc7d02SDouglas Gregor                                      bool IsInclusionDirective) {
8421805b8a4SDouglas Gregor   // If we've already handled this import, just return the cached result.
8431805b8a4SDouglas Gregor   // This one-element cache is important to eliminate redundant diagnostics
8441805b8a4SDouglas Gregor   // when both the preprocessor and parser see the same import declaration.
845ff2be53fSDouglas Gregor   if (!ImportLoc.isInvalid() && LastModuleImportLoc == ImportLoc) {
846ff2be53fSDouglas Gregor     // Make the named module visible.
847ff2be53fSDouglas Gregor     if (LastModuleImportResult)
848ff2be53fSDouglas Gregor       ModuleManager->makeModuleVisible(LastModuleImportResult, Visibility);
84969021974SDouglas Gregor     return LastModuleImportResult;
850ff2be53fSDouglas Gregor   }
8511805b8a4SDouglas Gregor 
85208142534SDouglas Gregor   // Determine what file we're searching from.
85308142534SDouglas Gregor   SourceManager &SourceMgr = getSourceManager();
85408142534SDouglas Gregor   SourceLocation ExpandedImportLoc = SourceMgr.getExpansionLoc(ImportLoc);
85508142534SDouglas Gregor   const FileEntry *CurFile
85608142534SDouglas Gregor     = SourceMgr.getFileEntryForID(SourceMgr.getFileID(ExpandedImportLoc));
85708142534SDouglas Gregor   if (!CurFile)
85808142534SDouglas Gregor     CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
85908142534SDouglas Gregor 
86071944203SDouglas Gregor   StringRef ModuleName = Path[0].first->getName();
86171944203SDouglas Gregor   SourceLocation ModuleNameLoc = Path[0].second;
86271944203SDouglas Gregor 
863de3ef502SDouglas Gregor   clang::Module *Module = 0;
8645196bc6bSDouglas Gregor 
8655196bc6bSDouglas Gregor   // If we don't already have information on this module, load the module now.
866de3ef502SDouglas Gregor   llvm::DenseMap<const IdentifierInfo *, clang::Module *>::iterator Known
86769021974SDouglas Gregor     = KnownModules.find(Path[0].first);
8682537a364SDouglas Gregor   if (Known != KnownModules.end()) {
8692537a364SDouglas Gregor     // Retrieve the cached top-level module.
8702537a364SDouglas Gregor     Module = Known->second;
8712537a364SDouglas Gregor   } else if (ModuleName == getLangOpts().CurrentModule) {
8722537a364SDouglas Gregor     // This is the module we're building.
8732537a364SDouglas Gregor     Module = PP->getHeaderSearchInfo().getModuleMap().findModule(ModuleName);
8742537a364SDouglas Gregor     Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
8752537a364SDouglas Gregor   } else {
8765196bc6bSDouglas Gregor     // Search for a module with the given name.
877279a6c37SDouglas Gregor     Module = PP->getHeaderSearchInfo().lookupModule(ModuleName);
8781735f4e7SDouglas Gregor     std::string ModuleFileName;
879279a6c37SDouglas Gregor     if (Module)
880279a6c37SDouglas Gregor       ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(Module);
881279a6c37SDouglas Gregor     else
882279a6c37SDouglas Gregor       ModuleFileName = PP->getHeaderSearchInfo().getModuleFileName(ModuleName);
883faeb1d46SDouglas Gregor 
884279a6c37SDouglas Gregor     if (ModuleFileName.empty()) {
885279a6c37SDouglas Gregor       getDiagnostics().Report(ModuleNameLoc, diag::err_module_not_found)
886279a6c37SDouglas Gregor         << ModuleName
887279a6c37SDouglas Gregor         << SourceRange(ImportLoc, ModuleNameLoc);
888279a6c37SDouglas Gregor       LastModuleImportLoc = ImportLoc;
889279a6c37SDouglas Gregor       LastModuleImportResult = 0;
890279a6c37SDouglas Gregor       return 0;
891279a6c37SDouglas Gregor     }
892279a6c37SDouglas Gregor 
893279a6c37SDouglas Gregor     const FileEntry *ModuleFile
894279a6c37SDouglas Gregor       = getFileManager().getFile(ModuleFileName, /*OpenFile=*/false,
895279a6c37SDouglas Gregor                                  /*CacheFailure=*/false);
896faeb1d46SDouglas Gregor     bool BuildingModule = false;
8976dc57927SDouglas Gregor     if (!ModuleFile && Module) {
8986dc57927SDouglas Gregor       // The module is not cached, but we have a module map from which we can
8996dc57927SDouglas Gregor       // build the module.
900dff0e892SDouglas Gregor 
901dff0e892SDouglas Gregor       // Check whether there is a cycle in the module graph.
902dff0e892SDouglas Gregor       SmallVectorImpl<std::string> &ModuleBuildPath
903dff0e892SDouglas Gregor         = getPreprocessorOpts().ModuleBuildPath;
904dff0e892SDouglas Gregor       SmallVectorImpl<std::string>::iterator Pos
90571944203SDouglas Gregor         = std::find(ModuleBuildPath.begin(), ModuleBuildPath.end(), ModuleName);
906dff0e892SDouglas Gregor       if (Pos != ModuleBuildPath.end()) {
9072c1dd271SDylan Noblesmith         SmallString<256> CyclePath;
908dff0e892SDouglas Gregor         for (; Pos != ModuleBuildPath.end(); ++Pos) {
909dff0e892SDouglas Gregor           CyclePath += *Pos;
910dff0e892SDouglas Gregor           CyclePath += " -> ";
911dff0e892SDouglas Gregor         }
91271944203SDouglas Gregor         CyclePath += ModuleName;
913dff0e892SDouglas Gregor 
914dff0e892SDouglas Gregor         getDiagnostics().Report(ModuleNameLoc, diag::err_module_cycle)
91571944203SDouglas Gregor           << ModuleName << CyclePath;
916dff0e892SDouglas Gregor         return 0;
917dff0e892SDouglas Gregor       }
918dff0e892SDouglas Gregor 
91944e688d4SDouglas Gregor       getDiagnostics().Report(ModuleNameLoc, diag::warn_module_build)
92071944203SDouglas Gregor         << ModuleName;
921faeb1d46SDouglas Gregor       BuildingModule = true;
9226dc57927SDouglas Gregor       compileModule(*this, Module, ModuleFileName);
923ca295457SDouglas Gregor       ModuleFile = FileMgr->getFile(ModuleFileName);
924faeb1d46SDouglas Gregor     }
925faeb1d46SDouglas Gregor 
92608142534SDouglas Gregor     if (!ModuleFile) {
927faeb1d46SDouglas Gregor       getDiagnostics().Report(ModuleNameLoc,
928faeb1d46SDouglas Gregor                               BuildingModule? diag::err_module_not_built
929faeb1d46SDouglas Gregor                                             : diag::err_module_not_found)
93071944203SDouglas Gregor         << ModuleName
93108142534SDouglas Gregor         << SourceRange(ImportLoc, ModuleNameLoc);
93208142534SDouglas Gregor       return 0;
93308142534SDouglas Gregor     }
93408142534SDouglas Gregor 
93508142534SDouglas Gregor     // If we don't already have an ASTReader, create one now.
93608142534SDouglas Gregor     if (!ModuleManager) {
93721931efcSDouglas Gregor       if (!hasASTContext())
93821931efcSDouglas Gregor         createASTContext();
93921931efcSDouglas Gregor 
94008142534SDouglas Gregor       std::string Sysroot = getHeaderSearchOpts().Sysroot;
94108142534SDouglas Gregor       const PreprocessorOptions &PPOpts = getPreprocessorOpts();
9428835e03cSDouglas Gregor       ModuleManager = new ASTReader(getPreprocessor(), *Context,
94308142534SDouglas Gregor                                     Sysroot.empty() ? "" : Sysroot.c_str(),
94408142534SDouglas Gregor                                     PPOpts.DisablePCHValidation,
94508142534SDouglas Gregor                                     PPOpts.DisableStatCache);
94621931efcSDouglas Gregor       if (hasASTConsumer()) {
94708142534SDouglas Gregor         ModuleManager->setDeserializationListener(
94808142534SDouglas Gregor           getASTConsumer().GetASTDeserializationListener());
94908142534SDouglas Gregor         getASTContext().setASTMutationListener(
95008142534SDouglas Gregor           getASTConsumer().GetASTMutationListener());
95121931efcSDouglas Gregor       }
952e2778999SDylan Noblesmith       OwningPtr<ExternalASTSource> Source;
95308142534SDouglas Gregor       Source.reset(ModuleManager);
95408142534SDouglas Gregor       getASTContext().setExternalSource(Source);
95521931efcSDouglas Gregor       if (hasSema())
95608142534SDouglas Gregor         ModuleManager->InitializeSema(getSema());
9576137d32cSDouglas Gregor       if (hasASTConsumer())
9586137d32cSDouglas Gregor         ModuleManager->StartTranslationUnit(&getASTConsumer());
95908142534SDouglas Gregor     }
96008142534SDouglas Gregor 
96108142534SDouglas Gregor     // Try to load the module we found.
96208142534SDouglas Gregor     switch (ModuleManager->ReadAST(ModuleFile->getName(),
96308142534SDouglas Gregor                                    serialization::MK_Module)) {
96408142534SDouglas Gregor     case ASTReader::Success:
96508142534SDouglas Gregor       break;
96608142534SDouglas Gregor 
96708142534SDouglas Gregor     case ASTReader::IgnorePCH:
96808142534SDouglas Gregor       // FIXME: The ASTReader will already have complained, but can we showhorn
96908142534SDouglas Gregor       // that diagnostic information into a more useful form?
97069021974SDouglas Gregor       KnownModules[Path[0].first] = 0;
97108142534SDouglas Gregor       return 0;
97208142534SDouglas Gregor 
97308142534SDouglas Gregor     case ASTReader::Failure:
97469021974SDouglas Gregor       // Already complained, but note now that we failed.
97569021974SDouglas Gregor       KnownModules[Path[0].first] = 0;
97608142534SDouglas Gregor       return 0;
97708142534SDouglas Gregor     }
97808142534SDouglas Gregor 
97969021974SDouglas Gregor     if (!Module) {
98069021974SDouglas Gregor       // If we loaded the module directly, without finding a module map first,
98169021974SDouglas Gregor       // we'll have loaded the module's information from the module itself.
98269021974SDouglas Gregor       Module = PP->getHeaderSearchInfo().getModuleMap()
98369021974SDouglas Gregor                  .findModule((Path[0].first->getName()));
9845196bc6bSDouglas Gregor     }
9855196bc6bSDouglas Gregor 
98669021974SDouglas Gregor     // Cache the result of this top-level module lookup for later.
98769021974SDouglas Gregor     Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first;
98869021974SDouglas Gregor   }
98969021974SDouglas Gregor 
99069021974SDouglas Gregor   // If we never found the module, fail.
99169021974SDouglas Gregor   if (!Module)
99269021974SDouglas Gregor     return 0;
99369021974SDouglas Gregor 
9945196bc6bSDouglas Gregor   // Verify that the rest of the module path actually corresponds to
9955196bc6bSDouglas Gregor   // a submodule.
99669021974SDouglas Gregor   if (Path.size() > 1) {
9975196bc6bSDouglas Gregor     for (unsigned I = 1, N = Path.size(); I != N; ++I) {
9985196bc6bSDouglas Gregor       StringRef Name = Path[I].first->getName();
999eb90e830SDouglas Gregor       clang::Module *Sub = Module->findSubmodule(Name);
10005196bc6bSDouglas Gregor 
1001eb90e830SDouglas Gregor       if (!Sub) {
10025196bc6bSDouglas Gregor         // Attempt to perform typo correction to find a module name that works.
10035196bc6bSDouglas Gregor         llvm::SmallVector<StringRef, 2> Best;
10045196bc6bSDouglas Gregor         unsigned BestEditDistance = (std::numeric_limits<unsigned>::max)();
10055196bc6bSDouglas Gregor 
1006eb90e830SDouglas Gregor         for (clang::Module::submodule_iterator J = Module->submodule_begin(),
1007eb90e830SDouglas Gregor                                             JEnd = Module->submodule_end();
1008eb44edadSMatt Beaumont-Gay              J != JEnd; ++J) {
1009eb90e830SDouglas Gregor           unsigned ED = Name.edit_distance((*J)->Name,
10105196bc6bSDouglas Gregor                                            /*AllowReplacements=*/true,
10115196bc6bSDouglas Gregor                                            BestEditDistance);
10125196bc6bSDouglas Gregor           if (ED <= BestEditDistance) {
1013eb90e830SDouglas Gregor             if (ED < BestEditDistance) {
10145196bc6bSDouglas Gregor               Best.clear();
1015eb90e830SDouglas Gregor               BestEditDistance = ED;
1016eb90e830SDouglas Gregor             }
1017eb90e830SDouglas Gregor 
1018eb90e830SDouglas Gregor             Best.push_back((*J)->Name);
10195196bc6bSDouglas Gregor           }
10205196bc6bSDouglas Gregor         }
10215196bc6bSDouglas Gregor 
10225196bc6bSDouglas Gregor         // If there was a clear winner, user it.
10235196bc6bSDouglas Gregor         if (Best.size() == 1) {
10245196bc6bSDouglas Gregor           getDiagnostics().Report(Path[I].second,
10255196bc6bSDouglas Gregor                                   diag::err_no_submodule_suggest)
102669021974SDouglas Gregor             << Path[I].first << Module->getFullModuleName() << Best[0]
10275196bc6bSDouglas Gregor             << SourceRange(Path[0].second, Path[I-1].second)
10285196bc6bSDouglas Gregor             << FixItHint::CreateReplacement(SourceRange(Path[I].second),
10295196bc6bSDouglas Gregor                                             Best[0]);
1030eb90e830SDouglas Gregor 
1031eb90e830SDouglas Gregor           Sub = Module->findSubmodule(Best[0]);
10325196bc6bSDouglas Gregor         }
10335196bc6bSDouglas Gregor       }
10345196bc6bSDouglas Gregor 
1035eb90e830SDouglas Gregor       if (!Sub) {
10365196bc6bSDouglas Gregor         // No submodule by this name. Complain, and don't look for further
10375196bc6bSDouglas Gregor         // submodules.
10385196bc6bSDouglas Gregor         getDiagnostics().Report(Path[I].second, diag::err_no_submodule)
103969021974SDouglas Gregor           << Path[I].first << Module->getFullModuleName()
10405196bc6bSDouglas Gregor           << SourceRange(Path[0].second, Path[I-1].second);
10415196bc6bSDouglas Gregor         break;
10425196bc6bSDouglas Gregor       }
10435196bc6bSDouglas Gregor 
1044eb90e830SDouglas Gregor       Module = Sub;
10455196bc6bSDouglas Gregor     }
10465196bc6bSDouglas Gregor   }
10475196bc6bSDouglas Gregor 
10482537a364SDouglas Gregor   // Make the named module visible, if it's not already part of the module
10492537a364SDouglas Gregor   // we are parsing.
105098a52db8SDouglas Gregor   if (ModuleName != getLangOpts().CurrentModule) {
105198a52db8SDouglas Gregor     if (!Module->IsFromModuleFile) {
105298a52db8SDouglas Gregor       // We have an umbrella header or directory that doesn't actually include
105398a52db8SDouglas Gregor       // all of the headers within the directory it covers. Complain about
105498a52db8SDouglas Gregor       // this missing submodule and recover by forgetting that we ever saw
105598a52db8SDouglas Gregor       // this submodule.
105698a52db8SDouglas Gregor       // FIXME: Should we detect this at module load time? It seems fairly
105798a52db8SDouglas Gregor       // expensive (and rare).
105898a52db8SDouglas Gregor       getDiagnostics().Report(ImportLoc, diag::warn_missing_submodule)
105998a52db8SDouglas Gregor         << Module->getFullModuleName()
106098a52db8SDouglas Gregor         << SourceRange(Path.front().second, Path.back().second);
106198a52db8SDouglas Gregor 
106298a52db8SDouglas Gregor       return 0;
106398a52db8SDouglas Gregor     }
10641fb5c3a6SDouglas Gregor 
10651fb5c3a6SDouglas Gregor     // Check whether this module is available.
10661fb5c3a6SDouglas Gregor     StringRef Feature;
106789929282SDouglas Gregor     if (!Module->isAvailable(getLangOpts(), getTarget(), Feature)) {
10681fb5c3a6SDouglas Gregor       getDiagnostics().Report(ImportLoc, diag::err_module_unavailable)
10691fb5c3a6SDouglas Gregor         << Module->getFullModuleName()
10701fb5c3a6SDouglas Gregor         << Feature
10711fb5c3a6SDouglas Gregor         << SourceRange(Path.front().second, Path.back().second);
10721fb5c3a6SDouglas Gregor       LastModuleImportLoc = ImportLoc;
10731fb5c3a6SDouglas Gregor       LastModuleImportResult = 0;
10741fb5c3a6SDouglas Gregor       return 0;
10751fb5c3a6SDouglas Gregor     }
10761fb5c3a6SDouglas Gregor 
1077ff2be53fSDouglas Gregor     ModuleManager->makeModuleVisible(Module, Visibility);
107898a52db8SDouglas Gregor   }
10795196bc6bSDouglas Gregor 
1080bcfc7d02SDouglas Gregor   // If this module import was due to an inclusion directive, create an
1081bcfc7d02SDouglas Gregor   // implicit import declaration to capture it in the AST.
1082bcfc7d02SDouglas Gregor   if (IsInclusionDirective && hasASTContext()) {
1083bcfc7d02SDouglas Gregor     TranslationUnitDecl *TU = getASTContext().getTranslationUnitDecl();
1084bcfc7d02SDouglas Gregor     TU->addDecl(ImportDecl::CreateImplicit(getASTContext(), TU,
1085bcfc7d02SDouglas Gregor                                            ImportLoc, Module,
1086bcfc7d02SDouglas Gregor                                            Path.back().second));
1087bcfc7d02SDouglas Gregor   }
1088bcfc7d02SDouglas Gregor 
10891805b8a4SDouglas Gregor   LastModuleImportLoc = ImportLoc;
109069021974SDouglas Gregor   LastModuleImportResult = Module;
109169021974SDouglas Gregor   return Module;
109208142534SDouglas Gregor }
1093