FrontendActions.cpp revision 651f13cea278ec967336033dd032faef0e9fc2ec
1//===--- FrontendActions.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/FrontendActions.h"
11#include "clang/AST/ASTConsumer.h"
12#include "clang/Basic/FileManager.h"
13#include "clang/Frontend/ASTConsumers.h"
14#include "clang/Frontend/ASTUnit.h"
15#include "clang/Frontend/CompilerInstance.h"
16#include "clang/Frontend/FrontendDiagnostic.h"
17#include "clang/Frontend/Utils.h"
18#include "clang/Lex/HeaderSearch.h"
19#include "clang/Lex/Pragma.h"
20#include "clang/Lex/Preprocessor.h"
21#include "clang/Parse/Parser.h"
22#include "clang/Serialization/ASTReader.h"
23#include "clang/Serialization/ASTWriter.h"
24#include "llvm/Support/FileSystem.h"
25#include "llvm/Support/MemoryBuffer.h"
26#include "llvm/Support/raw_ostream.h"
27#include "llvm/Support/system_error.h"
28#include <memory>
29
30using namespace clang;
31
32//===----------------------------------------------------------------------===//
33// Custom Actions
34//===----------------------------------------------------------------------===//
35
36ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI,
37                                               StringRef InFile) {
38  return new ASTConsumer();
39}
40
41void InitOnlyAction::ExecuteAction() {
42}
43
44//===----------------------------------------------------------------------===//
45// AST Consumer Actions
46//===----------------------------------------------------------------------===//
47
48ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
49                                               StringRef InFile) {
50  if (raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
51    return CreateASTPrinter(OS, CI.getFrontendOpts().ASTDumpFilter);
52  return 0;
53}
54
55ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
56                                              StringRef InFile) {
57  return CreateASTDumper(CI.getFrontendOpts().ASTDumpFilter,
58                         CI.getFrontendOpts().ASTDumpLookups);
59}
60
61ASTConsumer *ASTDeclListAction::CreateASTConsumer(CompilerInstance &CI,
62                                                  StringRef InFile) {
63  return CreateASTDeclNodeLister();
64}
65
66ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
67                                              StringRef InFile) {
68  return CreateASTViewer();
69}
70
71ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
72                                                       StringRef InFile) {
73  return CreateDeclContextPrinter();
74}
75
76ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
77                                                  StringRef InFile) {
78  std::string Sysroot;
79  std::string OutputFile;
80  raw_ostream *OS = 0;
81  if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
82    return 0;
83
84  if (!CI.getFrontendOpts().RelocatablePCH)
85    Sysroot.clear();
86  return new PCHGenerator(CI.getPreprocessor(), OutputFile, 0, Sysroot, OS);
87}
88
89bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
90                                                    StringRef InFile,
91                                                    std::string &Sysroot,
92                                                    std::string &OutputFile,
93                                                    raw_ostream *&OS) {
94  Sysroot = CI.getHeaderSearchOpts().Sysroot;
95  if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
96    CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
97    return true;
98  }
99
100  // We use createOutputFile here because this is exposed via libclang, and we
101  // must disable the RemoveFileOnSignal behavior.
102  // We use a temporary to avoid race conditions.
103  OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
104                           /*RemoveFileOnSignal=*/false, InFile,
105                           /*Extension=*/"", /*useTemporary=*/true);
106  if (!OS)
107    return true;
108
109  OutputFile = CI.getFrontendOpts().OutputFile;
110  return false;
111}
112
113ASTConsumer *GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI,
114                                                     StringRef InFile) {
115  std::string Sysroot;
116  std::string OutputFile;
117  raw_ostream *OS = 0;
118  if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS))
119    return 0;
120
121  return new PCHGenerator(CI.getPreprocessor(), OutputFile, Module,
122                          Sysroot, OS);
123}
124
125static SmallVectorImpl<char> &
126operator+=(SmallVectorImpl<char> &Includes, StringRef RHS) {
127  Includes.append(RHS.begin(), RHS.end());
128  return Includes;
129}
130
131static llvm::error_code addHeaderInclude(StringRef HeaderName,
132                                         SmallVectorImpl<char> &Includes,
133                                         const LangOptions &LangOpts,
134                                         bool IsExternC) {
135  if (IsExternC && LangOpts.CPlusPlus)
136    Includes += "extern \"C\" {\n";
137  if (LangOpts.ObjC1)
138    Includes += "#import \"";
139  else
140    Includes += "#include \"";
141  // Use an absolute path for the include; there's no reason to think that
142  // a relative path will work (. might not be on our include path) or that
143  // it will find the same file.
144  if (llvm::sys::path::is_absolute(HeaderName)) {
145    Includes += HeaderName;
146  } else {
147    SmallString<256> Header = HeaderName;
148    if (llvm::error_code Err = llvm::sys::fs::make_absolute(Header))
149      return Err;
150    Includes += Header;
151  }
152  Includes += "\"\n";
153  if (IsExternC && LangOpts.CPlusPlus)
154    Includes += "}\n";
155  return llvm::error_code::success();
156}
157
158static llvm::error_code addHeaderInclude(const FileEntry *Header,
159                                         SmallVectorImpl<char> &Includes,
160                                         const LangOptions &LangOpts,
161                                         bool IsExternC) {
162  return addHeaderInclude(Header->getName(), Includes, LangOpts, IsExternC);
163}
164
165/// \brief Collect the set of header includes needed to construct the given
166/// module and update the TopHeaders file set of the module.
167///
168/// \param Module The module we're collecting includes from.
169///
170/// \param Includes Will be augmented with the set of \#includes or \#imports
171/// needed to load all of the named headers.
172static llvm::error_code
173collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr,
174                            ModuleMap &ModMap, clang::Module *Module,
175                            SmallVectorImpl<char> &Includes) {
176  // Don't collect any headers for unavailable modules.
177  if (!Module->isAvailable())
178    return llvm::error_code::success();
179
180  // Add includes for each of these headers.
181  for (unsigned I = 0, N = Module->NormalHeaders.size(); I != N; ++I) {
182    const FileEntry *Header = Module->NormalHeaders[I];
183    Module->addTopHeader(Header);
184    if (llvm::error_code Err =
185            addHeaderInclude(Header, Includes, LangOpts, Module->IsExternC))
186      return Err;
187  }
188  // Note that Module->PrivateHeaders will not be a TopHeader.
189
190  if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) {
191    Module->addTopHeader(UmbrellaHeader);
192    if (Module->Parent) {
193      // Include the umbrella header for submodules.
194      if (llvm::error_code Err = addHeaderInclude(UmbrellaHeader, Includes,
195                                                  LangOpts, Module->IsExternC))
196        return Err;
197    }
198  } else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) {
199    // Add all of the headers we find in this subdirectory.
200    llvm::error_code EC;
201    SmallString<128> DirNative;
202    llvm::sys::path::native(UmbrellaDir->getName(), DirNative);
203    for (llvm::sys::fs::recursive_directory_iterator Dir(DirNative.str(), EC),
204                                                     DirEnd;
205         Dir != DirEnd && !EC; Dir.increment(EC)) {
206      // Check whether this entry has an extension typically associated with
207      // headers.
208      if (!llvm::StringSwitch<bool>(llvm::sys::path::extension(Dir->path()))
209          .Cases(".h", ".H", ".hh", ".hpp", true)
210          .Default(false))
211        continue;
212
213      // If this header is marked 'unavailable' in this module, don't include
214      // it.
215      if (const FileEntry *Header = FileMgr.getFile(Dir->path())) {
216        if (ModMap.isHeaderInUnavailableModule(Header))
217          continue;
218        Module->addTopHeader(Header);
219      }
220
221      // Include this header as part of the umbrella directory.
222      if (llvm::error_code Err = addHeaderInclude(Dir->path(), Includes,
223                                                  LangOpts, Module->IsExternC))
224        return Err;
225    }
226
227    if (EC)
228      return EC;
229  }
230
231  // Recurse into submodules.
232  for (clang::Module::submodule_iterator Sub = Module->submodule_begin(),
233                                      SubEnd = Module->submodule_end();
234       Sub != SubEnd; ++Sub)
235    if (llvm::error_code Err = collectModuleHeaderIncludes(
236            LangOpts, FileMgr, ModMap, *Sub, Includes))
237      return Err;
238
239  return llvm::error_code::success();
240}
241
242bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI,
243                                                 StringRef Filename) {
244  // Find the module map file.
245  const FileEntry *ModuleMap = CI.getFileManager().getFile(Filename);
246  if (!ModuleMap)  {
247    CI.getDiagnostics().Report(diag::err_module_map_not_found)
248      << Filename;
249    return false;
250  }
251
252  // Parse the module map file.
253  HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
254  if (HS.loadModuleMapFile(ModuleMap, IsSystem))
255    return false;
256
257  if (CI.getLangOpts().CurrentModule.empty()) {
258    CI.getDiagnostics().Report(diag::err_missing_module_name);
259
260    // FIXME: Eventually, we could consider asking whether there was just
261    // a single module described in the module map, and use that as a
262    // default. Then it would be fairly trivial to just "compile" a module
263    // map with a single module (the common case).
264    return false;
265  }
266
267  // If we're being run from the command-line, the module build stack will not
268  // have been filled in yet, so complete it now in order to allow us to detect
269  // module cycles.
270  SourceManager &SourceMgr = CI.getSourceManager();
271  if (SourceMgr.getModuleBuildStack().empty())
272    SourceMgr.pushModuleBuildStack(CI.getLangOpts().CurrentModule,
273                                   FullSourceLoc(SourceLocation(), SourceMgr));
274
275  // Dig out the module definition.
276  Module = HS.lookupModule(CI.getLangOpts().CurrentModule,
277                           /*AllowSearch=*/false);
278  if (!Module) {
279    CI.getDiagnostics().Report(diag::err_missing_module)
280      << CI.getLangOpts().CurrentModule << Filename;
281
282    return false;
283  }
284
285  // Check whether we can build this module at all.
286  clang::Module::Requirement Requirement;
287  clang::Module::HeaderDirective MissingHeader;
288  if (!Module->isAvailable(CI.getLangOpts(), CI.getTarget(), Requirement,
289                           MissingHeader)) {
290    if (MissingHeader.FileNameLoc.isValid()) {
291      CI.getDiagnostics().Report(diag::err_module_header_missing)
292        << MissingHeader.IsUmbrella << MissingHeader.FileName;
293    } else {
294      CI.getDiagnostics().Report(diag::err_module_unavailable)
295        << Module->getFullModuleName()
296        << Requirement.second << Requirement.first;
297    }
298
299    return false;
300  }
301
302  FileManager &FileMgr = CI.getFileManager();
303
304  // Collect the set of #includes we need to build the module.
305  SmallString<256> HeaderContents;
306  llvm::error_code Err = llvm::error_code::success();
307  if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader())
308    Err = addHeaderInclude(UmbrellaHeader, HeaderContents, CI.getLangOpts(),
309                           Module->IsExternC);
310  if (!Err)
311    Err = collectModuleHeaderIncludes(
312        CI.getLangOpts(), FileMgr,
313        CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), Module,
314        HeaderContents);
315
316  if (Err) {
317    CI.getDiagnostics().Report(diag::err_module_cannot_create_includes)
318      << Module->getFullModuleName() << Err.message();
319    return false;
320  }
321
322  llvm::MemoryBuffer *InputBuffer =
323      llvm::MemoryBuffer::getMemBufferCopy(HeaderContents,
324                                           Module::getModuleInputBufferName());
325  // Ownership of InputBuffer will be transferred to the SourceManager.
326  setCurrentInput(FrontendInputFile(InputBuffer, getCurrentFileKind(),
327                                    Module->IsSystem));
328  return true;
329}
330
331bool GenerateModuleAction::ComputeASTConsumerArguments(CompilerInstance &CI,
332                                                       StringRef InFile,
333                                                       std::string &Sysroot,
334                                                       std::string &OutputFile,
335                                                       raw_ostream *&OS) {
336  // If no output file was provided, figure out where this module would go
337  // in the module cache.
338  if (CI.getFrontendOpts().OutputFile.empty()) {
339    HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo();
340    SmallString<256> ModuleFileName(HS.getModuleCachePath());
341    llvm::sys::path::append(ModuleFileName,
342                            CI.getLangOpts().CurrentModule + ".pcm");
343    CI.getFrontendOpts().OutputFile = ModuleFileName.str();
344  }
345
346  // We use createOutputFile here because this is exposed via libclang, and we
347  // must disable the RemoveFileOnSignal behavior.
348  // We use a temporary to avoid race conditions.
349  OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
350                           /*RemoveFileOnSignal=*/false, InFile,
351                           /*Extension=*/"", /*useTemporary=*/true,
352                           /*CreateMissingDirectories=*/true);
353  if (!OS)
354    return true;
355
356  OutputFile = CI.getFrontendOpts().OutputFile;
357  return false;
358}
359
360ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
361                                                 StringRef InFile) {
362  return new ASTConsumer();
363}
364
365ASTConsumer *DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,
366                                                     StringRef InFile) {
367  return new ASTConsumer();
368}
369
370ASTConsumer *VerifyPCHAction::CreateASTConsumer(CompilerInstance &CI,
371                                                StringRef InFile) {
372  return new ASTConsumer();
373}
374
375void VerifyPCHAction::ExecuteAction() {
376  CompilerInstance &CI = getCompilerInstance();
377  bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
378  const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
379  std::unique_ptr<ASTReader> Reader(
380      new ASTReader(CI.getPreprocessor(), CI.getASTContext(),
381                    Sysroot.empty() ? "" : Sysroot.c_str(),
382                    /*DisableValidation*/ false,
383                    /*AllowPCHWithCompilerErrors*/ false,
384                    /*AllowConfigurationMismatch*/ true,
385                    /*ValidateSystemInputs*/ true));
386
387  Reader->ReadAST(getCurrentFile(),
388                  Preamble ? serialization::MK_Preamble
389                           : serialization::MK_PCH,
390                  SourceLocation(),
391                  ASTReader::ARR_ConfigurationMismatch);
392}
393
394namespace {
395  /// \brief AST reader listener that dumps module information for a module
396  /// file.
397  class DumpModuleInfoListener : public ASTReaderListener {
398    llvm::raw_ostream &Out;
399
400  public:
401    DumpModuleInfoListener(llvm::raw_ostream &Out) : Out(Out) { }
402
403#define DUMP_BOOLEAN(Value, Text)                       \
404    Out.indent(4) << Text << ": " << (Value? "Yes" : "No") << "\n"
405
406    bool ReadFullVersionInformation(StringRef FullVersion) override {
407      Out.indent(2)
408        << "Generated by "
409        << (FullVersion == getClangFullRepositoryVersion()? "this"
410                                                          : "a different")
411        << " Clang: " << FullVersion << "\n";
412      return ASTReaderListener::ReadFullVersionInformation(FullVersion);
413    }
414
415    bool ReadLanguageOptions(const LangOptions &LangOpts,
416                             bool Complain) override {
417      Out.indent(2) << "Language options:\n";
418#define LANGOPT(Name, Bits, Default, Description) \
419      DUMP_BOOLEAN(LangOpts.Name, Description);
420#define ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
421      Out.indent(4) << Description << ": "                   \
422                    << static_cast<unsigned>(LangOpts.get##Name()) << "\n";
423#define VALUE_LANGOPT(Name, Bits, Default, Description) \
424      Out.indent(4) << Description << ": " << LangOpts.Name << "\n";
425#define BENIGN_LANGOPT(Name, Bits, Default, Description)
426#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
427#include "clang/Basic/LangOptions.def"
428      return false;
429    }
430
431    bool ReadTargetOptions(const TargetOptions &TargetOpts,
432                           bool Complain) override {
433      Out.indent(2) << "Target options:\n";
434      Out.indent(4) << "  Triple: " << TargetOpts.Triple << "\n";
435      Out.indent(4) << "  CPU: " << TargetOpts.CPU << "\n";
436      Out.indent(4) << "  ABI: " << TargetOpts.ABI << "\n";
437      Out.indent(4) << "  Linker version: " << TargetOpts.LinkerVersion << "\n";
438
439      if (!TargetOpts.FeaturesAsWritten.empty()) {
440        Out.indent(4) << "Target features:\n";
441        for (unsigned I = 0, N = TargetOpts.FeaturesAsWritten.size();
442             I != N; ++I) {
443          Out.indent(6) << TargetOpts.FeaturesAsWritten[I] << "\n";
444        }
445      }
446
447      return false;
448    }
449
450    bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts,
451                                 bool Complain) override {
452      Out.indent(2) << "Header search options:\n";
453      Out.indent(4) << "System root [-isysroot=]: '" << HSOpts.Sysroot << "'\n";
454      DUMP_BOOLEAN(HSOpts.UseBuiltinIncludes,
455                   "Use builtin include directories [-nobuiltininc]");
456      DUMP_BOOLEAN(HSOpts.UseStandardSystemIncludes,
457                   "Use standard system include directories [-nostdinc]");
458      DUMP_BOOLEAN(HSOpts.UseStandardCXXIncludes,
459                   "Use standard C++ include directories [-nostdinc++]");
460      DUMP_BOOLEAN(HSOpts.UseLibcxx,
461                   "Use libc++ (rather than libstdc++) [-stdlib=]");
462      return false;
463    }
464
465    bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
466                                 bool Complain,
467                                 std::string &SuggestedPredefines) override {
468      Out.indent(2) << "Preprocessor options:\n";
469      DUMP_BOOLEAN(PPOpts.UsePredefines,
470                   "Uses compiler/target-specific predefines [-undef]");
471      DUMP_BOOLEAN(PPOpts.DetailedRecord,
472                   "Uses detailed preprocessing record (for indexing)");
473
474      if (!PPOpts.Macros.empty()) {
475        Out.indent(4) << "Predefined macros:\n";
476      }
477
478      for (std::vector<std::pair<std::string, bool/*isUndef*/> >::const_iterator
479             I = PPOpts.Macros.begin(), IEnd = PPOpts.Macros.end();
480           I != IEnd; ++I) {
481        Out.indent(6);
482        if (I->second)
483          Out << "-U";
484        else
485          Out << "-D";
486        Out << I->first << "\n";
487      }
488      return false;
489    }
490#undef DUMP_BOOLEAN
491  };
492}
493
494void DumpModuleInfoAction::ExecuteAction() {
495  // Set up the output file.
496  std::unique_ptr<llvm::raw_fd_ostream> OutFile;
497  StringRef OutputFileName = getCompilerInstance().getFrontendOpts().OutputFile;
498  if (!OutputFileName.empty() && OutputFileName != "-") {
499    std::string ErrorInfo;
500    OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str().c_str(),
501                                           ErrorInfo, llvm::sys::fs::F_Text));
502  }
503  llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs();
504
505  Out << "Information for module file '" << getCurrentFile() << "':\n";
506  DumpModuleInfoListener Listener(Out);
507  ASTReader::readASTFileControlBlock(getCurrentFile(),
508                                     getCompilerInstance().getFileManager(),
509                                     Listener);
510}
511
512//===----------------------------------------------------------------------===//
513// Preprocessor Actions
514//===----------------------------------------------------------------------===//
515
516void DumpRawTokensAction::ExecuteAction() {
517  Preprocessor &PP = getCompilerInstance().getPreprocessor();
518  SourceManager &SM = PP.getSourceManager();
519
520  // Start lexing the specified input file.
521  const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
522  Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOpts());
523  RawLex.SetKeepWhitespaceMode(true);
524
525  Token RawTok;
526  RawLex.LexFromRawLexer(RawTok);
527  while (RawTok.isNot(tok::eof)) {
528    PP.DumpToken(RawTok, true);
529    llvm::errs() << "\n";
530    RawLex.LexFromRawLexer(RawTok);
531  }
532}
533
534void DumpTokensAction::ExecuteAction() {
535  Preprocessor &PP = getCompilerInstance().getPreprocessor();
536  // Start preprocessing the specified input file.
537  Token Tok;
538  PP.EnterMainSourceFile();
539  do {
540    PP.Lex(Tok);
541    PP.DumpToken(Tok, true);
542    llvm::errs() << "\n";
543  } while (Tok.isNot(tok::eof));
544}
545
546void GeneratePTHAction::ExecuteAction() {
547  CompilerInstance &CI = getCompilerInstance();
548  if (CI.getFrontendOpts().OutputFile.empty() ||
549      CI.getFrontendOpts().OutputFile == "-") {
550    // FIXME: Don't fail this way.
551    // FIXME: Verify that we can actually seek in the given file.
552    llvm::report_fatal_error("PTH requires a seekable file for output!");
553  }
554  llvm::raw_fd_ostream *OS =
555    CI.createDefaultOutputFile(true, getCurrentFile());
556  if (!OS) return;
557
558  CacheTokens(CI.getPreprocessor(), OS);
559}
560
561void PreprocessOnlyAction::ExecuteAction() {
562  Preprocessor &PP = getCompilerInstance().getPreprocessor();
563
564  // Ignore unknown pragmas.
565  PP.AddPragmaHandler(new EmptyPragmaHandler());
566
567  Token Tok;
568  // Start parsing the specified input file.
569  PP.EnterMainSourceFile();
570  do {
571    PP.Lex(Tok);
572  } while (Tok.isNot(tok::eof));
573}
574
575void PrintPreprocessedAction::ExecuteAction() {
576  CompilerInstance &CI = getCompilerInstance();
577  // Output file may need to be set to 'Binary', to avoid converting Unix style
578  // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
579  //
580  // Look to see what type of line endings the file uses. If there's a
581  // CRLF, then we won't open the file up in binary mode. If there is
582  // just an LF or CR, then we will open the file up in binary mode.
583  // In this fashion, the output format should match the input format, unless
584  // the input format has inconsistent line endings.
585  //
586  // This should be a relatively fast operation since most files won't have
587  // all of their source code on a single line. However, that is still a
588  // concern, so if we scan for too long, we'll just assume the file should
589  // be opened in binary mode.
590  bool BinaryMode = true;
591  bool InvalidFile = false;
592  const SourceManager& SM = CI.getSourceManager();
593  const llvm::MemoryBuffer *Buffer = SM.getBuffer(SM.getMainFileID(),
594                                                     &InvalidFile);
595  if (!InvalidFile) {
596    const char *cur = Buffer->getBufferStart();
597    const char *end = Buffer->getBufferEnd();
598    const char *next = (cur != end) ? cur + 1 : end;
599
600    // Limit ourselves to only scanning 256 characters into the source
601    // file.  This is mostly a sanity check in case the file has no
602    // newlines whatsoever.
603    if (end - cur > 256) end = cur + 256;
604
605    while (next < end) {
606      if (*cur == 0x0D) {  // CR
607        if (*next == 0x0A)  // CRLF
608          BinaryMode = false;
609
610        break;
611      } else if (*cur == 0x0A)  // LF
612        break;
613
614      ++cur, ++next;
615    }
616  }
617
618  raw_ostream *OS = CI.createDefaultOutputFile(BinaryMode, getCurrentFile());
619  if (!OS) return;
620
621  DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
622                           CI.getPreprocessorOutputOpts());
623}
624
625void PrintPreambleAction::ExecuteAction() {
626  switch (getCurrentFileKind()) {
627  case IK_C:
628  case IK_CXX:
629  case IK_ObjC:
630  case IK_ObjCXX:
631  case IK_OpenCL:
632  case IK_CUDA:
633    break;
634
635  case IK_None:
636  case IK_Asm:
637  case IK_PreprocessedC:
638  case IK_PreprocessedCXX:
639  case IK_PreprocessedObjC:
640  case IK_PreprocessedObjCXX:
641  case IK_AST:
642  case IK_LLVM_IR:
643    // We can't do anything with these.
644    return;
645  }
646
647  CompilerInstance &CI = getCompilerInstance();
648  llvm::MemoryBuffer *Buffer
649      = CI.getFileManager().getBufferForFile(getCurrentFile());
650  if (Buffer) {
651    unsigned Preamble = Lexer::ComputePreamble(Buffer, CI.getLangOpts()).first;
652    llvm::outs().write(Buffer->getBufferStart(), Preamble);
653    delete Buffer;
654  }
655}
656