| //===--- FrontendActions.cpp ----------------------------------------------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include "clang/Frontend/FrontendActions.h" | 
 | #include "clang/AST/ASTConsumer.h" | 
 | #include "clang/Lex/Pragma.h" | 
 | #include "clang/Lex/Preprocessor.h" | 
 | #include "clang/Parse/Parser.h" | 
 | #include "clang/Basic/FileManager.h" | 
 | #include "clang/Frontend/ASTConsumers.h" | 
 | #include "clang/Frontend/ASTUnit.h" | 
 | #include "clang/Frontend/CompilerInstance.h" | 
 | #include "clang/Frontend/FrontendDiagnostic.h" | 
 | #include "clang/Frontend/Utils.h" | 
 | #include "clang/Serialization/ASTWriter.h" | 
 | #include "llvm/ADT/OwningPtr.h" | 
 | #include "llvm/Support/MemoryBuffer.h" | 
 | #include "llvm/Support/raw_ostream.h" | 
 | using namespace clang; | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // Custom Actions | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI, | 
 |                                                llvm::StringRef InFile) { | 
 |   return new ASTConsumer(); | 
 | } | 
 |  | 
 | void InitOnlyAction::ExecuteAction() { | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // AST Consumer Actions | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, | 
 |                                                llvm::StringRef InFile) { | 
 |   if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile)) | 
 |     return CreateASTPrinter(OS); | 
 |   return 0; | 
 | } | 
 |  | 
 | ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, | 
 |                                               llvm::StringRef InFile) { | 
 |   return CreateASTDumper(); | 
 | } | 
 |  | 
 | ASTConsumer *ASTDumpXMLAction::CreateASTConsumer(CompilerInstance &CI, | 
 |                                                  llvm::StringRef InFile) { | 
 |   llvm::raw_ostream *OS; | 
 |   if (CI.getFrontendOpts().OutputFile.empty()) | 
 |     OS = &llvm::outs(); | 
 |   else | 
 |     OS = CI.createDefaultOutputFile(false, InFile); | 
 |   if (!OS) return 0; | 
 |   return CreateASTDumperXML(*OS); | 
 | } | 
 |  | 
 | ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI, | 
 |                                               llvm::StringRef InFile) { | 
 |   return CreateASTViewer(); | 
 | } | 
 |  | 
 | ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI, | 
 |                                                        llvm::StringRef InFile) { | 
 |   return CreateDeclContextPrinter(); | 
 | } | 
 |  | 
 | ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, | 
 |                                                   llvm::StringRef InFile) { | 
 |   std::string Sysroot; | 
 |   std::string OutputFile; | 
 |   llvm::raw_ostream *OS = 0; | 
 |   bool Chaining; | 
 |   if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS, Chaining)) | 
 |     return 0; | 
 |  | 
 |   const char *isysroot = CI.getFrontendOpts().RelocatablePCH ? | 
 |                              Sysroot.c_str() : 0;   | 
 |   return new PCHGenerator(CI.getPreprocessor(), OutputFile, Chaining, isysroot, OS); | 
 | } | 
 |  | 
 | bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, | 
 |                                                     llvm::StringRef InFile, | 
 |                                                     std::string &Sysroot, | 
 |                                                     std::string &OutputFile, | 
 |                                                     llvm::raw_ostream *&OS, | 
 |                                                     bool &Chaining) { | 
 |   Sysroot = CI.getHeaderSearchOpts().Sysroot; | 
 |   if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) { | 
 |     CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot); | 
 |     return true; | 
 |   } | 
 |  | 
 |   // We use createOutputFile here because this is exposed via libclang, and we | 
 |   // must disable the RemoveFileOnSignal behavior. | 
 |   OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, | 
 |                            /*RemoveFileOnSignal=*/false, InFile); | 
 |   if (!OS) | 
 |     return true; | 
 |  | 
 |   OutputFile = CI.getFrontendOpts().OutputFile; | 
 |   Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH && | 
 |              !CI.getPreprocessorOpts().ImplicitPCHInclude.empty(); | 
 |   return false; | 
 | } | 
 |  | 
 | ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, | 
 |                                                  llvm::StringRef InFile) { | 
 |   return new ASTConsumer(); | 
 | } | 
 |  | 
 | //===----------------------------------------------------------------------===// | 
 | // Preprocessor Actions | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | void DumpRawTokensAction::ExecuteAction() { | 
 |   Preprocessor &PP = getCompilerInstance().getPreprocessor(); | 
 |   SourceManager &SM = PP.getSourceManager(); | 
 |  | 
 |   // Start lexing the specified input file. | 
 |   const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); | 
 |   Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions()); | 
 |   RawLex.SetKeepWhitespaceMode(true); | 
 |  | 
 |   Token RawTok; | 
 |   RawLex.LexFromRawLexer(RawTok); | 
 |   while (RawTok.isNot(tok::eof)) { | 
 |     PP.DumpToken(RawTok, true); | 
 |     llvm::errs() << "\n"; | 
 |     RawLex.LexFromRawLexer(RawTok); | 
 |   } | 
 | } | 
 |  | 
 | void DumpTokensAction::ExecuteAction() { | 
 |   Preprocessor &PP = getCompilerInstance().getPreprocessor(); | 
 |   // Start preprocessing the specified input file. | 
 |   Token Tok; | 
 |   PP.EnterMainSourceFile(); | 
 |   do { | 
 |     PP.Lex(Tok); | 
 |     PP.DumpToken(Tok, true); | 
 |     llvm::errs() << "\n"; | 
 |   } while (Tok.isNot(tok::eof)); | 
 | } | 
 |  | 
 | void GeneratePTHAction::ExecuteAction() { | 
 |   CompilerInstance &CI = getCompilerInstance(); | 
 |   if (CI.getFrontendOpts().OutputFile.empty() || | 
 |       CI.getFrontendOpts().OutputFile == "-") { | 
 |     // FIXME: Don't fail this way. | 
 |     // FIXME: Verify that we can actually seek in the given file. | 
 |     llvm::report_fatal_error("PTH requires a seekable file for output!"); | 
 |   } | 
 |   llvm::raw_fd_ostream *OS = | 
 |     CI.createDefaultOutputFile(true, getCurrentFile()); | 
 |   if (!OS) return; | 
 |  | 
 |   CacheTokens(CI.getPreprocessor(), OS); | 
 | } | 
 |  | 
 | void PreprocessOnlyAction::ExecuteAction() { | 
 |   Preprocessor &PP = getCompilerInstance().getPreprocessor(); | 
 |  | 
 |   // Ignore unknown pragmas. | 
 |   PP.AddPragmaHandler(new EmptyPragmaHandler()); | 
 |  | 
 |   Token Tok; | 
 |   // Start parsing the specified input file. | 
 |   PP.EnterMainSourceFile(); | 
 |   do { | 
 |     PP.Lex(Tok); | 
 |   } while (Tok.isNot(tok::eof)); | 
 | } | 
 |  | 
 | void PrintPreprocessedAction::ExecuteAction() { | 
 |   CompilerInstance &CI = getCompilerInstance(); | 
 |   // Output file needs to be set to 'Binary', to avoid converting Unix style | 
 |   // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>). | 
 |   llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); | 
 |   if (!OS) return; | 
 |  | 
 |   DoPrintPreprocessedInput(CI.getPreprocessor(), OS, | 
 |                            CI.getPreprocessorOutputOpts()); | 
 | } | 
 |  | 
 | void PrintPreambleAction::ExecuteAction() { | 
 |   switch (getCurrentFileKind()) { | 
 |   case IK_C: | 
 |   case IK_CXX: | 
 |   case IK_ObjC: | 
 |   case IK_ObjCXX: | 
 |   case IK_OpenCL: | 
 |   case IK_CUDA: | 
 |     break; | 
 |        | 
 |   case IK_None: | 
 |   case IK_Asm: | 
 |   case IK_PreprocessedC: | 
 |   case IK_PreprocessedCXX: | 
 |   case IK_PreprocessedObjC: | 
 |   case IK_PreprocessedObjCXX: | 
 |   case IK_AST: | 
 |   case IK_LLVM_IR: | 
 |     // We can't do anything with these. | 
 |     return; | 
 |   } | 
 |    | 
 |   CompilerInstance &CI = getCompilerInstance(); | 
 |   llvm::MemoryBuffer *Buffer | 
 |       = CI.getFileManager().getBufferForFile(getCurrentFile()); | 
 |   if (Buffer) { | 
 |     unsigned Preamble = Lexer::ComputePreamble(Buffer).first; | 
 |     llvm::outs().write(Buffer->getBufferStart(), Preamble); | 
 |     delete Buffer; | 
 |   } | 
 | } |