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