FrontendActions.cpp revision 4d800b41a27e7e5d94b365878b30034539a0d3b7
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 "llvm/ADT/OwningPtr.h" 22#include "llvm/Support/raw_ostream.h" 23using namespace clang; 24 25//===----------------------------------------------------------------------===// 26// Custom Actions 27//===----------------------------------------------------------------------===// 28 29ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI, 30 llvm::StringRef InFile) { 31 return new ASTConsumer(); 32} 33 34void InitOnlyAction::ExecuteAction() { 35} 36 37//===----------------------------------------------------------------------===// 38// AST Consumer Actions 39//===----------------------------------------------------------------------===// 40 41ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI, 42 llvm::StringRef InFile) { 43 if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile)) 44 return CreateASTPrinter(OS); 45 return 0; 46} 47 48ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI, 49 llvm::StringRef InFile) { 50 if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml")) 51 return CreateASTPrinterXML(OS); 52 return 0; 53} 54 55ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI, 56 llvm::StringRef InFile) { 57 return CreateASTDumper(); 58} 59 60ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI, 61 llvm::StringRef InFile) { 62 return CreateASTViewer(); 63} 64 65ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI, 66 llvm::StringRef InFile) { 67 return CreateDeclContextPrinter(); 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, 85 CI.getInvocation().getFrontendOpts().ChainedPCH ? 86 CI.getPCHReader() : 0, 87 Sysroot.c_str()); 88 89 return CreatePCHGenerator(CI.getPreprocessor(), OS, CI.getPCHReader()); 90} 91 92ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI, 93 llvm::StringRef InFile) { 94 return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance); 95} 96 97ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, 98 llvm::StringRef InFile) { 99 return new ASTConsumer(); 100} 101 102//===----------------------------------------------------------------------===// 103// Preprocessor Actions 104//===----------------------------------------------------------------------===// 105 106void DumpRawTokensAction::ExecuteAction() { 107 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 108 SourceManager &SM = PP.getSourceManager(); 109 110 // Start lexing the specified input file. 111 const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID()); 112 Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions()); 113 RawLex.SetKeepWhitespaceMode(true); 114 115 Token RawTok; 116 RawLex.LexFromRawLexer(RawTok); 117 while (RawTok.isNot(tok::eof)) { 118 PP.DumpToken(RawTok, true); 119 llvm::errs() << "\n"; 120 RawLex.LexFromRawLexer(RawTok); 121 } 122} 123 124void DumpTokensAction::ExecuteAction() { 125 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 126 // Start preprocessing the specified input file. 127 Token Tok; 128 PP.EnterMainSourceFile(); 129 do { 130 PP.Lex(Tok); 131 PP.DumpToken(Tok, true); 132 llvm::errs() << "\n"; 133 } while (Tok.isNot(tok::eof)); 134} 135 136void GeneratePTHAction::ExecuteAction() { 137 CompilerInstance &CI = getCompilerInstance(); 138 if (CI.getFrontendOpts().OutputFile.empty() || 139 CI.getFrontendOpts().OutputFile == "-") { 140 // FIXME: Don't fail this way. 141 // FIXME: Verify that we can actually seek in the given file. 142 llvm::report_fatal_error("PTH requires a seekable file for output!"); 143 } 144 llvm::raw_fd_ostream *OS = 145 CI.createDefaultOutputFile(true, getCurrentFile()); 146 if (!OS) return; 147 148 CacheTokens(CI.getPreprocessor(), OS); 149} 150 151void ParseOnlyAction::ExecuteAction() { 152 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 153 llvm::OwningPtr<Action> PA(new MinimalAction(PP)); 154 155 Parser P(PP, *PA); 156 PP.EnterMainSourceFile(); 157 P.ParseTranslationUnit(); 158} 159 160void PreprocessOnlyAction::ExecuteAction() { 161 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 162 163 // Ignore unknown pragmas. 164 PP.AddPragmaHandler(0, new EmptyPragmaHandler()); 165 166 Token Tok; 167 // Start parsing the specified input file. 168 PP.EnterMainSourceFile(); 169 do { 170 PP.Lex(Tok); 171 } while (Tok.isNot(tok::eof)); 172} 173 174void PrintParseAction::ExecuteAction() { 175 CompilerInstance &CI = getCompilerInstance(); 176 Preprocessor &PP = getCompilerInstance().getPreprocessor(); 177 llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, getCurrentFile()); 178 if (!OS) return; 179 180 llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS)); 181 182 Parser P(PP, *PA); 183 PP.EnterMainSourceFile(); 184 P.ParseTranslationUnit(); 185} 186 187void PrintPreprocessedAction::ExecuteAction() { 188 CompilerInstance &CI = getCompilerInstance(); 189 // Output file needs to be set to 'Binary', to avoid converting Unix style 190 // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>). 191 llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile()); 192 if (!OS) return; 193 194 DoPrintPreprocessedInput(CI.getPreprocessor(), OS, 195 CI.getPreprocessorOutputOpts()); 196} 197