Allow resolving headers from a PCH even after headers+PCH were moved to another path.
[clang.git] / lib / Frontend / FrontendActions.cpp
blobe454321c0cce48d74363616fdb6be9abaa1d7390
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 //===----------------------------------------------------------------------===//
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"
25 using namespace clang;
27 //===----------------------------------------------------------------------===//
28 // Custom Actions
29 //===----------------------------------------------------------------------===//
31 ASTConsumer *InitOnlyAction::CreateASTConsumer(CompilerInstance &CI,
32 llvm::StringRef InFile) {
33 return new ASTConsumer();
36 void InitOnlyAction::ExecuteAction() {
39 //===----------------------------------------------------------------------===//
40 // AST Consumer Actions
41 //===----------------------------------------------------------------------===//
43 ASTConsumer *ASTPrintAction::CreateASTConsumer(CompilerInstance &CI,
44 llvm::StringRef InFile) {
45 if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile))
46 return CreateASTPrinter(OS);
47 return 0;
50 ASTConsumer *ASTPrintXMLAction::CreateASTConsumer(CompilerInstance &CI,
51 llvm::StringRef InFile) {
52 if (llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile, "xml"))
53 return CreateASTPrinterXML(OS);
54 return 0;
57 ASTConsumer *ASTDumpAction::CreateASTConsumer(CompilerInstance &CI,
58 llvm::StringRef InFile) {
59 return CreateASTDumper();
62 ASTConsumer *ASTDumpXMLAction::CreateASTConsumer(CompilerInstance &CI,
63 llvm::StringRef InFile) {
64 llvm::raw_ostream *OS;
65 if (CI.getFrontendOpts().OutputFile.empty())
66 OS = &llvm::outs();
67 else
68 OS = CI.createDefaultOutputFile(false, InFile);
69 if (!OS) return 0;
70 return CreateASTDumperXML(*OS);
73 ASTConsumer *ASTViewAction::CreateASTConsumer(CompilerInstance &CI,
74 llvm::StringRef InFile) {
75 return CreateASTViewer();
78 ASTConsumer *DeclContextPrintAction::CreateASTConsumer(CompilerInstance &CI,
79 llvm::StringRef InFile) {
80 return CreateDeclContextPrinter();
83 ASTConsumer *GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI,
84 llvm::StringRef InFile) {
85 std::string Sysroot;
86 std::string OutputFile;
87 llvm::raw_ostream *OS = 0;
88 bool Chaining;
89 if (ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile, OS, Chaining))
90 return 0;
92 const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
93 Sysroot.c_str() : 0;
94 return new PCHGenerator(CI.getPreprocessor(), OutputFile, Chaining, isysroot, OS);
97 bool GeneratePCHAction::ComputeASTConsumerArguments(CompilerInstance &CI,
98 llvm::StringRef InFile,
99 std::string &Sysroot,
100 std::string &OutputFile,
101 llvm::raw_ostream *&OS,
102 bool &Chaining) {
103 Sysroot = CI.getHeaderSearchOpts().Sysroot;
104 if (CI.getFrontendOpts().RelocatablePCH && Sysroot.empty()) {
105 CI.getDiagnostics().Report(diag::err_relocatable_without_isysroot);
106 return true;
109 // We use createOutputFile here because this is exposed via libclang, and we
110 // must disable the RemoveFileOnSignal behavior.
111 OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true,
112 /*RemoveFileOnSignal=*/false, InFile);
113 if (!OS)
114 return true;
116 OutputFile = CI.getFrontendOpts().OutputFile;
117 Chaining = CI.getInvocation().getFrontendOpts().ChainedPCH &&
118 !CI.getPreprocessorOpts().ImplicitPCHInclude.empty();
119 return false;
122 ASTConsumer *InheritanceViewAction::CreateASTConsumer(CompilerInstance &CI,
123 llvm::StringRef InFile) {
124 return CreateInheritanceViewer(CI.getFrontendOpts().ViewClassInheritance);
127 ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI,
128 llvm::StringRef InFile) {
129 return new ASTConsumer();
132 //===----------------------------------------------------------------------===//
133 // Preprocessor Actions
134 //===----------------------------------------------------------------------===//
136 void DumpRawTokensAction::ExecuteAction() {
137 Preprocessor &PP = getCompilerInstance().getPreprocessor();
138 SourceManager &SM = PP.getSourceManager();
140 // Start lexing the specified input file.
141 const llvm::MemoryBuffer *FromFile = SM.getBuffer(SM.getMainFileID());
142 Lexer RawLex(SM.getMainFileID(), FromFile, SM, PP.getLangOptions());
143 RawLex.SetKeepWhitespaceMode(true);
145 Token RawTok;
146 RawLex.LexFromRawLexer(RawTok);
147 while (RawTok.isNot(tok::eof)) {
148 PP.DumpToken(RawTok, true);
149 llvm::errs() << "\n";
150 RawLex.LexFromRawLexer(RawTok);
154 void DumpTokensAction::ExecuteAction() {
155 Preprocessor &PP = getCompilerInstance().getPreprocessor();
156 // Start preprocessing the specified input file.
157 Token Tok;
158 PP.EnterMainSourceFile();
159 do {
160 PP.Lex(Tok);
161 PP.DumpToken(Tok, true);
162 llvm::errs() << "\n";
163 } while (Tok.isNot(tok::eof));
166 void GeneratePTHAction::ExecuteAction() {
167 CompilerInstance &CI = getCompilerInstance();
168 if (CI.getFrontendOpts().OutputFile.empty() ||
169 CI.getFrontendOpts().OutputFile == "-") {
170 // FIXME: Don't fail this way.
171 // FIXME: Verify that we can actually seek in the given file.
172 llvm::report_fatal_error("PTH requires a seekable file for output!");
174 llvm::raw_fd_ostream *OS =
175 CI.createDefaultOutputFile(true, getCurrentFile());
176 if (!OS) return;
178 CacheTokens(CI.getPreprocessor(), OS);
181 void PreprocessOnlyAction::ExecuteAction() {
182 Preprocessor &PP = getCompilerInstance().getPreprocessor();
184 // Ignore unknown pragmas.
185 PP.AddPragmaHandler(new EmptyPragmaHandler());
187 Token Tok;
188 // Start parsing the specified input file.
189 PP.EnterMainSourceFile();
190 do {
191 PP.Lex(Tok);
192 } while (Tok.isNot(tok::eof));
195 void PrintPreprocessedAction::ExecuteAction() {
196 CompilerInstance &CI = getCompilerInstance();
197 // Output file needs to be set to 'Binary', to avoid converting Unix style
198 // line feeds (<LF>) to Microsoft style line feeds (<CR><LF>).
199 llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, getCurrentFile());
200 if (!OS) return;
202 DoPrintPreprocessedInput(CI.getPreprocessor(), OS,
203 CI.getPreprocessorOutputOpts());
206 void PrintPreambleAction::ExecuteAction() {
207 switch (getCurrentFileKind()) {
208 case IK_C:
209 case IK_CXX:
210 case IK_ObjC:
211 case IK_ObjCXX:
212 case IK_OpenCL:
213 case IK_CUDA:
214 break;
216 case IK_None:
217 case IK_Asm:
218 case IK_PreprocessedC:
219 case IK_PreprocessedCXX:
220 case IK_PreprocessedObjC:
221 case IK_PreprocessedObjCXX:
222 case IK_AST:
223 case IK_LLVM_IR:
224 // We can't do anything with these.
225 return;
228 CompilerInstance &CI = getCompilerInstance();
229 llvm::MemoryBuffer *Buffer
230 = CI.getFileManager().getBufferForFile(getCurrentFile());
231 if (Buffer) {
232 unsigned Preamble = Lexer::ComputePreamble(Buffer).first;
233 llvm::outs().write(Buffer->getBufferStart(), Preamble);
234 delete Buffer;