FrontendActions.cpp revision e6ec11aa15c7104d57009c6e036bf4ae29c35fb2
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/Lex/Pragma.h" 13#include "clang/Lex/Preprocessor.h" 14#include "clang/Parse/Parser.h" 15#include "clang/Basic/FileManager.h" 16#include "clang/Frontend/ASTConsumers.h" 17#include "clang/Frontend/ASTUnit.h" 18#include "clang/Frontend/CompilerInstance.h" 19#include "clang/Frontend/FrontendDiagnostic.h" 20#include "clang/Frontend/Utils.h" 21#include "clang/Serialization/ASTWriter.h" 22#include "llvm/ADT/OwningPtr.h" 23#include "llvm/Support/MemoryBuffer.h" 24#include "llvm/Support/raw_ostream.h" 25using namespace clang; 26 27//===----------------------------------------------------------------------===// 28// Custom Actions 29//===----------------------------------------------------------------------===// 30 31ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI, 32 llvm::StringRef InFile) { 33 return new ASTConsumer(); 34} 35 36void InitOnlyAction::ExecuteAction() { 37} 38 39//===----------------------------------------------------------------------===// 40// AST Consumer Actions 41//===----------------------------------------------------------------------===// 42 43ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, 44 llvm::StringRef InFile) { 45 if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile)) 46 return CreateASTPrinter(OS); 47 return 0; 48} 49 50ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, 51 llvm::StringRef InFile) { 52 return CreateASTDumper(); 53} 54 55ASTConsumer *ASTDumpXMLAction::CreateASTConsumer(CompilerInstance &CI, 56 llvm::StringRef InFile) { 57 llvm::raw_ostream *OS; 58 if (CI.getFrontendOpts().OutputFile.empty()) 59 OS = &llvm::outs(); 60 else 61 OS = CI.createDefaultOutputFile(false, InFile); 62 if (!OS) return 0; 63 return CreateASTDumperXML(*OS); 64} 65 66ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI, 67 llvm::StringRef InFile) { 68 return CreateASTViewer(); 69} 70 71ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI, 72 llvm::StringRef InFile) { 73 return CreateDeclContextPrinter(); 74} 75 76ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, 77 llvm::StringRef InFile) { 78 std::string Sysroot; 79 std::string OutputFile; 80 llvm::raw_ostream *OS = 0; 81 bool Chaining; 82 if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS, Chaining)) 83 return 0; 84 85 const char *isysroot = CI.getFrontendOpts().RelocatablePCH ? 86 Sysroot.c_str() : 0; 87 return new PCHGenerator(CI.getPreprocessor(), OutputFile, Chaining, isysroot, OS); 88} 89 90bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, 91 llvm::StringRef InFile, 92 std::string &Sysroot, 93 std::string &OutputFile, 94 llvm::raw_ostream *&OS, 95 bool &Chaining) { 96 Sysroot = CI.getHeaderSearchOpts().Sysroot; 97 if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) { 98 CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot); 99 return true; 100 } 101 102 // We use createOutputFile here because this is exposed via libclang, and we 103 // must disable the RemoveFileOnSignal behavior. 104 OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, 105 /*RemoveFileOnSignal=*/false, InFile); 106 if (!OS) 107 return true; 108 109 OutputFile = CI.getFrontendOpts().OutputFile; 110 Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH && 111 !CI.getPreprocessorOpts().ImplicitPCHInclude.empty(); 112 return false; 113} 114 115ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, 116 llvm::StringRef InFile) { 117 return new ASTConsumer(); 118} 119 120//===----------------------------------------------------------------------===// 121// Preprocessor Actions 122//===----------------------------------------------------------------------===// 123 124void DumpRawTokensAction::ExecuteAction() { 125 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 126 SourceManager &SM = PP.getSourceManager(); 127 128 // Start lexing the specified input file. 129 const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); 130 Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions()); 131 RawLex.SetKeepWhitespaceMode(true); 132 133 Token RawTok; 134 RawLex.LexFromRawLexer(RawTok); 135 while (RawTok.isNot(tok::eof)) { 136 PP.DumpToken(RawTok, true); 137 llvm::errs() << "\n"; 138 RawLex.LexFromRawLexer(RawTok); 139 } 140} 141 142void DumpTokensAction::ExecuteAction() { 143 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 144 // Start preprocessing the specified input file. 145 Token Tok; 146 PP.EnterMainSourceFile(); 147 do { 148 PP.Lex(Tok); 149 PP.DumpToken(Tok, true); 150 llvm::errs() << "\n"; 151 } while (Tok.isNot(tok::eof)); 152} 153 154void GeneratePTHAction::ExecuteAction() { 155 CompilerInstance &CI = getCompilerInstance(); 156 if (CI.getFrontendOpts().OutputFile.empty() || 157 CI.getFrontendOpts().OutputFile == "-") { 158 // FIXME: Don't fail this way. 159 // FIXME: Verify that we can actually seek in the given file. 160 llvm::report_fatal_error("PTH requires a seekable file for output!"); 161 } 162 llvm::raw_fd_ostream *OS = 163 CI.createDefaultOutputFile(true, getCurrentFile()); 164 if (!OS) return; 165 166 CacheTokens(CI.getPreprocessor(), OS); 167} 168 169void PreprocessOnlyAction::ExecuteAction() { 170 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 171 172 // Ignore unknown pragmas. 173 PP.AddPragmaHandler(new EmptyPragmaHandler()); 174 175 Token Tok; 176 // Start parsing the specified input file. 177 PP.EnterMainSourceFile(); 178 do { 179 PP.Lex(Tok); 180 } while (Tok.isNot(tok::eof)); 181} 182 183void PrintPreprocessedAction::ExecuteAction() { 184 CompilerInstance &CI = getCompilerInstance(); 185 // Output file needs to be set to 'Binary', to avoid converting Unix style 186 // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>). 187 llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 188 if (!OS) return; 189 190 DoPrintPreprocessedInput(CI.getPreprocessor(), OS, 191 CI.getPreprocessorOutputOpts()); 192} 193 194void PrintPreambleAction::ExecuteAction() { 195 switch (getCurrentFileKind()) { 196 case IK_C: 197 case IK_CXX: 198 case IK_ObjC: 199 case IK_ObjCXX: 200 case IK_OpenCL: 201 case IK_CUDA: 202 break; 203 204 case IK_None: 205 case IK_Asm: 206 case IK_PreprocessedC: 207 case IK_PreprocessedCXX: 208 case IK_PreprocessedObjC: 209 case IK_PreprocessedObjCXX: 210 case IK_AST: 211 case IK_LLVM_IR: 212 // We can't do anything with these. 213 return; 214 } 215 216 CompilerInstance &CI = getCompilerInstance(); 217 llvm::MemoryBuffer *Buffer 218 = CI.getFileManager().getBufferForFile(getCurrentFile()); 219 if (Buffer) { 220 unsigned Preamble = Lexer::ComputePreamble(Buffer).first; 221 llvm::outs().write(Buffer->getBufferStart(), Preamble); 222 delete Buffer; 223 } 224} 225