FrontendActions.cpp revision 857281328fa824782bdd979c3bfdd97ecdbc1609
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/PCHWriter.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 *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI, 51 llvm::StringRef InFile) { 52 if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml")) 53 return CreateASTPrinterXML(OS); 54 return 0; 55} 56 57ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, 58 llvm::StringRef InFile) { 59 return CreateASTDumper(); 60} 61 62ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI, 63 llvm::StringRef InFile) { 64 return CreateASTViewer(); 65} 66 67ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI, 68 llvm::StringRef InFile) { 69 return CreateDeclContextPrinter(); 70} 71 72ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, 73 llvm::StringRef InFile) { 74 std::string Sysroot; 75 llvm::raw_ostream *OS = 0; 76 bool Chaining; 77 if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OS, Chaining)) 78 return 0; 79 80 const char *isysroot = CI.getFrontendOpts().RelocatablePCH ? 81 Sysroot.c_str() : 0; 82 return new PCHGenerator(CI.getPreprocessor(), Chaining, isysroot, OS); 83} 84 85bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI, 86 llvm::StringRef InFile, 87 std::string &Sysroot, 88 llvm::raw_ostream *&OS, 89 bool &Chaining) { 90 Sysroot = CI.getHeaderSearchOpts().Sysroot; 91 if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) { 92 CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot); 93 return true; 94 } 95 96 OS = CI.createDefaultOutputFile(true, InFile); 97 if (!OS) 98 return true; 99 100 Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH && 101 !CI.getPreprocessorOpts().ImplicitPCHInclude.empty(); 102 return false; 103} 104 105ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI, 106 llvm::StringRef InFile) { 107 return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance); 108} 109 110ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, 111 llvm::StringRef InFile) { 112 return new ASTConsumer(); 113} 114 115//===----------------------------------------------------------------------===// 116// Preprocessor Actions 117//===----------------------------------------------------------------------===// 118 119void DumpRawTokensAction::ExecuteAction() { 120 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 121 SourceManager &SM = PP.getSourceManager(); 122 123 // Start lexing the specified input file. 124 const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); 125 Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions()); 126 RawLex.SetKeepWhitespaceMode(true); 127 128 Token RawTok; 129 RawLex.LexFromRawLexer(RawTok); 130 while (RawTok.isNot(tok::eof)) { 131 PP.DumpToken(RawTok, true); 132 llvm::errs() << "\n"; 133 RawLex.LexFromRawLexer(RawTok); 134 } 135} 136 137void DumpTokensAction::ExecuteAction() { 138 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 139 // Start preprocessing the specified input file. 140 Token Tok; 141 PP.EnterMainSourceFile(); 142 do { 143 PP.Lex(Tok); 144 PP.DumpToken(Tok, true); 145 llvm::errs() << "\n"; 146 } while (Tok.isNot(tok::eof)); 147} 148 149void GeneratePTHAction::ExecuteAction() { 150 CompilerInstance &CI = getCompilerInstance(); 151 if (CI.getFrontendOpts().OutputFile.empty() || 152 CI.getFrontendOpts().OutputFile == "-") { 153 // FIXME: Don't fail this way. 154 // FIXME: Verify that we can actually seek in the given file. 155 llvm::report_fatal_error("PTH requires a seekable file for output!"); 156 } 157 llvm::raw_fd_ostream *OS = 158 CI.createDefaultOutputFile(true, getCurrentFile()); 159 if (!OS) return; 160 161 CacheTokens(CI.getPreprocessor(), OS); 162} 163 164void PreprocessOnlyAction::ExecuteAction() { 165 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 166 167 // Ignore unknown pragmas. 168 PP.AddPragmaHandler(new EmptyPragmaHandler()); 169 170 Token Tok; 171 // Start parsing the specified input file. 172 PP.EnterMainSourceFile(); 173 do { 174 PP.Lex(Tok); 175 } while (Tok.isNot(tok::eof)); 176} 177 178void PrintPreprocessedAction::ExecuteAction() { 179 CompilerInstance &CI = getCompilerInstance(); 180 // Output file needs to be set to 'Binary', to avoid converting Unix style 181 // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>). 182 llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 183 if (!OS) return; 184 185 DoPrintPreprocessedInput(CI.getPreprocessor(), OS, 186 CI.getPreprocessorOutputOpts()); 187} 188 189void PrintPreambleAction::ExecuteAction() { 190 switch (getCurrentFileKind()) { 191 case IK_C: 192 case IK_CXX: 193 case IK_ObjC: 194 case IK_ObjCXX: 195 case IK_OpenCL: 196 break; 197 198 case IK_None: 199 case IK_Asm: 200 case IK_PreprocessedC: 201 case IK_PreprocessedCXX: 202 case IK_PreprocessedObjC: 203 case IK_PreprocessedObjCXX: 204 case IK_AST: 205 case IK_LLVM_IR: 206 // We can't do anything with these. 207 return; 208 } 209 210 llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getFile(getCurrentFile()); 211 if (Buffer) { 212 unsigned Preamble = Lexer::ComputePreamble(Buffer).first; 213 llvm::outs().write(Buffer->getBufferStart(), Preamble); 214 delete Buffer; 215 } 216} 217