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