blob: bf66b85473500b07fe464a337625aa27dad5e6d6 [file] [log] [blame]
Argyrios Kyrtzidis3a08ec12009-06-20 08:27:14 +00001//===--- ASTUnit.cpp - ASTUnit utility ------------------------------------===//
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// ASTUnit Implementation.
11//
12//===----------------------------------------------------------------------===//
13
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000014#include "clang/Frontend/ASTUnit.h"
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000015#include "clang/AST/ASTContext.h"
Daniel Dunbar764c0822009-12-01 09:51:01 +000016#include "clang/AST/ASTConsumer.h"
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000017#include "clang/AST/DeclVisitor.h"
Douglas Gregorb61c07a2010-08-16 18:08:11 +000018#include "clang/AST/TypeOrdering.h"
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000019#include "clang/AST/StmtVisitor.h"
Daniel Dunbar55a17b62009-12-02 03:23:45 +000020#include "clang/Driver/Compilation.h"
21#include "clang/Driver/Driver.h"
22#include "clang/Driver/Job.h"
23#include "clang/Driver/Tool.h"
Daniel Dunbar764c0822009-12-01 09:51:01 +000024#include "clang/Frontend/CompilerInstance.h"
25#include "clang/Frontend/FrontendActions.h"
Daniel Dunbar55a17b62009-12-02 03:23:45 +000026#include "clang/Frontend/FrontendDiagnostic.h"
Daniel Dunbar764c0822009-12-01 09:51:01 +000027#include "clang/Frontend/FrontendOptions.h"
Douglas Gregor36e3b5c2010-10-11 21:37:58 +000028#include "clang/Frontend/Utils.h"
Sebastian Redlf5b13462010-08-18 23:57:17 +000029#include "clang/Serialization/ASTReader.h"
Sebastian Redl1914c6f2010-08-18 23:56:37 +000030#include "clang/Serialization/ASTWriter.h"
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000031#include "clang/Lex/HeaderSearch.h"
32#include "clang/Lex/Preprocessor.h"
Daniel Dunbarb9bbd542009-11-15 06:48:46 +000033#include "clang/Basic/TargetOptions.h"
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000034#include "clang/Basic/TargetInfo.h"
35#include "clang/Basic/Diagnostic.h"
Douglas Gregor40a5a7d2010-08-16 23:08:34 +000036#include "llvm/ADT/StringSet.h"
Douglas Gregoraa98ed92010-01-23 00:14:00 +000037#include "llvm/Support/MemoryBuffer.h"
Daniel Dunbar55a17b62009-12-02 03:23:45 +000038#include "llvm/System/Host.h"
Benjamin Kramer6c839f82009-10-18 11:34:14 +000039#include "llvm/System/Path.h"
Douglas Gregor028d3e42010-08-09 20:45:32 +000040#include "llvm/Support/raw_ostream.h"
Douglas Gregor15ba0b32010-07-30 20:58:08 +000041#include "llvm/Support/Timer.h"
Douglas Gregorbe2d8c62010-07-23 00:33:23 +000042#include <cstdlib>
Zhongxing Xu318e4032010-07-23 02:15:08 +000043#include <cstdio>
Douglas Gregor0e119552010-07-31 00:40:00 +000044#include <sys/stat.h>
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000045using namespace clang;
46
Douglas Gregorbb420ab2010-08-04 05:53:38 +000047/// \brief After failing to build a precompiled preamble (due to
48/// errors in the source that occurs in the preamble), the number of
49/// reparses during which we'll skip even trying to precompile the
50/// preamble.
51const unsigned DefaultPreambleRebuildInterval = 5;
52
Douglas Gregord03e8232010-04-05 21:10:19 +000053ASTUnit::ASTUnit(bool _MainFileIsAST)
Douglas Gregoraa21cc42010-07-19 21:46:24 +000054 : CaptureDiagnostics(false), MainFileIsAST(_MainFileIsAST),
Douglas Gregor028d3e42010-08-09 20:45:32 +000055 CompleteTranslationUnit(true), ConcurrencyCheckValue(CheckUnlocked),
Douglas Gregora0734c52010-08-19 01:33:06 +000056 PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
Douglas Gregor2c8bd472010-08-17 00:40:40 +000057 ShouldCacheCodeCompletionResults(false),
58 NumTopLevelDeclsAtLastCompletionCache(0),
Douglas Gregor4740c452010-08-19 00:45:44 +000059 CacheCodeCompletionCoolDown(0),
60 UnsafeToFree(false) {
Douglas Gregor15ba0b32010-07-30 20:58:08 +000061}
Douglas Gregord03e8232010-04-05 21:10:19 +000062
Daniel Dunbar764c0822009-12-01 09:51:01 +000063ASTUnit::~ASTUnit() {
Douglas Gregor0c7c2f82010-03-05 21:16:25 +000064 ConcurrencyCheckValue = CheckLocked;
Douglas Gregoraa21cc42010-07-19 21:46:24 +000065 CleanTemporaryFiles();
Douglas Gregor4dde7492010-07-23 23:58:40 +000066 if (!PreambleFile.empty())
Douglas Gregor15ba0b32010-07-30 20:58:08 +000067 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregor3f4bea02010-07-26 21:36:20 +000068
69 // Free the buffers associated with remapped files. We are required to
70 // perform this operation here because we explicitly request that the
71 // compiler instance *not* free these buffers for each invocation of the
72 // parser.
73 if (Invocation.get()) {
74 PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
75 for (PreprocessorOptions::remapped_file_buffer_iterator
76 FB = PPOpts.remapped_file_buffer_begin(),
77 FBEnd = PPOpts.remapped_file_buffer_end();
78 FB != FBEnd;
79 ++FB)
80 delete FB->second;
81 }
Douglas Gregor96c04262010-07-27 14:52:07 +000082
83 delete SavedMainFileBuffer;
Douglas Gregora0734c52010-08-19 01:33:06 +000084 delete PreambleBuffer;
85
Douglas Gregorb14904c2010-08-13 22:48:40 +000086 ClearCachedCompletionResults();
87
Douglas Gregor2c844822010-09-24 21:18:36 +000088 if (TimerGroup)
89 TimerGroup->printAll(llvm::errs());
90
Douglas Gregor15ba0b32010-07-30 20:58:08 +000091 for (unsigned I = 0, N = Timers.size(); I != N; ++I)
92 delete Timers[I];
Douglas Gregoraa21cc42010-07-19 21:46:24 +000093}
94
95void ASTUnit::CleanTemporaryFiles() {
Douglas Gregor6cb5ba42010-02-18 23:35:40 +000096 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
97 TemporaryFiles[I].eraseFromDisk();
Douglas Gregoraa21cc42010-07-19 21:46:24 +000098 TemporaryFiles.clear();
Steve Naroff44cd60e2009-10-15 22:23:48 +000099}
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000100
Douglas Gregor39982192010-08-15 06:18:01 +0000101/// \brief Determine the set of code-completion contexts in which this
102/// declaration should be shown.
103static unsigned getDeclShowContexts(NamedDecl *ND,
Douglas Gregor59cab552010-08-16 23:05:20 +0000104 const LangOptions &LangOpts,
105 bool &IsNestedNameSpecifier) {
106 IsNestedNameSpecifier = false;
107
Douglas Gregor39982192010-08-15 06:18:01 +0000108 if (isa<UsingShadowDecl>(ND))
109 ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl());
110 if (!ND)
111 return 0;
112
113 unsigned Contexts = 0;
114 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
115 isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) {
116 // Types can appear in these contexts.
117 if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
118 Contexts |= (1 << (CodeCompletionContext::CCC_TopLevel - 1))
119 | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
120 | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
121 | (1 << (CodeCompletionContext::CCC_Statement - 1))
Douglas Gregor5e35d592010-09-14 23:59:36 +0000122 | (1 << (CodeCompletionContext::CCC_Type - 1))
123 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1));
Douglas Gregor39982192010-08-15 06:18:01 +0000124
125 // In C++, types can appear in expressions contexts (for functional casts).
126 if (LangOpts.CPlusPlus)
127 Contexts |= (1 << (CodeCompletionContext::CCC_Expression - 1));
128
129 // In Objective-C, message sends can send interfaces. In Objective-C++,
130 // all types are available due to functional casts.
131 if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
132 Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
133
134 // Deal with tag names.
135 if (isa<EnumDecl>(ND)) {
136 Contexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1));
137
Douglas Gregor59cab552010-08-16 23:05:20 +0000138 // Part of the nested-name-specifier in C++0x.
Douglas Gregor39982192010-08-15 06:18:01 +0000139 if (LangOpts.CPlusPlus0x)
Douglas Gregor59cab552010-08-16 23:05:20 +0000140 IsNestedNameSpecifier = true;
Douglas Gregor39982192010-08-15 06:18:01 +0000141 } else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) {
142 if (Record->isUnion())
143 Contexts |= (1 << (CodeCompletionContext::CCC_UnionTag - 1));
144 else
145 Contexts |= (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
146
Douglas Gregor39982192010-08-15 06:18:01 +0000147 if (LangOpts.CPlusPlus)
Douglas Gregor59cab552010-08-16 23:05:20 +0000148 IsNestedNameSpecifier = true;
Douglas Gregor0ac41382010-09-23 23:01:17 +0000149 } else if (isa<ClassTemplateDecl>(ND))
Douglas Gregor59cab552010-08-16 23:05:20 +0000150 IsNestedNameSpecifier = true;
Douglas Gregor39982192010-08-15 06:18:01 +0000151 } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
152 // Values can appear in these contexts.
153 Contexts = (1 << (CodeCompletionContext::CCC_Statement - 1))
154 | (1 << (CodeCompletionContext::CCC_Expression - 1))
Douglas Gregor5e35d592010-09-14 23:59:36 +0000155 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
Douglas Gregor39982192010-08-15 06:18:01 +0000156 | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
157 } else if (isa<ObjCProtocolDecl>(ND)) {
158 Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
159 } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
Douglas Gregor59cab552010-08-16 23:05:20 +0000160 Contexts = (1 << (CodeCompletionContext::CCC_Namespace - 1));
Douglas Gregor39982192010-08-15 06:18:01 +0000161
162 // Part of the nested-name-specifier.
Douglas Gregor59cab552010-08-16 23:05:20 +0000163 IsNestedNameSpecifier = true;
Douglas Gregor39982192010-08-15 06:18:01 +0000164 }
165
166 return Contexts;
167}
168
Douglas Gregorb14904c2010-08-13 22:48:40 +0000169void ASTUnit::CacheCodeCompletionResults() {
170 if (!TheSema)
171 return;
172
173 llvm::Timer *CachingTimer = 0;
174 if (TimerGroup.get()) {
175 CachingTimer = new llvm::Timer("Cache global code completions",
176 *TimerGroup);
177 CachingTimer->startTimer();
178 Timers.push_back(CachingTimer);
179 }
180
181 // Clear out the previous results.
182 ClearCachedCompletionResults();
183
184 // Gather the set of global code completions.
John McCall276321a2010-08-25 06:19:51 +0000185 typedef CodeCompletionResult Result;
Douglas Gregorb14904c2010-08-13 22:48:40 +0000186 llvm::SmallVector<Result, 8> Results;
187 TheSema->GatherGlobalCodeCompletions(Results);
188
189 // Translate global code completions into cached completions.
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000190 llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
191
Douglas Gregorb14904c2010-08-13 22:48:40 +0000192 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
193 switch (Results[I].Kind) {
Douglas Gregor39982192010-08-15 06:18:01 +0000194 case Result::RK_Declaration: {
Douglas Gregor59cab552010-08-16 23:05:20 +0000195 bool IsNestedNameSpecifier = false;
Douglas Gregor39982192010-08-15 06:18:01 +0000196 CachedCodeCompletionResult CachedResult;
197 CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
198 CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
Douglas Gregor59cab552010-08-16 23:05:20 +0000199 Ctx->getLangOptions(),
200 IsNestedNameSpecifier);
Douglas Gregor39982192010-08-15 06:18:01 +0000201 CachedResult.Priority = Results[I].Priority;
202 CachedResult.Kind = Results[I].CursorKind;
Douglas Gregorf757a122010-08-23 23:00:57 +0000203 CachedResult.Availability = Results[I].Availability;
Douglas Gregor24747402010-08-16 16:46:30 +0000204
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000205 // Keep track of the type of this completion in an ASTContext-agnostic
206 // way.
Douglas Gregor24747402010-08-16 16:46:30 +0000207 QualType UsageType = getDeclUsageType(*Ctx, Results[I].Declaration);
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000208 if (UsageType.isNull()) {
Douglas Gregor24747402010-08-16 16:46:30 +0000209 CachedResult.TypeClass = STC_Void;
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000210 CachedResult.Type = 0;
211 } else {
212 CanQualType CanUsageType
213 = Ctx->getCanonicalType(UsageType.getUnqualifiedType());
214 CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
215
216 // Determine whether we have already seen this type. If so, we save
217 // ourselves the work of formatting the type string by using the
218 // temporary, CanQualType-based hash table to find the associated value.
219 unsigned &TypeValue = CompletionTypes[CanUsageType];
220 if (TypeValue == 0) {
221 TypeValue = CompletionTypes.size();
222 CachedCompletionTypes[QualType(CanUsageType).getAsString()]
223 = TypeValue;
224 }
225
226 CachedResult.Type = TypeValue;
Douglas Gregor24747402010-08-16 16:46:30 +0000227 }
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000228
Douglas Gregor39982192010-08-15 06:18:01 +0000229 CachedCompletionResults.push_back(CachedResult);
Douglas Gregor59cab552010-08-16 23:05:20 +0000230
231 /// Handle nested-name-specifiers in C++.
232 if (TheSema->Context.getLangOptions().CPlusPlus &&
233 IsNestedNameSpecifier && !Results[I].StartsNestedNameSpecifier) {
234 // The contexts in which a nested-name-specifier can appear in C++.
235 unsigned NNSContexts
236 = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
237 | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
238 | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
239 | (1 << (CodeCompletionContext::CCC_Statement - 1))
240 | (1 << (CodeCompletionContext::CCC_Expression - 1))
241 | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
242 | (1 << (CodeCompletionContext::CCC_EnumTag - 1))
243 | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
244 | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1))
Douglas Gregorc49f5b22010-08-23 18:23:48 +0000245 | (1 << (CodeCompletionContext::CCC_Type - 1))
Douglas Gregor5e35d592010-09-14 23:59:36 +0000246 | (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1))
247 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1));
Douglas Gregor59cab552010-08-16 23:05:20 +0000248
249 if (isa<NamespaceDecl>(Results[I].Declaration) ||
250 isa<NamespaceAliasDecl>(Results[I].Declaration))
251 NNSContexts |= (1 << (CodeCompletionContext::CCC_Namespace - 1));
252
253 if (unsigned RemainingContexts
254 = NNSContexts & ~CachedResult.ShowInContexts) {
255 // If there any contexts where this completion can be a
256 // nested-name-specifier but isn't already an option, create a
257 // nested-name-specifier completion.
258 Results[I].StartsNestedNameSpecifier = true;
259 CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
260 CachedResult.ShowInContexts = RemainingContexts;
261 CachedResult.Priority = CCP_NestedNameSpecifier;
262 CachedResult.TypeClass = STC_Void;
263 CachedResult.Type = 0;
264 CachedCompletionResults.push_back(CachedResult);
265 }
266 }
Douglas Gregorb14904c2010-08-13 22:48:40 +0000267 break;
Douglas Gregor39982192010-08-15 06:18:01 +0000268 }
269
Douglas Gregorb14904c2010-08-13 22:48:40 +0000270 case Result::RK_Keyword:
271 case Result::RK_Pattern:
272 // Ignore keywords and patterns; we don't care, since they are so
273 // easily regenerated.
274 break;
275
276 case Result::RK_Macro: {
277 CachedCodeCompletionResult CachedResult;
278 CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema);
279 CachedResult.ShowInContexts
280 = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
281 | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
282 | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
283 | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
284 | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
285 | (1 << (CodeCompletionContext::CCC_Statement - 1))
286 | (1 << (CodeCompletionContext::CCC_Expression - 1))
Douglas Gregor12785102010-08-24 20:21:13 +0000287 | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
Douglas Gregorec00a262010-08-24 22:20:20 +0000288 | (1 << (CodeCompletionContext::CCC_MacroNameUse - 1))
Douglas Gregor5e35d592010-09-14 23:59:36 +0000289 | (1 << (CodeCompletionContext::CCC_PreprocessorExpression - 1))
290 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1));
291
Douglas Gregorc49f5b22010-08-23 18:23:48 +0000292
Douglas Gregorb14904c2010-08-13 22:48:40 +0000293 CachedResult.Priority = Results[I].Priority;
294 CachedResult.Kind = Results[I].CursorKind;
Douglas Gregorf757a122010-08-23 23:00:57 +0000295 CachedResult.Availability = Results[I].Availability;
Douglas Gregor6e240332010-08-16 16:18:59 +0000296 CachedResult.TypeClass = STC_Void;
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000297 CachedResult.Type = 0;
Douglas Gregorb14904c2010-08-13 22:48:40 +0000298 CachedCompletionResults.push_back(CachedResult);
299 break;
300 }
301 }
302 Results[I].Destroy();
303 }
304
305 if (CachingTimer)
306 CachingTimer->stopTimer();
Douglas Gregor2c8bd472010-08-17 00:40:40 +0000307
308 // Make a note of the state when we performed this caching.
309 NumTopLevelDeclsAtLastCompletionCache = top_level_size();
310 CacheCodeCompletionCoolDown = 15;
Douglas Gregorb14904c2010-08-13 22:48:40 +0000311}
312
313void ASTUnit::ClearCachedCompletionResults() {
314 for (unsigned I = 0, N = CachedCompletionResults.size(); I != N; ++I)
315 delete CachedCompletionResults[I].Completion;
316 CachedCompletionResults.clear();
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000317 CachedCompletionTypes.clear();
Douglas Gregorb14904c2010-08-13 22:48:40 +0000318}
319
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000320namespace {
321
Sebastian Redl2c499f62010-08-18 23:56:43 +0000322/// \brief Gathers information from ASTReader that will be used to initialize
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000323/// a Preprocessor.
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000324class ASTInfoCollector : public ASTReaderListener {
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000325 LangOptions &LangOpt;
326 HeaderSearch &HSI;
327 std::string &TargetTriple;
328 std::string &Predefines;
329 unsigned &Counter;
Mike Stump11289f42009-09-09 15:08:12 +0000330
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000331 unsigned NumHeaderInfos;
Mike Stump11289f42009-09-09 15:08:12 +0000332
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000333public:
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000334 ASTInfoCollector(LangOptions &LangOpt, HeaderSearch &HSI,
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000335 std::string &TargetTriple, std::string &Predefines,
336 unsigned &Counter)
337 : LangOpt(LangOpt), HSI(HSI), TargetTriple(TargetTriple),
338 Predefines(Predefines), Counter(Counter), NumHeaderInfos(0) {}
Mike Stump11289f42009-09-09 15:08:12 +0000339
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000340 virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
341 LangOpt = LangOpts;
342 return false;
343 }
Mike Stump11289f42009-09-09 15:08:12 +0000344
Daniel Dunbar20a682d2009-11-11 00:52:11 +0000345 virtual bool ReadTargetTriple(llvm::StringRef Triple) {
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000346 TargetTriple = Triple;
347 return false;
348 }
Mike Stump11289f42009-09-09 15:08:12 +0000349
Sebastian Redl8b41f302010-07-14 23:29:55 +0000350 virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
Daniel Dunbar000c4ff2009-11-11 05:29:04 +0000351 llvm::StringRef OriginalFileName,
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000352 std::string &SuggestedPredefines) {
Sebastian Redl8b41f302010-07-14 23:29:55 +0000353 Predefines = Buffers[0].Data;
354 for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
355 Predefines += Buffers[I].Data;
356 }
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000357 return false;
358 }
Mike Stump11289f42009-09-09 15:08:12 +0000359
Douglas Gregora2f49452010-03-16 19:09:18 +0000360 virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000361 HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
362 }
Mike Stump11289f42009-09-09 15:08:12 +0000363
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000364 virtual void ReadCounter(unsigned Value) {
365 Counter = Value;
366 }
367};
368
Douglas Gregor33cdd812010-02-18 18:08:43 +0000369class StoredDiagnosticClient : public DiagnosticClient {
370 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags;
371
372public:
373 explicit StoredDiagnosticClient(
374 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
375 : StoredDiags(StoredDiags) { }
376
377 virtual void HandleDiagnostic(Diagnostic::Level Level,
378 const DiagnosticInfo &Info);
379};
380
381/// \brief RAII object that optionally captures diagnostics, if
382/// there is no diagnostic client to capture them already.
383class CaptureDroppedDiagnostics {
384 Diagnostic &Diags;
385 StoredDiagnosticClient Client;
386 DiagnosticClient *PreviousClient;
387
388public:
389 CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags,
390 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiags)
Douglas Gregor2dd19f12010-08-18 22:29:43 +0000391 : Diags(Diags), Client(StoredDiags), PreviousClient(0)
Douglas Gregor33cdd812010-02-18 18:08:43 +0000392 {
Douglas Gregor2dd19f12010-08-18 22:29:43 +0000393 if (RequestCapture || Diags.getClient() == 0) {
394 PreviousClient = Diags.takeClient();
Douglas Gregor33cdd812010-02-18 18:08:43 +0000395 Diags.setClient(&Client);
Douglas Gregor2dd19f12010-08-18 22:29:43 +0000396 }
Douglas Gregor33cdd812010-02-18 18:08:43 +0000397 }
398
399 ~CaptureDroppedDiagnostics() {
Douglas Gregor2dd19f12010-08-18 22:29:43 +0000400 if (Diags.getClient() == &Client) {
401 Diags.takeClient();
402 Diags.setClient(PreviousClient);
403 }
Douglas Gregor33cdd812010-02-18 18:08:43 +0000404 }
405};
406
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000407} // anonymous namespace
408
Douglas Gregor33cdd812010-02-18 18:08:43 +0000409void StoredDiagnosticClient::HandleDiagnostic(Diagnostic::Level Level,
410 const DiagnosticInfo &Info) {
411 StoredDiags.push_back(StoredDiagnostic(Level, Info));
412}
413
Steve Naroffc0683b92009-09-03 18:19:54 +0000414const std::string &ASTUnit::getOriginalSourceFileName() {
Daniel Dunbara8a50932009-12-02 08:44:16 +0000415 return OriginalSourceFile;
Steve Naroffc0683b92009-09-03 18:19:54 +0000416}
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000417
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000418const std::string &ASTUnit::getASTFileName() {
419 assert(isMainFileAST() && "Not an ASTUnit from an AST file!");
Sebastian Redl2c499f62010-08-18 23:56:43 +0000420 return static_cast<ASTReader *>(Ctx->getExternalSource())->getFileName();
Steve Naroff44cd60e2009-10-15 22:23:48 +0000421}
422
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000423ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
Douglas Gregor7f95d262010-04-05 23:52:57 +0000424 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Ted Kremenek8bcb1c62009-10-17 00:34:24 +0000425 bool OnlyLocalDecls,
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000426 RemappedFile *RemappedFiles,
Douglas Gregor33cdd812010-02-18 18:08:43 +0000427 unsigned NumRemappedFiles,
428 bool CaptureDiagnostics) {
Douglas Gregord03e8232010-04-05 21:10:19 +0000429 llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
430
Douglas Gregor7f95d262010-04-05 23:52:57 +0000431 if (!Diags.getPtr()) {
Douglas Gregord03e8232010-04-05 21:10:19 +0000432 // No diagnostics engine was provided, so create our own diagnostics object
433 // with the default options.
434 DiagnosticOptions DiagOpts;
Douglas Gregor7f95d262010-04-05 23:52:57 +0000435 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregord03e8232010-04-05 21:10:19 +0000436 }
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000437
438 AST->CaptureDiagnostics = CaptureDiagnostics;
Douglas Gregor16bef852009-10-16 20:01:17 +0000439 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregor7f95d262010-04-05 23:52:57 +0000440 AST->Diagnostics = Diags;
Douglas Gregord03e8232010-04-05 21:10:19 +0000441 AST->FileMgr.reset(new FileManager);
442 AST->SourceMgr.reset(new SourceManager(AST->getDiagnostics()));
Steve Naroff505fb842009-10-19 14:34:22 +0000443 AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
Douglas Gregor6fd55e02010-08-13 03:15:25 +0000444
Douglas Gregor33cdd812010-02-18 18:08:43 +0000445 // If requested, capture diagnostics in the ASTUnit.
Douglas Gregord03e8232010-04-05 21:10:19 +0000446 CaptureDroppedDiagnostics Capture(CaptureDiagnostics, AST->getDiagnostics(),
Douglas Gregora2433152010-04-05 18:10:21 +0000447 AST->StoredDiagnostics);
Douglas Gregor33cdd812010-02-18 18:08:43 +0000448
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000449 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
450 // Create the file entry for the file that we're mapping from.
451 const FileEntry *FromFile
452 = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
453 RemappedFiles[I].second->getBufferSize(),
454 0);
455 if (!FromFile) {
Douglas Gregord03e8232010-04-05 21:10:19 +0000456 AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000457 << RemappedFiles[I].first;
Douglas Gregor89a56c52010-02-27 01:32:48 +0000458 delete RemappedFiles[I].second;
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000459 continue;
460 }
461
462 // Override the contents of the "from" file with the contents of
463 // the "to" file.
464 AST->getSourceManager().overrideFileContents(FromFile,
465 RemappedFiles[I].second);
466 }
467
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000468 // Gather Info for preprocessor construction later on.
Mike Stump11289f42009-09-09 15:08:12 +0000469
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000470 LangOptions LangInfo;
471 HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
472 std::string TargetTriple;
473 std::string Predefines;
474 unsigned Counter;
475
Sebastian Redl2c499f62010-08-18 23:56:43 +0000476 llvm::OwningPtr<ASTReader> Reader;
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000477
Sebastian Redl2c499f62010-08-18 23:56:43 +0000478 Reader.reset(new ASTReader(AST->getSourceManager(), AST->getFileManager(),
Douglas Gregord03e8232010-04-05 21:10:19 +0000479 AST->getDiagnostics()));
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000480 Reader->setListener(new ASTInfoCollector(LangInfo, HeaderInfo, TargetTriple,
Daniel Dunbar2d9c7402009-09-03 05:59:35 +0000481 Predefines, Counter));
482
Sebastian Redl009e7f22010-10-05 16:15:19 +0000483 switch (Reader->ReadAST(Filename, ASTReader::MainFile)) {
Sebastian Redl2c499f62010-08-18 23:56:43 +0000484 case ASTReader::Success:
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000485 break;
Mike Stump11289f42009-09-09 15:08:12 +0000486
Sebastian Redl2c499f62010-08-18 23:56:43 +0000487 case ASTReader::Failure:
488 case ASTReader::IgnorePCH:
Douglas Gregord03e8232010-04-05 21:10:19 +0000489 AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000490 return NULL;
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000491 }
Mike Stump11289f42009-09-09 15:08:12 +0000492
Daniel Dunbara8a50932009-12-02 08:44:16 +0000493 AST->OriginalSourceFile = Reader->getOriginalSourceFile();
494
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000495 // AST file loaded successfully. Now create the preprocessor.
Mike Stump11289f42009-09-09 15:08:12 +0000496
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000497 // Get information about the target being compiled for.
Daniel Dunbarb9bbd542009-11-15 06:48:46 +0000498 //
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000499 // FIXME: This is broken, we should store the TargetOptions in the AST file.
Daniel Dunbarb9bbd542009-11-15 06:48:46 +0000500 TargetOptions TargetOpts;
501 TargetOpts.ABI = "";
John McCall1c456c82010-08-22 06:43:33 +0000502 TargetOpts.CXXABI = "";
Daniel Dunbarb9bbd542009-11-15 06:48:46 +0000503 TargetOpts.CPU = "";
504 TargetOpts.Features.clear();
505 TargetOpts.Triple = TargetTriple;
Douglas Gregord03e8232010-04-05 21:10:19 +0000506 AST->Target.reset(TargetInfo::CreateTargetInfo(AST->getDiagnostics(),
507 TargetOpts));
508 AST->PP.reset(new Preprocessor(AST->getDiagnostics(), LangInfo,
509 *AST->Target.get(),
Daniel Dunbar7cd285f2009-09-21 03:03:39 +0000510 AST->getSourceManager(), HeaderInfo));
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000511 Preprocessor &PP = *AST->PP.get();
512
Daniel Dunbarb7bbfdd2009-09-21 03:03:47 +0000513 PP.setPredefines(Reader->getSuggestedPredefines());
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000514 PP.setCounterValue(Counter);
Daniel Dunbar2d9c7402009-09-03 05:59:35 +0000515 Reader->setPreprocessor(PP);
Mike Stump11289f42009-09-09 15:08:12 +0000516
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000517 // Create and initialize the ASTContext.
518
519 AST->Ctx.reset(new ASTContext(LangInfo,
Daniel Dunbar7cd285f2009-09-21 03:03:39 +0000520 AST->getSourceManager(),
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000521 *AST->Target.get(),
522 PP.getIdentifierTable(),
523 PP.getSelectorTable(),
524 PP.getBuiltinInfo(),
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000525 /* size_reserve = */0));
526 ASTContext &Context = *AST->Ctx.get();
Mike Stump11289f42009-09-09 15:08:12 +0000527
Daniel Dunbar2d9c7402009-09-03 05:59:35 +0000528 Reader->InitializeContext(Context);
Mike Stump11289f42009-09-09 15:08:12 +0000529
Sebastian Redl2c499f62010-08-18 23:56:43 +0000530 // Attach the AST reader to the AST context as an external AST
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000531 // source, so that declarations will be deserialized from the
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000532 // AST file as needed.
Sebastian Redl2c499f62010-08-18 23:56:43 +0000533 ASTReader *ReaderPtr = Reader.get();
Douglas Gregor6fd55e02010-08-13 03:15:25 +0000534 llvm::OwningPtr<ExternalASTSource> Source(Reader.take());
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000535 Context.setExternalSource(Source);
536
Douglas Gregor6fd55e02010-08-13 03:15:25 +0000537 // Create an AST consumer, even though it isn't used.
538 AST->Consumer.reset(new ASTConsumer);
539
Sebastian Redl2c499f62010-08-18 23:56:43 +0000540 // Create a semantic analysis object and tell the AST reader about it.
Douglas Gregor6fd55e02010-08-13 03:15:25 +0000541 AST->TheSema.reset(new Sema(PP, Context, *AST->Consumer));
542 AST->TheSema->Initialize();
543 ReaderPtr->InitializeSema(*AST->TheSema);
544
Mike Stump11289f42009-09-09 15:08:12 +0000545 return AST.take();
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000546}
Daniel Dunbar764c0822009-12-01 09:51:01 +0000547
548namespace {
549
Daniel Dunbar644dca02009-12-04 08:17:33 +0000550class TopLevelDeclTrackerConsumer : public ASTConsumer {
551 ASTUnit &Unit;
552
553public:
554 TopLevelDeclTrackerConsumer(ASTUnit &_Unit) : Unit(_Unit) {}
555
556 void HandleTopLevelDecl(DeclGroupRef D) {
Ted Kremenekacc59c32010-05-03 20:16:35 +0000557 for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
558 Decl *D = *it;
559 // FIXME: Currently ObjC method declarations are incorrectly being
560 // reported as top-level declarations, even though their DeclContext
561 // is the containing ObjC @interface/@implementation. This is a
562 // fundamental problem in the parser right now.
563 if (isa<ObjCMethodDecl>(D))
564 continue;
Douglas Gregore9db88f2010-08-03 19:06:41 +0000565 Unit.addTopLevelDecl(D);
Ted Kremenekacc59c32010-05-03 20:16:35 +0000566 }
Daniel Dunbar644dca02009-12-04 08:17:33 +0000567 }
Sebastian Redleaa4ade2010-08-11 18:52:41 +0000568
569 // We're not interested in "interesting" decls.
570 void HandleInterestingDecl(DeclGroupRef) {}
Daniel Dunbar644dca02009-12-04 08:17:33 +0000571};
572
573class TopLevelDeclTrackerAction : public ASTFrontendAction {
574public:
575 ASTUnit &Unit;
576
Daniel Dunbar764c0822009-12-01 09:51:01 +0000577 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
578 llvm::StringRef InFile) {
Daniel Dunbar644dca02009-12-04 08:17:33 +0000579 return new TopLevelDeclTrackerConsumer(Unit);
Daniel Dunbar764c0822009-12-01 09:51:01 +0000580 }
581
582public:
Daniel Dunbar644dca02009-12-04 08:17:33 +0000583 TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
584
Daniel Dunbar764c0822009-12-01 09:51:01 +0000585 virtual bool hasCodeCompletionSupport() const { return false; }
Douglas Gregor028d3e42010-08-09 20:45:32 +0000586 virtual bool usesCompleteTranslationUnit() {
587 return Unit.isCompleteTranslationUnit();
588 }
Daniel Dunbar764c0822009-12-01 09:51:01 +0000589};
590
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000591class PrecompilePreambleConsumer : public PCHGenerator {
592 ASTUnit &Unit;
Douglas Gregore9db88f2010-08-03 19:06:41 +0000593 std::vector<Decl *> TopLevelDecls;
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000594
595public:
596 PrecompilePreambleConsumer(ASTUnit &Unit,
597 const Preprocessor &PP, bool Chaining,
598 const char *isysroot, llvm::raw_ostream *Out)
599 : PCHGenerator(PP, Chaining, isysroot, Out), Unit(Unit) { }
600
Douglas Gregore9db88f2010-08-03 19:06:41 +0000601 virtual void HandleTopLevelDecl(DeclGroupRef D) {
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000602 for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
603 Decl *D = *it;
604 // FIXME: Currently ObjC method declarations are incorrectly being
605 // reported as top-level declarations, even though their DeclContext
606 // is the containing ObjC @interface/@implementation. This is a
607 // fundamental problem in the parser right now.
608 if (isa<ObjCMethodDecl>(D))
609 continue;
Douglas Gregore9db88f2010-08-03 19:06:41 +0000610 TopLevelDecls.push_back(D);
611 }
612 }
613
614 virtual void HandleTranslationUnit(ASTContext &Ctx) {
615 PCHGenerator::HandleTranslationUnit(Ctx);
616 if (!Unit.getDiagnostics().hasErrorOccurred()) {
617 // Translate the top-level declarations we captured during
618 // parsing into declaration IDs in the precompiled
619 // preamble. This will allow us to deserialize those top-level
620 // declarations when requested.
621 for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I)
622 Unit.addTopLevelDeclFromPreamble(
623 getWriter().getDeclID(TopLevelDecls[I]));
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000624 }
625 }
626};
627
628class PrecompilePreambleAction : public ASTFrontendAction {
629 ASTUnit &Unit;
630
631public:
632 explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {}
633
634 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
635 llvm::StringRef InFile) {
636 std::string Sysroot;
637 llvm::raw_ostream *OS = 0;
638 bool Chaining;
639 if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
640 OS, Chaining))
641 return 0;
642
643 const char *isysroot = CI.getFrontendOpts().RelocatablePCH ?
644 Sysroot.c_str() : 0;
645 return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Chaining,
646 isysroot, OS);
647 }
648
649 virtual bool hasCodeCompletionSupport() const { return false; }
650 virtual bool hasASTFileSupport() const { return false; }
Douglas Gregor028d3e42010-08-09 20:45:32 +0000651 virtual bool usesCompleteTranslationUnit() { return false; }
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000652};
653
Daniel Dunbar764c0822009-12-01 09:51:01 +0000654}
655
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000656/// Parse the source file into a translation unit using the given compiler
657/// invocation, replacing the current translation unit.
658///
659/// \returns True if a failure occurred that causes the ASTUnit not to
660/// contain any translation-unit information, false otherwise.
Douglas Gregor6481ef12010-07-24 00:38:13 +0000661bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
Douglas Gregor96c04262010-07-27 14:52:07 +0000662 delete SavedMainFileBuffer;
663 SavedMainFileBuffer = 0;
664
Douglas Gregora0734c52010-08-19 01:33:06 +0000665 if (!Invocation.get()) {
666 delete OverrideMainBuffer;
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000667 return true;
Douglas Gregora0734c52010-08-19 01:33:06 +0000668 }
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000669
Daniel Dunbar764c0822009-12-01 09:51:01 +0000670 // Create the compiler instance to use for building the AST.
Daniel Dunbar7afbb8c2009-12-02 08:43:56 +0000671 CompilerInstance Clang;
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000672 Clang.setInvocation(Invocation.take());
673 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
674
Douglas Gregor8e984da2010-08-04 16:47:14 +0000675 // Set up diagnostics, capturing any diagnostics that would
676 // otherwise be dropped.
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000677 Clang.setDiagnostics(&getDiagnostics());
Douglas Gregor8e984da2010-08-04 16:47:14 +0000678 CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
679 getDiagnostics(),
680 StoredDiagnostics);
Douglas Gregord03e8232010-04-05 21:10:19 +0000681
Daniel Dunbar764c0822009-12-01 09:51:01 +0000682 // Create the target instance.
683 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
684 Clang.getTargetOpts()));
Douglas Gregora0734c52010-08-19 01:33:06 +0000685 if (!Clang.hasTarget()) {
686 delete OverrideMainBuffer;
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000687 return true;
Douglas Gregora0734c52010-08-19 01:33:06 +0000688 }
689
Daniel Dunbar764c0822009-12-01 09:51:01 +0000690 // Inform the target of the language options.
691 //
692 // FIXME: We shouldn't need to do this, the target should be immutable once
693 // created. This complexity should be lifted elsewhere.
694 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000695
Daniel Dunbar764c0822009-12-01 09:51:01 +0000696 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
697 "Invocation must have exactly one source file!");
Daniel Dunbar9b491e72010-06-07 23:22:09 +0000698 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
Daniel Dunbar764c0822009-12-01 09:51:01 +0000699 "FIXME: AST inputs not yet supported here!");
Daniel Dunbar9507f9c2010-06-07 23:26:47 +0000700 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
701 "IR inputs not support here!");
Daniel Dunbar764c0822009-12-01 09:51:01 +0000702
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000703 // Configure the various subsystems.
704 // FIXME: Should we retain the previous file manager?
705 FileMgr.reset(new FileManager);
706 SourceMgr.reset(new SourceManager(getDiagnostics()));
Douglas Gregor6fd55e02010-08-13 03:15:25 +0000707 TheSema.reset();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000708 Ctx.reset();
709 PP.reset();
710
711 // Clear out old caches and data.
712 TopLevelDecls.clear();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000713 CleanTemporaryFiles();
714 PreprocessedEntitiesByFile.clear();
Douglas Gregord9a30af2010-08-02 20:51:39 +0000715
Douglas Gregor7b02b582010-08-20 00:02:33 +0000716 if (!OverrideMainBuffer) {
Douglas Gregord9a30af2010-08-02 20:51:39 +0000717 StoredDiagnostics.clear();
Douglas Gregor7b02b582010-08-20 00:02:33 +0000718 TopLevelDeclsInPreamble.clear();
719 }
720
Daniel Dunbar764c0822009-12-01 09:51:01 +0000721 // Create a file manager object to provide access to and cache the filesystem.
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000722 Clang.setFileManager(&getFileManager());
723
Daniel Dunbar764c0822009-12-01 09:51:01 +0000724 // Create the source manager.
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000725 Clang.setSourceManager(&getSourceManager());
726
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000727 // If the main file has been overridden due to the use of a preamble,
728 // make that override happen and introduce the preamble.
729 PreprocessorOptions &PreprocessorOpts = Clang.getPreprocessorOpts();
Douglas Gregor8e984da2010-08-04 16:47:14 +0000730 std::string PriorImplicitPCHInclude;
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000731 if (OverrideMainBuffer) {
732 PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
733 PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
734 PreprocessorOpts.PrecompiledPreambleBytes.second
735 = PreambleEndsAtStartOfLine;
Douglas Gregor8e984da2010-08-04 16:47:14 +0000736 PriorImplicitPCHInclude = PreprocessorOpts.ImplicitPCHInclude;
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000737 PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
Douglas Gregorce3a8292010-07-27 00:27:13 +0000738 PreprocessorOpts.DisablePCHValidation = true;
Douglas Gregor96c04262010-07-27 14:52:07 +0000739
740 // Keep track of the override buffer;
741 SavedMainFileBuffer = OverrideMainBuffer;
Douglas Gregord9a30af2010-08-02 20:51:39 +0000742
743 // The stored diagnostic has the old source manager in it; update
744 // the locations to refer into the new source manager. Since we've
745 // been careful to make sure that the source manager's state
746 // before and after are identical, so that we can reuse the source
747 // location itself.
748 for (unsigned I = 0, N = StoredDiagnostics.size(); I != N; ++I) {
749 FullSourceLoc Loc(StoredDiagnostics[I].getLocation(),
750 getSourceManager());
751 StoredDiagnostics[I].setLocation(Loc);
752 }
Douglas Gregor7b02b582010-08-20 00:02:33 +0000753 } else {
754 PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
755 PreprocessorOpts.PrecompiledPreambleBytes.second = false;
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000756 }
757
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000758 llvm::OwningPtr<TopLevelDeclTrackerAction> Act;
759 Act.reset(new TopLevelDeclTrackerAction(*this));
Daniel Dunbar644dca02009-12-04 08:17:33 +0000760 if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
Daniel Dunbar86546382010-06-07 23:23:06 +0000761 Clang.getFrontendOpts().Inputs[0].first))
Daniel Dunbar764c0822009-12-01 09:51:01 +0000762 goto error;
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000763
Daniel Dunbar644dca02009-12-04 08:17:33 +0000764 Act->Execute();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000765
Daniel Dunbard2f8be32009-12-01 21:57:33 +0000766 // Steal the created target, context, and preprocessor, and take back the
767 // source and file managers.
Douglas Gregor6fd55e02010-08-13 03:15:25 +0000768 TheSema.reset(Clang.takeSema());
769 Consumer.reset(Clang.takeASTConsumer());
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000770 Ctx.reset(Clang.takeASTContext());
771 PP.reset(Clang.takePreprocessor());
Daniel Dunbar764c0822009-12-01 09:51:01 +0000772 Clang.takeSourceManager();
773 Clang.takeFileManager();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000774 Target.reset(Clang.takeTarget());
775
Daniel Dunbar644dca02009-12-04 08:17:33 +0000776 Act->EndSourceFile();
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000777
778 // Remove the overridden buffer we used for the preamble.
Douglas Gregor8e984da2010-08-04 16:47:14 +0000779 if (OverrideMainBuffer) {
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000780 PreprocessorOpts.eraseRemappedFile(
781 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor8e984da2010-08-04 16:47:14 +0000782 PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
783 }
784
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000785 Invocation.reset(Clang.takeInvocation());
Douglas Gregorb14904c2010-08-13 22:48:40 +0000786
787 // If we were asked to cache code-completion results and don't have any
788 // results yet, do so now.
789 if (ShouldCacheCodeCompletionResults && CachedCompletionResults.empty())
790 CacheCodeCompletionResults();
Douglas Gregorbb6a8812010-10-08 04:03:57 +0000791
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000792 return false;
793
Daniel Dunbar764c0822009-12-01 09:51:01 +0000794error:
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000795 // Remove the overridden buffer we used for the preamble.
Douglas Gregorce3a8292010-07-27 00:27:13 +0000796 if (OverrideMainBuffer) {
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000797 PreprocessorOpts.eraseRemappedFile(
798 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregorce3a8292010-07-27 00:27:13 +0000799 PreprocessorOpts.DisablePCHValidation = true;
Douglas Gregor8e984da2010-08-04 16:47:14 +0000800 PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
Douglas Gregora0734c52010-08-19 01:33:06 +0000801 delete OverrideMainBuffer;
Douglas Gregora3d3ba12010-10-06 21:11:08 +0000802 SavedMainFileBuffer = 0;
Douglas Gregorce3a8292010-07-27 00:27:13 +0000803 }
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000804
Daniel Dunbar764c0822009-12-01 09:51:01 +0000805 Clang.takeSourceManager();
806 Clang.takeFileManager();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000807 Invocation.reset(Clang.takeInvocation());
808 return true;
809}
810
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000811/// \brief Simple function to retrieve a path for a preamble precompiled header.
812static std::string GetPreamblePCHPath() {
813 // FIXME: This is lame; sys::Path should provide this function (in particular,
814 // it should know how to find the temporary files dir).
815 // FIXME: This is really lame. I copied this code from the Driver!
Douglas Gregor250ab1d2010-09-11 18:05:19 +0000816 // FIXME: This is a hack so that we can override the preamble file during
817 // crash-recovery testing, which is the only case where the preamble files
818 // are not necessarily cleaned up.
819 const char *TmpFile = ::getenv("CINDEXTEST_PREAMBLE_FILE");
820 if (TmpFile)
821 return TmpFile;
822
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000823 std::string Error;
824 const char *TmpDir = ::getenv("TMPDIR");
825 if (!TmpDir)
826 TmpDir = ::getenv("TEMP");
827 if (!TmpDir)
828 TmpDir = ::getenv("TMP");
Douglas Gregorce3449f2010-09-11 17:51:16 +0000829#ifdef LLVM_ON_WIN32
830 if (!TmpDir)
831 TmpDir = ::getenv("USERPROFILE");
832#endif
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000833 if (!TmpDir)
834 TmpDir = "/tmp";
835 llvm::sys::Path P(TmpDir);
Douglas Gregorce3449f2010-09-11 17:51:16 +0000836 P.createDirectoryOnDisk(true);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000837 P.appendComponent("preamble");
Douglas Gregor20975b22010-08-11 13:06:56 +0000838 P.appendSuffix("pch");
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000839 if (P.createTemporaryFileOnDisk())
840 return std::string();
841
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000842 return P.str();
843}
844
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000845/// \brief Compute the preamble for the main file, providing the source buffer
846/// that corresponds to the main file along with a pair (bytes, start-of-line)
847/// that describes the preamble.
848std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
Douglas Gregor028d3e42010-08-09 20:45:32 +0000849ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
850 unsigned MaxLines, bool &CreatedBuffer) {
Douglas Gregor4dde7492010-07-23 23:58:40 +0000851 FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000852 PreprocessorOptions &PreprocessorOpts
Douglas Gregor4dde7492010-07-23 23:58:40 +0000853 = Invocation.getPreprocessorOpts();
854 CreatedBuffer = false;
855
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000856 // Try to determine if the main file has been remapped, either from the
857 // command line (to another file) or directly through the compiler invocation
858 // (to a memory buffer).
Douglas Gregor4dde7492010-07-23 23:58:40 +0000859 llvm::MemoryBuffer *Buffer = 0;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000860 llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
861 if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
862 // Check whether there is a file-file remapping of the main file
863 for (PreprocessorOptions::remapped_file_iterator
Douglas Gregor4dde7492010-07-23 23:58:40 +0000864 M = PreprocessorOpts.remapped_file_begin(),
865 E = PreprocessorOpts.remapped_file_end();
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000866 M != E;
867 ++M) {
868 llvm::sys::PathWithStatus MPath(M->first);
869 if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
870 if (MainFileStatus->uniqueID == MStatus->uniqueID) {
871 // We found a remapping. Try to load the resulting, remapped source.
Douglas Gregor4dde7492010-07-23 23:58:40 +0000872 if (CreatedBuffer) {
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000873 delete Buffer;
Douglas Gregor4dde7492010-07-23 23:58:40 +0000874 CreatedBuffer = false;
875 }
876
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000877 Buffer = llvm::MemoryBuffer::getFile(M->second);
878 if (!Buffer)
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000879 return std::make_pair((llvm::MemoryBuffer*)0,
880 std::make_pair(0, true));
Douglas Gregor4dde7492010-07-23 23:58:40 +0000881 CreatedBuffer = true;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000882 }
883 }
884 }
885
886 // Check whether there is a file-buffer remapping. It supercedes the
887 // file-file remapping.
888 for (PreprocessorOptions::remapped_file_buffer_iterator
889 M = PreprocessorOpts.remapped_file_buffer_begin(),
890 E = PreprocessorOpts.remapped_file_buffer_end();
891 M != E;
892 ++M) {
893 llvm::sys::PathWithStatus MPath(M->first);
894 if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
895 if (MainFileStatus->uniqueID == MStatus->uniqueID) {
896 // We found a remapping.
Douglas Gregor4dde7492010-07-23 23:58:40 +0000897 if (CreatedBuffer) {
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000898 delete Buffer;
Douglas Gregor4dde7492010-07-23 23:58:40 +0000899 CreatedBuffer = false;
900 }
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000901
Douglas Gregor4dde7492010-07-23 23:58:40 +0000902 Buffer = const_cast<llvm::MemoryBuffer *>(M->second);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000903 }
904 }
Douglas Gregor4dde7492010-07-23 23:58:40 +0000905 }
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000906 }
907
908 // If the main source file was not remapped, load it now.
909 if (!Buffer) {
910 Buffer = llvm::MemoryBuffer::getFile(FrontendOpts.Inputs[0].second);
911 if (!Buffer)
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000912 return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
Douglas Gregor4dde7492010-07-23 23:58:40 +0000913
914 CreatedBuffer = true;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +0000915 }
916
Douglas Gregor028d3e42010-08-09 20:45:32 +0000917 return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer, MaxLines));
Douglas Gregor4dde7492010-07-23 23:58:40 +0000918}
919
Douglas Gregor6481ef12010-07-24 00:38:13 +0000920static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
921 bool DeleteOld,
922 unsigned NewSize,
923 llvm::StringRef NewName) {
924 llvm::MemoryBuffer *Result
925 = llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName);
926 memcpy(const_cast<char*>(Result->getBufferStart()),
927 Old->getBufferStart(), Old->getBufferSize());
928 memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(),
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000929 ' ', NewSize - Old->getBufferSize() - 1);
930 const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
Douglas Gregor6481ef12010-07-24 00:38:13 +0000931
932 if (DeleteOld)
933 delete Old;
934
935 return Result;
936}
937
Douglas Gregor4dde7492010-07-23 23:58:40 +0000938/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
939/// the source file.
940///
941/// This routine will compute the preamble of the main source file. If a
942/// non-trivial preamble is found, it will precompile that preamble into a
943/// precompiled header so that the precompiled preamble can be used to reduce
944/// reparsing time. If a precompiled preamble has already been constructed,
945/// this routine will determine if it is still valid and, if so, avoid
946/// rebuilding the precompiled preamble.
947///
Douglas Gregor028d3e42010-08-09 20:45:32 +0000948/// \param AllowRebuild When true (the default), this routine is
949/// allowed to rebuild the precompiled preamble if it is found to be
950/// out-of-date.
951///
952/// \param MaxLines When non-zero, the maximum number of lines that
953/// can occur within the preamble.
954///
Douglas Gregor6481ef12010-07-24 00:38:13 +0000955/// \returns If the precompiled preamble can be used, returns a newly-allocated
956/// buffer that should be used in place of the main file when doing so.
957/// Otherwise, returns a NULL pointer.
Douglas Gregor028d3e42010-08-09 20:45:32 +0000958llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
Douglas Gregorb97b6662010-08-20 00:59:43 +0000959 CompilerInvocation PreambleInvocation,
Douglas Gregor028d3e42010-08-09 20:45:32 +0000960 bool AllowRebuild,
961 unsigned MaxLines) {
Douglas Gregor4dde7492010-07-23 23:58:40 +0000962 FrontendOptions &FrontendOpts = PreambleInvocation.getFrontendOpts();
963 PreprocessorOptions &PreprocessorOpts
964 = PreambleInvocation.getPreprocessorOpts();
965
966 bool CreatedPreambleBuffer = false;
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000967 std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
Douglas Gregor028d3e42010-08-09 20:45:32 +0000968 = ComputePreamble(PreambleInvocation, MaxLines, CreatedPreambleBuffer);
Douglas Gregor4dde7492010-07-23 23:58:40 +0000969
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000970 if (!NewPreamble.second.first) {
Douglas Gregor4dde7492010-07-23 23:58:40 +0000971 // We couldn't find a preamble in the main source. Clear out the current
972 // preamble, if we have one. It's obviously no good any more.
973 Preamble.clear();
974 if (!PreambleFile.empty()) {
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000975 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregor4dde7492010-07-23 23:58:40 +0000976 PreambleFile.clear();
977 }
978 if (CreatedPreambleBuffer)
979 delete NewPreamble.first;
Douglas Gregorbb420ab2010-08-04 05:53:38 +0000980
981 // The next time we actually see a preamble, precompile it.
982 PreambleRebuildCounter = 1;
Douglas Gregor6481ef12010-07-24 00:38:13 +0000983 return 0;
Douglas Gregor4dde7492010-07-23 23:58:40 +0000984 }
985
986 if (!Preamble.empty()) {
987 // We've previously computed a preamble. Check whether we have the same
988 // preamble now that we did before, and that there's enough space in
989 // the main-file buffer within the precompiled preamble to fit the
990 // new main file.
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000991 if (Preamble.size() == NewPreamble.second.first &&
992 PreambleEndsAtStartOfLine == NewPreamble.second.second &&
Douglas Gregorf5275a82010-07-24 00:42:07 +0000993 NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
Douglas Gregor4dde7492010-07-23 23:58:40 +0000994 memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000995 NewPreamble.second.first) == 0) {
Douglas Gregor4dde7492010-07-23 23:58:40 +0000996 // The preamble has not changed. We may be able to re-use the precompiled
997 // preamble.
Douglas Gregord9a30af2010-08-02 20:51:39 +0000998
Douglas Gregor0e119552010-07-31 00:40:00 +0000999 // Check that none of the files used by the preamble have changed.
1000 bool AnyFileChanged = false;
1001
1002 // First, make a record of those files that have been overridden via
1003 // remapping or unsaved_files.
1004 llvm::StringMap<std::pair<off_t, time_t> > OverriddenFiles;
1005 for (PreprocessorOptions::remapped_file_iterator
1006 R = PreprocessorOpts.remapped_file_begin(),
1007 REnd = PreprocessorOpts.remapped_file_end();
1008 !AnyFileChanged && R != REnd;
1009 ++R) {
1010 struct stat StatBuf;
1011 if (stat(R->second.c_str(), &StatBuf)) {
1012 // If we can't stat the file we're remapping to, assume that something
1013 // horrible happened.
1014 AnyFileChanged = true;
1015 break;
1016 }
Douglas Gregor6481ef12010-07-24 00:38:13 +00001017
Douglas Gregor0e119552010-07-31 00:40:00 +00001018 OverriddenFiles[R->first] = std::make_pair(StatBuf.st_size,
1019 StatBuf.st_mtime);
1020 }
1021 for (PreprocessorOptions::remapped_file_buffer_iterator
1022 R = PreprocessorOpts.remapped_file_buffer_begin(),
1023 REnd = PreprocessorOpts.remapped_file_buffer_end();
1024 !AnyFileChanged && R != REnd;
1025 ++R) {
1026 // FIXME: Should we actually compare the contents of file->buffer
1027 // remappings?
1028 OverriddenFiles[R->first] = std::make_pair(R->second->getBufferSize(),
1029 0);
1030 }
1031
1032 // Check whether anything has changed.
1033 for (llvm::StringMap<std::pair<off_t, time_t> >::iterator
1034 F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end();
1035 !AnyFileChanged && F != FEnd;
1036 ++F) {
1037 llvm::StringMap<std::pair<off_t, time_t> >::iterator Overridden
1038 = OverriddenFiles.find(F->first());
1039 if (Overridden != OverriddenFiles.end()) {
1040 // This file was remapped; check whether the newly-mapped file
1041 // matches up with the previous mapping.
1042 if (Overridden->second != F->second)
1043 AnyFileChanged = true;
1044 continue;
1045 }
1046
1047 // The file was not remapped; check whether it has changed on disk.
1048 struct stat StatBuf;
1049 if (stat(F->first(), &StatBuf)) {
1050 // If we can't stat the file, assume that something horrible happened.
1051 AnyFileChanged = true;
1052 } else if (StatBuf.st_size != F->second.first ||
1053 StatBuf.st_mtime != F->second.second)
1054 AnyFileChanged = true;
1055 }
1056
1057 if (!AnyFileChanged) {
Douglas Gregord9a30af2010-08-02 20:51:39 +00001058 // Okay! We can re-use the precompiled preamble.
1059
1060 // Set the state of the diagnostic object to mimic its state
1061 // after parsing the preamble.
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00001062 // FIXME: This won't catch any #pragma push warning changes that
1063 // have occurred in the preamble.
Douglas Gregord9a30af2010-08-02 20:51:39 +00001064 getDiagnostics().Reset();
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00001065 ProcessWarningOptions(getDiagnostics(),
1066 PreambleInvocation.getDiagnosticOpts());
Douglas Gregord9a30af2010-08-02 20:51:39 +00001067 getDiagnostics().setNumWarnings(NumWarningsInPreamble);
1068 if (StoredDiagnostics.size() > NumStoredDiagnosticsInPreamble)
1069 StoredDiagnostics.erase(
1070 StoredDiagnostics.begin() + NumStoredDiagnosticsInPreamble,
1071 StoredDiagnostics.end());
1072
1073 // Create a version of the main file buffer that is padded to
1074 // buffer size we reserved when creating the preamble.
Douglas Gregor0e119552010-07-31 00:40:00 +00001075 return CreatePaddedMainFileBuffer(NewPreamble.first,
1076 CreatedPreambleBuffer,
1077 PreambleReservedSize,
1078 FrontendOpts.Inputs[0].second);
1079 }
Douglas Gregor4dde7492010-07-23 23:58:40 +00001080 }
Douglas Gregor028d3e42010-08-09 20:45:32 +00001081
1082 // If we aren't allowed to rebuild the precompiled preamble, just
1083 // return now.
1084 if (!AllowRebuild)
1085 return 0;
Douglas Gregorbb6a8812010-10-08 04:03:57 +00001086
Douglas Gregor4dde7492010-07-23 23:58:40 +00001087 // We can't reuse the previously-computed preamble. Build a new one.
1088 Preamble.clear();
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001089 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001090 PreambleRebuildCounter = 1;
Douglas Gregor028d3e42010-08-09 20:45:32 +00001091 } else if (!AllowRebuild) {
1092 // We aren't allowed to rebuild the precompiled preamble; just
1093 // return now.
1094 return 0;
1095 }
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001096
1097 // If the preamble rebuild counter > 1, it's because we previously
1098 // failed to build a preamble and we're not yet ready to try
1099 // again. Decrement the counter and return a failure.
1100 if (PreambleRebuildCounter > 1) {
1101 --PreambleRebuildCounter;
1102 return 0;
1103 }
1104
Douglas Gregore10f0e52010-09-11 17:56:52 +00001105 // Create a temporary file for the precompiled preamble. In rare
1106 // circumstances, this can fail.
1107 std::string PreamblePCHPath = GetPreamblePCHPath();
1108 if (PreamblePCHPath.empty()) {
1109 // Try again next time.
1110 PreambleRebuildCounter = 1;
1111 return 0;
1112 }
1113
Douglas Gregor4dde7492010-07-23 23:58:40 +00001114 // We did not previously compute a preamble, or it can't be reused anyway.
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001115 llvm::Timer *PreambleTimer = 0;
1116 if (TimerGroup.get()) {
1117 PreambleTimer = new llvm::Timer("Precompiling preamble", *TimerGroup);
1118 PreambleTimer->startTimer();
1119 Timers.push_back(PreambleTimer);
1120 }
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001121
1122 // Create a new buffer that stores the preamble. The buffer also contains
1123 // extra space for the original contents of the file (which will be present
1124 // when we actually parse the file) along with more room in case the file
Douglas Gregor4dde7492010-07-23 23:58:40 +00001125 // grows.
1126 PreambleReservedSize = NewPreamble.first->getBufferSize();
1127 if (PreambleReservedSize < 4096)
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001128 PreambleReservedSize = 8191;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001129 else
Douglas Gregor4dde7492010-07-23 23:58:40 +00001130 PreambleReservedSize *= 2;
1131
Douglas Gregord9a30af2010-08-02 20:51:39 +00001132 // Save the preamble text for later; we'll need to compare against it for
1133 // subsequent reparses.
1134 Preamble.assign(NewPreamble.first->getBufferStart(),
1135 NewPreamble.first->getBufferStart()
1136 + NewPreamble.second.first);
1137 PreambleEndsAtStartOfLine = NewPreamble.second.second;
1138
Douglas Gregora0734c52010-08-19 01:33:06 +00001139 delete PreambleBuffer;
1140 PreambleBuffer
Douglas Gregor4dde7492010-07-23 23:58:40 +00001141 = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001142 FrontendOpts.Inputs[0].second);
1143 memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
Douglas Gregor4dde7492010-07-23 23:58:40 +00001144 NewPreamble.first->getBufferStart(), Preamble.size());
1145 memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001146 ' ', PreambleReservedSize - Preamble.size() - 1);
1147 const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001148
1149 // Remap the main source file to the preamble buffer.
Douglas Gregor4dde7492010-07-23 23:58:40 +00001150 llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001151 PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
1152
1153 // Tell the compiler invocation to generate a temporary precompiled header.
1154 FrontendOpts.ProgramAction = frontend::GeneratePCH;
Douglas Gregor9e136b52010-10-01 01:05:22 +00001155 FrontendOpts.ChainedPCH = true;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001156 // FIXME: Generate the precompiled header into memory?
Douglas Gregore10f0e52010-09-11 17:56:52 +00001157 FrontendOpts.OutputFile = PreamblePCHPath;
Douglas Gregorbb6a8812010-10-08 04:03:57 +00001158 PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
1159 PreprocessorOpts.PrecompiledPreambleBytes.second = false;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001160
1161 // Create the compiler instance to use for building the precompiled preamble.
1162 CompilerInstance Clang;
1163 Clang.setInvocation(&PreambleInvocation);
1164 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
1165
Douglas Gregor8e984da2010-08-04 16:47:14 +00001166 // Set up diagnostics, capturing all of the diagnostics produced.
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001167 Clang.setDiagnostics(&getDiagnostics());
Douglas Gregor8e984da2010-08-04 16:47:14 +00001168 CaptureDroppedDiagnostics Capture(CaptureDiagnostics,
1169 getDiagnostics(),
1170 StoredDiagnostics);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001171
1172 // Create the target instance.
1173 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
1174 Clang.getTargetOpts()));
1175 if (!Clang.hasTarget()) {
Douglas Gregor4dde7492010-07-23 23:58:40 +00001176 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
1177 Preamble.clear();
1178 if (CreatedPreambleBuffer)
1179 delete NewPreamble.first;
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001180 if (PreambleTimer)
1181 PreambleTimer->stopTimer();
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001182 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregora0734c52010-08-19 01:33:06 +00001183 PreprocessorOpts.eraseRemappedFile(
1184 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor6481ef12010-07-24 00:38:13 +00001185 return 0;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001186 }
1187
1188 // Inform the target of the language options.
1189 //
1190 // FIXME: We shouldn't need to do this, the target should be immutable once
1191 // created. This complexity should be lifted elsewhere.
1192 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
1193
1194 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
1195 "Invocation must have exactly one source file!");
1196 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
1197 "FIXME: AST inputs not yet supported here!");
1198 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
1199 "IR inputs not support here!");
1200
1201 // Clear out old caches and data.
Douglas Gregorbb6a8812010-10-08 04:03:57 +00001202 getDiagnostics().Reset();
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00001203 ProcessWarningOptions(getDiagnostics(), Clang.getDiagnosticOpts());
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001204 StoredDiagnostics.clear();
Douglas Gregore9db88f2010-08-03 19:06:41 +00001205 TopLevelDecls.clear();
1206 TopLevelDeclsInPreamble.clear();
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001207
1208 // Create a file manager object to provide access to and cache the filesystem.
1209 Clang.setFileManager(new FileManager);
1210
1211 // Create the source manager.
1212 Clang.setSourceManager(new SourceManager(getDiagnostics()));
1213
Douglas Gregor48c8cd32010-08-03 08:14:03 +00001214 llvm::OwningPtr<PrecompilePreambleAction> Act;
1215 Act.reset(new PrecompilePreambleAction(*this));
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001216 if (!Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
1217 Clang.getFrontendOpts().Inputs[0].first)) {
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001218 Clang.takeInvocation();
Douglas Gregor4dde7492010-07-23 23:58:40 +00001219 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
1220 Preamble.clear();
1221 if (CreatedPreambleBuffer)
1222 delete NewPreamble.first;
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001223 if (PreambleTimer)
1224 PreambleTimer->stopTimer();
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001225 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregora0734c52010-08-19 01:33:06 +00001226 PreprocessorOpts.eraseRemappedFile(
1227 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor6481ef12010-07-24 00:38:13 +00001228 return 0;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001229 }
1230
1231 Act->Execute();
1232 Act->EndSourceFile();
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001233 Clang.takeInvocation();
1234
Douglas Gregore9db88f2010-08-03 19:06:41 +00001235 if (Diagnostics->hasErrorOccurred()) {
Douglas Gregor4dde7492010-07-23 23:58:40 +00001236 // There were errors parsing the preamble, so no precompiled header was
1237 // generated. Forget that we even tried.
Douglas Gregora6f74e22010-09-27 16:43:25 +00001238 // FIXME: Should we leave a note for ourselves to try again?
Douglas Gregor4dde7492010-07-23 23:58:40 +00001239 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
1240 Preamble.clear();
1241 if (CreatedPreambleBuffer)
1242 delete NewPreamble.first;
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001243 if (PreambleTimer)
1244 PreambleTimer->stopTimer();
Douglas Gregore9db88f2010-08-03 19:06:41 +00001245 TopLevelDeclsInPreamble.clear();
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001246 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregora0734c52010-08-19 01:33:06 +00001247 PreprocessorOpts.eraseRemappedFile(
1248 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor6481ef12010-07-24 00:38:13 +00001249 return 0;
Douglas Gregor4dde7492010-07-23 23:58:40 +00001250 }
1251
1252 // Keep track of the preamble we precompiled.
1253 PreambleFile = FrontendOpts.OutputFile;
Douglas Gregord9a30af2010-08-02 20:51:39 +00001254 NumStoredDiagnosticsInPreamble = StoredDiagnostics.size();
1255 NumWarningsInPreamble = getDiagnostics().getNumWarnings();
Douglas Gregor0e119552010-07-31 00:40:00 +00001256
1257 // Keep track of all of the files that the source manager knows about,
1258 // so we can verify whether they have changed or not.
1259 FilesInPreamble.clear();
1260 SourceManager &SourceMgr = Clang.getSourceManager();
1261 const llvm::MemoryBuffer *MainFileBuffer
1262 = SourceMgr.getBuffer(SourceMgr.getMainFileID());
1263 for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(),
1264 FEnd = SourceMgr.fileinfo_end();
1265 F != FEnd;
1266 ++F) {
1267 const FileEntry *File = F->second->Entry;
1268 if (!File || F->second->getRawBuffer() == MainFileBuffer)
1269 continue;
1270
1271 FilesInPreamble[File->getName()]
1272 = std::make_pair(F->second->getSize(), File->getModificationTime());
1273 }
1274
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001275 if (PreambleTimer)
1276 PreambleTimer->stopTimer();
Douglas Gregora6f74e22010-09-27 16:43:25 +00001277
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001278 PreambleRebuildCounter = 1;
Douglas Gregora0734c52010-08-19 01:33:06 +00001279 PreprocessorOpts.eraseRemappedFile(
1280 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor6481ef12010-07-24 00:38:13 +00001281 return CreatePaddedMainFileBuffer(NewPreamble.first,
1282 CreatedPreambleBuffer,
1283 PreambleReservedSize,
1284 FrontendOpts.Inputs[0].second);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001285}
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001286
Douglas Gregore9db88f2010-08-03 19:06:41 +00001287void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
1288 std::vector<Decl *> Resolved;
1289 Resolved.reserve(TopLevelDeclsInPreamble.size());
1290 ExternalASTSource &Source = *getASTContext().getExternalSource();
1291 for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
1292 // Resolve the declaration ID to an actual declaration, possibly
1293 // deserializing the declaration in the process.
1294 Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
1295 if (D)
1296 Resolved.push_back(D);
1297 }
1298 TopLevelDeclsInPreamble.clear();
1299 TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
1300}
1301
1302unsigned ASTUnit::getMaxPCHLevel() const {
1303 if (!getOnlyLocalDecls())
1304 return Decl::MaxPCHLevel;
1305
Sebastian Redl009e7f22010-10-05 16:15:19 +00001306 return 0;
Douglas Gregore9db88f2010-08-03 19:06:41 +00001307}
1308
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001309ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
1310 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
1311 bool OnlyLocalDecls,
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001312 bool CaptureDiagnostics,
Douglas Gregor028d3e42010-08-09 20:45:32 +00001313 bool PrecompilePreamble,
Douglas Gregorb14904c2010-08-13 22:48:40 +00001314 bool CompleteTranslationUnit,
1315 bool CacheCodeCompletionResults) {
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001316 if (!Diags.getPtr()) {
1317 // No diagnostics engine was provided, so create our own diagnostics object
1318 // with the default options.
1319 DiagnosticOptions DiagOpts;
1320 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
1321 }
1322
1323 // Create the AST unit.
1324 llvm::OwningPtr<ASTUnit> AST;
1325 AST.reset(new ASTUnit(false));
1326 AST->Diagnostics = Diags;
1327 AST->CaptureDiagnostics = CaptureDiagnostics;
1328 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregor028d3e42010-08-09 20:45:32 +00001329 AST->CompleteTranslationUnit = CompleteTranslationUnit;
Douglas Gregorb14904c2010-08-13 22:48:40 +00001330 AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001331 AST->Invocation.reset(CI);
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001332 CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001333
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001334 if (getenv("LIBCLANG_TIMING"))
1335 AST->TimerGroup.reset(
1336 new llvm::TimerGroup(CI->getFrontendOpts().Inputs[0].second));
1337
1338
Douglas Gregor6481ef12010-07-24 00:38:13 +00001339 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregora5fd5222010-07-28 22:12:37 +00001340 // FIXME: When C++ PCH is ready, allow use of it for a precompiled preamble.
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001341 if (PrecompilePreamble && !CI->getLangOpts().CPlusPlus) {
1342 AST->PreambleRebuildCounter = 1;
Douglas Gregorb97b6662010-08-20 00:59:43 +00001343 OverrideMainBuffer
1344 = AST->getMainBufferWithPrecompiledPreamble(*AST->Invocation);
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001345 }
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001346
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001347 llvm::Timer *ParsingTimer = 0;
1348 if (AST->TimerGroup.get()) {
1349 ParsingTimer = new llvm::Timer("Initial parse", *AST->TimerGroup);
1350 ParsingTimer->startTimer();
1351 AST->Timers.push_back(ParsingTimer);
1352 }
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001353
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001354 bool Failed = AST->Parse(OverrideMainBuffer);
1355 if (ParsingTimer)
1356 ParsingTimer->stopTimer();
1357
1358 return Failed? 0 : AST.take();
Daniel Dunbar764c0822009-12-01 09:51:01 +00001359}
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001360
1361ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
1362 const char **ArgEnd,
Douglas Gregor7f95d262010-04-05 23:52:57 +00001363 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Daniel Dunbar8d4a2022009-12-13 03:46:13 +00001364 llvm::StringRef ResourceFilesPath,
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001365 bool OnlyLocalDecls,
Douglas Gregoraa98ed92010-01-23 00:14:00 +00001366 RemappedFile *RemappedFiles,
Douglas Gregor33cdd812010-02-18 18:08:43 +00001367 unsigned NumRemappedFiles,
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001368 bool CaptureDiagnostics,
Douglas Gregor028d3e42010-08-09 20:45:32 +00001369 bool PrecompilePreamble,
Douglas Gregorb14904c2010-08-13 22:48:40 +00001370 bool CompleteTranslationUnit,
1371 bool CacheCodeCompletionResults) {
Douglas Gregor2dd19f12010-08-18 22:29:43 +00001372 bool CreatedDiagnosticsObject = false;
1373
Douglas Gregor7f95d262010-04-05 23:52:57 +00001374 if (!Diags.getPtr()) {
Douglas Gregord03e8232010-04-05 21:10:19 +00001375 // No diagnostics engine was provided, so create our own diagnostics object
1376 // with the default options.
1377 DiagnosticOptions DiagOpts;
Douglas Gregor7f95d262010-04-05 23:52:57 +00001378 Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
Douglas Gregor2dd19f12010-08-18 22:29:43 +00001379 CreatedDiagnosticsObject = true;
Douglas Gregord03e8232010-04-05 21:10:19 +00001380 }
1381
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001382 llvm::SmallVector<const char *, 16> Args;
1383 Args.push_back("<clang>"); // FIXME: Remove dummy argument.
1384 Args.insert(Args.end(), ArgBegin, ArgEnd);
1385
1386 // FIXME: Find a cleaner way to force the driver into restricted modes. We
1387 // also want to force it to use clang.
1388 Args.push_back("-fsyntax-only");
1389
Daniel Dunbar8d4a2022009-12-13 03:46:13 +00001390 // FIXME: We shouldn't have to pass in the path info.
Daniel Dunbare38764c2010-07-19 00:44:04 +00001391 driver::Driver TheDriver("clang", llvm::sys::getHostTriple(),
Douglas Gregord03e8232010-04-05 21:10:19 +00001392 "a.out", false, false, *Diags);
Daniel Dunbarfcf2d422010-01-25 00:44:02 +00001393
1394 // Don't check that inputs exist, they have been remapped.
1395 TheDriver.setCheckInputsExist(false);
1396
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001397 llvm::OwningPtr<driver::Compilation> C(
1398 TheDriver.BuildCompilation(Args.size(), Args.data()));
1399
1400 // We expect to get back exactly one command job, if we didn't something
1401 // failed.
1402 const driver::JobList &Jobs = C->getJobs();
1403 if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
1404 llvm::SmallString<256> Msg;
1405 llvm::raw_svector_ostream OS(Msg);
1406 C->PrintJob(OS, C->getJobs(), "; ", true);
Douglas Gregord03e8232010-04-05 21:10:19 +00001407 Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001408 return 0;
1409 }
1410
1411 const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
1412 if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
Douglas Gregord03e8232010-04-05 21:10:19 +00001413 Diags->Report(diag::err_fe_expected_clang_command);
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001414 return 0;
1415 }
1416
1417 const driver::ArgStringList &CCArgs = Cmd->getArguments();
Daniel Dunbar6b03ece2010-01-30 21:47:16 +00001418 llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
Dan Gohman145f3f12010-04-19 16:39:44 +00001419 CompilerInvocation::CreateFromArgs(*CI,
1420 const_cast<const char **>(CCArgs.data()),
1421 const_cast<const char **>(CCArgs.data()) +
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001422 CCArgs.size(),
Douglas Gregord03e8232010-04-05 21:10:19 +00001423 *Diags);
Daniel Dunbard6136772009-12-13 03:45:58 +00001424
Douglas Gregoraa98ed92010-01-23 00:14:00 +00001425 // Override any files that need remapping
1426 for (unsigned I = 0; I != NumRemappedFiles; ++I)
Daniel Dunbar6b03ece2010-01-30 21:47:16 +00001427 CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
Daniel Dunbar19511922010-02-16 01:55:04 +00001428 RemappedFiles[I].second);
Douglas Gregoraa98ed92010-01-23 00:14:00 +00001429
Daniel Dunbara5a166d2009-12-15 00:06:45 +00001430 // Override the resources path.
Daniel Dunbar6b03ece2010-01-30 21:47:16 +00001431 CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001432
Douglas Gregor4c6ed902010-08-18 23:38:21 +00001433 CI->getFrontendOpts().DisableFree = false;
Douglas Gregor33cdd812010-02-18 18:08:43 +00001434 return LoadFromCompilerInvocation(CI.take(), Diags, OnlyLocalDecls,
Douglas Gregor028d3e42010-08-09 20:45:32 +00001435 CaptureDiagnostics, PrecompilePreamble,
Douglas Gregorb14904c2010-08-13 22:48:40 +00001436 CompleteTranslationUnit,
1437 CacheCodeCompletionResults);
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001438}
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001439
1440bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
1441 if (!Invocation.get())
1442 return true;
1443
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001444 llvm::Timer *ReparsingTimer = 0;
1445 if (TimerGroup.get()) {
1446 ReparsingTimer = new llvm::Timer("Reparse", *TimerGroup);
1447 ReparsingTimer->startTimer();
1448 Timers.push_back(ReparsingTimer);
1449 }
1450
Douglas Gregor0e119552010-07-31 00:40:00 +00001451 // Remap files.
Douglas Gregor7b02b582010-08-20 00:02:33 +00001452 PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
1453 for (PreprocessorOptions::remapped_file_buffer_iterator
1454 R = PPOpts.remapped_file_buffer_begin(),
1455 REnd = PPOpts.remapped_file_buffer_end();
1456 R != REnd;
1457 ++R) {
1458 delete R->second;
1459 }
Douglas Gregor0e119552010-07-31 00:40:00 +00001460 Invocation->getPreprocessorOpts().clearRemappedFiles();
1461 for (unsigned I = 0; I != NumRemappedFiles; ++I)
1462 Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1463 RemappedFiles[I].second);
1464
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001465 // If we have a preamble file lying around, or if we might try to
1466 // build a precompiled preamble, do so now.
Douglas Gregor6481ef12010-07-24 00:38:13 +00001467 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001468 if (!PreambleFile.empty() || PreambleRebuildCounter > 0)
Douglas Gregorb97b6662010-08-20 00:59:43 +00001469 OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
Douglas Gregor4dde7492010-07-23 23:58:40 +00001470
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001471 // Clear out the diagnostics state.
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00001472 if (!OverrideMainBuffer) {
Douglas Gregord9a30af2010-08-02 20:51:39 +00001473 getDiagnostics().Reset();
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00001474 ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
1475 }
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001476
Douglas Gregor4dde7492010-07-23 23:58:40 +00001477 // Parse the sources
Douglas Gregor6481ef12010-07-24 00:38:13 +00001478 bool Result = Parse(OverrideMainBuffer);
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001479 if (ReparsingTimer)
1480 ReparsingTimer->stopTimer();
Douglas Gregor2c8bd472010-08-17 00:40:40 +00001481
1482 if (ShouldCacheCodeCompletionResults) {
1483 if (CacheCodeCompletionCoolDown > 0)
1484 --CacheCodeCompletionCoolDown;
1485 else if (top_level_size() != NumTopLevelDeclsAtLastCompletionCache)
1486 CacheCodeCompletionResults();
1487 }
1488
Douglas Gregor4dde7492010-07-23 23:58:40 +00001489 return Result;
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001490}
Douglas Gregor8e984da2010-08-04 16:47:14 +00001491
Douglas Gregorb14904c2010-08-13 22:48:40 +00001492//----------------------------------------------------------------------------//
1493// Code completion
1494//----------------------------------------------------------------------------//
1495
1496namespace {
1497 /// \brief Code completion consumer that combines the cached code-completion
1498 /// results from an ASTUnit with the code-completion results provided to it,
1499 /// then passes the result on to
1500 class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
1501 unsigned NormalContexts;
1502 ASTUnit &AST;
1503 CodeCompleteConsumer &Next;
1504
1505 public:
1506 AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
Douglas Gregor39982192010-08-15 06:18:01 +00001507 bool IncludeMacros, bool IncludeCodePatterns,
1508 bool IncludeGlobals)
1509 : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
Douglas Gregorb14904c2010-08-13 22:48:40 +00001510 Next.isOutputBinary()), AST(AST), Next(Next)
1511 {
1512 // Compute the set of contexts in which we will look when we don't have
1513 // any information about the specific context.
1514 NormalContexts
1515 = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
1516 | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
1517 | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
1518 | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
1519 | (1 << (CodeCompletionContext::CCC_Statement - 1))
1520 | (1 << (CodeCompletionContext::CCC_Expression - 1))
1521 | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
1522 | (1 << (CodeCompletionContext::CCC_MemberAccess - 1))
Douglas Gregor5e35d592010-09-14 23:59:36 +00001523 | (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1))
Douglas Gregor0ac41382010-09-23 23:01:17 +00001524 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
1525 | (1 << (CodeCompletionContext::CCC_Recovery - 1));
Douglas Gregor5e35d592010-09-14 23:59:36 +00001526
Douglas Gregorb14904c2010-08-13 22:48:40 +00001527 if (AST.getASTContext().getLangOptions().CPlusPlus)
1528 NormalContexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1))
1529 | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
1530 | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
1531 }
1532
1533 virtual void ProcessCodeCompleteResults(Sema &S,
1534 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00001535 CodeCompletionResult *Results,
Douglas Gregord46cf182010-08-16 20:01:48 +00001536 unsigned NumResults);
Douglas Gregorb14904c2010-08-13 22:48:40 +00001537
1538 virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
1539 OverloadCandidate *Candidates,
1540 unsigned NumCandidates) {
1541 Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
1542 }
1543 };
1544}
Douglas Gregord46cf182010-08-16 20:01:48 +00001545
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001546/// \brief Helper function that computes which global names are hidden by the
1547/// local code-completion results.
1548void CalculateHiddenNames(const CodeCompletionContext &Context,
John McCall276321a2010-08-25 06:19:51 +00001549 CodeCompletionResult *Results,
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001550 unsigned NumResults,
1551 ASTContext &Ctx,
1552 llvm::StringSet<> &HiddenNames) {
1553 bool OnlyTagNames = false;
1554 switch (Context.getKind()) {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001555 case CodeCompletionContext::CCC_Recovery:
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001556 case CodeCompletionContext::CCC_TopLevel:
1557 case CodeCompletionContext::CCC_ObjCInterface:
1558 case CodeCompletionContext::CCC_ObjCImplementation:
1559 case CodeCompletionContext::CCC_ObjCIvarList:
1560 case CodeCompletionContext::CCC_ClassStructUnion:
1561 case CodeCompletionContext::CCC_Statement:
1562 case CodeCompletionContext::CCC_Expression:
1563 case CodeCompletionContext::CCC_ObjCMessageReceiver:
1564 case CodeCompletionContext::CCC_MemberAccess:
1565 case CodeCompletionContext::CCC_Namespace:
1566 case CodeCompletionContext::CCC_Type:
Douglas Gregorc49f5b22010-08-23 18:23:48 +00001567 case CodeCompletionContext::CCC_Name:
1568 case CodeCompletionContext::CCC_PotentiallyQualifiedName:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001569 case CodeCompletionContext::CCC_ParenthesizedExpression:
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001570 break;
1571
1572 case CodeCompletionContext::CCC_EnumTag:
1573 case CodeCompletionContext::CCC_UnionTag:
1574 case CodeCompletionContext::CCC_ClassOrStructTag:
1575 OnlyTagNames = true;
1576 break;
1577
1578 case CodeCompletionContext::CCC_ObjCProtocolName:
Douglas Gregor12785102010-08-24 20:21:13 +00001579 case CodeCompletionContext::CCC_MacroName:
1580 case CodeCompletionContext::CCC_MacroNameUse:
Douglas Gregorec00a262010-08-24 22:20:20 +00001581 case CodeCompletionContext::CCC_PreprocessorExpression:
Douglas Gregor0de55ce2010-08-25 18:41:16 +00001582 case CodeCompletionContext::CCC_PreprocessorDirective:
Douglas Gregorea147052010-08-25 18:04:30 +00001583 case CodeCompletionContext::CCC_NaturalLanguage:
Douglas Gregor67c692c2010-08-26 15:07:07 +00001584 case CodeCompletionContext::CCC_SelectorName:
Douglas Gregor28c78432010-08-27 17:35:51 +00001585 case CodeCompletionContext::CCC_TypeQualifiers:
Douglas Gregor0ac41382010-09-23 23:01:17 +00001586 case CodeCompletionContext::CCC_Other:
Douglas Gregor0de55ce2010-08-25 18:41:16 +00001587 // We're looking for nothing, or we're looking for names that cannot
1588 // be hidden.
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001589 return;
1590 }
1591
John McCall276321a2010-08-25 06:19:51 +00001592 typedef CodeCompletionResult Result;
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001593 for (unsigned I = 0; I != NumResults; ++I) {
1594 if (Results[I].Kind != Result::RK_Declaration)
1595 continue;
1596
1597 unsigned IDNS
1598 = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
1599
1600 bool Hiding = false;
1601 if (OnlyTagNames)
1602 Hiding = (IDNS & Decl::IDNS_Tag);
1603 else {
1604 unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
Douglas Gregor59cab552010-08-16 23:05:20 +00001605 Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
1606 Decl::IDNS_NonMemberOperator);
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001607 if (Ctx.getLangOptions().CPlusPlus)
1608 HiddenIDNS |= Decl::IDNS_Tag;
1609 Hiding = (IDNS & HiddenIDNS);
1610 }
1611
1612 if (!Hiding)
1613 continue;
1614
1615 DeclarationName Name = Results[I].Declaration->getDeclName();
1616 if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
1617 HiddenNames.insert(Identifier->getName());
1618 else
1619 HiddenNames.insert(Name.getAsString());
1620 }
1621}
1622
1623
Douglas Gregord46cf182010-08-16 20:01:48 +00001624void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
1625 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00001626 CodeCompletionResult *Results,
Douglas Gregord46cf182010-08-16 20:01:48 +00001627 unsigned NumResults) {
1628 // Merge the results we were given with the results we cached.
1629 bool AddedResult = false;
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001630 unsigned InContexts
Douglas Gregor0ac41382010-09-23 23:01:17 +00001631 = (Context.getKind() == CodeCompletionContext::CCC_Recovery? NormalContexts
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001632 : (1 << (Context.getKind() - 1)));
1633
1634 // Contains the set of names that are hidden by "local" completion results.
1635 llvm::StringSet<> HiddenNames;
Douglas Gregor12785102010-08-24 20:21:13 +00001636 llvm::SmallVector<CodeCompletionString *, 4> StringsToDestroy;
John McCall276321a2010-08-25 06:19:51 +00001637 typedef CodeCompletionResult Result;
Douglas Gregord46cf182010-08-16 20:01:48 +00001638 llvm::SmallVector<Result, 8> AllResults;
1639 for (ASTUnit::cached_completion_iterator
Douglas Gregordf239672010-08-16 21:23:13 +00001640 C = AST.cached_completion_begin(),
1641 CEnd = AST.cached_completion_end();
Douglas Gregord46cf182010-08-16 20:01:48 +00001642 C != CEnd; ++C) {
1643 // If the context we are in matches any of the contexts we are
1644 // interested in, we'll add this result.
1645 if ((C->ShowInContexts & InContexts) == 0)
1646 continue;
1647
1648 // If we haven't added any results previously, do so now.
1649 if (!AddedResult) {
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001650 CalculateHiddenNames(Context, Results, NumResults, S.Context,
1651 HiddenNames);
Douglas Gregord46cf182010-08-16 20:01:48 +00001652 AllResults.insert(AllResults.end(), Results, Results + NumResults);
1653 AddedResult = true;
1654 }
1655
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001656 // Determine whether this global completion result is hidden by a local
1657 // completion result. If so, skip it.
1658 if (C->Kind != CXCursor_MacroDefinition &&
1659 HiddenNames.count(C->Completion->getTypedText()))
1660 continue;
1661
Douglas Gregord46cf182010-08-16 20:01:48 +00001662 // Adjust priority based on similar type classes.
1663 unsigned Priority = C->Priority;
Douglas Gregor8850aa32010-08-25 18:03:13 +00001664 CXCursorKind CursorKind = C->Kind;
Douglas Gregor12785102010-08-24 20:21:13 +00001665 CodeCompletionString *Completion = C->Completion;
Douglas Gregord46cf182010-08-16 20:01:48 +00001666 if (!Context.getPreferredType().isNull()) {
1667 if (C->Kind == CXCursor_MacroDefinition) {
1668 Priority = getMacroUsagePriority(C->Completion->getTypedText(),
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001669 S.getLangOptions(),
Douglas Gregor12785102010-08-24 20:21:13 +00001670 Context.getPreferredType()->isAnyPointerType());
Douglas Gregord46cf182010-08-16 20:01:48 +00001671 } else if (C->Type) {
1672 CanQualType Expected
Douglas Gregordf239672010-08-16 21:23:13 +00001673 = S.Context.getCanonicalType(
Douglas Gregord46cf182010-08-16 20:01:48 +00001674 Context.getPreferredType().getUnqualifiedType());
1675 SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
1676 if (ExpectedSTC == C->TypeClass) {
1677 // We know this type is similar; check for an exact match.
1678 llvm::StringMap<unsigned> &CachedCompletionTypes
Douglas Gregordf239672010-08-16 21:23:13 +00001679 = AST.getCachedCompletionTypes();
Douglas Gregord46cf182010-08-16 20:01:48 +00001680 llvm::StringMap<unsigned>::iterator Pos
Douglas Gregordf239672010-08-16 21:23:13 +00001681 = CachedCompletionTypes.find(QualType(Expected).getAsString());
Douglas Gregord46cf182010-08-16 20:01:48 +00001682 if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)
1683 Priority /= CCF_ExactTypeMatch;
1684 else
1685 Priority /= CCF_SimilarTypeMatch;
1686 }
1687 }
1688 }
1689
Douglas Gregor12785102010-08-24 20:21:13 +00001690 // Adjust the completion string, if required.
1691 if (C->Kind == CXCursor_MacroDefinition &&
1692 Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
1693 // Create a new code-completion string that just contains the
1694 // macro name, without its arguments.
1695 Completion = new CodeCompletionString;
1696 Completion->AddTypedTextChunk(C->Completion->getTypedText());
1697 StringsToDestroy.push_back(Completion);
Douglas Gregor8850aa32010-08-25 18:03:13 +00001698 CursorKind = CXCursor_NotImplemented;
1699 Priority = CCP_CodePattern;
Douglas Gregor12785102010-08-24 20:21:13 +00001700 }
1701
Douglas Gregor8850aa32010-08-25 18:03:13 +00001702 AllResults.push_back(Result(Completion, Priority, CursorKind,
Douglas Gregorf757a122010-08-23 23:00:57 +00001703 C->Availability));
Douglas Gregord46cf182010-08-16 20:01:48 +00001704 }
1705
1706 // If we did not add any cached completion results, just forward the
1707 // results we were given to the next consumer.
1708 if (!AddedResult) {
1709 Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
1710 return;
1711 }
Douglas Gregor49f67ce2010-08-26 13:48:20 +00001712
Douglas Gregord46cf182010-08-16 20:01:48 +00001713 Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
1714 AllResults.size());
Douglas Gregor12785102010-08-24 20:21:13 +00001715
1716 for (unsigned I = 0, N = StringsToDestroy.size(); I != N; ++I)
1717 delete StringsToDestroy[I];
Douglas Gregord46cf182010-08-16 20:01:48 +00001718}
1719
1720
1721
Douglas Gregor8e984da2010-08-04 16:47:14 +00001722void ASTUnit::CodeComplete(llvm::StringRef File, unsigned Line, unsigned Column,
1723 RemappedFile *RemappedFiles,
1724 unsigned NumRemappedFiles,
Douglas Gregorb68bc592010-08-05 09:09:23 +00001725 bool IncludeMacros,
1726 bool IncludeCodePatterns,
Douglas Gregor8e984da2010-08-04 16:47:14 +00001727 CodeCompleteConsumer &Consumer,
1728 Diagnostic &Diag, LangOptions &LangOpts,
1729 SourceManager &SourceMgr, FileManager &FileMgr,
Douglas Gregorb97b6662010-08-20 00:59:43 +00001730 llvm::SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
1731 llvm::SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
Douglas Gregor8e984da2010-08-04 16:47:14 +00001732 if (!Invocation.get())
1733 return;
1734
Douglas Gregor028d3e42010-08-09 20:45:32 +00001735 llvm::Timer *CompletionTimer = 0;
1736 if (TimerGroup.get()) {
1737 llvm::SmallString<128> TimerName;
1738 llvm::raw_svector_ostream TimerNameOut(TimerName);
1739 TimerNameOut << "Code completion @ " << File << ":" << Line << ":"
1740 << Column;
1741 CompletionTimer = new llvm::Timer(TimerNameOut.str(), *TimerGroup);
1742 CompletionTimer->startTimer();
1743 Timers.push_back(CompletionTimer);
1744 }
1745
Douglas Gregor8e984da2010-08-04 16:47:14 +00001746 CompilerInvocation CCInvocation(*Invocation);
1747 FrontendOptions &FrontendOpts = CCInvocation.getFrontendOpts();
1748 PreprocessorOptions &PreprocessorOpts = CCInvocation.getPreprocessorOpts();
Douglas Gregorb68bc592010-08-05 09:09:23 +00001749
Douglas Gregorb14904c2010-08-13 22:48:40 +00001750 FrontendOpts.ShowMacrosInCodeCompletion
1751 = IncludeMacros && CachedCompletionResults.empty();
Douglas Gregorb68bc592010-08-05 09:09:23 +00001752 FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns;
Douglas Gregor39982192010-08-15 06:18:01 +00001753 FrontendOpts.ShowGlobalSymbolsInCodeCompletion
1754 = CachedCompletionResults.empty();
Douglas Gregor8e984da2010-08-04 16:47:14 +00001755 FrontendOpts.CodeCompletionAt.FileName = File;
1756 FrontendOpts.CodeCompletionAt.Line = Line;
1757 FrontendOpts.CodeCompletionAt.Column = Column;
1758
1759 // Set the language options appropriately.
1760 LangOpts = CCInvocation.getLangOpts();
1761
1762 CompilerInstance Clang;
1763 Clang.setInvocation(&CCInvocation);
1764 OriginalSourceFile = Clang.getFrontendOpts().Inputs[0].second;
1765
1766 // Set up diagnostics, capturing any diagnostics produced.
1767 Clang.setDiagnostics(&Diag);
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00001768 ProcessWarningOptions(Diag, CCInvocation.getDiagnosticOpts());
Douglas Gregor8e984da2010-08-04 16:47:14 +00001769 CaptureDroppedDiagnostics Capture(true,
1770 Clang.getDiagnostics(),
1771 StoredDiagnostics);
Douglas Gregor8e984da2010-08-04 16:47:14 +00001772
1773 // Create the target instance.
1774 Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
1775 Clang.getTargetOpts()));
1776 if (!Clang.hasTarget()) {
Douglas Gregor8e984da2010-08-04 16:47:14 +00001777 Clang.takeInvocation();
Douglas Gregor2dd19f12010-08-18 22:29:43 +00001778 return;
Douglas Gregor8e984da2010-08-04 16:47:14 +00001779 }
1780
1781 // Inform the target of the language options.
1782 //
1783 // FIXME: We shouldn't need to do this, the target should be immutable once
1784 // created. This complexity should be lifted elsewhere.
1785 Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
1786
1787 assert(Clang.getFrontendOpts().Inputs.size() == 1 &&
1788 "Invocation must have exactly one source file!");
1789 assert(Clang.getFrontendOpts().Inputs[0].first != IK_AST &&
1790 "FIXME: AST inputs not yet supported here!");
1791 assert(Clang.getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
1792 "IR inputs not support here!");
1793
1794
1795 // Use the source and file managers that we were given.
1796 Clang.setFileManager(&FileMgr);
1797 Clang.setSourceManager(&SourceMgr);
1798
1799 // Remap files.
1800 PreprocessorOpts.clearRemappedFiles();
Douglas Gregord8a5dba2010-08-04 17:07:00 +00001801 PreprocessorOpts.RetainRemappedFileBuffers = true;
Douglas Gregorb97b6662010-08-20 00:59:43 +00001802 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
Douglas Gregor8e984da2010-08-04 16:47:14 +00001803 PreprocessorOpts.addRemappedFile(RemappedFiles[I].first,
1804 RemappedFiles[I].second);
Douglas Gregorb97b6662010-08-20 00:59:43 +00001805 OwnedBuffers.push_back(RemappedFiles[I].second);
1806 }
Douglas Gregor8e984da2010-08-04 16:47:14 +00001807
Douglas Gregorb14904c2010-08-13 22:48:40 +00001808 // Use the code completion consumer we were given, but adding any cached
1809 // code-completion results.
1810 AugmentedCodeCompleteConsumer
1811 AugmentedConsumer(*this, Consumer, FrontendOpts.ShowMacrosInCodeCompletion,
Douglas Gregor39982192010-08-15 06:18:01 +00001812 FrontendOpts.ShowCodePatternsInCodeCompletion,
1813 FrontendOpts.ShowGlobalSymbolsInCodeCompletion);
Douglas Gregorb14904c2010-08-13 22:48:40 +00001814 Clang.setCodeCompletionConsumer(&AugmentedConsumer);
Douglas Gregor8e984da2010-08-04 16:47:14 +00001815
Douglas Gregor028d3e42010-08-09 20:45:32 +00001816 // If we have a precompiled preamble, try to use it. We only allow
1817 // the use of the precompiled preamble if we're if the completion
1818 // point is within the main file, after the end of the precompiled
1819 // preamble.
1820 llvm::MemoryBuffer *OverrideMainBuffer = 0;
1821 if (!PreambleFile.empty()) {
1822 using llvm::sys::FileStatus;
1823 llvm::sys::PathWithStatus CompleteFilePath(File);
1824 llvm::sys::PathWithStatus MainPath(OriginalSourceFile);
1825 if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus())
1826 if (const FileStatus *MainStatus = MainPath.getFileStatus())
1827 if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID())
Douglas Gregorb97b6662010-08-20 00:59:43 +00001828 OverrideMainBuffer
Douglas Gregor8e817b62010-08-25 18:04:15 +00001829 = getMainBufferWithPrecompiledPreamble(CCInvocation, false,
1830 Line - 1);
Douglas Gregor028d3e42010-08-09 20:45:32 +00001831 }
1832
1833 // If the main file has been overridden due to the use of a preamble,
1834 // make that override happen and introduce the preamble.
1835 if (OverrideMainBuffer) {
1836 PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
1837 PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
1838 PreprocessorOpts.PrecompiledPreambleBytes.second
1839 = PreambleEndsAtStartOfLine;
1840 PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
1841 PreprocessorOpts.DisablePCHValidation = true;
1842
1843 // The stored diagnostics have the old source manager. Copy them
1844 // to our output set of stored diagnostics, updating the source
1845 // manager to the one we were given.
1846 for (unsigned I = 0, N = this->StoredDiagnostics.size(); I != N; ++I) {
1847 StoredDiagnostics.push_back(this->StoredDiagnostics[I]);
1848 FullSourceLoc Loc(StoredDiagnostics[I].getLocation(), SourceMgr);
1849 StoredDiagnostics[I].setLocation(Loc);
1850 }
Douglas Gregorb97b6662010-08-20 00:59:43 +00001851
1852 OwnedBuffers.push_back(OverrideMainBuffer);
Douglas Gregor7b02b582010-08-20 00:02:33 +00001853 } else {
1854 PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
1855 PreprocessorOpts.PrecompiledPreambleBytes.second = false;
Douglas Gregor028d3e42010-08-09 20:45:32 +00001856 }
1857
Douglas Gregor8e984da2010-08-04 16:47:14 +00001858 llvm::OwningPtr<SyntaxOnlyAction> Act;
1859 Act.reset(new SyntaxOnlyAction);
1860 if (Act->BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0].second,
1861 Clang.getFrontendOpts().Inputs[0].first)) {
1862 Act->Execute();
1863 Act->EndSourceFile();
1864 }
Douglas Gregor028d3e42010-08-09 20:45:32 +00001865
1866 if (CompletionTimer)
1867 CompletionTimer->stopTimer();
Douglas Gregor8e984da2010-08-04 16:47:14 +00001868
1869 // Steal back our resources.
1870 Clang.takeFileManager();
1871 Clang.takeSourceManager();
1872 Clang.takeInvocation();
Douglas Gregor8e984da2010-08-04 16:47:14 +00001873 Clang.takeCodeCompletionConsumer();
1874}
Douglas Gregore9386682010-08-13 05:36:37 +00001875
1876bool ASTUnit::Save(llvm::StringRef File) {
1877 if (getDiagnostics().hasErrorOccurred())
1878 return true;
1879
1880 // FIXME: Can we somehow regenerate the stat cache here, or do we need to
1881 // unconditionally create a stat cache when we parse the file?
1882 std::string ErrorInfo;
Benjamin Kramer340045b2010-08-15 16:54:31 +00001883 llvm::raw_fd_ostream Out(File.str().c_str(), ErrorInfo,
1884 llvm::raw_fd_ostream::F_Binary);
Douglas Gregore9386682010-08-13 05:36:37 +00001885 if (!ErrorInfo.empty() || Out.has_error())
1886 return true;
1887
1888 std::vector<unsigned char> Buffer;
1889 llvm::BitstreamWriter Stream(Buffer);
Sebastian Redl55c0ad52010-08-18 23:56:21 +00001890 ASTWriter Writer(Stream);
1891 Writer.WriteAST(getSema(), 0, 0);
Douglas Gregore9386682010-08-13 05:36:37 +00001892
1893 // Write the generated bitstream to "Out".
Douglas Gregor2dd19f12010-08-18 22:29:43 +00001894 if (!Buffer.empty())
1895 Out.write((char *)&Buffer.front(), Buffer.size());
Douglas Gregore9386682010-08-13 05:36:37 +00001896 Out.close();
1897 return Out.has_error();
1898}