FrontendActions.cpp revision b33fbaa5f14452b6dc2442e89266acb0810616fd
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/Preprocessor.h" 13#include "clang/Parse/Parser.h" 14#include "clang/Basic/FileManager.h" 15#include "clang/Frontend/AnalysisConsumer.h" 16#include "clang/Frontend/ASTConsumers.h" 17#include "clang/Frontend/ASTUnit.h" 18#include "clang/Frontend/CompilerInstance.h" 19#include "clang/Frontend/FixItRewriter.h" 20#include "clang/Frontend/FrontendDiagnostic.h" 21#include "clang/Frontend/Utils.h" 22#include "llvm/Support/raw_ostream.h" 23using namespace clang; 24 25//===----------------------------------------------------------------------===// 26// AST Consumer Actions 27//===----------------------------------------------------------------------===// 28 29ASTConsumer *AnalysisAction::CreateASTConsumer(CompilerInstance &CI, 30 llvm::StringRef InFile) { 31 return CreateAnalysisConsumer(CI.getPreprocessor(), 32 CI.getFrontendOpts().OutputFile, 33 CI.getAnalyzerOpts()); 34} 35 36ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, 37 llvm::StringRef InFile) { 38 return CreateASTPrinter(CI.createDefaultOutputFile(false, InFile)); 39} 40 41ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI, 42 llvm::StringRef InFile) { 43 return CreateASTPrinterXML(CI.createDefaultOutputFile(false, InFile, 44 "xml")); 45} 46 47ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, 48 llvm::StringRef InFile) { 49 return CreateASTDumper(); 50} 51 52ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI, 53 llvm::StringRef InFile) { 54 return CreateASTViewer(); 55} 56 57ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI, 58 llvm::StringRef InFile) { 59 return CreateDeclContextPrinter(); 60} 61 62ASTConsumer *DumpRecordAction::CreateASTConsumer(CompilerInstance &CI, 63 llvm::StringRef InFile) { 64 return CreateRecordLayoutDumper(); 65} 66 67ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, 68 llvm::StringRef InFile) { 69 const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot; 70 if (CI.getFrontendOpts().RelocatablePCH && 71 Sysroot.empty()) { 72 CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot); 73 return 0; 74 } 75 76 llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile); 77 if (CI.getFrontendOpts().RelocatablePCH) 78 return CreatePCHGenerator(CI.getPreprocessor(), OS, Sysroot.c_str()); 79 80 return CreatePCHGenerator(CI.getPreprocessor(), OS); 81} 82 83ASTConsumer *HTMLPrintAction::CreateASTConsumer(CompilerInstance &CI, 84 llvm::StringRef InFile) { 85 return CreateHTMLPrinter(CI.createDefaultOutputFile(false, InFile), 86 CI.getPreprocessor()); 87} 88 89ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI, 90 llvm::StringRef InFile) { 91 return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance); 92} 93 94FixItAction::FixItAction() {} 95FixItAction::~FixItAction() {} 96 97ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI, 98 llvm::StringRef InFile) { 99 return new ASTConsumer(); 100} 101 102/// AddFixItLocations - Add any individual user specified "fix-it" locations, 103/// and return true on success. 104static bool AddFixItLocations(CompilerInstance &CI, 105 FixItRewriter &FixItRewrite) { 106 const std::vector<ParsedSourceLocation> &Locs = 107 CI.getFrontendOpts().FixItLocations; 108 for (unsigned i = 0, e = Locs.size(); i != e; ++i) { 109 const FileEntry *File = CI.getFileManager().getFile(Locs[i].FileName); 110 if (!File) { 111 CI.getDiagnostics().Report(diag::err_fe_unable_to_find_fixit_file) 112 << Locs[i].FileName; 113 return false; 114 } 115 116 RequestedSourceLocation Requested; 117 Requested.File = File; 118 Requested.Line = Locs[i].Line; 119 Requested.Column = Locs[i].Column; 120 FixItRewrite.addFixItLocation(Requested); 121 } 122 123 return true; 124} 125 126bool FixItAction::BeginSourceFileAction(CompilerInstance &CI, 127 llvm::StringRef Filename) { 128 Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(), 129 CI.getLangOpts())); 130 if (!AddFixItLocations(CI, *Rewriter)) 131 return false; 132 133 return true; 134} 135 136void FixItAction::EndSourceFileAction() { 137 const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts(); 138 Rewriter->WriteFixedFile(getCurrentFile(), FEOpts.OutputFile); 139} 140 141ASTConsumer *RewriteObjCAction::CreateASTConsumer(CompilerInstance &CI, 142 llvm::StringRef InFile) { 143 return CreateObjCRewriter(InFile, 144 CI.createDefaultOutputFile(true, InFile, "cpp"), 145 CI.getDiagnostics(), CI.getLangOpts(), 146 CI.getDiagnosticOpts().NoRewriteMacros); 147} 148 149ASTConsumer *RewriteBlocksAction::CreateASTConsumer(CompilerInstance &CI, 150 llvm::StringRef InFile) { 151 return CreateBlockRewriter(InFile, CI.getDiagnostics(), CI.getLangOpts()); 152} 153 154ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, 155 llvm::StringRef InFile) { 156 return new ASTConsumer(); 157} 158 159CodeGenAction::CodeGenAction(unsigned _Act) : Act(_Act) {} 160 161ASTConsumer *CodeGenAction::CreateASTConsumer(CompilerInstance &CI, 162 llvm::StringRef InFile) { 163 BackendAction BA = static_cast<BackendAction>(Act); 164 llvm::OwningPtr<llvm::raw_ostream> OS; 165 if (BA == Backend_EmitAssembly) 166 OS.reset(CI.createDefaultOutputFile(false, InFile, "s")); 167 else if (BA == Backend_EmitLL) 168 OS.reset(CI.createDefaultOutputFile(false, InFile, "ll")); 169 else if (BA == Backend_EmitBC) 170 OS.reset(CI.createDefaultOutputFile(true, InFile, "bc")); 171 172 return CreateBackendConsumer(BA, CI.getDiagnostics(), CI.getLangOpts(), 173 CI.getCodeGenOpts(), CI.getTargetOpts(), 174 CI.getFrontendOpts().ShowTimers, InFile, 175 OS.take(), CI.getLLVMContext()); 176} 177 178EmitAssemblyAction::EmitAssemblyAction() 179 : CodeGenAction(Backend_EmitAssembly) {} 180 181EmitBCAction::EmitBCAction() : CodeGenAction(Backend_EmitBC) {} 182 183EmitLLVMAction::EmitLLVMAction() : CodeGenAction(Backend_EmitLL) {} 184 185EmitLLVMOnlyAction::EmitLLVMOnlyAction() : CodeGenAction(Backend_EmitNothing) {} 186 187//===----------------------------------------------------------------------===// 188// Preprocessor Actions 189//===----------------------------------------------------------------------===// 190 191void DumpRawTokensAction::ExecuteAction() { 192 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 193 SourceManager &SM = PP.getSourceManager(); 194 195 // Start lexing the specified input file. 196 const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); 197 Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions()); 198 RawLex.SetKeepWhitespaceMode(true); 199 200 Token RawTok; 201 RawLex.LexFromRawLexer(RawTok); 202 while (RawTok.isNot(tok::eof)) { 203 PP.DumpToken(RawTok, true); 204 llvm::errs() << "\n"; 205 RawLex.LexFromRawLexer(RawTok); 206 } 207} 208 209void DumpTokensAction::ExecuteAction() { 210 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 211 // Start preprocessing the specified input file. 212 Token Tok; 213 PP.EnterMainSourceFile(); 214 do { 215 PP.Lex(Tok); 216 PP.DumpToken(Tok, true); 217 llvm::errs() << "\n"; 218 } while (Tok.isNot(tok::eof)); 219} 220 221void GeneratePTHAction::ExecuteAction() { 222 CompilerInstance &CI = getCompilerInstance(); 223 if (CI.getFrontendOpts().OutputFile.empty() || 224 CI.getFrontendOpts().OutputFile == "-") { 225 // FIXME: Don't fail this way. 226 // FIXME: Verify that we can actually seek in the given file. 227 llvm::llvm_report_error("PTH requires a seekable file for output!"); 228 } 229 llvm::raw_fd_ostream *OS = 230 CI.createDefaultOutputFile(true, getCurrentFile()); 231 CacheTokens(CI.getPreprocessor(), OS); 232} 233 234void ParseOnlyAction::ExecuteAction() { 235 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 236 llvm::OwningPtr<Action> PA(new MinimalAction(PP)); 237 238 Parser P(PP, *PA); 239 PP.EnterMainSourceFile(); 240 P.ParseTranslationUnit(); 241} 242 243void PreprocessOnlyAction::ExecuteAction() { 244 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 245 246 Token Tok; 247 // Start parsing the specified input file. 248 PP.EnterMainSourceFile(); 249 do { 250 PP.Lex(Tok); 251 } while (Tok.isNot(tok::eof)); 252} 253 254void PrintParseAction::ExecuteAction() { 255 CompilerInstance &CI = getCompilerInstance(); 256 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 257 llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile()); 258 llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS)); 259 260 Parser P(PP, *PA); 261 PP.EnterMainSourceFile(); 262 P.ParseTranslationUnit(); 263} 264 265void PrintPreprocessedAction::ExecuteAction() { 266 CompilerInstance &CI = getCompilerInstance(); 267 llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile()); 268 DoPrintPreprocessedInput(CI.getPreprocessor(), OS, 269 CI.getPreprocessorOutputOpts()); 270} 271 272void RewriteMacrosAction::ExecuteAction() { 273 CompilerInstance &CI = getCompilerInstance(); 274 llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 275 RewriteMacrosInInput(CI.getPreprocessor(), OS); 276} 277 278void RewriteTestAction::ExecuteAction() { 279 CompilerInstance &CI = getCompilerInstance(); 280 llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile()); 281 DoRewriteTest(CI.getPreprocessor(), OS); 282} 283