FrontendActions.cpp revision f4f6c9db68465b886ec2e596feaa6ecc782395a4
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/MemoryBuffer.h"
23#include "llvm/Support/raw_ostream.h"
24using namespace clang;
25
26//===----------------------------------------------------------------------===//
27// Custom Actions
28//===----------------------------------------------------------------------===//
29
30ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI,
31                                               llvm::StringRef InFile) {
32  return new ASTConsumer();
33}
34
35void InitOnlyAction::ExecuteAction() {
36}
37
38//===----------------------------------------------------------------------===//
39// AST Consumer Actions
40//===----------------------------------------------------------------------===//
41
42ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
43                                               llvm::StringRef InFile) {
44  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
45    return CreateASTPrinter(OS);
46  return 0;
47}
48
49ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
50                                                  llvm::StringRef InFile) {
51  if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml"))
52    return CreateASTPrinterXML(OS);
53  return 0;
54}
55
56ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
57                                              llvm::StringRef InFile) {
58  return CreateASTDumper();
59}
60
61ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
62                                              llvm::StringRef InFile) {
63  return CreateASTViewer();
64}
65
66ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
67                                                       llvm::StringRef InFile) {
68  return CreateDeclContextPrinter();
69}
70
71ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
72                                                  llvm::StringRef InFile) {
73  const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
74  if (CI.getFrontendOpts().RelocatablePCH &&
75      Sysroot.empty()) {
76    CI.getDiagnostics().Report(diag::err_relocatable_without_without_isysroot);
77    return 0;
78  }
79
80  llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
81  if (!OS)
82    return 0;
83
84  PCHReader *Chain = CI.getInvocation().getFrontendOpts().ChainedPCH ?
85                               CI.getPCHReader() : 0;
86  const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
87                             Sysroot.c_str() : 0;
88  return CreatePCHGenerator(CI.getPreprocessor(), OS, Chain, isysroot);
89}
90
91ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
92                                                      llvm::StringRef InFile) {
93  return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance);
94}
95
96ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
97                                                 llvm::StringRef InFile) {
98  return new ASTConsumer();
99}
100
101//===----------------------------------------------------------------------===//
102// Preprocessor Actions
103//===----------------------------------------------------------------------===//
104
105void DumpRawTokensAction::ExecuteAction() {
106  Preprocessor &PP = getCompilerInstance().getPreprocessor();
107  SourceManager &SM = PP.getSourceManager();
108
109  // Start lexing the specified input file.
110  const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
111  Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
112  RawLex.SetKeepWhitespaceMode(true);
113
114  Token RawTok;
115  RawLex.LexFromRawLexer(RawTok);
116  while (RawTok.isNot(tok::eof)) {
117    PP.DumpToken(RawTok, true);
118    llvm::errs() << "\n";
119    RawLex.LexFromRawLexer(RawTok);
120  }
121}
122
123void DumpTokensAction::ExecuteAction() {
124  Preprocessor &PP = getCompilerInstance().getPreprocessor();
125  // Start preprocessing the specified input file.
126  Token Tok;
127  PP.EnterMainSourceFile();
128  do {
129    PP.Lex(Tok);
130    PP.DumpToken(Tok, true);
131    llvm::errs() << "\n";
132  } while (Tok.isNot(tok::eof));
133}
134
135void GeneratePTHAction::ExecuteAction() {
136  CompilerInstance &CI = getCompilerInstance();
137  if (CI.getFrontendOpts().OutputFile.empty() ||
138      CI.getFrontendOpts().OutputFile == "-") {
139    // FIXME: Don't fail this way.
140    // FIXME: Verify that we can actually seek in the given file.
141    llvm::report_fatal_error("PTH requires a seekable file for output!");
142  }
143  llvm::raw_fd_ostream *OS =
144    CI.createDefaultOutputFile(true, getCurrentFile());
145  if (!OS) return;
146
147  CacheTokens(CI.getPreprocessor(), OS);
148}
149
150void PreprocessOnlyAction::ExecuteAction() {
151  Preprocessor &PP = getCompilerInstance().getPreprocessor();
152
153  // Ignore unknown pragmas.
154  PP.AddPragmaHandler(new EmptyPragmaHandler());
155
156  Token Tok;
157  // Start parsing the specified input file.
158  PP.EnterMainSourceFile();
159  do {
160    PP.Lex(Tok);
161  } while (Tok.isNot(tok::eof));
162}
163
164void PrintPreprocessedAction::ExecuteAction() {
165  CompilerInstance &CI = getCompilerInstance();
166  // Output file needs to be set to 'Binary', to avoid converting Unix style
167  // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
168  llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
169  if (!OS) return;
170
171  DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
172                           CI.getPreprocessorOutputOpts());
173}
174
175void PrintPreambleAction::ExecuteAction() {
176  switch (getCurrentFileKind()) {
177  case IK_C:
178  case IK_CXX:
179  case IK_ObjC:
180  case IK_ObjCXX:
181  case IK_OpenCL:
182    break;
183
184  case IK_None:
185  case IK_Asm:
186  case IK_PreprocessedC:
187  case IK_PreprocessedCXX:
188  case IK_PreprocessedObjC:
189  case IK_PreprocessedObjCXX:
190  case IK_AST:
191  case IK_LLVM_IR:
192    // We can't do anything with these.
193    return;
194  }
195
196  llvm::MemoryBuffer *Buffer = llvm::MemoryBuffer::getFile(getCurrentFile());
197  if (Buffer) {
198    unsigned Preamble = Lexer::ComputePreamble(Buffer).first;
199    llvm::outs().write(Buffer->getBufferStart(), Preamble);
200    delete Buffer;
201  }
202}
203