blob: e1ae63cf371a02ac2711ef2a359267e793cd4e4b [file] [log] [blame]
Daniel Dunbar2a79e162009-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"
11#include "clang/Basic/Diagnostic.h"
Daniel Dunbar16b74492009-11-13 04:12:06 +000012#include "clang/Basic/FileManager.h"
13#include "clang/Basic/SourceManager.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000014#include "clang/Basic/TargetInfo.h"
Daniel Dunbar22dacfa2009-11-13 05:52:11 +000015#include "clang/Lex/HeaderSearch.h"
16#include "clang/Lex/Preprocessor.h"
17#include "clang/Lex/PTHManager.h"
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +000018#include "clang/Frontend/ChainedDiagnosticClient.h"
19#include "clang/Frontend/TextDiagnosticBuffer.h"
20#include "clang/Frontend/TextDiagnosticPrinter.h"
Daniel Dunbar22dacfa2009-11-13 05:52:11 +000021#include "clang/Frontend/Utils.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000022#include "llvm/LLVMContext.h"
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +000023#include "llvm/Support/raw_ostream.h"
Daniel Dunbar2a79e162009-11-13 03:51:44 +000024using namespace clang;
25
26CompilerInstance::CompilerInstance(llvm::LLVMContext *_LLVMContext,
27 bool _OwnsLLVMContext)
28 : LLVMContext(_LLVMContext),
29 OwnsLLVMContext(_OwnsLLVMContext) {
30}
31
32CompilerInstance::~CompilerInstance() {
33 if (OwnsLLVMContext)
34 delete LLVMContext;
35}
Daniel Dunbar16b74492009-11-13 04:12:06 +000036
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +000037// Diagnostics
38
39static void SetUpBuildDumpLog(const DiagnosticOptions &DiagOpts,
40 unsigned argc, char **argv,
41 llvm::OwningPtr<DiagnosticClient> &DiagClient) {
42 std::string ErrorInfo;
43 llvm::raw_ostream *OS =
44 new llvm::raw_fd_ostream(DiagOpts.DumpBuildInformation.c_str(), ErrorInfo);
45 if (!ErrorInfo.empty()) {
46 // FIXME: Do not fail like this.
47 llvm::errs() << "error opening -dump-build-information file '"
48 << DiagOpts.DumpBuildInformation << "', option ignored!\n";
49 delete OS;
50 return;
51 }
52
53 (*OS) << "clang-cc command line arguments: ";
54 for (unsigned i = 0; i != argc; ++i)
55 (*OS) << argv[i] << ' ';
56 (*OS) << '\n';
57
58 // Chain in a diagnostic client which will log the diagnostics.
59 DiagnosticClient *Logger =
60 new TextDiagnosticPrinter(*OS, DiagOpts, /*OwnsOutputStream=*/true);
61 DiagClient.reset(new ChainedDiagnosticClient(DiagClient.take(), Logger));
62}
63
64void CompilerInstance::createDiagnostics(int Argc, char **Argv) {
65 Diagnostics.reset(createDiagnostics(getDiagnosticOpts(), Argc, Argv));
66
67 if (Diagnostics)
68 DiagClient.reset(Diagnostics->getClient());
69}
70
71Diagnostic *CompilerInstance::createDiagnostics(const DiagnosticOptions &Opts,
72 int Argc, char **Argv) {
73 // Create the diagnostic client for reporting errors or for
74 // implementing -verify.
75 llvm::OwningPtr<DiagnosticClient> DiagClient;
76 if (Opts.VerifyDiagnostics) {
77 // When checking diagnostics, just buffer them up.
78 DiagClient.reset(new TextDiagnosticBuffer());
79 } else {
80 DiagClient.reset(new TextDiagnosticPrinter(llvm::errs(), Opts));
81 }
82
83 if (!Opts.DumpBuildInformation.empty())
84 SetUpBuildDumpLog(Opts, Argc, Argv, DiagClient);
85
86 // Configure our handling of diagnostics.
87 Diagnostic *Diags = new Diagnostic(DiagClient.take());
88 if (ProcessWarningOptions(*Diags, Opts))
89 return 0;
90
91 return Diags;
92}
93
94// File Manager
95
Daniel Dunbar16b74492009-11-13 04:12:06 +000096void CompilerInstance::createFileManager() {
97 FileMgr.reset(new FileManager());
98}
99
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000100// Source Manager
101
Daniel Dunbar16b74492009-11-13 04:12:06 +0000102void CompilerInstance::createSourceManager() {
103 SourceMgr.reset(new SourceManager());
104}
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000105
Daniel Dunbar0fbb3d92009-11-13 05:52:34 +0000106// Preprocessor
107
Daniel Dunbar22dacfa2009-11-13 05:52:11 +0000108void CompilerInstance::createPreprocessor() {
109 PP.reset(createPreprocessor(getDiagnostics(), getLangOpts(),
110 getPreprocessorOpts(), getHeaderSearchOpts(),
111 getDependencyOutputOpts(), getTarget(),
112 getSourceManager(), getFileManager()));
113}
114
115Preprocessor *
116CompilerInstance::createPreprocessor(Diagnostic &Diags,
117 const LangOptions &LangInfo,
118 const PreprocessorOptions &PPOpts,
119 const HeaderSearchOptions &HSOpts,
120 const DependencyOutputOptions &DepOpts,
121 const TargetInfo &Target,
122 SourceManager &SourceMgr,
123 FileManager &FileMgr) {
124 // Create a PTH manager if we are using some form of a token cache.
125 PTHManager *PTHMgr = 0;
126 if (!PPOpts.getTokenCache().empty())
127 PTHMgr = PTHManager::Create(PPOpts.getTokenCache(), Diags);
128
129 // FIXME: Don't fail like this.
130 if (Diags.hasErrorOccurred())
131 exit(1);
132
133 // Create the Preprocessor.
134 HeaderSearch *HeaderInfo = new HeaderSearch(FileMgr);
135 Preprocessor *PP = new Preprocessor(Diags, LangInfo, Target,
136 SourceMgr, *HeaderInfo, PTHMgr,
137 /*OwnsHeaderSearch=*/true);
138
139 // Note that this is different then passing PTHMgr to Preprocessor's ctor.
140 // That argument is used as the IdentifierInfoLookup argument to
141 // IdentifierTable's ctor.
142 if (PTHMgr) {
143 PTHMgr->setPreprocessor(PP);
144 PP->setPTHManager(PTHMgr);
145 }
146
147 InitializePreprocessor(*PP, PPOpts, HSOpts);
148
149 // Handle generating dependencies, if requested.
150 if (!DepOpts.OutputFile.empty())
151 AttachDependencyFileGen(*PP, DepOpts);
152
153 return PP;
154}