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