blob: e7c3611f0fd1118d9f76670ea418c6699d0090ba [file] [log] [blame]
Daniel Dunbar636404a2009-11-13 03:51:44 +00001//===--- CompilerInstance.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/CompilerInstance.h"
Daniel Dunbardf3e30c2009-11-13 08:20:47 +000011#include "clang/AST/ASTContext.h"
Daniel Dunbar636404a2009-11-13 03:51:44 +000012#include "clang/Basic/Diagnostic.h"
Daniel Dunbar546a6762009-11-13 04:12:06 +000013#include "clang/Basic/FileManager.h"
14#include "clang/Basic/SourceManager.h"
Daniel Dunbar636404a2009-11-13 03:51:44 +000015#include "clang/Basic/TargetInfo.h"
Daniel Dunbaraaa148f2009-11-13 05:52:11 +000016#include "clang/Lex/HeaderSearch.h"
17#include "clang/Lex/Preprocessor.h"
18#include "clang/Lex/PTHManager.h"
Daniel Dunbar7d75afc2009-11-13 05:52:34 +000019#include "clang/Frontend/ChainedDiagnosticClient.h"
Daniel Dunbar599313e2009-11-13 08:21:10 +000020#include "clang/Frontend/PCHReader.h"
Daniel Dunbar7d75afc2009-11-13 05:52:34 +000021#include "clang/Frontend/TextDiagnosticBuffer.h"
22#include "clang/Frontend/TextDiagnosticPrinter.h"
Daniel Dunbaraaa148f2009-11-13 05:52:11 +000023#include "clang/Frontend/Utils.h"
Daniel Dunbar636404a2009-11-13 03:51:44 +000024#include "llvm/LLVMContext.h"
Daniel Dunbar7d75afc2009-11-13 05:52:34 +000025#include "llvm/Support/raw_ostream.h"
Daniel Dunbar636404a2009-11-13 03:51:44 +000026using namespace clang;
27
28CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext,
29 bool _OwnsLLVMContext)
30 : LLVMContext(_LLVMContext),
31 OwnsLLVMContext(_OwnsLLVMContext) {
32}
33
34CompilerInstance::~CompilerInstance() {
35 if (OwnsLLVMContext)
36 delete LLVMContext;
37}
Daniel Dunbar546a6762009-11-13 04:12:06 +000038
Daniel Dunbar7d75afc2009-11-13 05:52:34 +000039// Diagnostics
40
41static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
42 unsigned argc, char **argv,
43 llvm::OwningPtr<DiagnosticClient> &DiagClient) {
44 std::string ErrorInfo;
45 llvm::raw_ostream *OS =
46 new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo);
47 if (!ErrorInfo.empty()) {
48 // FIXME: Do not fail like this.
49 llvm::errs() << "error opening -dump-build-information file '"
50 << DiagOpts.DumpBuildInformation << "', option ignored!\n";
51 delete OS;
52 return;
53 }
54
55 (*OS) << "clang-cc command line arguments: ";
56 for (unsigned i = 0; i != argc; ++i)
57 (*OS) << argv[i] << ' ';
58 (*OS) << '\n';
59
60 // Chain in a diagnostic client which will log the diagnostics.
61 DiagnosticClient *Logger =
62 new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true);
63 DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger));
64}
65
66void CompilerInstance::createDiagnostics(int Argc, char **Argv) {
67 Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv));
68
69 if (Diagnostics)
70 DiagClient.reset(Diagnostics->getClient());
71}
72
73Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
74 int Argc, char **Argv) {
75 // Create the diagnostic client for reporting errors or for
76 // implementing -verify.
77 llvm::OwningPtr<DiagnosticClient> DiagClient;
78 if (Opts.VerifyDiagnostics) {
79 // When checking diagnostics, just buffer them up.
80 DiagClient.reset(new TextDiagnosticBuffer());
81 } else {
82 DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
83 }
84
85 if (!Opts.DumpBuildInformation.empty())
86 SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient);
87
88 // Configure our handling of diagnostics.
89 Diagnostic *Diags = new Diagnostic(DiagClient.take());
90 if (ProcessWarningOptions(*Diags, Opts))
91 return 0;
92
93 return Diags;
94}
95
96// File Manager
97
Daniel Dunbar546a6762009-11-13 04:12:06 +000098void CompilerInstance::createFileManager() {
99 FileMgr.reset(new FileManager());
100}
101
Daniel Dunbar7d75afc2009-11-13 05:52:34 +0000102// Source Manager
103
Daniel Dunbar546a6762009-11-13 04:12:06 +0000104void CompilerInstance::createSourceManager() {
105 SourceMgr.reset(new SourceManager());
106}
Daniel Dunbaraaa148f2009-11-13 05:52:11 +0000107
Daniel Dunbar7d75afc2009-11-13 05:52:34 +0000108// Preprocessor
109
Daniel Dunbaraaa148f2009-11-13 05:52:11 +0000110void CompilerInstance::createPreprocessor() {
111 PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
112 getPreprocessorOpts(), getHeaderSearchOpts(),
113 getDependencyOutputOpts(), getTarget(),
114 getSourceManager(), getFileManager()));
115}
116
117Preprocessor *
118CompilerInstance::createPreprocessor(Diagnostic &Diags,
119 const LangOptions &LangInfo,
120 const PreprocessorOptions &PPOpts,
121 const HeaderSearchOptions &HSOpts,
122 const DependencyOutputOptions &DepOpts,
123 const TargetInfo &Target,
124 SourceManager &SourceMgr,
125 FileManager &FileMgr) {
126 // Create a PTH manager if we are using some form of a token cache.
127 PTHManager *PTHMgr = 0;
128 if (!PPOpts.getTokenCache().empty())
129 PTHMgr = PTHManager::Create(PPOpts.getTokenCache(), Diags);
130
131 // FIXME: Don't fail like this.
132 if (Diags.hasErrorOccurred())
133 exit(1);
134
135 // Create the Preprocessor.
136 HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
137 Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
138 SourceMgr, *HeaderInfo, PTHMgr,
139 /*OwnsHeaderSearch=*/true);
140
141 // Note that this is different then passing PTHMgr to Preprocessor's ctor.
142 // That argument is used as the IdentifierInfoLookup argument to
143 // IdentifierTable's ctor.
144 if (PTHMgr) {
145 PTHMgr->setPreprocessor(PP);
146 PP->setPTHManager(PTHMgr);
147 }
148
149 InitializePreprocessor(*PP, PPOpts, HSOpts);
150
151 // Handle generating dependencies, if requested.
152 if (!DepOpts.OutputFile.empty())
153 AttachDependencyFileGen(*PP, DepOpts);
154
155 return PP;
156}
Daniel Dunbardf3e30c2009-11-13 08:20:47 +0000157
158// ASTContext
159
160void CompilerInstance::createASTContext() {
161 Preprocessor &PP = getPreprocessor();
162 Context.reset(new ASTContext(getLangOpts(), PP.getSourceManager(),
163 getTarget(), PP.getIdentifierTable(),
164 PP.getSelectorTable(), PP.getBuiltinInfo(),
165 /*FreeMemory=*/ !getFrontendOpts().DisableFree,
166 /*size_reserve=*/ 0));
167}
Daniel Dunbar599313e2009-11-13 08:21:10 +0000168
169// ExternalASTSource
170
171void CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path) {
172 llvm::OwningPtr<ExternalASTSource> Source;
173 Source.reset(createPCHExternalASTSource(Path, getHeaderSearchOpts().Sysroot,
174 getPreprocessor(), getASTContext()));
175 getASTContext().setExternalSource(Source);
176}
177
178ExternalASTSource *
179CompilerInstance::createPCHExternalASTSource(llvm::StringRef Path,
180 const std::string &Sysroot,
181 Preprocessor &PP,
182 ASTContext &Context) {
183 llvm::OwningPtr<PCHReader> Reader;
184 Reader.reset(new PCHReader(PP, &Context,
185 Sysroot.empty() ? 0 : Sysroot.c_str()));
186
187 switch (Reader->ReadPCH(Path)) {
188 case PCHReader::Success:
189 // Set the predefines buffer as suggested by the PCH reader. Typically, the
190 // predefines buffer will be empty.
191 PP.setPredefines(Reader->getSuggestedPredefines());
192 return Reader.take();
193
194 case PCHReader::Failure:
195 // Unrecoverable failure: don't even try to process the input file.
196 break;
197
198 case PCHReader::IgnorePCH:
199 // No suitable PCH file could be found. Return an error.
200 break;
201 }
202
203 return 0;
204}