xref: /llvm-project/clang/lib/Frontend/CompilerInstance.cpp (revision faeb1d46586271ab1b8a0158cbd5073ef0c6abca)
1 //===--- CompilerInstance.cpp ---------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "clang/Frontend/CompilerInstance.h"
11 #include "clang/Sema/Sema.h"
12 #include "clang/AST/ASTConsumer.h"
13 #include "clang/AST/ASTContext.h"
14 #include "clang/Basic/Diagnostic.h"
15 #include "clang/Basic/FileManager.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Basic/Version.h"
19 #include "clang/Lex/HeaderSearch.h"
20 #include "clang/Lex/Preprocessor.h"
21 #include "clang/Lex/PTHManager.h"
22 #include "clang/Frontend/ChainedDiagnosticClient.h"
23 #include "clang/Frontend/FrontendAction.h"
24 #include "clang/Frontend/FrontendActions.h"
25 #include "clang/Frontend/FrontendDiagnostic.h"
26 #include "clang/Frontend/LogDiagnosticPrinter.h"
27 #include "clang/Frontend/TextDiagnosticPrinter.h"
28 #include "clang/Frontend/VerifyDiagnosticsClient.h"
29 #include "clang/Frontend/Utils.h"
30 #include "clang/Serialization/ASTReader.h"
31 #include "clang/Sema/CodeCompleteConsumer.h"
32 #include "llvm/Support/FileSystem.h"
33 #include "llvm/Support/MemoryBuffer.h"
34 #include "llvm/Support/raw_ostream.h"
35 #include "llvm/ADT/Statistic.h"
36 #include "llvm/Support/Timer.h"
37 #include "llvm/Support/Host.h"
38 #include "llvm/Support/Path.h"
39 #include "llvm/Support/Program.h"
40 #include "llvm/Support/Signals.h"
41 #include "llvm/Support/system_error.h"
42 #include "llvm/Config/config.h"
43 using namespace clang;
44 
45 CompilerInstance::CompilerInstance()
46   : Invocation(new CompilerInvocation()), ModuleManager(0) {
47 }
48 
49 CompilerInstance::~CompilerInstance() {
50 }
51 
52 void CompilerInstance::setInvocation(CompilerInvocation *Value) {
53   Invocation = Value;
54 }
55 
56 void CompilerInstance::setDiagnostics(Diagnostic *Value) {
57   Diagnostics = Value;
58 }
59 
60 void CompilerInstance::setTarget(TargetInfo *Value) {
61   Target = Value;
62 }
63 
64 void CompilerInstance::setFileManager(FileManager *Value) {
65   FileMgr = Value;
66 }
67 
68 void CompilerInstance::setSourceManager(SourceManager *Value) {
69   SourceMgr = Value;
70 }
71 
72 void CompilerInstance::setPreprocessor(Preprocessor *Value) { PP = Value; }
73 
74 void CompilerInstance::setASTContext(ASTContext *Value) { Context = Value; }
75 
76 void CompilerInstance::setSema(Sema *S) {
77   TheSema.reset(S);
78 }
79 
80 void CompilerInstance::setASTConsumer(ASTConsumer *Value) {
81   Consumer.reset(Value);
82 }
83 
84 void CompilerInstance::setCodeCompletionConsumer(CodeCompleteConsumer *Value) {
85   CompletionConsumer.reset(Value);
86 }
87 
88 // Diagnostics
89 static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
90                               unsigned argc, const char* const *argv,
91                               Diagnostic &Diags) {
92   std::string ErrorInfo;
93   llvm::OwningPtr<raw_ostream> OS(
94     new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo));
95   if (!ErrorInfo.empty()) {
96     Diags.Report(diag::err_fe_unable_to_open_logfile)
97                  << DiagOpts.DumpBuildInformation << ErrorInfo;
98     return;
99   }
100 
101   (*OS) << "clang -cc1 command line arguments: ";
102   for (unsigned i = 0; i != argc; ++i)
103     (*OS) << argv[i] << ' ';
104   (*OS) << '\n';
105 
106   // Chain in a diagnostic client which will log the diagnostics.
107   DiagnosticClient *Logger =
108     new TextDiagnosticPrinter(*OS.take(), DiagOpts, /*OwnsOutputStream=*/true);
109   Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger));
110 }
111 
112 static void SetUpDiagnosticLog(const DiagnosticOptions &DiagOpts,
113                                const CodeGenOptions *CodeGenOpts,
114                                Diagnostic &Diags) {
115   std::string ErrorInfo;
116   bool OwnsStream = false;
117   raw_ostream *OS = &llvm::errs();
118   if (DiagOpts.DiagnosticLogFile != "-") {
119     // Create the output stream.
120     llvm::raw_fd_ostream *FileOS(
121       new llvm::raw_fd_ostream(DiagOpts.DiagnosticLogFile.c_str(),
122                                ErrorInfo, llvm::raw_fd_ostream::F_Append));
123     if (!ErrorInfo.empty()) {
124       Diags.Report(diag::warn_fe_cc_log_diagnostics_failure)
125         << DiagOpts.DumpBuildInformation << ErrorInfo;
126     } else {
127       FileOS->SetUnbuffered();
128       FileOS->SetUseAtomicWrites(true);
129       OS = FileOS;
130       OwnsStream = true;
131     }
132   }
133 
134   // Chain in the diagnostic client which will log the diagnostics.
135   LogDiagnosticPrinter *Logger = new LogDiagnosticPrinter(*OS, DiagOpts,
136                                                           OwnsStream);
137   if (CodeGenOpts)
138     Logger->setDwarfDebugFlags(CodeGenOpts->DwarfDebugFlags);
139   Diags.setClient(new ChainedDiagnosticClient(Diags.takeClient(), Logger));
140 }
141 
142 void CompilerInstance::createDiagnostics(int Argc, const char* const *Argv,
143                                          DiagnosticClient *Client) {
144   Diagnostics = createDiagnostics(getDiagnosticOpts(), Argc, Argv, Client,
145                                   &getCodeGenOpts());
146 }
147 
148 llvm::IntrusiveRefCntPtr<Diagnostic>
149 CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
150                                     int Argc, const char* const *Argv,
151                                     DiagnosticClient *Client,
152                                     const CodeGenOptions *CodeGenOpts) {
153   llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
154   llvm::IntrusiveRefCntPtr<Diagnostic> Diags(new Diagnostic(DiagID));
155 
156   // Create the diagnostic client for reporting errors or for
157   // implementing -verify.
158   if (Client)
159     Diags->setClient(Client);
160   else
161     Diags->setClient(new TextDiagnosticPrinter(llvm::errs(), Opts));
162 
163   // Chain in -verify checker, if requested.
164   if (Opts.VerifyDiagnostics)
165     Diags->setClient(new VerifyDiagnosticsClient(*Diags, Diags->takeClient()));
166 
167   // Chain in -diagnostic-log-file dumper, if requested.
168   if (!Opts.DiagnosticLogFile.empty())
169     SetUpDiagnosticLog(Opts, CodeGenOpts, *Diags);
170 
171   if (!Opts.DumpBuildInformation.empty())
172     SetUpBuildDumpLog(Opts, Argc, Argv, *Diags);
173 
174   // Configure our handling of diagnostics.
175   ProcessWarningOptions(*Diags, Opts);
176 
177   return Diags;
178 }
179 
180 // File Manager
181 
182 void CompilerInstance::createFileManager() {
183   FileMgr = new FileManager(getFileSystemOpts());
184 }
185 
186 // Source Manager
187 
188 void CompilerInstance::createSourceManager(FileManager &FileMgr) {
189   SourceMgr = new SourceManager(getDiagnostics(), FileMgr);
190 }
191 
192 // Preprocessor
193 
194 void CompilerInstance::createPreprocessor() {
195   const PreprocessorOptions &PPOpts = getPreprocessorOpts();
196 
197   // Create a PTH manager if we are using some form of a token cache.
198   PTHManager *PTHMgr = 0;
199   if (!PPOpts.TokenCache.empty())
200     PTHMgr = PTHManager::Create(PPOpts.TokenCache, getDiagnostics());
201 
202   // Create the Preprocessor.
203   HeaderSearch *HeaderInfo = new HeaderSearch(getFileManager());
204   PP = new Preprocessor(getDiagnostics(), getLangOpts(), &getTarget(),
205                         getSourceManager(), *HeaderInfo, *this, PTHMgr,
206                         /*OwnsHeaderSearch=*/true);
207 
208   // Note that this is different then passing PTHMgr to Preprocessor's ctor.
209   // That argument is used as the IdentifierInfoLookup argument to
210   // IdentifierTable's ctor.
211   if (PTHMgr) {
212     PTHMgr->setPreprocessor(&*PP);
213     PP->setPTHManager(PTHMgr);
214   }
215 
216   if (PPOpts.DetailedRecord)
217     PP->createPreprocessingRecord(
218                                   PPOpts.DetailedRecordIncludesNestedMacroExpansions);
219 
220   InitializePreprocessor(*PP, PPOpts, getHeaderSearchOpts(), getFrontendOpts());
221 
222   // Handle generating dependencies, if requested.
223   const DependencyOutputOptions &DepOpts = getDependencyOutputOpts();
224   if (!DepOpts.OutputFile.empty())
225     AttachDependencyFileGen(*PP, DepOpts);
226 
227   // Handle generating header include information, if requested.
228   if (DepOpts.ShowHeaderIncludes)
229     AttachHeaderIncludeGen(*PP);
230   if (!DepOpts.HeaderIncludeOutputFile.empty()) {
231     StringRef OutputPath = DepOpts.HeaderIncludeOutputFile;
232     if (OutputPath == "-")
233       OutputPath = "";
234     AttachHeaderIncludeGen(*PP, /*ShowAllHeaders=*/true, OutputPath,
235                            /*ShowDepth=*/false);
236   }
237 }
238 
239 // ASTContext
240 
241 void CompilerInstance::createASTContext() {
242   Preprocessor &PP = getPreprocessor();
243   Context = new ASTContext(getLangOpts(), PP.getSourceManager(),
244                            &getTarget(), PP.getIdentifierTable(),
245                            PP.getSelectorTable(), PP.getBuiltinInfo(),
246                            /*size_reserve=*/ 0);
247 }
248 
249 // ExternalASTSource
250 
251 void CompilerInstance::createPCHExternalASTSource(StringRef Path,
252                                                   bool DisablePCHValidation,
253                                                   bool DisableStatCache,
254                                                  void *DeserializationListener){
255   llvm::OwningPtr<ExternalASTSource> Source;
256   bool Preamble = getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
257   Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
258                                           DisablePCHValidation,
259                                           DisableStatCache,
260                                           getPreprocessor(), getASTContext(),
261                                           DeserializationListener,
262                                           Preamble));
263   ModuleManager = static_cast<ASTReader*>(Source.get());
264   getASTContext().setExternalSource(Source);
265 }
266 
267 ExternalASTSource *
268 CompilerInstance::createPCHExternalASTSource(StringRef Path,
269                                              const std::string &Sysroot,
270                                              bool DisablePCHValidation,
271                                              bool DisableStatCache,
272                                              Preprocessor &PP,
273                                              ASTContext &Context,
274                                              void *DeserializationListener,
275                                              bool Preamble) {
276   llvm::OwningPtr<ASTReader> Reader;
277   Reader.reset(new ASTReader(PP, Context,
278                              Sysroot.empty() ? "" : Sysroot.c_str(),
279                              DisablePCHValidation, DisableStatCache));
280 
281   Reader->setDeserializationListener(
282             static_cast<ASTDeserializationListener *>(DeserializationListener));
283   switch (Reader->ReadAST(Path,
284                           Preamble ? serialization::MK_Preamble
285                                    : serialization::MK_PCH)) {
286   case ASTReader::Success:
287     // Set the predefines buffer as suggested by the PCH reader. Typically, the
288     // predefines buffer will be empty.
289     PP.setPredefines(Reader->getSuggestedPredefines());
290     return Reader.take();
291 
292   case ASTReader::Failure:
293     // Unrecoverable failure: don't even try to process the input file.
294     break;
295 
296   case ASTReader::IgnorePCH:
297     // No suitable PCH file could be found. Return an error.
298     break;
299   }
300 
301   return 0;
302 }
303 
304 // Code Completion
305 
306 static bool EnableCodeCompletion(Preprocessor &PP,
307                                  const std::string &Filename,
308                                  unsigned Line,
309                                  unsigned Column) {
310   // Tell the source manager to chop off the given file at a specific
311   // line and column.
312   const FileEntry *Entry = PP.getFileManager().getFile(Filename);
313   if (!Entry) {
314     PP.getDiagnostics().Report(diag::err_fe_invalid_code_complete_file)
315       << Filename;
316     return true;
317   }
318 
319   // Truncate the named file at the given line/column.
320   PP.SetCodeCompletionPoint(Entry, Line, Column);
321   return false;
322 }
323 
324 void CompilerInstance::createCodeCompletionConsumer() {
325   const ParsedSourceLocation &Loc = getFrontendOpts().CodeCompletionAt;
326   if (!CompletionConsumer) {
327     CompletionConsumer.reset(
328       createCodeCompletionConsumer(getPreprocessor(),
329                                    Loc.FileName, Loc.Line, Loc.Column,
330                                    getFrontendOpts().ShowMacrosInCodeCompletion,
331                              getFrontendOpts().ShowCodePatternsInCodeCompletion,
332                            getFrontendOpts().ShowGlobalSymbolsInCodeCompletion,
333                                    llvm::outs()));
334     if (!CompletionConsumer)
335       return;
336   } else if (EnableCodeCompletion(getPreprocessor(), Loc.FileName,
337                                   Loc.Line, Loc.Column)) {
338     CompletionConsumer.reset();
339     return;
340   }
341 
342   if (CompletionConsumer->isOutputBinary() &&
343       llvm::sys::Program::ChangeStdoutToBinary()) {
344     getPreprocessor().getDiagnostics().Report(diag::err_fe_stdout_binary);
345     CompletionConsumer.reset();
346   }
347 }
348 
349 void CompilerInstance::createFrontendTimer() {
350   FrontendTimer.reset(new llvm::Timer("Clang front-end timer"));
351 }
352 
353 CodeCompleteConsumer *
354 CompilerInstance::createCodeCompletionConsumer(Preprocessor &PP,
355                                                const std::string &Filename,
356                                                unsigned Line,
357                                                unsigned Column,
358                                                bool ShowMacros,
359                                                bool ShowCodePatterns,
360                                                bool ShowGlobals,
361                                                raw_ostream &OS) {
362   if (EnableCodeCompletion(PP, Filename, Line, Column))
363     return 0;
364 
365   // Set up the creation routine for code-completion.
366   return new PrintingCodeCompleteConsumer(ShowMacros, ShowCodePatterns,
367                                           ShowGlobals, OS);
368 }
369 
370 void CompilerInstance::createSema(TranslationUnitKind TUKind,
371                                   CodeCompleteConsumer *CompletionConsumer) {
372   TheSema.reset(new Sema(getPreprocessor(), getASTContext(), getASTConsumer(),
373                          TUKind, CompletionConsumer));
374 }
375 
376 // Output Files
377 
378 void CompilerInstance::addOutputFile(const OutputFile &OutFile) {
379   assert(OutFile.OS && "Attempt to add empty stream to output list!");
380   OutputFiles.push_back(OutFile);
381 }
382 
383 void CompilerInstance::clearOutputFiles(bool EraseFiles) {
384   for (std::list<OutputFile>::iterator
385          it = OutputFiles.begin(), ie = OutputFiles.end(); it != ie; ++it) {
386     delete it->OS;
387     if (!it->TempFilename.empty()) {
388       if (EraseFiles) {
389         bool existed;
390         llvm::sys::fs::remove(it->TempFilename, existed);
391       } else {
392         llvm::SmallString<128> NewOutFile(it->Filename);
393 
394         // If '-working-directory' was passed, the output filename should be
395         // relative to that.
396         FileMgr->FixupRelativePath(NewOutFile);
397         if (llvm::error_code ec = llvm::sys::fs::rename(it->TempFilename,
398                                                         NewOutFile.str())) {
399           getDiagnostics().Report(diag::err_fe_unable_to_rename_temp)
400             << it->TempFilename << it->Filename << ec.message();
401 
402           bool existed;
403           llvm::sys::fs::remove(it->TempFilename, existed);
404         }
405       }
406     } else if (!it->Filename.empty() && EraseFiles)
407       llvm::sys::Path(it->Filename).eraseFromDisk();
408 
409   }
410   OutputFiles.clear();
411 }
412 
413 llvm::raw_fd_ostream *
414 CompilerInstance::createDefaultOutputFile(bool Binary,
415                                           StringRef InFile,
416                                           StringRef Extension) {
417   return createOutputFile(getFrontendOpts().OutputFile, Binary,
418                           /*RemoveFileOnSignal=*/true, InFile, Extension);
419 }
420 
421 llvm::raw_fd_ostream *
422 CompilerInstance::createOutputFile(StringRef OutputPath,
423                                    bool Binary, bool RemoveFileOnSignal,
424                                    StringRef InFile,
425                                    StringRef Extension,
426                                    bool UseTemporary) {
427   std::string Error, OutputPathName, TempPathName;
428   llvm::raw_fd_ostream *OS = createOutputFile(OutputPath, Error, Binary,
429                                               RemoveFileOnSignal,
430                                               InFile, Extension,
431                                               UseTemporary,
432                                               &OutputPathName,
433                                               &TempPathName);
434   if (!OS) {
435     getDiagnostics().Report(diag::err_fe_unable_to_open_output)
436       << OutputPath << Error;
437     return 0;
438   }
439 
440   // Add the output file -- but don't try to remove "-", since this means we are
441   // using stdin.
442   addOutputFile(OutputFile((OutputPathName != "-") ? OutputPathName : "",
443                 TempPathName, OS));
444 
445   return OS;
446 }
447 
448 llvm::raw_fd_ostream *
449 CompilerInstance::createOutputFile(StringRef OutputPath,
450                                    std::string &Error,
451                                    bool Binary,
452                                    bool RemoveFileOnSignal,
453                                    StringRef InFile,
454                                    StringRef Extension,
455                                    bool UseTemporary,
456                                    std::string *ResultPathName,
457                                    std::string *TempPathName) {
458   std::string OutFile, TempFile;
459   if (!OutputPath.empty()) {
460     OutFile = OutputPath;
461   } else if (InFile == "-") {
462     OutFile = "-";
463   } else if (!Extension.empty()) {
464     llvm::sys::Path Path(InFile);
465     Path.eraseSuffix();
466     Path.appendSuffix(Extension);
467     OutFile = Path.str();
468   } else {
469     OutFile = "-";
470   }
471 
472   llvm::OwningPtr<llvm::raw_fd_ostream> OS;
473   std::string OSFile;
474 
475   if (UseTemporary && OutFile != "-") {
476     llvm::sys::Path OutPath(OutFile);
477     // Only create the temporary if we can actually write to OutPath, otherwise
478     // we want to fail early.
479     bool Exists;
480     if ((llvm::sys::fs::exists(OutPath.str(), Exists) || !Exists) ||
481         (OutPath.isRegularFile() && OutPath.canWrite())) {
482       // Create a temporary file.
483       llvm::SmallString<128> TempPath;
484       TempPath = OutFile;
485       TempPath += "-%%%%%%%%";
486       int fd;
487       if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath,
488                                /*makeAbsolute=*/false) == llvm::errc::success) {
489         OS.reset(new llvm::raw_fd_ostream(fd, /*shouldClose=*/true));
490         OSFile = TempFile = TempPath.str();
491       }
492     }
493   }
494 
495   if (!OS) {
496     OSFile = OutFile;
497     OS.reset(
498       new llvm::raw_fd_ostream(OSFile.c_str(), Error,
499                                (Binary ? llvm::raw_fd_ostream::F_Binary : 0)));
500     if (!Error.empty())
501       return 0;
502   }
503 
504   // Make sure the out stream file gets removed if we crash.
505   if (RemoveFileOnSignal)
506     llvm::sys::RemoveFileOnSignal(llvm::sys::Path(OSFile));
507 
508   if (ResultPathName)
509     *ResultPathName = OutFile;
510   if (TempPathName)
511     *TempPathName = TempFile;
512 
513   return OS.take();
514 }
515 
516 // Initialization Utilities
517 
518 bool CompilerInstance::InitializeSourceManager(StringRef InputFile) {
519   return InitializeSourceManager(InputFile, getDiagnostics(), getFileManager(),
520                                  getSourceManager(), getFrontendOpts());
521 }
522 
523 bool CompilerInstance::InitializeSourceManager(StringRef InputFile,
524                                                Diagnostic &Diags,
525                                                FileManager &FileMgr,
526                                                SourceManager &SourceMgr,
527                                                const FrontendOptions &Opts) {
528   // Figure out where to get and map in the main file, unless it's already
529   // been created (e.g., by a precompiled preamble).
530   if (!SourceMgr.getMainFileID().isInvalid()) {
531     // Do nothing: the main file has already been set.
532   } else if (InputFile != "-") {
533     const FileEntry *File = FileMgr.getFile(InputFile);
534     if (!File) {
535       Diags.Report(diag::err_fe_error_reading) << InputFile;
536       return false;
537     }
538     SourceMgr.createMainFileID(File);
539   } else {
540     llvm::OwningPtr<llvm::MemoryBuffer> SB;
541     if (llvm::MemoryBuffer::getSTDIN(SB)) {
542       // FIXME: Give ec.message() in this diag.
543       Diags.Report(diag::err_fe_error_reading_stdin);
544       return false;
545     }
546     const FileEntry *File = FileMgr.getVirtualFile(SB->getBufferIdentifier(),
547                                                    SB->getBufferSize(), 0);
548     SourceMgr.createMainFileID(File);
549     SourceMgr.overrideFileContents(File, SB.take());
550   }
551 
552   assert(!SourceMgr.getMainFileID().isInvalid() &&
553          "Couldn't establish MainFileID!");
554   return true;
555 }
556 
557 // High-Level Operations
558 
559 bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
560   assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
561   assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
562   assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
563 
564   // FIXME: Take this as an argument, once all the APIs we used have moved to
565   // taking it as an input instead of hard-coding llvm::errs.
566   raw_ostream &OS = llvm::errs();
567 
568   // Create the target instance.
569   setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
570   if (!hasTarget())
571     return false;
572 
573   // Inform the target of the language options.
574   //
575   // FIXME: We shouldn't need to do this, the target should be immutable once
576   // created. This complexity should be lifted elsewhere.
577   getTarget().setForcedLangOptions(getLangOpts());
578 
579   // Validate/process some options.
580   if (getHeaderSearchOpts().Verbose)
581     OS << "clang -cc1 version " CLANG_VERSION_STRING
582        << " based upon " << PACKAGE_STRING
583        << " hosted on " << llvm::sys::getHostTriple() << "\n";
584 
585   if (getFrontendOpts().ShowTimers)
586     createFrontendTimer();
587 
588   if (getFrontendOpts().ShowStats)
589     llvm::EnableStatistics();
590 
591   for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
592     const std::string &InFile = getFrontendOpts().Inputs[i].second;
593 
594     // Reset the ID tables if we are reusing the SourceManager.
595     if (hasSourceManager())
596       getSourceManager().clearIDTables();
597 
598     if (Act.BeginSourceFile(*this, InFile, getFrontendOpts().Inputs[i].first)) {
599       Act.Execute();
600       Act.EndSourceFile();
601     }
602   }
603 
604   if (getDiagnosticOpts().ShowCarets) {
605     // We can have multiple diagnostics sharing one diagnostic client.
606     // Get the total number of warnings/errors from the client.
607     unsigned NumWarnings = getDiagnostics().getClient()->getNumWarnings();
608     unsigned NumErrors = getDiagnostics().getClient()->getNumErrors();
609 
610     if (NumWarnings)
611       OS << NumWarnings << " warning" << (NumWarnings == 1 ? "" : "s");
612     if (NumWarnings && NumErrors)
613       OS << " and ";
614     if (NumErrors)
615       OS << NumErrors << " error" << (NumErrors == 1 ? "" : "s");
616     if (NumWarnings || NumErrors)
617       OS << " generated.\n";
618   }
619 
620   if (getFrontendOpts().ShowStats && hasFileManager()) {
621     getFileManager().PrintStats();
622     OS << "\n";
623   }
624 
625   return !getDiagnostics().getClient()->getNumErrors();
626 }
627 
628 /// \brief Determine the appropriate source input kind based on language
629 /// options.
630 static InputKind getSourceInputKindFromOptions(const LangOptions &LangOpts) {
631   if (LangOpts.OpenCL)
632     return IK_OpenCL;
633   if (LangOpts.CUDA)
634     return IK_CUDA;
635   if (LangOpts.ObjC1)
636     return LangOpts.CPlusPlus? IK_ObjCXX : IK_ObjC;
637   return LangOpts.CPlusPlus? IK_CXX : IK_C;
638 }
639 
640 /// \brief Compile a module file for the given module name with the given
641 /// umbrella header, using the options provided by the importing compiler
642 /// instance.
643 static void compileModule(CompilerInstance &ImportingInstance,
644                           StringRef ModuleName,
645                           StringRef UmbrellaHeader) {
646   // Determine the file that we'll be writing to.
647   llvm::SmallString<128> ModuleFile;
648   ModuleFile +=
649     ImportingInstance.getInvocation().getHeaderSearchOpts().ModuleCachePath;
650   llvm::sys::path::append(ModuleFile, ModuleName + ".pcm");
651 
652   // Construct a compiler invocation for creating this module.
653   llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation
654     (new CompilerInvocation(ImportingInstance.getInvocation()));
655   FrontendOptions &FrontendOpts = Invocation->getFrontendOpts();
656   FrontendOpts.OutputFile = ModuleFile.str();
657   FrontendOpts.DisableFree = false;
658   FrontendOpts.Inputs.clear();
659   FrontendOpts.Inputs.push_back(
660     std::make_pair(getSourceInputKindFromOptions(Invocation->getLangOpts()),
661                                                  UmbrellaHeader));
662   // FIXME: Strip away all of the compilation options that won't be transferred
663   // down to the module. This presumably includes -D flags, optimization
664   // settings, etc.
665 
666   // Construct a compiler instance that will be used to actually create the
667   // module.
668   CompilerInstance Instance;
669   Instance.setInvocation(&*Invocation);
670   //  Instance.setDiagnostics(&ImportingInstance.getDiagnostics());
671   // FIXME: Need to route diagnostics over to the same diagnostic client!
672   Instance.createDiagnostics(0, 0, 0);
673 
674   // Construct a module-generating action.
675   GeneratePCHAction CreateModuleAction(true);
676 
677   // Execute the action to actually build the module in-place.
678   // FIXME: Need to synchronize when multiple processes do this.
679   Instance.ExecuteAction(CreateModuleAction);
680 
681   // Tell the importing instance's file manager to forget about the module
682   // file, since we've just created it.
683   ImportingInstance.getFileManager().forgetFile(ModuleFile);
684 }
685 
686 ModuleKey CompilerInstance::loadModule(SourceLocation ImportLoc,
687                                        IdentifierInfo &ModuleName,
688                                        SourceLocation ModuleNameLoc) {
689   // Determine what file we're searching from.
690   SourceManager &SourceMgr = getSourceManager();
691   SourceLocation ExpandedImportLoc = SourceMgr.getExpansionLoc(ImportLoc);
692   const FileEntry *CurFile
693     = SourceMgr.getFileEntryForID(SourceMgr.getFileID(ExpandedImportLoc));
694   if (!CurFile)
695     CurFile = SourceMgr.getFileEntryForID(SourceMgr.getMainFileID());
696 
697   // Search for a module with the given name.
698   std::string UmbrellaHeader;
699   const FileEntry *ModuleFile
700     = PP->getHeaderSearchInfo().lookupModule(ModuleName.getName(),
701                                              &UmbrellaHeader);
702 
703   bool BuildingModule = false;
704   if (!ModuleFile && !UmbrellaHeader.empty()) {
705     // We didn't find the module, but there is an umbrella header that
706     // can be used to create the module file. Create a separate compilation
707     // module to do so.
708     BuildingModule = true;
709     compileModule(*this, ModuleName.getName(), UmbrellaHeader);
710     ModuleFile = PP->getHeaderSearchInfo().lookupModule(ModuleName.getName());
711   }
712 
713   if (!ModuleFile) {
714     getDiagnostics().Report(ModuleNameLoc,
715                             BuildingModule? diag::err_module_not_built
716                                           : diag::err_module_not_found)
717       << ModuleName.getName()
718       << SourceRange(ImportLoc, ModuleNameLoc);
719     return 0;
720   }
721 
722   // If we don't already have an ASTReader, create one now.
723   if (!ModuleManager) {
724     std::string Sysroot = getHeaderSearchOpts().Sysroot;
725     const PreprocessorOptions &PPOpts = getPreprocessorOpts();
726     ModuleManager = new ASTReader(getPreprocessor(), *Context,
727                                   Sysroot.empty() ? "" : Sysroot.c_str(),
728                                   PPOpts.DisablePCHValidation,
729                                   PPOpts.DisableStatCache);
730     ModuleManager->setDeserializationListener(
731       getASTConsumer().GetASTDeserializationListener());
732     getASTContext().setASTMutationListener(
733       getASTConsumer().GetASTMutationListener());
734     llvm::OwningPtr<ExternalASTSource> Source;
735     Source.reset(ModuleManager);
736     getASTContext().setExternalSource(Source);
737     ModuleManager->InitializeSema(getSema());
738   }
739 
740   // Try to load the module we found.
741   switch (ModuleManager->ReadAST(ModuleFile->getName(),
742                                  serialization::MK_Module)) {
743   case ASTReader::Success:
744     break;
745 
746   case ASTReader::IgnorePCH:
747     // FIXME: The ASTReader will already have complained, but can we showhorn
748     // that diagnostic information into a more useful form?
749     return 0;
750 
751   case ASTReader::Failure:
752     // Already complained.
753     return 0;
754   }
755 
756   // FIXME: The module file's FileEntry makes a poor key indeed!
757   return (ModuleKey)ModuleFile;
758 }
759 
760