blob: b8551e9a420c9063764bcd03d563f2fe569e24ca [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"
Argyrios Kyrtzidisbc1f48f2011-03-07 22:45:01 +000023#include "clang/Driver/ArgList.h"
24#include "clang/Driver/Options.h"
Daniel Dunbar55a17b62009-12-02 03:23:45 +000025#include "clang/Driver/Tool.h"
Daniel Dunbar764c0822009-12-01 09:51:01 +000026#include "clang/Frontend/CompilerInstance.h"
27#include "clang/Frontend/FrontendActions.h"
Daniel Dunbar55a17b62009-12-02 03:23:45 +000028#include "clang/Frontend/FrontendDiagnostic.h"
Daniel Dunbar764c0822009-12-01 09:51:01 +000029#include "clang/Frontend/FrontendOptions.h"
Douglas Gregor36e3b5c2010-10-11 21:37:58 +000030#include "clang/Frontend/Utils.h"
Sebastian Redlf5b13462010-08-18 23:57:17 +000031#include "clang/Serialization/ASTReader.h"
Douglas Gregorf88e35b2010-11-30 06:16:57 +000032#include "clang/Serialization/ASTSerializationListener.h"
Sebastian Redl1914c6f2010-08-18 23:56:37 +000033#include "clang/Serialization/ASTWriter.h"
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000034#include "clang/Lex/HeaderSearch.h"
35#include "clang/Lex/Preprocessor.h"
Daniel Dunbarb9bbd542009-11-15 06:48:46 +000036#include "clang/Basic/TargetOptions.h"
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000037#include "clang/Basic/TargetInfo.h"
38#include "clang/Basic/Diagnostic.h"
Chris Lattnerce6c42f2011-03-23 04:04:01 +000039#include "llvm/ADT/ArrayRef.h"
Douglas Gregordf7a79a2011-02-16 18:16:54 +000040#include "llvm/ADT/StringExtras.h"
Douglas Gregor40a5a7d2010-08-16 23:08:34 +000041#include "llvm/ADT/StringSet.h"
Douglas Gregor9aeaa4d2010-12-07 00:05:48 +000042#include "llvm/Support/Atomic.h"
Douglas Gregoraa98ed92010-01-23 00:14:00 +000043#include "llvm/Support/MemoryBuffer.h"
Michael J. Spencer8aaf4992010-11-29 18:12:39 +000044#include "llvm/Support/Host.h"
45#include "llvm/Support/Path.h"
Douglas Gregor028d3e42010-08-09 20:45:32 +000046#include "llvm/Support/raw_ostream.h"
Douglas Gregor15ba0b32010-07-30 20:58:08 +000047#include "llvm/Support/Timer.h"
Argyrios Kyrtzidis55e75572011-07-21 18:44:49 +000048#include "llvm/Support/FileSystem.h"
Ted Kremenek4422bfe2011-03-18 02:06:56 +000049#include "llvm/Support/CrashRecoveryContext.h"
Douglas Gregorbe2d8c62010-07-23 00:33:23 +000050#include <cstdlib>
Zhongxing Xu318e4032010-07-23 02:15:08 +000051#include <cstdio>
Douglas Gregor0e119552010-07-31 00:40:00 +000052#include <sys/stat.h>
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +000053using namespace clang;
54
Douglas Gregor16896c42010-10-28 15:44:59 +000055using llvm::TimeRecord;
56
57namespace {
58 class SimpleTimer {
59 bool WantTiming;
60 TimeRecord Start;
61 std::string Output;
62
Benjamin Kramerf2e5a912010-11-09 20:00:56 +000063 public:
Douglas Gregor1cbdd952010-11-01 13:48:43 +000064 explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) {
Douglas Gregor16896c42010-10-28 15:44:59 +000065 if (WantTiming)
Benjamin Kramerf2e5a912010-11-09 20:00:56 +000066 Start = TimeRecord::getCurrentTime();
Douglas Gregor16896c42010-10-28 15:44:59 +000067 }
68
Chris Lattner0e62c1c2011-07-23 10:55:15 +000069 void setOutput(const Twine &Output) {
Douglas Gregor16896c42010-10-28 15:44:59 +000070 if (WantTiming)
Benjamin Kramerf2e5a912010-11-09 20:00:56 +000071 this->Output = Output.str();
Douglas Gregor16896c42010-10-28 15:44:59 +000072 }
73
Douglas Gregor16896c42010-10-28 15:44:59 +000074 ~SimpleTimer() {
75 if (WantTiming) {
76 TimeRecord Elapsed = TimeRecord::getCurrentTime();
77 Elapsed -= Start;
78 llvm::errs() << Output << ':';
79 Elapsed.print(Elapsed, llvm::errs());
80 llvm::errs() << '\n';
81 }
82 }
83 };
84}
85
Douglas Gregorbb420ab2010-08-04 05:53:38 +000086/// \brief After failing to build a precompiled preamble (due to
87/// errors in the source that occurs in the preamble), the number of
88/// reparses during which we'll skip even trying to precompile the
89/// preamble.
90const unsigned DefaultPreambleRebuildInterval = 5;
91
Douglas Gregor68dbaea2010-11-17 00:13:31 +000092/// \brief Tracks the number of ASTUnit objects that are currently active.
93///
94/// Used for debugging purposes only.
Douglas Gregor9aeaa4d2010-12-07 00:05:48 +000095static llvm::sys::cas_flag ActiveASTUnitObjects;
Douglas Gregor68dbaea2010-11-17 00:13:31 +000096
Douglas Gregord03e8232010-04-05 21:10:19 +000097ASTUnit::ASTUnit(bool _MainFileIsAST)
Argyrios Kyrtzidis35dcda72011-03-09 17:21:42 +000098 : OnlyLocalDecls(false), CaptureDiagnostics(false),
99 MainFileIsAST(_MainFileIsAST),
Douglas Gregor69f74f82011-08-25 22:30:56 +0000100 TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
Argyrios Kyrtzidis4954bc12011-03-05 01:03:48 +0000101 OwnsRemappedFileBuffers(true),
Douglas Gregor16896c42010-10-28 15:44:59 +0000102 NumStoredDiagnosticsFromDriver(0),
Douglas Gregor7bb8af62010-10-12 00:50:20 +0000103 ConcurrencyCheckValue(CheckUnlocked),
Douglas Gregora0734c52010-08-19 01:33:06 +0000104 PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
Douglas Gregor2c8bd472010-08-17 00:40:40 +0000105 ShouldCacheCodeCompletionResults(false),
Chandler Carruthde81fc82011-07-14 09:02:10 +0000106 NestedMacroExpansions(true),
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000107 CompletionCacheTopLevelHashValue(0),
108 PreambleTopLevelHashValue(0),
109 CurrentTopLevelHashValue(0),
Douglas Gregor4740c452010-08-19 00:45:44 +0000110 UnsafeToFree(false) {
Douglas Gregor68dbaea2010-11-17 00:13:31 +0000111 if (getenv("LIBCLANG_OBJTRACKING")) {
Douglas Gregor9aeaa4d2010-12-07 00:05:48 +0000112 llvm::sys::AtomicIncrement(&ActiveASTUnitObjects);
Douglas Gregor68dbaea2010-11-17 00:13:31 +0000113 fprintf(stderr, "+++ %d translation units\n", ActiveASTUnitObjects);
114 }
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000115}
Douglas Gregord03e8232010-04-05 21:10:19 +0000116
Daniel Dunbar764c0822009-12-01 09:51:01 +0000117ASTUnit::~ASTUnit() {
Douglas Gregor0c7c2f82010-03-05 21:16:25 +0000118 ConcurrencyCheckValue = CheckLocked;
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000119 CleanTemporaryFiles();
Douglas Gregor4dde7492010-07-23 23:58:40 +0000120 if (!PreambleFile.empty())
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000121 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000122
123 // Free the buffers associated with remapped files. We are required to
124 // perform this operation here because we explicitly request that the
125 // compiler instance *not* free these buffers for each invocation of the
126 // parser.
Ted Kremenek5e14d392011-03-21 18:40:17 +0000127 if (Invocation.getPtr() && OwnsRemappedFileBuffers) {
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000128 PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
129 for (PreprocessorOptions::remapped_file_buffer_iterator
130 FB = PPOpts.remapped_file_buffer_begin(),
131 FBEnd = PPOpts.remapped_file_buffer_end();
132 FB != FBEnd;
133 ++FB)
134 delete FB->second;
135 }
Douglas Gregor96c04262010-07-27 14:52:07 +0000136
137 delete SavedMainFileBuffer;
Douglas Gregora0734c52010-08-19 01:33:06 +0000138 delete PreambleBuffer;
139
Douglas Gregor16896c42010-10-28 15:44:59 +0000140 ClearCachedCompletionResults();
Douglas Gregor68dbaea2010-11-17 00:13:31 +0000141
142 if (getenv("LIBCLANG_OBJTRACKING")) {
Douglas Gregor9aeaa4d2010-12-07 00:05:48 +0000143 llvm::sys::AtomicDecrement(&ActiveASTUnitObjects);
Douglas Gregor68dbaea2010-11-17 00:13:31 +0000144 fprintf(stderr, "--- %d translation units\n", ActiveASTUnitObjects);
145 }
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000146}
147
148void ASTUnit::CleanTemporaryFiles() {
Douglas Gregor6cb5ba42010-02-18 23:35:40 +0000149 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
150 TemporaryFiles[I].eraseFromDisk();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000151 TemporaryFiles.clear();
Steve Naroff44cd60e2009-10-15 22:23:48 +0000152}
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000153
Douglas Gregor39982192010-08-15 06:18:01 +0000154/// \brief Determine the set of code-completion contexts in which this
155/// declaration should be shown.
156static unsigned getDeclShowContexts(NamedDecl *ND,
Douglas Gregor59cab552010-08-16 23:05:20 +0000157 const LangOptions &LangOpts,
158 bool &IsNestedNameSpecifier) {
159 IsNestedNameSpecifier = false;
160
Douglas Gregor39982192010-08-15 06:18:01 +0000161 if (isa<UsingShadowDecl>(ND))
162 ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl());
163 if (!ND)
164 return 0;
165
166 unsigned Contexts = 0;
167 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
168 isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) {
169 // Types can appear in these contexts.
170 if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
171 Contexts |= (1 << (CodeCompletionContext::CCC_TopLevel - 1))
172 | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
173 | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
174 | (1 << (CodeCompletionContext::CCC_Statement - 1))
Douglas Gregor5e35d592010-09-14 23:59:36 +0000175 | (1 << (CodeCompletionContext::CCC_Type - 1))
176 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1));
Douglas Gregor39982192010-08-15 06:18:01 +0000177
178 // In C++, types can appear in expressions contexts (for functional casts).
179 if (LangOpts.CPlusPlus)
180 Contexts |= (1 << (CodeCompletionContext::CCC_Expression - 1));
181
182 // In Objective-C, message sends can send interfaces. In Objective-C++,
183 // all types are available due to functional casts.
184 if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
185 Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
Douglas Gregor21325842011-07-07 16:03:39 +0000186
187 // In Objective-C, you can only be a subclass of another Objective-C class
188 if (isa<ObjCInterfaceDecl>(ND))
Douglas Gregor2c595ad2011-07-30 06:55:39 +0000189 Contexts |= (1 << (CodeCompletionContext::CCC_ObjCInterfaceName - 1));
Douglas Gregor39982192010-08-15 06:18:01 +0000190
191 // Deal with tag names.
192 if (isa<EnumDecl>(ND)) {
193 Contexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1));
194
Douglas Gregor59cab552010-08-16 23:05:20 +0000195 // Part of the nested-name-specifier in C++0x.
Douglas Gregor39982192010-08-15 06:18:01 +0000196 if (LangOpts.CPlusPlus0x)
Douglas Gregor59cab552010-08-16 23:05:20 +0000197 IsNestedNameSpecifier = true;
Douglas Gregor39982192010-08-15 06:18:01 +0000198 } else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) {
199 if (Record->isUnion())
200 Contexts |= (1 << (CodeCompletionContext::CCC_UnionTag - 1));
201 else
202 Contexts |= (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
203
Douglas Gregor39982192010-08-15 06:18:01 +0000204 if (LangOpts.CPlusPlus)
Douglas Gregor59cab552010-08-16 23:05:20 +0000205 IsNestedNameSpecifier = true;
Douglas Gregor0ac41382010-09-23 23:01:17 +0000206 } else if (isa<ClassTemplateDecl>(ND))
Douglas Gregor59cab552010-08-16 23:05:20 +0000207 IsNestedNameSpecifier = true;
Douglas Gregor39982192010-08-15 06:18:01 +0000208 } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
209 // Values can appear in these contexts.
210 Contexts = (1 << (CodeCompletionContext::CCC_Statement - 1))
211 | (1 << (CodeCompletionContext::CCC_Expression - 1))
Douglas Gregor5e35d592010-09-14 23:59:36 +0000212 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
Douglas Gregor39982192010-08-15 06:18:01 +0000213 | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
214 } else if (isa<ObjCProtocolDecl>(ND)) {
215 Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
Douglas Gregor21325842011-07-07 16:03:39 +0000216 } else if (isa<ObjCCategoryDecl>(ND)) {
217 Contexts = (1 << (CodeCompletionContext::CCC_ObjCCategoryName - 1));
Douglas Gregor39982192010-08-15 06:18:01 +0000218 } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
Douglas Gregor59cab552010-08-16 23:05:20 +0000219 Contexts = (1 << (CodeCompletionContext::CCC_Namespace - 1));
Douglas Gregor39982192010-08-15 06:18:01 +0000220
221 // Part of the nested-name-specifier.
Douglas Gregor59cab552010-08-16 23:05:20 +0000222 IsNestedNameSpecifier = true;
Douglas Gregor39982192010-08-15 06:18:01 +0000223 }
224
225 return Contexts;
226}
227
Douglas Gregorb14904c2010-08-13 22:48:40 +0000228void ASTUnit::CacheCodeCompletionResults() {
229 if (!TheSema)
230 return;
231
Douglas Gregor16896c42010-10-28 15:44:59 +0000232 SimpleTimer Timer(WantTiming);
Benjamin Kramerf2e5a912010-11-09 20:00:56 +0000233 Timer.setOutput("Cache global code completions for " + getMainFileName());
Douglas Gregorb14904c2010-08-13 22:48:40 +0000234
235 // Clear out the previous results.
236 ClearCachedCompletionResults();
237
238 // Gather the set of global code completions.
John McCall276321a2010-08-25 06:19:51 +0000239 typedef CodeCompletionResult Result;
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000240 SmallVector<Result, 8> Results;
Douglas Gregor162b7122011-02-16 19:08:06 +0000241 CachedCompletionAllocator = new GlobalCodeCompletionAllocator;
242 TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator, Results);
Douglas Gregorb14904c2010-08-13 22:48:40 +0000243
244 // Translate global code completions into cached completions.
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000245 llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
246
Douglas Gregorb14904c2010-08-13 22:48:40 +0000247 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
248 switch (Results[I].Kind) {
Douglas Gregor39982192010-08-15 06:18:01 +0000249 case Result::RK_Declaration: {
Douglas Gregor59cab552010-08-16 23:05:20 +0000250 bool IsNestedNameSpecifier = false;
Douglas Gregor39982192010-08-15 06:18:01 +0000251 CachedCodeCompletionResult CachedResult;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000252 CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema,
Douglas Gregor162b7122011-02-16 19:08:06 +0000253 *CachedCompletionAllocator);
Douglas Gregor39982192010-08-15 06:18:01 +0000254 CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
Douglas Gregor59cab552010-08-16 23:05:20 +0000255 Ctx->getLangOptions(),
256 IsNestedNameSpecifier);
Douglas Gregor39982192010-08-15 06:18:01 +0000257 CachedResult.Priority = Results[I].Priority;
258 CachedResult.Kind = Results[I].CursorKind;
Douglas Gregorf757a122010-08-23 23:00:57 +0000259 CachedResult.Availability = Results[I].Availability;
Douglas Gregor24747402010-08-16 16:46:30 +0000260
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000261 // Keep track of the type of this completion in an ASTContext-agnostic
262 // way.
Douglas Gregor24747402010-08-16 16:46:30 +0000263 QualType UsageType = getDeclUsageType(*Ctx, Results[I].Declaration);
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000264 if (UsageType.isNull()) {
Douglas Gregor24747402010-08-16 16:46:30 +0000265 CachedResult.TypeClass = STC_Void;
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000266 CachedResult.Type = 0;
267 } else {
268 CanQualType CanUsageType
269 = Ctx->getCanonicalType(UsageType.getUnqualifiedType());
270 CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
271
272 // Determine whether we have already seen this type. If so, we save
273 // ourselves the work of formatting the type string by using the
274 // temporary, CanQualType-based hash table to find the associated value.
275 unsigned &TypeValue = CompletionTypes[CanUsageType];
276 if (TypeValue == 0) {
277 TypeValue = CompletionTypes.size();
278 CachedCompletionTypes[QualType(CanUsageType).getAsString()]
279 = TypeValue;
280 }
281
282 CachedResult.Type = TypeValue;
Douglas Gregor24747402010-08-16 16:46:30 +0000283 }
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000284
Douglas Gregor39982192010-08-15 06:18:01 +0000285 CachedCompletionResults.push_back(CachedResult);
Douglas Gregor59cab552010-08-16 23:05:20 +0000286
287 /// Handle nested-name-specifiers in C++.
288 if (TheSema->Context.getLangOptions().CPlusPlus &&
289 IsNestedNameSpecifier && !Results[I].StartsNestedNameSpecifier) {
290 // The contexts in which a nested-name-specifier can appear in C++.
291 unsigned NNSContexts
292 = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
293 | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
294 | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
295 | (1 << (CodeCompletionContext::CCC_Statement - 1))
296 | (1 << (CodeCompletionContext::CCC_Expression - 1))
297 | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
298 | (1 << (CodeCompletionContext::CCC_EnumTag - 1))
299 | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
300 | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1))
Douglas Gregorc49f5b22010-08-23 18:23:48 +0000301 | (1 << (CodeCompletionContext::CCC_Type - 1))
Douglas Gregor5e35d592010-09-14 23:59:36 +0000302 | (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1))
303 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1));
Douglas Gregor59cab552010-08-16 23:05:20 +0000304
305 if (isa<NamespaceDecl>(Results[I].Declaration) ||
306 isa<NamespaceAliasDecl>(Results[I].Declaration))
307 NNSContexts |= (1 << (CodeCompletionContext::CCC_Namespace - 1));
308
309 if (unsigned RemainingContexts
310 = NNSContexts & ~CachedResult.ShowInContexts) {
311 // If there any contexts where this completion can be a
312 // nested-name-specifier but isn't already an option, create a
313 // nested-name-specifier completion.
314 Results[I].StartsNestedNameSpecifier = true;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000315 CachedResult.Completion
316 = Results[I].CreateCodeCompletionString(*TheSema,
Douglas Gregor162b7122011-02-16 19:08:06 +0000317 *CachedCompletionAllocator);
Douglas Gregor59cab552010-08-16 23:05:20 +0000318 CachedResult.ShowInContexts = RemainingContexts;
319 CachedResult.Priority = CCP_NestedNameSpecifier;
320 CachedResult.TypeClass = STC_Void;
321 CachedResult.Type = 0;
322 CachedCompletionResults.push_back(CachedResult);
323 }
324 }
Douglas Gregorb14904c2010-08-13 22:48:40 +0000325 break;
Douglas Gregor39982192010-08-15 06:18:01 +0000326 }
327
Douglas Gregorb14904c2010-08-13 22:48:40 +0000328 case Result::RK_Keyword:
329 case Result::RK_Pattern:
330 // Ignore keywords and patterns; we don't care, since they are so
331 // easily regenerated.
332 break;
333
334 case Result::RK_Macro: {
335 CachedCodeCompletionResult CachedResult;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000336 CachedResult.Completion
337 = Results[I].CreateCodeCompletionString(*TheSema,
Douglas Gregor162b7122011-02-16 19:08:06 +0000338 *CachedCompletionAllocator);
Douglas Gregorb14904c2010-08-13 22:48:40 +0000339 CachedResult.ShowInContexts
340 = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
341 | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
342 | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
343 | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
344 | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
345 | (1 << (CodeCompletionContext::CCC_Statement - 1))
346 | (1 << (CodeCompletionContext::CCC_Expression - 1))
Douglas Gregor12785102010-08-24 20:21:13 +0000347 | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
Douglas Gregorec00a262010-08-24 22:20:20 +0000348 | (1 << (CodeCompletionContext::CCC_MacroNameUse - 1))
Douglas Gregor5e35d592010-09-14 23:59:36 +0000349 | (1 << (CodeCompletionContext::CCC_PreprocessorExpression - 1))
Douglas Gregor3a69eaf2011-02-18 23:30:37 +0000350 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
351 | (1 << (CodeCompletionContext::CCC_OtherWithMacros - 1));
Douglas Gregorc49f5b22010-08-23 18:23:48 +0000352
Douglas Gregorb14904c2010-08-13 22:48:40 +0000353 CachedResult.Priority = Results[I].Priority;
354 CachedResult.Kind = Results[I].CursorKind;
Douglas Gregorf757a122010-08-23 23:00:57 +0000355 CachedResult.Availability = Results[I].Availability;
Douglas Gregor6e240332010-08-16 16:18:59 +0000356 CachedResult.TypeClass = STC_Void;
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000357 CachedResult.Type = 0;
Douglas Gregorb14904c2010-08-13 22:48:40 +0000358 CachedCompletionResults.push_back(CachedResult);
359 break;
360 }
361 }
Douglas Gregorb14904c2010-08-13 22:48:40 +0000362 }
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000363
364 // Save the current top-level hash value.
365 CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;
Douglas Gregorb14904c2010-08-13 22:48:40 +0000366}
367
368void ASTUnit::ClearCachedCompletionResults() {
Douglas Gregorb14904c2010-08-13 22:48:40 +0000369 CachedCompletionResults.clear();
Douglas Gregorb61c07a2010-08-16 18:08:11 +0000370 CachedCompletionTypes.clear();
Douglas Gregor162b7122011-02-16 19:08:06 +0000371 CachedCompletionAllocator = 0;
Douglas Gregorb14904c2010-08-13 22:48:40 +0000372}
373
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000374namespace {
375
Sebastian Redl2c499f62010-08-18 23:56:43 +0000376/// \brief Gathers information from ASTReader that will be used to initialize
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000377/// a Preprocessor.
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000378class ASTInfoCollector : public ASTReaderListener {
Douglas Gregor83297df2011-09-01 23:39:15 +0000379 Preprocessor &PP;
Douglas Gregore8bbc122011-09-02 00:18:52 +0000380 ASTContext &Context;
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000381 LangOptions &LangOpt;
382 HeaderSearch &HSI;
Douglas Gregor83297df2011-09-01 23:39:15 +0000383 llvm::IntrusiveRefCntPtr<TargetInfo> &Target;
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000384 std::string &Predefines;
385 unsigned &Counter;
Mike Stump11289f42009-09-09 15:08:12 +0000386
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000387 unsigned NumHeaderInfos;
Mike Stump11289f42009-09-09 15:08:12 +0000388
Douglas Gregore8bbc122011-09-02 00:18:52 +0000389 bool InitializedLanguage;
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000390public:
Douglas Gregore8bbc122011-09-02 00:18:52 +0000391 ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt,
392 HeaderSearch &HSI,
Douglas Gregor83297df2011-09-01 23:39:15 +0000393 llvm::IntrusiveRefCntPtr<TargetInfo> &Target,
394 std::string &Predefines,
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000395 unsigned &Counter)
Douglas Gregore8bbc122011-09-02 00:18:52 +0000396 : PP(PP), Context(Context), LangOpt(LangOpt), HSI(HSI), Target(Target),
Douglas Gregor83297df2011-09-01 23:39:15 +0000397 Predefines(Predefines), Counter(Counter), NumHeaderInfos(0),
Douglas Gregore8bbc122011-09-02 00:18:52 +0000398 InitializedLanguage(false) {}
Mike Stump11289f42009-09-09 15:08:12 +0000399
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000400 virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
Douglas Gregore8bbc122011-09-02 00:18:52 +0000401 if (InitializedLanguage)
Douglas Gregor83297df2011-09-01 23:39:15 +0000402 return false;
403
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000404 LangOpt = LangOpts;
Douglas Gregor83297df2011-09-01 23:39:15 +0000405
406 // Initialize the preprocessor.
407 PP.Initialize(*Target);
Douglas Gregore8bbc122011-09-02 00:18:52 +0000408
409 // Initialize the ASTContext
410 Context.InitBuiltinTypes(*Target);
411
412 InitializedLanguage = true;
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000413 return false;
414 }
Mike Stump11289f42009-09-09 15:08:12 +0000415
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000416 virtual bool ReadTargetTriple(StringRef Triple) {
Douglas Gregor83297df2011-09-01 23:39:15 +0000417 // If we've already initialized the target, don't do it again.
418 if (Target)
419 return false;
420
421 // FIXME: This is broken, we should store the TargetOptions in the AST file.
422 TargetOptions TargetOpts;
423 TargetOpts.ABI = "";
424 TargetOpts.CXXABI = "";
425 TargetOpts.CPU = "";
426 TargetOpts.Features.clear();
427 TargetOpts.Triple = Triple;
428 Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(), TargetOpts);
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000429 return false;
430 }
Mike Stump11289f42009-09-09 15:08:12 +0000431
Sebastian Redl8b41f302010-07-14 23:29:55 +0000432 virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000433 StringRef OriginalFileName,
Nick Lewycky36079892011-02-23 21:16:44 +0000434 std::string &SuggestedPredefines,
435 FileManager &FileMgr) {
Sebastian Redl8b41f302010-07-14 23:29:55 +0000436 Predefines = Buffers[0].Data;
437 for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
438 Predefines += Buffers[I].Data;
439 }
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000440 return false;
441 }
Mike Stump11289f42009-09-09 15:08:12 +0000442
Douglas Gregora2f49452010-03-16 19:09:18 +0000443 virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000444 HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
445 }
Mike Stump11289f42009-09-09 15:08:12 +0000446
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000447 virtual void ReadCounter(unsigned Value) {
448 Counter = Value;
449 }
450};
451
Douglas Gregor33cdd812010-02-18 18:08:43 +0000452class StoredDiagnosticClient : public DiagnosticClient {
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000453 SmallVectorImpl<StoredDiagnostic> &StoredDiags;
Douglas Gregor33cdd812010-02-18 18:08:43 +0000454
455public:
456 explicit StoredDiagnosticClient(
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000457 SmallVectorImpl<StoredDiagnostic> &StoredDiags)
Douglas Gregor33cdd812010-02-18 18:08:43 +0000458 : StoredDiags(StoredDiags) { }
459
460 virtual void HandleDiagnostic(Diagnostic::Level Level,
461 const DiagnosticInfo &Info);
462};
463
464/// \brief RAII object that optionally captures diagnostics, if
465/// there is no diagnostic client to capture them already.
466class CaptureDroppedDiagnostics {
467 Diagnostic &Diags;
468 StoredDiagnosticClient Client;
469 DiagnosticClient *PreviousClient;
470
471public:
472 CaptureDroppedDiagnostics(bool RequestCapture, Diagnostic &Diags,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000473 SmallVectorImpl<StoredDiagnostic> &StoredDiags)
Douglas Gregor2dd19f12010-08-18 22:29:43 +0000474 : Diags(Diags), Client(StoredDiags), PreviousClient(0)
Douglas Gregor33cdd812010-02-18 18:08:43 +0000475 {
Douglas Gregor2dd19f12010-08-18 22:29:43 +0000476 if (RequestCapture || Diags.getClient() == 0) {
477 PreviousClient = Diags.takeClient();
Douglas Gregor33cdd812010-02-18 18:08:43 +0000478 Diags.setClient(&Client);
Douglas Gregor2dd19f12010-08-18 22:29:43 +0000479 }
Douglas Gregor33cdd812010-02-18 18:08:43 +0000480 }
481
482 ~CaptureDroppedDiagnostics() {
Douglas Gregor2dd19f12010-08-18 22:29:43 +0000483 if (Diags.getClient() == &Client) {
484 Diags.takeClient();
485 Diags.setClient(PreviousClient);
486 }
Douglas Gregor33cdd812010-02-18 18:08:43 +0000487 }
488};
489
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000490} // anonymous namespace
491
Douglas Gregor33cdd812010-02-18 18:08:43 +0000492void StoredDiagnosticClient::HandleDiagnostic(Diagnostic::Level Level,
493 const DiagnosticInfo &Info) {
Argyrios Kyrtzidisc79346a2010-11-18 20:06:46 +0000494 // Default implementation (Warnings/errors count).
495 DiagnosticClient::HandleDiagnostic(Level, Info);
496
Douglas Gregor33cdd812010-02-18 18:08:43 +0000497 StoredDiags.push_back(StoredDiagnostic(Level, Info));
498}
499
Steve Naroffc0683b92009-09-03 18:19:54 +0000500const std::string &ASTUnit::getOriginalSourceFileName() {
Daniel Dunbara8a50932009-12-02 08:44:16 +0000501 return OriginalSourceFile;
Steve Naroffc0683b92009-09-03 18:19:54 +0000502}
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000503
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000504llvm::MemoryBuffer *ASTUnit::getBufferForFile(StringRef Filename,
Chris Lattner26b5c192010-11-23 09:19:42 +0000505 std::string *ErrorStr) {
Chris Lattner5159f612010-11-23 08:35:12 +0000506 assert(FileMgr);
Chris Lattner26b5c192010-11-23 09:19:42 +0000507 return FileMgr->getBufferForFile(Filename, ErrorStr);
Argyrios Kyrtzidis71731d62010-11-03 22:45:23 +0000508}
509
Douglas Gregor44c6ee72010-11-11 00:39:14 +0000510/// \brief Configure the diagnostics object for use with ASTUnit.
511void ASTUnit::ConfigureDiags(llvm::IntrusiveRefCntPtr<Diagnostic> &Diags,
Douglas Gregor345c1bc2011-01-19 01:02:47 +0000512 const char **ArgBegin, const char **ArgEnd,
Douglas Gregor44c6ee72010-11-11 00:39:14 +0000513 ASTUnit &AST, bool CaptureDiagnostics) {
514 if (!Diags.getPtr()) {
515 // No diagnostics engine was provided, so create our own diagnostics object
516 // with the default options.
517 DiagnosticOptions DiagOpts;
518 DiagnosticClient *Client = 0;
519 if (CaptureDiagnostics)
520 Client = new StoredDiagnosticClient(AST.StoredDiagnostics);
Douglas Gregor345c1bc2011-01-19 01:02:47 +0000521 Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd- ArgBegin,
522 ArgBegin, Client);
Douglas Gregor44c6ee72010-11-11 00:39:14 +0000523 } else if (CaptureDiagnostics) {
524 Diags->setClient(new StoredDiagnosticClient(AST.StoredDiagnostics));
525 }
526}
527
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000528ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
Douglas Gregor7f95d262010-04-05 23:52:57 +0000529 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Argyrios Kyrtzidis71731d62010-11-03 22:45:23 +0000530 const FileSystemOptions &FileSystemOpts,
Ted Kremenek8bcb1c62009-10-17 00:34:24 +0000531 bool OnlyLocalDecls,
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000532 RemappedFile *RemappedFiles,
Douglas Gregor33cdd812010-02-18 18:08:43 +0000533 unsigned NumRemappedFiles,
534 bool CaptureDiagnostics) {
Douglas Gregord03e8232010-04-05 21:10:19 +0000535 llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
Ted Kremenek4422bfe2011-03-18 02:06:56 +0000536
537 // Recover resources if we crash before exiting this method.
Ted Kremenek022a4902011-03-22 01:15:24 +0000538 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
539 ASTUnitCleanup(AST.get());
540 llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic,
541 llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> >
542 DiagCleanup(Diags.getPtr());
Ted Kremenek4422bfe2011-03-18 02:06:56 +0000543
Douglas Gregor345c1bc2011-01-19 01:02:47 +0000544 ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000545
Douglas Gregor16bef852009-10-16 20:01:17 +0000546 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregor44c6ee72010-11-11 00:39:14 +0000547 AST->CaptureDiagnostics = CaptureDiagnostics;
Douglas Gregor7f95d262010-04-05 23:52:57 +0000548 AST->Diagnostics = Diags;
Ted Kremenek5e14d392011-03-21 18:40:17 +0000549 AST->FileMgr = new FileManager(FileSystemOpts);
550 AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
551 AST->getFileManager());
Chris Lattner5159f612010-11-23 08:35:12 +0000552 AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
Douglas Gregor6fd55e02010-08-13 03:15:25 +0000553
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000554 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
Argyrios Kyrtzidis11e6f0a2011-03-05 01:03:53 +0000555 FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
556 if (const llvm::MemoryBuffer *
557 memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
558 // Create the file entry for the file that we're mapping from.
559 const FileEntry *FromFile
560 = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
561 memBuf->getBufferSize(),
562 0);
563 if (!FromFile) {
564 AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
565 << RemappedFiles[I].first;
566 delete memBuf;
567 continue;
568 }
569
570 // Override the contents of the "from" file with the contents of
571 // the "to" file.
572 AST->getSourceManager().overrideFileContents(FromFile, memBuf);
573
574 } else {
575 const char *fname = fileOrBuf.get<const char *>();
576 const FileEntry *ToFile = AST->FileMgr->getFile(fname);
577 if (!ToFile) {
578 AST->getDiagnostics().Report(diag::err_fe_remap_missing_to_file)
579 << RemappedFiles[I].first << fname;
580 continue;
581 }
582
583 // Create the file entry for the file that we're mapping from.
584 const FileEntry *FromFile
585 = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
586 ToFile->getSize(),
587 0);
588 if (!FromFile) {
589 AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
590 << RemappedFiles[I].first;
591 delete memBuf;
592 continue;
593 }
594
595 // Override the contents of the "from" file with the contents of
596 // the "to" file.
597 AST->getSourceManager().overrideFileContents(FromFile, ToFile);
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000598 }
Douglas Gregoraa98ed92010-01-23 00:14:00 +0000599 }
600
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000601 // Gather Info for preprocessor construction later on.
Mike Stump11289f42009-09-09 15:08:12 +0000602
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000603 HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000604 std::string Predefines;
605 unsigned Counter;
606
Sebastian Redl2c499f62010-08-18 23:56:43 +0000607 llvm::OwningPtr<ASTReader> Reader;
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000608
Douglas Gregor83297df2011-09-01 23:39:15 +0000609 AST->PP = new Preprocessor(AST->getDiagnostics(), AST->ASTFileLangOpts,
610 /*Target=*/0, AST->getSourceManager(), HeaderInfo,
611 *AST,
612 /*IILookup=*/0,
613 /*OwnsHeaderSearch=*/false,
614 /*DelayInitialization=*/true);
Douglas Gregore8bbc122011-09-02 00:18:52 +0000615 Preprocessor &PP = *AST->PP;
616
617 AST->Ctx = new ASTContext(AST->ASTFileLangOpts,
618 AST->getSourceManager(),
619 /*Target=*/0,
620 PP.getIdentifierTable(),
621 PP.getSelectorTable(),
622 PP.getBuiltinInfo(),
623 /* size_reserve = */0,
624 /*DelayInitialization=*/true);
625 ASTContext &Context = *AST->Ctx;
Douglas Gregor83297df2011-09-01 23:39:15 +0000626
Douglas Gregor8835e032011-09-02 00:26:20 +0000627 Reader.reset(new ASTReader(PP, Context));
Ted Kremenek2159b8d2011-05-04 23:27:12 +0000628
629 // Recover resources if we crash before exiting this method.
630 llvm::CrashRecoveryContextCleanupRegistrar<ASTReader>
631 ReaderCleanup(Reader.get());
632
Douglas Gregore8bbc122011-09-02 00:18:52 +0000633 Reader->setListener(new ASTInfoCollector(*AST->PP, Context,
Douglas Gregor83297df2011-09-01 23:39:15 +0000634 AST->ASTFileLangOpts, HeaderInfo,
635 AST->Target, Predefines, Counter));
Daniel Dunbar2d9c7402009-09-03 05:59:35 +0000636
Douglas Gregora6895d82011-07-22 16:00:58 +0000637 switch (Reader->ReadAST(Filename, serialization::MK_MainFile)) {
Sebastian Redl2c499f62010-08-18 23:56:43 +0000638 case ASTReader::Success:
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000639 break;
Mike Stump11289f42009-09-09 15:08:12 +0000640
Sebastian Redl2c499f62010-08-18 23:56:43 +0000641 case ASTReader::Failure:
642 case ASTReader::IgnorePCH:
Douglas Gregord03e8232010-04-05 21:10:19 +0000643 AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000644 return NULL;
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000645 }
Mike Stump11289f42009-09-09 15:08:12 +0000646
Daniel Dunbara8a50932009-12-02 08:44:16 +0000647 AST->OriginalSourceFile = Reader->getOriginalSourceFile();
648
Daniel Dunbarb7bbfdd2009-09-21 03:03:47 +0000649 PP.setPredefines(Reader->getSuggestedPredefines());
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000650 PP.setCounterValue(Counter);
Mike Stump11289f42009-09-09 15:08:12 +0000651
Sebastian Redl2c499f62010-08-18 23:56:43 +0000652 // Attach the AST reader to the AST context as an external AST
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000653 // source, so that declarations will be deserialized from the
Sebastian Redld44cd6a2010-08-18 23:57:06 +0000654 // AST file as needed.
Sebastian Redl2c499f62010-08-18 23:56:43 +0000655 ASTReader *ReaderPtr = Reader.get();
Douglas Gregor6fd55e02010-08-13 03:15:25 +0000656 llvm::OwningPtr<ExternalASTSource> Source(Reader.take());
Ted Kremenek2159b8d2011-05-04 23:27:12 +0000657
658 // Unregister the cleanup for ASTReader. It will get cleaned up
659 // by the ASTUnit cleanup.
660 ReaderCleanup.unregister();
661
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000662 Context.setExternalSource(Source);
663
Douglas Gregor6fd55e02010-08-13 03:15:25 +0000664 // Create an AST consumer, even though it isn't used.
665 AST->Consumer.reset(new ASTConsumer);
666
Sebastian Redl2c499f62010-08-18 23:56:43 +0000667 // Create a semantic analysis object and tell the AST reader about it.
Douglas Gregor6fd55e02010-08-13 03:15:25 +0000668 AST->TheSema.reset(new Sema(PP, Context, *AST->Consumer));
669 AST->TheSema->Initialize();
670 ReaderPtr->InitializeSema(*AST->TheSema);
671
Mike Stump11289f42009-09-09 15:08:12 +0000672 return AST.take();
Argyrios Kyrtzidisce379752009-06-20 08:08:23 +0000673}
Daniel Dunbar764c0822009-12-01 09:51:01 +0000674
675namespace {
676
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000677/// \brief Preprocessor callback class that updates a hash value with the names
678/// of all macros that have been defined by the translation unit.
679class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {
680 unsigned &Hash;
681
682public:
683 explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) { }
684
685 virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
686 Hash = llvm::HashString(MacroNameTok.getIdentifierInfo()->getName(), Hash);
687 }
688};
689
690/// \brief Add the given declaration to the hash of all top-level entities.
691void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
692 if (!D)
693 return;
694
695 DeclContext *DC = D->getDeclContext();
696 if (!DC)
697 return;
698
699 if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))
700 return;
701
702 if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
703 if (ND->getIdentifier())
704 Hash = llvm::HashString(ND->getIdentifier()->getName(), Hash);
705 else if (DeclarationName Name = ND->getDeclName()) {
706 std::string NameStr = Name.getAsString();
707 Hash = llvm::HashString(NameStr, Hash);
708 }
709 return;
710 }
711
712 if (ObjCForwardProtocolDecl *Forward
713 = dyn_cast<ObjCForwardProtocolDecl>(D)) {
714 for (ObjCForwardProtocolDecl::protocol_iterator
715 P = Forward->protocol_begin(),
716 PEnd = Forward->protocol_end();
717 P != PEnd; ++P)
718 AddTopLevelDeclarationToHash(*P, Hash);
719 return;
720 }
721
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000722 if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(D)) {
Fariborz Jahanian3a039e32011-08-27 20:50:59 +0000723 AddTopLevelDeclarationToHash(Class->getForwardInterfaceDecl(), Hash);
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000724 return;
725 }
726}
727
Daniel Dunbar644dca02009-12-04 08:17:33 +0000728class TopLevelDeclTrackerConsumer : public ASTConsumer {
729 ASTUnit &Unit;
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000730 unsigned &Hash;
731
Daniel Dunbar644dca02009-12-04 08:17:33 +0000732public:
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000733 TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)
734 : Unit(_Unit), Hash(Hash) {
735 Hash = 0;
736 }
737
Daniel Dunbar644dca02009-12-04 08:17:33 +0000738 void HandleTopLevelDecl(DeclGroupRef D) {
Ted Kremenekacc59c32010-05-03 20:16:35 +0000739 for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
740 Decl *D = *it;
741 // FIXME: Currently ObjC method declarations are incorrectly being
742 // reported as top-level declarations, even though their DeclContext
743 // is the containing ObjC @interface/@implementation. This is a
744 // fundamental problem in the parser right now.
745 if (isa<ObjCMethodDecl>(D))
746 continue;
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000747
748 AddTopLevelDeclarationToHash(D, Hash);
Douglas Gregore9db88f2010-08-03 19:06:41 +0000749 Unit.addTopLevelDecl(D);
Ted Kremenekacc59c32010-05-03 20:16:35 +0000750 }
Daniel Dunbar644dca02009-12-04 08:17:33 +0000751 }
Sebastian Redleaa4ade2010-08-11 18:52:41 +0000752
753 // We're not interested in "interesting" decls.
754 void HandleInterestingDecl(DeclGroupRef) {}
Daniel Dunbar644dca02009-12-04 08:17:33 +0000755};
756
757class TopLevelDeclTrackerAction : public ASTFrontendAction {
758public:
759 ASTUnit &Unit;
760
Daniel Dunbar764c0822009-12-01 09:51:01 +0000761 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000762 StringRef InFile) {
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000763 CI.getPreprocessor().addPPCallbacks(
764 new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue()));
765 return new TopLevelDeclTrackerConsumer(Unit,
766 Unit.getCurrentTopLevelHashValue());
Daniel Dunbar764c0822009-12-01 09:51:01 +0000767 }
768
769public:
Daniel Dunbar644dca02009-12-04 08:17:33 +0000770 TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
771
Daniel Dunbar764c0822009-12-01 09:51:01 +0000772 virtual bool hasCodeCompletionSupport() const { return false; }
Douglas Gregor69f74f82011-08-25 22:30:56 +0000773 virtual TranslationUnitKind getTranslationUnitKind() {
774 return Unit.getTranslationUnitKind();
Douglas Gregor028d3e42010-08-09 20:45:32 +0000775 }
Daniel Dunbar764c0822009-12-01 09:51:01 +0000776};
777
Douglas Gregorf88e35b2010-11-30 06:16:57 +0000778class PrecompilePreambleConsumer : public PCHGenerator,
779 public ASTSerializationListener {
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000780 ASTUnit &Unit;
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000781 unsigned &Hash;
Douglas Gregore9db88f2010-08-03 19:06:41 +0000782 std::vector<Decl *> TopLevelDecls;
Douglas Gregorf88e35b2010-11-30 06:16:57 +0000783
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000784public:
Douglas Gregor36db4f92011-08-25 22:35:51 +0000785 PrecompilePreambleConsumer(ASTUnit &Unit, const Preprocessor &PP,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000786 StringRef isysroot, raw_ostream *Out)
Douglas Gregor4a69c2e2011-09-01 17:04:32 +0000787 : PCHGenerator(PP, "", /*IsModule=*/false, isysroot, Out), Unit(Unit),
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000788 Hash(Unit.getCurrentTopLevelHashValue()) {
789 Hash = 0;
790 }
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000791
Douglas Gregore9db88f2010-08-03 19:06:41 +0000792 virtual void HandleTopLevelDecl(DeclGroupRef D) {
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000793 for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
794 Decl *D = *it;
795 // FIXME: Currently ObjC method declarations are incorrectly being
796 // reported as top-level declarations, even though their DeclContext
797 // is the containing ObjC @interface/@implementation. This is a
798 // fundamental problem in the parser right now.
799 if (isa<ObjCMethodDecl>(D))
800 continue;
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000801 AddTopLevelDeclarationToHash(D, Hash);
Douglas Gregore9db88f2010-08-03 19:06:41 +0000802 TopLevelDecls.push_back(D);
803 }
804 }
805
806 virtual void HandleTranslationUnit(ASTContext &Ctx) {
807 PCHGenerator::HandleTranslationUnit(Ctx);
808 if (!Unit.getDiagnostics().hasErrorOccurred()) {
809 // Translate the top-level declarations we captured during
810 // parsing into declaration IDs in the precompiled
811 // preamble. This will allow us to deserialize those top-level
812 // declarations when requested.
813 for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I)
814 Unit.addTopLevelDeclFromPreamble(
815 getWriter().getDeclID(TopLevelDecls[I]));
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000816 }
817 }
Douglas Gregorf88e35b2010-11-30 06:16:57 +0000818
819 virtual void SerializedPreprocessedEntity(PreprocessedEntity *Entity,
820 uint64_t Offset) {
821 Unit.addPreprocessedEntityFromPreamble(Offset);
822 }
823
824 virtual ASTSerializationListener *GetASTSerializationListener() {
825 return this;
826 }
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000827};
828
829class PrecompilePreambleAction : public ASTFrontendAction {
830 ASTUnit &Unit;
831
832public:
833 explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {}
834
835 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000836 StringRef InFile) {
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000837 std::string Sysroot;
Argyrios Kyrtzidis10b23682011-02-15 17:54:22 +0000838 std::string OutputFile;
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000839 raw_ostream *OS = 0;
Argyrios Kyrtzidis10b23682011-02-15 17:54:22 +0000840 if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
841 OutputFile,
Douglas Gregor36db4f92011-08-25 22:35:51 +0000842 OS))
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000843 return 0;
844
Douglas Gregorc567ba22011-07-22 16:35:34 +0000845 if (!CI.getFrontendOpts().RelocatablePCH)
846 Sysroot.clear();
847
Douglas Gregordf7a79a2011-02-16 18:16:54 +0000848 CI.getPreprocessor().addPPCallbacks(
849 new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue()));
Douglas Gregor36db4f92011-08-25 22:35:51 +0000850 return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Sysroot,
851 OS);
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000852 }
853
854 virtual bool hasCodeCompletionSupport() const { return false; }
855 virtual bool hasASTFileSupport() const { return false; }
Douglas Gregor69f74f82011-08-25 22:30:56 +0000856 virtual TranslationUnitKind getTranslationUnitKind() { return TU_Prefix; }
Douglas Gregor48c8cd32010-08-03 08:14:03 +0000857};
858
Daniel Dunbar764c0822009-12-01 09:51:01 +0000859}
860
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000861/// Parse the source file into a translation unit using the given compiler
862/// invocation, replacing the current translation unit.
863///
864/// \returns True if a failure occurred that causes the ASTUnit not to
865/// contain any translation-unit information, false otherwise.
Douglas Gregor6481ef12010-07-24 00:38:13 +0000866bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
Douglas Gregor96c04262010-07-27 14:52:07 +0000867 delete SavedMainFileBuffer;
868 SavedMainFileBuffer = 0;
869
Ted Kremenek5e14d392011-03-21 18:40:17 +0000870 if (!Invocation) {
Douglas Gregora0734c52010-08-19 01:33:06 +0000871 delete OverrideMainBuffer;
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000872 return true;
Douglas Gregora0734c52010-08-19 01:33:06 +0000873 }
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000874
Daniel Dunbar764c0822009-12-01 09:51:01 +0000875 // Create the compiler instance to use for building the AST.
Ted Kremenek84de4a12011-03-21 18:40:07 +0000876 llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance());
877
878 // Recover resources if we crash before exiting this method.
Ted Kremenek022a4902011-03-22 01:15:24 +0000879 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
880 CICleanup(Clang.get());
Ted Kremenek84de4a12011-03-21 18:40:07 +0000881
Ted Kremenek5e14d392011-03-21 18:40:17 +0000882 Clang->setInvocation(&*Invocation);
Ted Kremenek84de4a12011-03-21 18:40:07 +0000883 OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000884
Douglas Gregor8e984da2010-08-04 16:47:14 +0000885 // Set up diagnostics, capturing any diagnostics that would
886 // otherwise be dropped.
Ted Kremenek84de4a12011-03-21 18:40:07 +0000887 Clang->setDiagnostics(&getDiagnostics());
Douglas Gregord03e8232010-04-05 21:10:19 +0000888
Daniel Dunbar764c0822009-12-01 09:51:01 +0000889 // Create the target instance.
Ted Kremenek84de4a12011-03-21 18:40:07 +0000890 Clang->getTargetOpts().Features = TargetFeatures;
891 Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Ted Kremenek5e14d392011-03-21 18:40:17 +0000892 Clang->getTargetOpts()));
Ted Kremenek84de4a12011-03-21 18:40:07 +0000893 if (!Clang->hasTarget()) {
Douglas Gregora0734c52010-08-19 01:33:06 +0000894 delete OverrideMainBuffer;
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000895 return true;
Douglas Gregora0734c52010-08-19 01:33:06 +0000896 }
897
Daniel Dunbar764c0822009-12-01 09:51:01 +0000898 // Inform the target of the language options.
899 //
900 // FIXME: We shouldn't need to do this, the target should be immutable once
901 // created. This complexity should be lifted elsewhere.
Ted Kremenek84de4a12011-03-21 18:40:07 +0000902 Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000903
Ted Kremenek84de4a12011-03-21 18:40:07 +0000904 assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
Daniel Dunbar764c0822009-12-01 09:51:01 +0000905 "Invocation must have exactly one source file!");
Ted Kremenek84de4a12011-03-21 18:40:07 +0000906 assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
Daniel Dunbar764c0822009-12-01 09:51:01 +0000907 "FIXME: AST inputs not yet supported here!");
Ted Kremenek84de4a12011-03-21 18:40:07 +0000908 assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
Daniel Dunbar9507f9c2010-06-07 23:26:47 +0000909 "IR inputs not support here!");
Daniel Dunbar764c0822009-12-01 09:51:01 +0000910
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000911 // Configure the various subsystems.
912 // FIXME: Should we retain the previous file manager?
Ted Kremenek84de4a12011-03-21 18:40:07 +0000913 FileSystemOpts = Clang->getFileSystemOpts();
Ted Kremenek5e14d392011-03-21 18:40:17 +0000914 FileMgr = new FileManager(FileSystemOpts);
915 SourceMgr = new SourceManager(getDiagnostics(), *FileMgr);
Douglas Gregor6fd55e02010-08-13 03:15:25 +0000916 TheSema.reset();
Ted Kremenek5e14d392011-03-21 18:40:17 +0000917 Ctx = 0;
918 PP = 0;
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000919
920 // Clear out old caches and data.
921 TopLevelDecls.clear();
Douglas Gregorf88e35b2010-11-30 06:16:57 +0000922 PreprocessedEntities.clear();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000923 CleanTemporaryFiles();
924 PreprocessedEntitiesByFile.clear();
Douglas Gregord9a30af2010-08-02 20:51:39 +0000925
Douglas Gregor7b02b582010-08-20 00:02:33 +0000926 if (!OverrideMainBuffer) {
Douglas Gregor7bb8af62010-10-12 00:50:20 +0000927 StoredDiagnostics.erase(
928 StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
929 StoredDiagnostics.end());
Douglas Gregor7b02b582010-08-20 00:02:33 +0000930 TopLevelDeclsInPreamble.clear();
Douglas Gregorf88e35b2010-11-30 06:16:57 +0000931 PreprocessedEntitiesInPreamble.clear();
Douglas Gregor7b02b582010-08-20 00:02:33 +0000932 }
933
Daniel Dunbar764c0822009-12-01 09:51:01 +0000934 // Create a file manager object to provide access to and cache the filesystem.
Ted Kremenek84de4a12011-03-21 18:40:07 +0000935 Clang->setFileManager(&getFileManager());
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000936
Daniel Dunbar764c0822009-12-01 09:51:01 +0000937 // Create the source manager.
Ted Kremenek84de4a12011-03-21 18:40:07 +0000938 Clang->setSourceManager(&getSourceManager());
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000939
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000940 // If the main file has been overridden due to the use of a preamble,
941 // make that override happen and introduce the preamble.
Ted Kremenek84de4a12011-03-21 18:40:07 +0000942 PreprocessorOptions &PreprocessorOpts = Clang->getPreprocessorOpts();
Chandler Carruthde81fc82011-07-14 09:02:10 +0000943 PreprocessorOpts.DetailedRecordIncludesNestedMacroExpansions
944 = NestedMacroExpansions;
Douglas Gregor8e984da2010-08-04 16:47:14 +0000945 std::string PriorImplicitPCHInclude;
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000946 if (OverrideMainBuffer) {
947 PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
948 PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
949 PreprocessorOpts.PrecompiledPreambleBytes.second
950 = PreambleEndsAtStartOfLine;
Douglas Gregor8e984da2010-08-04 16:47:14 +0000951 PriorImplicitPCHInclude = PreprocessorOpts.ImplicitPCHInclude;
Douglas Gregor15ba0b32010-07-30 20:58:08 +0000952 PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
Douglas Gregorce3a8292010-07-27 00:27:13 +0000953 PreprocessorOpts.DisablePCHValidation = true;
Douglas Gregor96c04262010-07-27 14:52:07 +0000954
Douglas Gregord9a30af2010-08-02 20:51:39 +0000955 // The stored diagnostic has the old source manager in it; update
956 // the locations to refer into the new source manager. Since we've
957 // been careful to make sure that the source manager's state
958 // before and after are identical, so that we can reuse the source
959 // location itself.
Douglas Gregor7bb8af62010-10-12 00:50:20 +0000960 for (unsigned I = NumStoredDiagnosticsFromDriver,
961 N = StoredDiagnostics.size();
962 I < N; ++I) {
Douglas Gregord9a30af2010-08-02 20:51:39 +0000963 FullSourceLoc Loc(StoredDiagnostics[I].getLocation(),
964 getSourceManager());
965 StoredDiagnostics[I].setLocation(Loc);
966 }
Douglas Gregor7bb8af62010-10-12 00:50:20 +0000967
968 // Keep track of the override buffer;
969 SavedMainFileBuffer = OverrideMainBuffer;
Douglas Gregor7b02b582010-08-20 00:02:33 +0000970 } else {
971 PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
972 PreprocessorOpts.PrecompiledPreambleBytes.second = false;
Douglas Gregor3f4bea02010-07-26 21:36:20 +0000973 }
974
Ted Kremenek022a4902011-03-22 01:15:24 +0000975 llvm::OwningPtr<TopLevelDeclTrackerAction> Act(
976 new TopLevelDeclTrackerAction(*this));
977
978 // Recover resources if we crash before exiting this method.
979 llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
980 ActCleanup(Act.get());
981
Ted Kremenek84de4a12011-03-21 18:40:07 +0000982 if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
983 Clang->getFrontendOpts().Inputs[0].first))
Daniel Dunbar764c0822009-12-01 09:51:01 +0000984 goto error;
Douglas Gregor925296b2011-07-19 16:10:42 +0000985
986 if (OverrideMainBuffer) {
Jonathan D. Turner2214acd2011-07-22 17:25:03 +0000987 std::string ModName = PreambleFile;
Douglas Gregor925296b2011-07-19 16:10:42 +0000988 TranslateStoredDiagnostics(Clang->getModuleManager(), ModName,
989 getSourceManager(), PreambleDiagnostics,
990 StoredDiagnostics);
991 }
992
Daniel Dunbar644dca02009-12-04 08:17:33 +0000993 Act->Execute();
Douglas Gregoraa21cc42010-07-19 21:46:24 +0000994
Ted Kremenek5e14d392011-03-21 18:40:17 +0000995 // Steal the created target, context, and preprocessor.
Ted Kremenek84de4a12011-03-21 18:40:07 +0000996 TheSema.reset(Clang->takeSema());
997 Consumer.reset(Clang->takeASTConsumer());
Ted Kremenek5e14d392011-03-21 18:40:17 +0000998 Ctx = &Clang->getASTContext();
999 PP = &Clang->getPreprocessor();
1000 Clang->setSourceManager(0);
1001 Clang->setFileManager(0);
1002 Target = &Clang->getTarget();
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001003
Daniel Dunbar644dca02009-12-04 08:17:33 +00001004 Act->EndSourceFile();
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001005
1006 // Remove the overridden buffer we used for the preamble.
Douglas Gregor8e984da2010-08-04 16:47:14 +00001007 if (OverrideMainBuffer) {
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001008 PreprocessorOpts.eraseRemappedFile(
1009 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor8e984da2010-08-04 16:47:14 +00001010 PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
1011 }
1012
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001013 return false;
Ted Kremenek5e14d392011-03-21 18:40:17 +00001014
Daniel Dunbar764c0822009-12-01 09:51:01 +00001015error:
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001016 // Remove the overridden buffer we used for the preamble.
Douglas Gregorce3a8292010-07-27 00:27:13 +00001017 if (OverrideMainBuffer) {
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001018 PreprocessorOpts.eraseRemappedFile(
1019 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor8e984da2010-08-04 16:47:14 +00001020 PreprocessorOpts.ImplicitPCHInclude = PriorImplicitPCHInclude;
Douglas Gregora0734c52010-08-19 01:33:06 +00001021 delete OverrideMainBuffer;
Douglas Gregora3d3ba12010-10-06 21:11:08 +00001022 SavedMainFileBuffer = 0;
Douglas Gregorce3a8292010-07-27 00:27:13 +00001023 }
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001024
Douglas Gregorefc46952010-10-12 16:25:54 +00001025 StoredDiagnostics.clear();
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001026 return true;
1027}
1028
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001029/// \brief Simple function to retrieve a path for a preamble precompiled header.
1030static std::string GetPreamblePCHPath() {
1031 // FIXME: This is lame; sys::Path should provide this function (in particular,
1032 // it should know how to find the temporary files dir).
1033 // FIXME: This is really lame. I copied this code from the Driver!
Douglas Gregor250ab1d2010-09-11 18:05:19 +00001034 // FIXME: This is a hack so that we can override the preamble file during
1035 // crash-recovery testing, which is the only case where the preamble files
1036 // are not necessarily cleaned up.
1037 const char *TmpFile = ::getenv("CINDEXTEST_PREAMBLE_FILE");
1038 if (TmpFile)
1039 return TmpFile;
1040
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001041 std::string Error;
1042 const char *TmpDir = ::getenv("TMPDIR");
1043 if (!TmpDir)
1044 TmpDir = ::getenv("TEMP");
1045 if (!TmpDir)
1046 TmpDir = ::getenv("TMP");
Douglas Gregorce3449f2010-09-11 17:51:16 +00001047#ifdef LLVM_ON_WIN32
1048 if (!TmpDir)
1049 TmpDir = ::getenv("USERPROFILE");
1050#endif
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001051 if (!TmpDir)
1052 TmpDir = "/tmp";
1053 llvm::sys::Path P(TmpDir);
Douglas Gregorce3449f2010-09-11 17:51:16 +00001054 P.createDirectoryOnDisk(true);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001055 P.appendComponent("preamble");
Douglas Gregor20975b22010-08-11 13:06:56 +00001056 P.appendSuffix("pch");
Argyrios Kyrtzidisff9a5502011-07-21 18:44:46 +00001057 if (P.makeUnique(/*reuse_current=*/false, /*ErrMsg*/0))
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001058 return std::string();
1059
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001060 return P.str();
1061}
1062
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001063/// \brief Compute the preamble for the main file, providing the source buffer
1064/// that corresponds to the main file along with a pair (bytes, start-of-line)
1065/// that describes the preamble.
1066std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
Douglas Gregor028d3e42010-08-09 20:45:32 +00001067ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
1068 unsigned MaxLines, bool &CreatedBuffer) {
Douglas Gregor4dde7492010-07-23 23:58:40 +00001069 FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
Chris Lattner5159f612010-11-23 08:35:12 +00001070 PreprocessorOptions &PreprocessorOpts = Invocation.getPreprocessorOpts();
Douglas Gregor4dde7492010-07-23 23:58:40 +00001071 CreatedBuffer = false;
1072
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001073 // Try to determine if the main file has been remapped, either from the
1074 // command line (to another file) or directly through the compiler invocation
1075 // (to a memory buffer).
Douglas Gregor4dde7492010-07-23 23:58:40 +00001076 llvm::MemoryBuffer *Buffer = 0;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001077 llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
1078 if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
1079 // Check whether there is a file-file remapping of the main file
1080 for (PreprocessorOptions::remapped_file_iterator
Douglas Gregor4dde7492010-07-23 23:58:40 +00001081 M = PreprocessorOpts.remapped_file_begin(),
1082 E = PreprocessorOpts.remapped_file_end();
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001083 M != E;
1084 ++M) {
1085 llvm::sys::PathWithStatus MPath(M->first);
1086 if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
1087 if (MainFileStatus->uniqueID == MStatus->uniqueID) {
1088 // We found a remapping. Try to load the resulting, remapped source.
Douglas Gregor4dde7492010-07-23 23:58:40 +00001089 if (CreatedBuffer) {
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001090 delete Buffer;
Douglas Gregor4dde7492010-07-23 23:58:40 +00001091 CreatedBuffer = false;
1092 }
1093
Argyrios Kyrtzidis71731d62010-11-03 22:45:23 +00001094 Buffer = getBufferForFile(M->second);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001095 if (!Buffer)
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001096 return std::make_pair((llvm::MemoryBuffer*)0,
1097 std::make_pair(0, true));
Douglas Gregor4dde7492010-07-23 23:58:40 +00001098 CreatedBuffer = true;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001099 }
1100 }
1101 }
1102
1103 // Check whether there is a file-buffer remapping. It supercedes the
1104 // file-file remapping.
1105 for (PreprocessorOptions::remapped_file_buffer_iterator
1106 M = PreprocessorOpts.remapped_file_buffer_begin(),
1107 E = PreprocessorOpts.remapped_file_buffer_end();
1108 M != E;
1109 ++M) {
1110 llvm::sys::PathWithStatus MPath(M->first);
1111 if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
1112 if (MainFileStatus->uniqueID == MStatus->uniqueID) {
1113 // We found a remapping.
Douglas Gregor4dde7492010-07-23 23:58:40 +00001114 if (CreatedBuffer) {
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001115 delete Buffer;
Douglas Gregor4dde7492010-07-23 23:58:40 +00001116 CreatedBuffer = false;
1117 }
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001118
Douglas Gregor4dde7492010-07-23 23:58:40 +00001119 Buffer = const_cast<llvm::MemoryBuffer *>(M->second);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001120 }
1121 }
Douglas Gregor4dde7492010-07-23 23:58:40 +00001122 }
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001123 }
1124
1125 // If the main source file was not remapped, load it now.
1126 if (!Buffer) {
Argyrios Kyrtzidis71731d62010-11-03 22:45:23 +00001127 Buffer = getBufferForFile(FrontendOpts.Inputs[0].second);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001128 if (!Buffer)
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001129 return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
Douglas Gregor4dde7492010-07-23 23:58:40 +00001130
1131 CreatedBuffer = true;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001132 }
1133
Argyrios Kyrtzidis7aecbc72011-08-25 20:39:19 +00001134 return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer,
1135 Invocation.getLangOpts(),
1136 MaxLines));
Douglas Gregor4dde7492010-07-23 23:58:40 +00001137}
1138
Douglas Gregor6481ef12010-07-24 00:38:13 +00001139static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
Douglas Gregor6481ef12010-07-24 00:38:13 +00001140 unsigned NewSize,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001141 StringRef NewName) {
Douglas Gregor6481ef12010-07-24 00:38:13 +00001142 llvm::MemoryBuffer *Result
1143 = llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName);
1144 memcpy(const_cast<char*>(Result->getBufferStart()),
1145 Old->getBufferStart(), Old->getBufferSize());
1146 memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(),
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001147 ' ', NewSize - Old->getBufferSize() - 1);
1148 const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
Douglas Gregor6481ef12010-07-24 00:38:13 +00001149
Douglas Gregor6481ef12010-07-24 00:38:13 +00001150 return Result;
1151}
1152
Douglas Gregor4dde7492010-07-23 23:58:40 +00001153/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
1154/// the source file.
1155///
1156/// This routine will compute the preamble of the main source file. If a
1157/// non-trivial preamble is found, it will precompile that preamble into a
1158/// precompiled header so that the precompiled preamble can be used to reduce
1159/// reparsing time. If a precompiled preamble has already been constructed,
1160/// this routine will determine if it is still valid and, if so, avoid
1161/// rebuilding the precompiled preamble.
1162///
Douglas Gregor028d3e42010-08-09 20:45:32 +00001163/// \param AllowRebuild When true (the default), this routine is
1164/// allowed to rebuild the precompiled preamble if it is found to be
1165/// out-of-date.
1166///
1167/// \param MaxLines When non-zero, the maximum number of lines that
1168/// can occur within the preamble.
1169///
Douglas Gregor6481ef12010-07-24 00:38:13 +00001170/// \returns If the precompiled preamble can be used, returns a newly-allocated
1171/// buffer that should be used in place of the main file when doing so.
1172/// Otherwise, returns a NULL pointer.
Douglas Gregor028d3e42010-08-09 20:45:32 +00001173llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
Douglas Gregor3cc15812011-07-01 18:22:13 +00001174 const CompilerInvocation &PreambleInvocationIn,
Douglas Gregor028d3e42010-08-09 20:45:32 +00001175 bool AllowRebuild,
1176 unsigned MaxLines) {
Douglas Gregor3cc15812011-07-01 18:22:13 +00001177
1178 llvm::IntrusiveRefCntPtr<CompilerInvocation>
1179 PreambleInvocation(new CompilerInvocation(PreambleInvocationIn));
1180 FrontendOptions &FrontendOpts = PreambleInvocation->getFrontendOpts();
Douglas Gregor4dde7492010-07-23 23:58:40 +00001181 PreprocessorOptions &PreprocessorOpts
Douglas Gregor3cc15812011-07-01 18:22:13 +00001182 = PreambleInvocation->getPreprocessorOpts();
Douglas Gregor4dde7492010-07-23 23:58:40 +00001183
1184 bool CreatedPreambleBuffer = false;
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001185 std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
Douglas Gregor3cc15812011-07-01 18:22:13 +00001186 = ComputePreamble(*PreambleInvocation, MaxLines, CreatedPreambleBuffer);
Douglas Gregor4dde7492010-07-23 23:58:40 +00001187
Douglas Gregor925296b2011-07-19 16:10:42 +00001188 // If ComputePreamble() Take ownership of the preamble buffer.
Douglas Gregor3edb1672010-11-16 20:45:51 +00001189 llvm::OwningPtr<llvm::MemoryBuffer> OwnedPreambleBuffer;
1190 if (CreatedPreambleBuffer)
1191 OwnedPreambleBuffer.reset(NewPreamble.first);
1192
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001193 if (!NewPreamble.second.first) {
Douglas Gregor4dde7492010-07-23 23:58:40 +00001194 // We couldn't find a preamble in the main source. Clear out the current
1195 // preamble, if we have one. It's obviously no good any more.
1196 Preamble.clear();
1197 if (!PreambleFile.empty()) {
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001198 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregor4dde7492010-07-23 23:58:40 +00001199 PreambleFile.clear();
1200 }
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001201
1202 // The next time we actually see a preamble, precompile it.
1203 PreambleRebuildCounter = 1;
Douglas Gregor6481ef12010-07-24 00:38:13 +00001204 return 0;
Douglas Gregor4dde7492010-07-23 23:58:40 +00001205 }
1206
1207 if (!Preamble.empty()) {
1208 // We've previously computed a preamble. Check whether we have the same
1209 // preamble now that we did before, and that there's enough space in
1210 // the main-file buffer within the precompiled preamble to fit the
1211 // new main file.
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001212 if (Preamble.size() == NewPreamble.second.first &&
1213 PreambleEndsAtStartOfLine == NewPreamble.second.second &&
Douglas Gregorf5275a82010-07-24 00:42:07 +00001214 NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
Douglas Gregor4dde7492010-07-23 23:58:40 +00001215 memcmp(&Preamble[0], NewPreamble.first->getBufferStart(),
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001216 NewPreamble.second.first) == 0) {
Douglas Gregor4dde7492010-07-23 23:58:40 +00001217 // The preamble has not changed. We may be able to re-use the precompiled
1218 // preamble.
Douglas Gregord9a30af2010-08-02 20:51:39 +00001219
Douglas Gregor0e119552010-07-31 00:40:00 +00001220 // Check that none of the files used by the preamble have changed.
1221 bool AnyFileChanged = false;
1222
1223 // First, make a record of those files that have been overridden via
1224 // remapping or unsaved_files.
1225 llvm::StringMap<std::pair<off_t, time_t> > OverriddenFiles;
1226 for (PreprocessorOptions::remapped_file_iterator
1227 R = PreprocessorOpts.remapped_file_begin(),
1228 REnd = PreprocessorOpts.remapped_file_end();
1229 !AnyFileChanged && R != REnd;
1230 ++R) {
1231 struct stat StatBuf;
Anders Carlsson9583f792011-03-18 19:23:38 +00001232 if (FileMgr->getNoncachedStatValue(R->second, StatBuf)) {
Douglas Gregor0e119552010-07-31 00:40:00 +00001233 // If we can't stat the file we're remapping to, assume that something
1234 // horrible happened.
1235 AnyFileChanged = true;
1236 break;
1237 }
Douglas Gregor6481ef12010-07-24 00:38:13 +00001238
Douglas Gregor0e119552010-07-31 00:40:00 +00001239 OverriddenFiles[R->first] = std::make_pair(StatBuf.st_size,
1240 StatBuf.st_mtime);
1241 }
1242 for (PreprocessorOptions::remapped_file_buffer_iterator
1243 R = PreprocessorOpts.remapped_file_buffer_begin(),
1244 REnd = PreprocessorOpts.remapped_file_buffer_end();
1245 !AnyFileChanged && R != REnd;
1246 ++R) {
1247 // FIXME: Should we actually compare the contents of file->buffer
1248 // remappings?
1249 OverriddenFiles[R->first] = std::make_pair(R->second->getBufferSize(),
1250 0);
1251 }
1252
1253 // Check whether anything has changed.
1254 for (llvm::StringMap<std::pair<off_t, time_t> >::iterator
1255 F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end();
1256 !AnyFileChanged && F != FEnd;
1257 ++F) {
1258 llvm::StringMap<std::pair<off_t, time_t> >::iterator Overridden
1259 = OverriddenFiles.find(F->first());
1260 if (Overridden != OverriddenFiles.end()) {
1261 // This file was remapped; check whether the newly-mapped file
1262 // matches up with the previous mapping.
1263 if (Overridden->second != F->second)
1264 AnyFileChanged = true;
1265 continue;
1266 }
1267
1268 // The file was not remapped; check whether it has changed on disk.
1269 struct stat StatBuf;
Anders Carlsson9583f792011-03-18 19:23:38 +00001270 if (FileMgr->getNoncachedStatValue(F->first(), StatBuf)) {
Douglas Gregor0e119552010-07-31 00:40:00 +00001271 // If we can't stat the file, assume that something horrible happened.
1272 AnyFileChanged = true;
1273 } else if (StatBuf.st_size != F->second.first ||
1274 StatBuf.st_mtime != F->second.second)
1275 AnyFileChanged = true;
1276 }
1277
1278 if (!AnyFileChanged) {
Douglas Gregord9a30af2010-08-02 20:51:39 +00001279 // Okay! We can re-use the precompiled preamble.
1280
1281 // Set the state of the diagnostic object to mimic its state
1282 // after parsing the preamble.
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00001283 // FIXME: This won't catch any #pragma push warning changes that
1284 // have occurred in the preamble.
Douglas Gregord9a30af2010-08-02 20:51:39 +00001285 getDiagnostics().Reset();
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00001286 ProcessWarningOptions(getDiagnostics(),
Douglas Gregor3cc15812011-07-01 18:22:13 +00001287 PreambleInvocation->getDiagnosticOpts());
Douglas Gregord9a30af2010-08-02 20:51:39 +00001288 getDiagnostics().setNumWarnings(NumWarningsInPreamble);
Douglas Gregord9a30af2010-08-02 20:51:39 +00001289
1290 // Create a version of the main file buffer that is padded to
1291 // buffer size we reserved when creating the preamble.
Douglas Gregor0e119552010-07-31 00:40:00 +00001292 return CreatePaddedMainFileBuffer(NewPreamble.first,
Douglas Gregor0e119552010-07-31 00:40:00 +00001293 PreambleReservedSize,
1294 FrontendOpts.Inputs[0].second);
1295 }
Douglas Gregor4dde7492010-07-23 23:58:40 +00001296 }
Douglas Gregor028d3e42010-08-09 20:45:32 +00001297
1298 // If we aren't allowed to rebuild the precompiled preamble, just
1299 // return now.
1300 if (!AllowRebuild)
1301 return 0;
Douglas Gregorbb6a8812010-10-08 04:03:57 +00001302
Douglas Gregor4dde7492010-07-23 23:58:40 +00001303 // We can't reuse the previously-computed preamble. Build a new one.
1304 Preamble.clear();
Douglas Gregor925296b2011-07-19 16:10:42 +00001305 PreambleDiagnostics.clear();
Douglas Gregor15ba0b32010-07-30 20:58:08 +00001306 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001307 PreambleRebuildCounter = 1;
Douglas Gregor028d3e42010-08-09 20:45:32 +00001308 } else if (!AllowRebuild) {
1309 // We aren't allowed to rebuild the precompiled preamble; just
1310 // return now.
1311 return 0;
1312 }
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001313
1314 // If the preamble rebuild counter > 1, it's because we previously
1315 // failed to build a preamble and we're not yet ready to try
1316 // again. Decrement the counter and return a failure.
1317 if (PreambleRebuildCounter > 1) {
1318 --PreambleRebuildCounter;
1319 return 0;
1320 }
1321
Douglas Gregore10f0e52010-09-11 17:56:52 +00001322 // Create a temporary file for the precompiled preamble. In rare
1323 // circumstances, this can fail.
1324 std::string PreamblePCHPath = GetPreamblePCHPath();
1325 if (PreamblePCHPath.empty()) {
1326 // Try again next time.
1327 PreambleRebuildCounter = 1;
1328 return 0;
1329 }
1330
Douglas Gregor4dde7492010-07-23 23:58:40 +00001331 // We did not previously compute a preamble, or it can't be reused anyway.
Douglas Gregor16896c42010-10-28 15:44:59 +00001332 SimpleTimer PreambleTimer(WantTiming);
Benjamin Kramerf2e5a912010-11-09 20:00:56 +00001333 PreambleTimer.setOutput("Precompiling preamble");
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001334
1335 // Create a new buffer that stores the preamble. The buffer also contains
1336 // extra space for the original contents of the file (which will be present
1337 // when we actually parse the file) along with more room in case the file
Douglas Gregor4dde7492010-07-23 23:58:40 +00001338 // grows.
1339 PreambleReservedSize = NewPreamble.first->getBufferSize();
1340 if (PreambleReservedSize < 4096)
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001341 PreambleReservedSize = 8191;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001342 else
Douglas Gregor4dde7492010-07-23 23:58:40 +00001343 PreambleReservedSize *= 2;
1344
Douglas Gregord9a30af2010-08-02 20:51:39 +00001345 // Save the preamble text for later; we'll need to compare against it for
1346 // subsequent reparses.
1347 Preamble.assign(NewPreamble.first->getBufferStart(),
1348 NewPreamble.first->getBufferStart()
1349 + NewPreamble.second.first);
1350 PreambleEndsAtStartOfLine = NewPreamble.second.second;
1351
Douglas Gregora0734c52010-08-19 01:33:06 +00001352 delete PreambleBuffer;
1353 PreambleBuffer
Douglas Gregor4dde7492010-07-23 23:58:40 +00001354 = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001355 FrontendOpts.Inputs[0].second);
1356 memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
Douglas Gregor4dde7492010-07-23 23:58:40 +00001357 NewPreamble.first->getBufferStart(), Preamble.size());
1358 memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
Douglas Gregor3f4bea02010-07-26 21:36:20 +00001359 ' ', PreambleReservedSize - Preamble.size() - 1);
1360 const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001361
1362 // Remap the main source file to the preamble buffer.
Douglas Gregor4dde7492010-07-23 23:58:40 +00001363 llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001364 PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
1365
1366 // Tell the compiler invocation to generate a temporary precompiled header.
1367 FrontendOpts.ProgramAction = frontend::GeneratePCH;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001368 // FIXME: Generate the precompiled header into memory?
Douglas Gregore10f0e52010-09-11 17:56:52 +00001369 FrontendOpts.OutputFile = PreamblePCHPath;
Douglas Gregorbb6a8812010-10-08 04:03:57 +00001370 PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
1371 PreprocessorOpts.PrecompiledPreambleBytes.second = false;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001372
1373 // Create the compiler instance to use for building the precompiled preamble.
Ted Kremenek84de4a12011-03-21 18:40:07 +00001374 llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance());
1375
1376 // Recover resources if we crash before exiting this method.
Ted Kremenek022a4902011-03-22 01:15:24 +00001377 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
1378 CICleanup(Clang.get());
Ted Kremenek84de4a12011-03-21 18:40:07 +00001379
Douglas Gregor3cc15812011-07-01 18:22:13 +00001380 Clang->setInvocation(&*PreambleInvocation);
Ted Kremenek84de4a12011-03-21 18:40:07 +00001381 OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001382
Douglas Gregor8e984da2010-08-04 16:47:14 +00001383 // Set up diagnostics, capturing all of the diagnostics produced.
Ted Kremenek84de4a12011-03-21 18:40:07 +00001384 Clang->setDiagnostics(&getDiagnostics());
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001385
1386 // Create the target instance.
Ted Kremenek84de4a12011-03-21 18:40:07 +00001387 Clang->getTargetOpts().Features = TargetFeatures;
1388 Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
1389 Clang->getTargetOpts()));
1390 if (!Clang->hasTarget()) {
Douglas Gregor4dde7492010-07-23 23:58:40 +00001391 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
1392 Preamble.clear();
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001393 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregora0734c52010-08-19 01:33:06 +00001394 PreprocessorOpts.eraseRemappedFile(
1395 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor6481ef12010-07-24 00:38:13 +00001396 return 0;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001397 }
1398
1399 // Inform the target of the language options.
1400 //
1401 // FIXME: We shouldn't need to do this, the target should be immutable once
1402 // created. This complexity should be lifted elsewhere.
Ted Kremenek84de4a12011-03-21 18:40:07 +00001403 Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001404
Ted Kremenek84de4a12011-03-21 18:40:07 +00001405 assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001406 "Invocation must have exactly one source file!");
Ted Kremenek84de4a12011-03-21 18:40:07 +00001407 assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001408 "FIXME: AST inputs not yet supported here!");
Ted Kremenek84de4a12011-03-21 18:40:07 +00001409 assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001410 "IR inputs not support here!");
1411
1412 // Clear out old caches and data.
Douglas Gregorbb6a8812010-10-08 04:03:57 +00001413 getDiagnostics().Reset();
Ted Kremenek84de4a12011-03-21 18:40:07 +00001414 ProcessWarningOptions(getDiagnostics(), Clang->getDiagnosticOpts());
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001415 StoredDiagnostics.erase(
1416 StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
1417 StoredDiagnostics.end());
Douglas Gregore9db88f2010-08-03 19:06:41 +00001418 TopLevelDecls.clear();
1419 TopLevelDeclsInPreamble.clear();
Douglas Gregorf88e35b2010-11-30 06:16:57 +00001420 PreprocessedEntities.clear();
1421 PreprocessedEntitiesInPreamble.clear();
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001422
1423 // Create a file manager object to provide access to and cache the filesystem.
Ted Kremenek84de4a12011-03-21 18:40:07 +00001424 Clang->setFileManager(new FileManager(Clang->getFileSystemOpts()));
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001425
1426 // Create the source manager.
Ted Kremenek84de4a12011-03-21 18:40:07 +00001427 Clang->setSourceManager(new SourceManager(getDiagnostics(),
Ted Kremenek5e14d392011-03-21 18:40:17 +00001428 Clang->getFileManager()));
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001429
Douglas Gregor48c8cd32010-08-03 08:14:03 +00001430 llvm::OwningPtr<PrecompilePreambleAction> Act;
1431 Act.reset(new PrecompilePreambleAction(*this));
Ted Kremenek84de4a12011-03-21 18:40:07 +00001432 if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
1433 Clang->getFrontendOpts().Inputs[0].first)) {
Douglas Gregor4dde7492010-07-23 23:58:40 +00001434 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
1435 Preamble.clear();
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001436 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregora0734c52010-08-19 01:33:06 +00001437 PreprocessorOpts.eraseRemappedFile(
1438 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor6481ef12010-07-24 00:38:13 +00001439 return 0;
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001440 }
1441
1442 Act->Execute();
1443 Act->EndSourceFile();
Ted Kremenek5e14d392011-03-21 18:40:17 +00001444
Douglas Gregore9db88f2010-08-03 19:06:41 +00001445 if (Diagnostics->hasErrorOccurred()) {
Douglas Gregor4dde7492010-07-23 23:58:40 +00001446 // There were errors parsing the preamble, so no precompiled header was
1447 // generated. Forget that we even tried.
Douglas Gregora6f74e22010-09-27 16:43:25 +00001448 // FIXME: Should we leave a note for ourselves to try again?
Douglas Gregor4dde7492010-07-23 23:58:40 +00001449 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
1450 Preamble.clear();
Douglas Gregore9db88f2010-08-03 19:06:41 +00001451 TopLevelDeclsInPreamble.clear();
Douglas Gregorf88e35b2010-11-30 06:16:57 +00001452 PreprocessedEntities.clear();
1453 PreprocessedEntitiesInPreamble.clear();
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001454 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregora0734c52010-08-19 01:33:06 +00001455 PreprocessorOpts.eraseRemappedFile(
1456 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor6481ef12010-07-24 00:38:13 +00001457 return 0;
Douglas Gregor4dde7492010-07-23 23:58:40 +00001458 }
1459
Douglas Gregor925296b2011-07-19 16:10:42 +00001460 // Transfer any diagnostics generated when parsing the preamble into the set
1461 // of preamble diagnostics.
1462 PreambleDiagnostics.clear();
1463 PreambleDiagnostics.insert(PreambleDiagnostics.end(),
1464 StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
1465 StoredDiagnostics.end());
1466 StoredDiagnostics.erase(
1467 StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
1468 StoredDiagnostics.end());
1469
Douglas Gregor4dde7492010-07-23 23:58:40 +00001470 // Keep track of the preamble we precompiled.
1471 PreambleFile = FrontendOpts.OutputFile;
Douglas Gregord9a30af2010-08-02 20:51:39 +00001472 NumWarningsInPreamble = getDiagnostics().getNumWarnings();
Douglas Gregor0e119552010-07-31 00:40:00 +00001473
1474 // Keep track of all of the files that the source manager knows about,
1475 // so we can verify whether they have changed or not.
1476 FilesInPreamble.clear();
Ted Kremenek84de4a12011-03-21 18:40:07 +00001477 SourceManager &SourceMgr = Clang->getSourceManager();
Douglas Gregor0e119552010-07-31 00:40:00 +00001478 const llvm::MemoryBuffer *MainFileBuffer
1479 = SourceMgr.getBuffer(SourceMgr.getMainFileID());
1480 for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(),
1481 FEnd = SourceMgr.fileinfo_end();
1482 F != FEnd;
1483 ++F) {
Argyrios Kyrtzidis11e6f0a2011-03-05 01:03:53 +00001484 const FileEntry *File = F->second->OrigEntry;
Douglas Gregor0e119552010-07-31 00:40:00 +00001485 if (!File || F->second->getRawBuffer() == MainFileBuffer)
1486 continue;
1487
1488 FilesInPreamble[File->getName()]
1489 = std::make_pair(F->second->getSize(), File->getModificationTime());
1490 }
1491
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001492 PreambleRebuildCounter = 1;
Douglas Gregora0734c52010-08-19 01:33:06 +00001493 PreprocessorOpts.eraseRemappedFile(
1494 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregordf7a79a2011-02-16 18:16:54 +00001495
1496 // If the hash of top-level entities differs from the hash of the top-level
1497 // entities the last time we rebuilt the preamble, clear out the completion
1498 // cache.
1499 if (CurrentTopLevelHashValue != PreambleTopLevelHashValue) {
1500 CompletionCacheTopLevelHashValue = 0;
1501 PreambleTopLevelHashValue = CurrentTopLevelHashValue;
1502 }
1503
Douglas Gregor6481ef12010-07-24 00:38:13 +00001504 return CreatePaddedMainFileBuffer(NewPreamble.first,
Douglas Gregor6481ef12010-07-24 00:38:13 +00001505 PreambleReservedSize,
1506 FrontendOpts.Inputs[0].second);
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001507}
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001508
Douglas Gregore9db88f2010-08-03 19:06:41 +00001509void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
1510 std::vector<Decl *> Resolved;
1511 Resolved.reserve(TopLevelDeclsInPreamble.size());
1512 ExternalASTSource &Source = *getASTContext().getExternalSource();
1513 for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
1514 // Resolve the declaration ID to an actual declaration, possibly
1515 // deserializing the declaration in the process.
1516 Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
1517 if (D)
1518 Resolved.push_back(D);
1519 }
1520 TopLevelDeclsInPreamble.clear();
1521 TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
1522}
1523
Douglas Gregorf88e35b2010-11-30 06:16:57 +00001524void ASTUnit::RealizePreprocessedEntitiesFromPreamble() {
1525 if (!PP)
1526 return;
1527
1528 PreprocessingRecord *PPRec = PP->getPreprocessingRecord();
1529 if (!PPRec)
1530 return;
1531
1532 ExternalPreprocessingRecordSource *External = PPRec->getExternalSource();
1533 if (!External)
1534 return;
1535
1536 for (unsigned I = 0, N = PreprocessedEntitiesInPreamble.size(); I != N; ++I) {
1537 if (PreprocessedEntity *PE
Douglas Gregor46c50012011-02-11 19:46:30 +00001538 = External->ReadPreprocessedEntityAtOffset(
1539 PreprocessedEntitiesInPreamble[I]))
Douglas Gregorf88e35b2010-11-30 06:16:57 +00001540 PreprocessedEntities.push_back(PE);
1541 }
1542
1543 if (PreprocessedEntities.empty())
1544 return;
1545
1546 PreprocessedEntities.insert(PreprocessedEntities.end(),
1547 PPRec->begin(true), PPRec->end(true));
1548}
1549
1550ASTUnit::pp_entity_iterator ASTUnit::pp_entity_begin() {
1551 if (!PreprocessedEntitiesInPreamble.empty() &&
1552 PreprocessedEntities.empty())
1553 RealizePreprocessedEntitiesFromPreamble();
1554
Douglas Gregorf88e35b2010-11-30 06:16:57 +00001555 return PreprocessedEntities.begin();
1556}
1557
1558ASTUnit::pp_entity_iterator ASTUnit::pp_entity_end() {
1559 if (!PreprocessedEntitiesInPreamble.empty() &&
1560 PreprocessedEntities.empty())
1561 RealizePreprocessedEntitiesFromPreamble();
Douglas Gregor4a9c39a2011-07-21 00:47:40 +00001562
Douglas Gregorf88e35b2010-11-30 06:16:57 +00001563 return PreprocessedEntities.end();
1564}
1565
Douglas Gregore9db88f2010-08-03 19:06:41 +00001566unsigned ASTUnit::getMaxPCHLevel() const {
1567 if (!getOnlyLocalDecls())
1568 return Decl::MaxPCHLevel;
1569
Sebastian Redl009e7f22010-10-05 16:15:19 +00001570 return 0;
Douglas Gregore9db88f2010-08-03 19:06:41 +00001571}
1572
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001573StringRef ASTUnit::getMainFileName() const {
Douglas Gregor16896c42010-10-28 15:44:59 +00001574 return Invocation->getFrontendOpts().Inputs[0].second;
1575}
1576
Argyrios Kyrtzidis35dcda72011-03-09 17:21:42 +00001577ASTUnit *ASTUnit::create(CompilerInvocation *CI,
1578 llvm::IntrusiveRefCntPtr<Diagnostic> Diags) {
1579 llvm::OwningPtr<ASTUnit> AST;
1580 AST.reset(new ASTUnit(false));
1581 ConfigureDiags(Diags, 0, 0, *AST, /*CaptureDiagnostics=*/false);
1582 AST->Diagnostics = Diags;
Ted Kremenek5e14d392011-03-21 18:40:17 +00001583 AST->Invocation = CI;
Anders Carlssonc30dcec2011-03-18 18:22:40 +00001584 AST->FileSystemOpts = CI->getFileSystemOpts();
Ted Kremenek5e14d392011-03-21 18:40:17 +00001585 AST->FileMgr = new FileManager(AST->FileSystemOpts);
1586 AST->SourceMgr = new SourceManager(*Diags, *AST->FileMgr);
Argyrios Kyrtzidis35dcda72011-03-09 17:21:42 +00001587
1588 return AST.take();
1589}
1590
Argyrios Kyrtzidisf1f67592011-05-03 23:26:34 +00001591ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
1592 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
1593 ASTFrontendAction *Action) {
1594 assert(CI && "A CompilerInvocation is required");
1595
1596 // Create the AST unit.
1597 llvm::OwningPtr<ASTUnit> AST;
1598 AST.reset(new ASTUnit(false));
1599 ConfigureDiags(Diags, 0, 0, *AST, /*CaptureDiagnostics*/false);
1600 AST->Diagnostics = Diags;
1601 AST->OnlyLocalDecls = false;
1602 AST->CaptureDiagnostics = false;
Douglas Gregor69f74f82011-08-25 22:30:56 +00001603 AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete;
Argyrios Kyrtzidisf1f67592011-05-03 23:26:34 +00001604 AST->ShouldCacheCodeCompletionResults = false;
1605 AST->Invocation = CI;
1606
1607 // Recover resources if we crash before exiting this method.
1608 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
1609 ASTUnitCleanup(AST.get());
1610 llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic,
1611 llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> >
1612 DiagCleanup(Diags.getPtr());
1613
1614 // We'll manage file buffers ourselves.
1615 CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
1616 CI->getFrontendOpts().DisableFree = false;
1617 ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());
1618
1619 // Save the target features.
1620 AST->TargetFeatures = CI->getTargetOpts().Features;
1621
1622 // Create the compiler instance to use for building the AST.
1623 llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance());
1624
1625 // Recover resources if we crash before exiting this method.
1626 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
1627 CICleanup(Clang.get());
1628
1629 Clang->setInvocation(CI);
1630 AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
1631
1632 // Set up diagnostics, capturing any diagnostics that would
1633 // otherwise be dropped.
1634 Clang->setDiagnostics(&AST->getDiagnostics());
1635
1636 // Create the target instance.
1637 Clang->getTargetOpts().Features = AST->TargetFeatures;
1638 Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
1639 Clang->getTargetOpts()));
1640 if (!Clang->hasTarget())
1641 return 0;
1642
1643 // Inform the target of the language options.
1644 //
1645 // FIXME: We shouldn't need to do this, the target should be immutable once
1646 // created. This complexity should be lifted elsewhere.
1647 Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
1648
1649 assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
1650 "Invocation must have exactly one source file!");
1651 assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
1652 "FIXME: AST inputs not yet supported here!");
1653 assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
1654 "IR inputs not supported here!");
1655
1656 // Configure the various subsystems.
1657 AST->FileSystemOpts = Clang->getFileSystemOpts();
1658 AST->FileMgr = new FileManager(AST->FileSystemOpts);
1659 AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr);
1660 AST->TheSema.reset();
1661 AST->Ctx = 0;
1662 AST->PP = 0;
1663
1664 // Create a file manager object to provide access to and cache the filesystem.
1665 Clang->setFileManager(&AST->getFileManager());
1666
1667 // Create the source manager.
1668 Clang->setSourceManager(&AST->getSourceManager());
1669
1670 ASTFrontendAction *Act = Action;
1671
1672 llvm::OwningPtr<TopLevelDeclTrackerAction> TrackerAct;
1673 if (!Act) {
1674 TrackerAct.reset(new TopLevelDeclTrackerAction(*AST));
1675 Act = TrackerAct.get();
1676 }
1677
1678 // Recover resources if we crash before exiting this method.
1679 llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
1680 ActCleanup(TrackerAct.get());
1681
1682 if (!Act->BeginSourceFile(*Clang.get(),
1683 Clang->getFrontendOpts().Inputs[0].second,
1684 Clang->getFrontendOpts().Inputs[0].first))
1685 return 0;
1686
1687 Act->Execute();
1688
1689 // Steal the created target, context, and preprocessor.
1690 AST->TheSema.reset(Clang->takeSema());
1691 AST->Consumer.reset(Clang->takeASTConsumer());
1692 AST->Ctx = &Clang->getASTContext();
1693 AST->PP = &Clang->getPreprocessor();
1694 Clang->setSourceManager(0);
1695 Clang->setFileManager(0);
1696 AST->Target = &Clang->getTarget();
1697
1698 Act->EndSourceFile();
1699
1700 return AST.take();
1701}
1702
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001703bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
1704 if (!Invocation)
1705 return true;
1706
1707 // We'll manage file buffers ourselves.
1708 Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;
1709 Invocation->getFrontendOpts().DisableFree = false;
Douglas Gregor345c1bc2011-01-19 01:02:47 +00001710 ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001711
Douglas Gregorffd6dc42011-01-27 18:02:58 +00001712 // Save the target features.
1713 TargetFeatures = Invocation->getTargetOpts().Features;
1714
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001715 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregorf5a18542010-10-27 17:24:53 +00001716 if (PrecompilePreamble) {
Douglas Gregorc6592922010-11-15 23:00:34 +00001717 PreambleRebuildCounter = 2;
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001718 OverrideMainBuffer
1719 = getMainBufferWithPrecompiledPreamble(*Invocation);
1720 }
1721
Douglas Gregor16896c42010-10-28 15:44:59 +00001722 SimpleTimer ParsingTimer(WantTiming);
Benjamin Kramerf2e5a912010-11-09 20:00:56 +00001723 ParsingTimer.setOutput("Parsing " + getMainFileName());
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001724
Ted Kremenek022a4902011-03-22 01:15:24 +00001725 // Recover resources if we crash before exiting this method.
1726 llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>
1727 MemBufferCleanup(OverrideMainBuffer);
1728
Douglas Gregor16896c42010-10-28 15:44:59 +00001729 return Parse(OverrideMainBuffer);
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001730}
1731
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001732ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
1733 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
1734 bool OnlyLocalDecls,
Douglas Gregorbe2d8c62010-07-23 00:33:23 +00001735 bool CaptureDiagnostics,
Douglas Gregor028d3e42010-08-09 20:45:32 +00001736 bool PrecompilePreamble,
Douglas Gregor69f74f82011-08-25 22:30:56 +00001737 TranslationUnitKind TUKind,
Douglas Gregor998caea2011-05-06 16:33:08 +00001738 bool CacheCodeCompletionResults,
Chandler Carruthde81fc82011-07-14 09:02:10 +00001739 bool NestedMacroExpansions) {
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001740 // Create the AST unit.
1741 llvm::OwningPtr<ASTUnit> AST;
1742 AST.reset(new ASTUnit(false));
Douglas Gregor345c1bc2011-01-19 01:02:47 +00001743 ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001744 AST->Diagnostics = Diags;
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001745 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregor44c6ee72010-11-11 00:39:14 +00001746 AST->CaptureDiagnostics = CaptureDiagnostics;
Douglas Gregor69f74f82011-08-25 22:30:56 +00001747 AST->TUKind = TUKind;
Douglas Gregorb14904c2010-08-13 22:48:40 +00001748 AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
Ted Kremenek5e14d392011-03-21 18:40:17 +00001749 AST->Invocation = CI;
Chandler Carruthde81fc82011-07-14 09:02:10 +00001750 AST->NestedMacroExpansions = NestedMacroExpansions;
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001751
Ted Kremenek4422bfe2011-03-18 02:06:56 +00001752 // Recover resources if we crash before exiting this method.
Ted Kremenek022a4902011-03-22 01:15:24 +00001753 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
1754 ASTUnitCleanup(AST.get());
1755 llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic,
1756 llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> >
1757 DiagCleanup(Diags.getPtr());
Ted Kremenek4422bfe2011-03-18 02:06:56 +00001758
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001759 return AST->LoadFromCompilerInvocation(PrecompilePreamble)? 0 : AST.take();
Daniel Dunbar764c0822009-12-01 09:51:01 +00001760}
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001761
1762ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
1763 const char **ArgEnd,
Douglas Gregor7f95d262010-04-05 23:52:57 +00001764 llvm::IntrusiveRefCntPtr<Diagnostic> Diags,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001765 StringRef ResourceFilesPath,
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001766 bool OnlyLocalDecls,
Douglas Gregor44c6ee72010-11-11 00:39:14 +00001767 bool CaptureDiagnostics,
Douglas Gregoraa98ed92010-01-23 00:14:00 +00001768 RemappedFile *RemappedFiles,
Douglas Gregor33cdd812010-02-18 18:08:43 +00001769 unsigned NumRemappedFiles,
Argyrios Kyrtzidis97d3a382011-03-08 23:35:24 +00001770 bool RemappedFilesKeepOriginalName,
Douglas Gregor028d3e42010-08-09 20:45:32 +00001771 bool PrecompilePreamble,
Douglas Gregor69f74f82011-08-25 22:30:56 +00001772 TranslationUnitKind TUKind,
Douglas Gregorf5a18542010-10-27 17:24:53 +00001773 bool CacheCodeCompletionResults,
Chandler Carruthde81fc82011-07-14 09:02:10 +00001774 bool NestedMacroExpansions) {
Douglas Gregor7f95d262010-04-05 23:52:57 +00001775 if (!Diags.getPtr()) {
Douglas Gregord03e8232010-04-05 21:10:19 +00001776 // No diagnostics engine was provided, so create our own diagnostics object
1777 // with the default options.
1778 DiagnosticOptions DiagOpts;
Douglas Gregor345c1bc2011-01-19 01:02:47 +00001779 Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd - ArgBegin,
1780 ArgBegin);
Douglas Gregord03e8232010-04-05 21:10:19 +00001781 }
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001782
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001783 SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001784
Ted Kremenek5e14d392011-03-21 18:40:17 +00001785 llvm::IntrusiveRefCntPtr<CompilerInvocation> CI;
Douglas Gregor44c6ee72010-11-11 00:39:14 +00001786
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001787 {
Douglas Gregor925296b2011-07-19 16:10:42 +00001788
Douglas Gregor44c6ee72010-11-11 00:39:14 +00001789 CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001790 StoredDiagnostics);
Daniel Dunbarfcf2d422010-01-25 00:44:02 +00001791
Argyrios Kyrtzidis5cf423e2011-04-04 23:11:45 +00001792 CI = clang::createInvocationFromCommandLine(
Frits van Bommel717d7ed2011-07-18 12:00:32 +00001793 llvm::makeArrayRef(ArgBegin, ArgEnd),
1794 Diags);
Argyrios Kyrtzidisf606b822011-04-04 21:38:51 +00001795 if (!CI)
Argyrios Kyrtzidisbc1f48f2011-03-07 22:45:01 +00001796 return 0;
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001797 }
Douglas Gregor44c6ee72010-11-11 00:39:14 +00001798
Douglas Gregoraa98ed92010-01-23 00:14:00 +00001799 // Override any files that need remapping
Argyrios Kyrtzidis11e6f0a2011-03-05 01:03:53 +00001800 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
1801 FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
1802 if (const llvm::MemoryBuffer *
1803 memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
1804 CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, memBuf);
1805 } else {
1806 const char *fname = fileOrBuf.get<const char *>();
1807 CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, fname);
1808 }
1809 }
Argyrios Kyrtzidis97d3a382011-03-08 23:35:24 +00001810 CI->getPreprocessorOpts().RemappedFilesKeepOriginalName =
1811 RemappedFilesKeepOriginalName;
Douglas Gregoraa98ed92010-01-23 00:14:00 +00001812
Daniel Dunbara5a166d2009-12-15 00:06:45 +00001813 // Override the resources path.
Daniel Dunbar6b03ece2010-01-30 21:47:16 +00001814 CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001815
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001816 // Create the AST unit.
1817 llvm::OwningPtr<ASTUnit> AST;
1818 AST.reset(new ASTUnit(false));
Douglas Gregor345c1bc2011-01-19 01:02:47 +00001819 ConfigureDiags(Diags, ArgBegin, ArgEnd, *AST, CaptureDiagnostics);
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001820 AST->Diagnostics = Diags;
Anders Carlssonc30dcec2011-03-18 18:22:40 +00001821
1822 AST->FileSystemOpts = CI->getFileSystemOpts();
Ted Kremenek5e14d392011-03-21 18:40:17 +00001823 AST->FileMgr = new FileManager(AST->FileSystemOpts);
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001824 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregor44c6ee72010-11-11 00:39:14 +00001825 AST->CaptureDiagnostics = CaptureDiagnostics;
Douglas Gregor69f74f82011-08-25 22:30:56 +00001826 AST->TUKind = TUKind;
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001827 AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
1828 AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
Douglas Gregor7bb8af62010-10-12 00:50:20 +00001829 AST->StoredDiagnostics.swap(StoredDiagnostics);
Ted Kremenek5e14d392011-03-21 18:40:17 +00001830 AST->Invocation = CI;
Chandler Carruthde81fc82011-07-14 09:02:10 +00001831 AST->NestedMacroExpansions = NestedMacroExpansions;
Ted Kremenek4422bfe2011-03-18 02:06:56 +00001832
1833 // Recover resources if we crash before exiting this method.
Ted Kremenek022a4902011-03-22 01:15:24 +00001834 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
1835 ASTUnitCleanup(AST.get());
1836 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInvocation,
1837 llvm::CrashRecoveryContextReleaseRefCleanup<CompilerInvocation> >
1838 CICleanup(CI.getPtr());
1839 llvm::CrashRecoveryContextCleanupRegistrar<Diagnostic,
1840 llvm::CrashRecoveryContextReleaseRefCleanup<Diagnostic> >
1841 DiagCleanup(Diags.getPtr());
Ted Kremenek4422bfe2011-03-18 02:06:56 +00001842
Chris Lattner5159f612010-11-23 08:35:12 +00001843 return AST->LoadFromCompilerInvocation(PrecompilePreamble) ? 0 : AST.take();
Daniel Dunbar55a17b62009-12-02 03:23:45 +00001844}
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001845
1846bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
Ted Kremenek5e14d392011-03-21 18:40:17 +00001847 if (!Invocation)
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001848 return true;
1849
Douglas Gregor16896c42010-10-28 15:44:59 +00001850 SimpleTimer ParsingTimer(WantTiming);
Benjamin Kramerf2e5a912010-11-09 20:00:56 +00001851 ParsingTimer.setOutput("Reparsing " + getMainFileName());
Douglas Gregor16896c42010-10-28 15:44:59 +00001852
Douglas Gregor0e119552010-07-31 00:40:00 +00001853 // Remap files.
Douglas Gregor7b02b582010-08-20 00:02:33 +00001854 PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
Douglas Gregor606c4ac2011-02-05 19:42:43 +00001855 PPOpts.DisableStatCache = true;
Douglas Gregor7b02b582010-08-20 00:02:33 +00001856 for (PreprocessorOptions::remapped_file_buffer_iterator
1857 R = PPOpts.remapped_file_buffer_begin(),
1858 REnd = PPOpts.remapped_file_buffer_end();
1859 R != REnd;
1860 ++R) {
1861 delete R->second;
1862 }
Douglas Gregor0e119552010-07-31 00:40:00 +00001863 Invocation->getPreprocessorOpts().clearRemappedFiles();
Argyrios Kyrtzidis11e6f0a2011-03-05 01:03:53 +00001864 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
1865 FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
1866 if (const llvm::MemoryBuffer *
1867 memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
1868 Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1869 memBuf);
1870 } else {
1871 const char *fname = fileOrBuf.get<const char *>();
1872 Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1873 fname);
1874 }
1875 }
Douglas Gregor0e119552010-07-31 00:40:00 +00001876
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001877 // If we have a preamble file lying around, or if we might try to
1878 // build a precompiled preamble, do so now.
Douglas Gregor6481ef12010-07-24 00:38:13 +00001879 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregorbb420ab2010-08-04 05:53:38 +00001880 if (!PreambleFile.empty() || PreambleRebuildCounter > 0)
Douglas Gregorb97b6662010-08-20 00:59:43 +00001881 OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
Douglas Gregor4dde7492010-07-23 23:58:40 +00001882
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001883 // Clear out the diagnostics state.
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00001884 if (!OverrideMainBuffer) {
Douglas Gregord9a30af2010-08-02 20:51:39 +00001885 getDiagnostics().Reset();
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00001886 ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
1887 }
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001888
Douglas Gregor4dde7492010-07-23 23:58:40 +00001889 // Parse the sources
Douglas Gregordf7a79a2011-02-16 18:16:54 +00001890 bool Result = Parse(OverrideMainBuffer);
1891
1892 // If we're caching global code-completion results, and the top-level
1893 // declarations have changed, clear out the code-completion cache.
1894 if (!Result && ShouldCacheCodeCompletionResults &&
1895 CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)
1896 CacheCodeCompletionResults();
1897
Douglas Gregor3f35bb22011-08-04 20:04:59 +00001898 // We now need to clear out the completion allocator for
1899 // clang_getCursorCompletionString; it'll be recreated if necessary.
1900 CursorCompletionAllocator = 0;
1901
Douglas Gregor4dde7492010-07-23 23:58:40 +00001902 return Result;
Douglas Gregoraa21cc42010-07-19 21:46:24 +00001903}
Douglas Gregor8e984da2010-08-04 16:47:14 +00001904
Douglas Gregorb14904c2010-08-13 22:48:40 +00001905//----------------------------------------------------------------------------//
1906// Code completion
1907//----------------------------------------------------------------------------//
1908
1909namespace {
1910 /// \brief Code completion consumer that combines the cached code-completion
1911 /// results from an ASTUnit with the code-completion results provided to it,
1912 /// then passes the result on to
1913 class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
Douglas Gregor21325842011-07-07 16:03:39 +00001914 unsigned long long NormalContexts;
Douglas Gregorb14904c2010-08-13 22:48:40 +00001915 ASTUnit &AST;
1916 CodeCompleteConsumer &Next;
1917
1918 public:
1919 AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
Douglas Gregor39982192010-08-15 06:18:01 +00001920 bool IncludeMacros, bool IncludeCodePatterns,
1921 bool IncludeGlobals)
1922 : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
Douglas Gregorb14904c2010-08-13 22:48:40 +00001923 Next.isOutputBinary()), AST(AST), Next(Next)
1924 {
1925 // Compute the set of contexts in which we will look when we don't have
1926 // any information about the specific context.
1927 NormalContexts
Douglas Gregor21325842011-07-07 16:03:39 +00001928 = (1LL << (CodeCompletionContext::CCC_TopLevel - 1))
1929 | (1LL << (CodeCompletionContext::CCC_ObjCInterface - 1))
1930 | (1LL << (CodeCompletionContext::CCC_ObjCImplementation - 1))
1931 | (1LL << (CodeCompletionContext::CCC_ObjCIvarList - 1))
1932 | (1LL << (CodeCompletionContext::CCC_Statement - 1))
1933 | (1LL << (CodeCompletionContext::CCC_Expression - 1))
1934 | (1LL << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
1935 | (1LL << (CodeCompletionContext::CCC_DotMemberAccess - 1))
1936 | (1LL << (CodeCompletionContext::CCC_ArrowMemberAccess - 1))
1937 | (1LL << (CodeCompletionContext::CCC_ObjCPropertyAccess - 1))
1938 | (1LL << (CodeCompletionContext::CCC_ObjCProtocolName - 1))
1939 | (1LL << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
1940 | (1LL << (CodeCompletionContext::CCC_Recovery - 1));
Douglas Gregor5e35d592010-09-14 23:59:36 +00001941
Douglas Gregorb14904c2010-08-13 22:48:40 +00001942 if (AST.getASTContext().getLangOptions().CPlusPlus)
Douglas Gregor21325842011-07-07 16:03:39 +00001943 NormalContexts |= (1LL << (CodeCompletionContext::CCC_EnumTag - 1))
1944 | (1LL << (CodeCompletionContext::CCC_UnionTag - 1))
1945 | (1LL << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
Douglas Gregorb14904c2010-08-13 22:48:40 +00001946 }
1947
1948 virtual void ProcessCodeCompleteResults(Sema &S,
1949 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00001950 CodeCompletionResult *Results,
Douglas Gregord46cf182010-08-16 20:01:48 +00001951 unsigned NumResults);
Douglas Gregorb14904c2010-08-13 22:48:40 +00001952
1953 virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
1954 OverloadCandidate *Candidates,
1955 unsigned NumCandidates) {
1956 Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
1957 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001958
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00001959 virtual CodeCompletionAllocator &getAllocator() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001960 return Next.getAllocator();
1961 }
Douglas Gregorb14904c2010-08-13 22:48:40 +00001962 };
1963}
Douglas Gregord46cf182010-08-16 20:01:48 +00001964
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001965/// \brief Helper function that computes which global names are hidden by the
1966/// local code-completion results.
Ted Kremenek6a153372010-11-07 06:11:36 +00001967static void CalculateHiddenNames(const CodeCompletionContext &Context,
1968 CodeCompletionResult *Results,
1969 unsigned NumResults,
1970 ASTContext &Ctx,
1971 llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001972 bool OnlyTagNames = false;
1973 switch (Context.getKind()) {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001974 case CodeCompletionContext::CCC_Recovery:
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001975 case CodeCompletionContext::CCC_TopLevel:
1976 case CodeCompletionContext::CCC_ObjCInterface:
1977 case CodeCompletionContext::CCC_ObjCImplementation:
1978 case CodeCompletionContext::CCC_ObjCIvarList:
1979 case CodeCompletionContext::CCC_ClassStructUnion:
1980 case CodeCompletionContext::CCC_Statement:
1981 case CodeCompletionContext::CCC_Expression:
1982 case CodeCompletionContext::CCC_ObjCMessageReceiver:
Douglas Gregor21325842011-07-07 16:03:39 +00001983 case CodeCompletionContext::CCC_DotMemberAccess:
1984 case CodeCompletionContext::CCC_ArrowMemberAccess:
1985 case CodeCompletionContext::CCC_ObjCPropertyAccess:
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001986 case CodeCompletionContext::CCC_Namespace:
1987 case CodeCompletionContext::CCC_Type:
Douglas Gregorc49f5b22010-08-23 18:23:48 +00001988 case CodeCompletionContext::CCC_Name:
1989 case CodeCompletionContext::CCC_PotentiallyQualifiedName:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001990 case CodeCompletionContext::CCC_ParenthesizedExpression:
Douglas Gregor2c595ad2011-07-30 06:55:39 +00001991 case CodeCompletionContext::CCC_ObjCInterfaceName:
Douglas Gregor6199f2d2010-08-16 21:18:39 +00001992 break;
1993
1994 case CodeCompletionContext::CCC_EnumTag:
1995 case CodeCompletionContext::CCC_UnionTag:
1996 case CodeCompletionContext::CCC_ClassOrStructTag:
1997 OnlyTagNames = true;
1998 break;
1999
2000 case CodeCompletionContext::CCC_ObjCProtocolName:
Douglas Gregor12785102010-08-24 20:21:13 +00002001 case CodeCompletionContext::CCC_MacroName:
2002 case CodeCompletionContext::CCC_MacroNameUse:
Douglas Gregorec00a262010-08-24 22:20:20 +00002003 case CodeCompletionContext::CCC_PreprocessorExpression:
Douglas Gregor0de55ce2010-08-25 18:41:16 +00002004 case CodeCompletionContext::CCC_PreprocessorDirective:
Douglas Gregorea147052010-08-25 18:04:30 +00002005 case CodeCompletionContext::CCC_NaturalLanguage:
Douglas Gregor67c692c2010-08-26 15:07:07 +00002006 case CodeCompletionContext::CCC_SelectorName:
Douglas Gregor28c78432010-08-27 17:35:51 +00002007 case CodeCompletionContext::CCC_TypeQualifiers:
Douglas Gregor0ac41382010-09-23 23:01:17 +00002008 case CodeCompletionContext::CCC_Other:
Douglas Gregor3a69eaf2011-02-18 23:30:37 +00002009 case CodeCompletionContext::CCC_OtherWithMacros:
Douglas Gregor21325842011-07-07 16:03:39 +00002010 case CodeCompletionContext::CCC_ObjCInstanceMessage:
2011 case CodeCompletionContext::CCC_ObjCClassMessage:
2012 case CodeCompletionContext::CCC_ObjCCategoryName:
Douglas Gregor0de55ce2010-08-25 18:41:16 +00002013 // We're looking for nothing, or we're looking for names that cannot
2014 // be hidden.
Douglas Gregor6199f2d2010-08-16 21:18:39 +00002015 return;
2016 }
2017
John McCall276321a2010-08-25 06:19:51 +00002018 typedef CodeCompletionResult Result;
Douglas Gregor6199f2d2010-08-16 21:18:39 +00002019 for (unsigned I = 0; I != NumResults; ++I) {
2020 if (Results[I].Kind != Result::RK_Declaration)
2021 continue;
2022
2023 unsigned IDNS
2024 = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
2025
2026 bool Hiding = false;
2027 if (OnlyTagNames)
2028 Hiding = (IDNS & Decl::IDNS_Tag);
2029 else {
2030 unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
Douglas Gregor59cab552010-08-16 23:05:20 +00002031 Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
2032 Decl::IDNS_NonMemberOperator);
Douglas Gregor6199f2d2010-08-16 21:18:39 +00002033 if (Ctx.getLangOptions().CPlusPlus)
2034 HiddenIDNS |= Decl::IDNS_Tag;
2035 Hiding = (IDNS & HiddenIDNS);
2036 }
2037
2038 if (!Hiding)
2039 continue;
2040
2041 DeclarationName Name = Results[I].Declaration->getDeclName();
2042 if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
2043 HiddenNames.insert(Identifier->getName());
2044 else
2045 HiddenNames.insert(Name.getAsString());
2046 }
2047}
2048
2049
Douglas Gregord46cf182010-08-16 20:01:48 +00002050void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
2051 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00002052 CodeCompletionResult *Results,
Douglas Gregord46cf182010-08-16 20:01:48 +00002053 unsigned NumResults) {
2054 // Merge the results we were given with the results we cached.
2055 bool AddedResult = false;
Douglas Gregor6199f2d2010-08-16 21:18:39 +00002056 unsigned InContexts
Douglas Gregor0ac41382010-09-23 23:01:17 +00002057 = (Context.getKind() == CodeCompletionContext::CCC_Recovery? NormalContexts
NAKAMURA Takumi203f87c2011-08-17 01:46:16 +00002058 : (1ULL << (Context.getKind() - 1)));
Douglas Gregor6199f2d2010-08-16 21:18:39 +00002059 // Contains the set of names that are hidden by "local" completion results.
Ted Kremenek6a153372010-11-07 06:11:36 +00002060 llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
John McCall276321a2010-08-25 06:19:51 +00002061 typedef CodeCompletionResult Result;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002062 SmallVector<Result, 8> AllResults;
Douglas Gregord46cf182010-08-16 20:01:48 +00002063 for (ASTUnit::cached_completion_iterator
Douglas Gregordf239672010-08-16 21:23:13 +00002064 C = AST.cached_completion_begin(),
2065 CEnd = AST.cached_completion_end();
Douglas Gregord46cf182010-08-16 20:01:48 +00002066 C != CEnd; ++C) {
2067 // If the context we are in matches any of the contexts we are
2068 // interested in, we'll add this result.
2069 if ((C->ShowInContexts & InContexts) == 0)
2070 continue;
2071
2072 // If we haven't added any results previously, do so now.
2073 if (!AddedResult) {
Douglas Gregor6199f2d2010-08-16 21:18:39 +00002074 CalculateHiddenNames(Context, Results, NumResults, S.Context,
2075 HiddenNames);
Douglas Gregord46cf182010-08-16 20:01:48 +00002076 AllResults.insert(AllResults.end(), Results, Results + NumResults);
2077 AddedResult = true;
2078 }
2079
Douglas Gregor6199f2d2010-08-16 21:18:39 +00002080 // Determine whether this global completion result is hidden by a local
2081 // completion result. If so, skip it.
2082 if (C->Kind != CXCursor_MacroDefinition &&
2083 HiddenNames.count(C->Completion->getTypedText()))
2084 continue;
2085
Douglas Gregord46cf182010-08-16 20:01:48 +00002086 // Adjust priority based on similar type classes.
2087 unsigned Priority = C->Priority;
Douglas Gregor8850aa32010-08-25 18:03:13 +00002088 CXCursorKind CursorKind = C->Kind;
Douglas Gregor12785102010-08-24 20:21:13 +00002089 CodeCompletionString *Completion = C->Completion;
Douglas Gregord46cf182010-08-16 20:01:48 +00002090 if (!Context.getPreferredType().isNull()) {
2091 if (C->Kind == CXCursor_MacroDefinition) {
2092 Priority = getMacroUsagePriority(C->Completion->getTypedText(),
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002093 S.getLangOptions(),
Douglas Gregor12785102010-08-24 20:21:13 +00002094 Context.getPreferredType()->isAnyPointerType());
Douglas Gregord46cf182010-08-16 20:01:48 +00002095 } else if (C->Type) {
2096 CanQualType Expected
Douglas Gregordf239672010-08-16 21:23:13 +00002097 = S.Context.getCanonicalType(
Douglas Gregord46cf182010-08-16 20:01:48 +00002098 Context.getPreferredType().getUnqualifiedType());
2099 SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
2100 if (ExpectedSTC == C->TypeClass) {
2101 // We know this type is similar; check for an exact match.
2102 llvm::StringMap<unsigned> &CachedCompletionTypes
Douglas Gregordf239672010-08-16 21:23:13 +00002103 = AST.getCachedCompletionTypes();
Douglas Gregord46cf182010-08-16 20:01:48 +00002104 llvm::StringMap<unsigned>::iterator Pos
Douglas Gregordf239672010-08-16 21:23:13 +00002105 = CachedCompletionTypes.find(QualType(Expected).getAsString());
Douglas Gregord46cf182010-08-16 20:01:48 +00002106 if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)
2107 Priority /= CCF_ExactTypeMatch;
2108 else
2109 Priority /= CCF_SimilarTypeMatch;
2110 }
2111 }
2112 }
2113
Douglas Gregor12785102010-08-24 20:21:13 +00002114 // Adjust the completion string, if required.
2115 if (C->Kind == CXCursor_MacroDefinition &&
2116 Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
2117 // Create a new code-completion string that just contains the
2118 // macro name, without its arguments.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002119 CodeCompletionBuilder Builder(getAllocator(), CCP_CodePattern,
2120 C->Availability);
2121 Builder.AddTypedTextChunk(C->Completion->getTypedText());
Douglas Gregor8850aa32010-08-25 18:03:13 +00002122 CursorKind = CXCursor_NotImplemented;
2123 Priority = CCP_CodePattern;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002124 Completion = Builder.TakeString();
Douglas Gregor12785102010-08-24 20:21:13 +00002125 }
2126
Douglas Gregor8850aa32010-08-25 18:03:13 +00002127 AllResults.push_back(Result(Completion, Priority, CursorKind,
Douglas Gregorf757a122010-08-23 23:00:57 +00002128 C->Availability));
Douglas Gregord46cf182010-08-16 20:01:48 +00002129 }
2130
2131 // If we did not add any cached completion results, just forward the
2132 // results we were given to the next consumer.
2133 if (!AddedResult) {
2134 Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
2135 return;
2136 }
Douglas Gregor49f67ce2010-08-26 13:48:20 +00002137
Douglas Gregord46cf182010-08-16 20:01:48 +00002138 Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
2139 AllResults.size());
2140}
2141
2142
2143
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002144void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
Douglas Gregor8e984da2010-08-04 16:47:14 +00002145 RemappedFile *RemappedFiles,
2146 unsigned NumRemappedFiles,
Douglas Gregorb68bc592010-08-05 09:09:23 +00002147 bool IncludeMacros,
2148 bool IncludeCodePatterns,
Douglas Gregor8e984da2010-08-04 16:47:14 +00002149 CodeCompleteConsumer &Consumer,
2150 Diagnostic &Diag, LangOptions &LangOpts,
2151 SourceManager &SourceMgr, FileManager &FileMgr,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002152 SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
2153 SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
Ted Kremenek5e14d392011-03-21 18:40:17 +00002154 if (!Invocation)
Douglas Gregor8e984da2010-08-04 16:47:14 +00002155 return;
2156
Douglas Gregor16896c42010-10-28 15:44:59 +00002157 SimpleTimer CompletionTimer(WantTiming);
Benjamin Kramerf2e5a912010-11-09 20:00:56 +00002158 CompletionTimer.setOutput("Code completion @ " + File + ":" +
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002159 Twine(Line) + ":" + Twine(Column));
Douglas Gregor028d3e42010-08-09 20:45:32 +00002160
Ted Kremenek5e14d392011-03-21 18:40:17 +00002161 llvm::IntrusiveRefCntPtr<CompilerInvocation>
2162 CCInvocation(new CompilerInvocation(*Invocation));
2163
2164 FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts();
2165 PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts();
Douglas Gregorb68bc592010-08-05 09:09:23 +00002166
Douglas Gregorb14904c2010-08-13 22:48:40 +00002167 FrontendOpts.ShowMacrosInCodeCompletion
2168 = IncludeMacros && CachedCompletionResults.empty();
Douglas Gregorb68bc592010-08-05 09:09:23 +00002169 FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns;
Douglas Gregor39982192010-08-15 06:18:01 +00002170 FrontendOpts.ShowGlobalSymbolsInCodeCompletion
2171 = CachedCompletionResults.empty();
Douglas Gregor8e984da2010-08-04 16:47:14 +00002172 FrontendOpts.CodeCompletionAt.FileName = File;
2173 FrontendOpts.CodeCompletionAt.Line = Line;
2174 FrontendOpts.CodeCompletionAt.Column = Column;
2175
2176 // Set the language options appropriately.
Ted Kremenek5e14d392011-03-21 18:40:17 +00002177 LangOpts = CCInvocation->getLangOpts();
Douglas Gregor8e984da2010-08-04 16:47:14 +00002178
Ted Kremenek84de4a12011-03-21 18:40:07 +00002179 llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance());
2180
2181 // Recover resources if we crash before exiting this method.
Ted Kremenek022a4902011-03-22 01:15:24 +00002182 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
2183 CICleanup(Clang.get());
Ted Kremenek84de4a12011-03-21 18:40:07 +00002184
Ted Kremenek5e14d392011-03-21 18:40:17 +00002185 Clang->setInvocation(&*CCInvocation);
Ted Kremenek84de4a12011-03-21 18:40:07 +00002186 OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
Douglas Gregor8e984da2010-08-04 16:47:14 +00002187
2188 // Set up diagnostics, capturing any diagnostics produced.
Ted Kremenek84de4a12011-03-21 18:40:07 +00002189 Clang->setDiagnostics(&Diag);
Ted Kremenek5e14d392011-03-21 18:40:17 +00002190 ProcessWarningOptions(Diag, CCInvocation->getDiagnosticOpts());
Douglas Gregor8e984da2010-08-04 16:47:14 +00002191 CaptureDroppedDiagnostics Capture(true,
Ted Kremenek84de4a12011-03-21 18:40:07 +00002192 Clang->getDiagnostics(),
Douglas Gregor8e984da2010-08-04 16:47:14 +00002193 StoredDiagnostics);
Douglas Gregor8e984da2010-08-04 16:47:14 +00002194
2195 // Create the target instance.
Ted Kremenek84de4a12011-03-21 18:40:07 +00002196 Clang->getTargetOpts().Features = TargetFeatures;
2197 Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
2198 Clang->getTargetOpts()));
2199 if (!Clang->hasTarget()) {
Ted Kremenek5e14d392011-03-21 18:40:17 +00002200 Clang->setInvocation(0);
Douglas Gregor2dd19f12010-08-18 22:29:43 +00002201 return;
Douglas Gregor8e984da2010-08-04 16:47:14 +00002202 }
2203
2204 // Inform the target of the language options.
2205 //
2206 // FIXME: We shouldn't need to do this, the target should be immutable once
2207 // created. This complexity should be lifted elsewhere.
Ted Kremenek84de4a12011-03-21 18:40:07 +00002208 Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
Douglas Gregor8e984da2010-08-04 16:47:14 +00002209
Ted Kremenek84de4a12011-03-21 18:40:07 +00002210 assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
Douglas Gregor8e984da2010-08-04 16:47:14 +00002211 "Invocation must have exactly one source file!");
Ted Kremenek84de4a12011-03-21 18:40:07 +00002212 assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
Douglas Gregor8e984da2010-08-04 16:47:14 +00002213 "FIXME: AST inputs not yet supported here!");
Ted Kremenek84de4a12011-03-21 18:40:07 +00002214 assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
Douglas Gregor8e984da2010-08-04 16:47:14 +00002215 "IR inputs not support here!");
2216
2217
2218 // Use the source and file managers that we were given.
Ted Kremenek84de4a12011-03-21 18:40:07 +00002219 Clang->setFileManager(&FileMgr);
2220 Clang->setSourceManager(&SourceMgr);
Douglas Gregor8e984da2010-08-04 16:47:14 +00002221
2222 // Remap files.
2223 PreprocessorOpts.clearRemappedFiles();
Douglas Gregord8a5dba2010-08-04 17:07:00 +00002224 PreprocessorOpts.RetainRemappedFileBuffers = true;
Douglas Gregorb97b6662010-08-20 00:59:43 +00002225 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
Argyrios Kyrtzidis11e6f0a2011-03-05 01:03:53 +00002226 FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
2227 if (const llvm::MemoryBuffer *
2228 memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
2229 PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, memBuf);
2230 OwnedBuffers.push_back(memBuf);
2231 } else {
2232 const char *fname = fileOrBuf.get<const char *>();
2233 PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, fname);
2234 }
Douglas Gregorb97b6662010-08-20 00:59:43 +00002235 }
Douglas Gregor8e984da2010-08-04 16:47:14 +00002236
Douglas Gregorb14904c2010-08-13 22:48:40 +00002237 // Use the code completion consumer we were given, but adding any cached
2238 // code-completion results.
Douglas Gregore9186e62010-11-29 16:13:56 +00002239 AugmentedCodeCompleteConsumer *AugmentedConsumer
2240 = new AugmentedCodeCompleteConsumer(*this, Consumer,
2241 FrontendOpts.ShowMacrosInCodeCompletion,
2242 FrontendOpts.ShowCodePatternsInCodeCompletion,
2243 FrontendOpts.ShowGlobalSymbolsInCodeCompletion);
Ted Kremenek84de4a12011-03-21 18:40:07 +00002244 Clang->setCodeCompletionConsumer(AugmentedConsumer);
Douglas Gregor8e984da2010-08-04 16:47:14 +00002245
Douglas Gregor028d3e42010-08-09 20:45:32 +00002246 // If we have a precompiled preamble, try to use it. We only allow
2247 // the use of the precompiled preamble if we're if the completion
2248 // point is within the main file, after the end of the precompiled
2249 // preamble.
2250 llvm::MemoryBuffer *OverrideMainBuffer = 0;
2251 if (!PreambleFile.empty()) {
2252 using llvm::sys::FileStatus;
2253 llvm::sys::PathWithStatus CompleteFilePath(File);
2254 llvm::sys::PathWithStatus MainPath(OriginalSourceFile);
2255 if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus())
2256 if (const FileStatus *MainStatus = MainPath.getFileStatus())
2257 if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID())
Douglas Gregorb97b6662010-08-20 00:59:43 +00002258 OverrideMainBuffer
Ted Kremenek5e14d392011-03-21 18:40:17 +00002259 = getMainBufferWithPrecompiledPreamble(*CCInvocation, false,
Douglas Gregor8e817b62010-08-25 18:04:15 +00002260 Line - 1);
Douglas Gregor028d3e42010-08-09 20:45:32 +00002261 }
2262
2263 // If the main file has been overridden due to the use of a preamble,
2264 // make that override happen and introduce the preamble.
Douglas Gregor606c4ac2011-02-05 19:42:43 +00002265 PreprocessorOpts.DisableStatCache = true;
Douglas Gregor7bb8af62010-10-12 00:50:20 +00002266 StoredDiagnostics.insert(StoredDiagnostics.end(),
2267 this->StoredDiagnostics.begin(),
2268 this->StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver);
Douglas Gregor028d3e42010-08-09 20:45:32 +00002269 if (OverrideMainBuffer) {
2270 PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
2271 PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
2272 PreprocessorOpts.PrecompiledPreambleBytes.second
2273 = PreambleEndsAtStartOfLine;
2274 PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
2275 PreprocessorOpts.DisablePCHValidation = true;
2276
Douglas Gregorb97b6662010-08-20 00:59:43 +00002277 OwnedBuffers.push_back(OverrideMainBuffer);
Douglas Gregor7b02b582010-08-20 00:02:33 +00002278 } else {
2279 PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
2280 PreprocessorOpts.PrecompiledPreambleBytes.second = false;
Douglas Gregor028d3e42010-08-09 20:45:32 +00002281 }
2282
Douglas Gregor998caea2011-05-06 16:33:08 +00002283 // Disable the preprocessing record
2284 PreprocessorOpts.DetailedRecord = false;
2285
Douglas Gregor8e984da2010-08-04 16:47:14 +00002286 llvm::OwningPtr<SyntaxOnlyAction> Act;
2287 Act.reset(new SyntaxOnlyAction);
Ted Kremenek84de4a12011-03-21 18:40:07 +00002288 if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
2289 Clang->getFrontendOpts().Inputs[0].first)) {
Douglas Gregor925296b2011-07-19 16:10:42 +00002290 if (OverrideMainBuffer) {
Jonathan D. Turner2214acd2011-07-22 17:25:03 +00002291 std::string ModName = PreambleFile;
Douglas Gregor925296b2011-07-19 16:10:42 +00002292 TranslateStoredDiagnostics(Clang->getModuleManager(), ModName,
2293 getSourceManager(), PreambleDiagnostics,
2294 StoredDiagnostics);
2295 }
Douglas Gregor8e984da2010-08-04 16:47:14 +00002296 Act->Execute();
2297 Act->EndSourceFile();
2298 }
Douglas Gregor8e984da2010-08-04 16:47:14 +00002299}
Douglas Gregore9386682010-08-13 05:36:37 +00002300
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002301CXSaveError ASTUnit::Save(StringRef File) {
Douglas Gregor8a60bbe2011-07-06 17:40:26 +00002302 if (getDiagnostics().hasUnrecoverableErrorOccurred())
Douglas Gregor30c80fa2011-07-06 16:43:36 +00002303 return CXSaveError_TranslationErrors;
Argyrios Kyrtzidis55e75572011-07-21 18:44:49 +00002304
2305 // Write to a temporary file and later rename it to the actual file, to avoid
2306 // possible race conditions.
Argyrios Kyrtzidis08a2bfd2011-07-28 00:45:10 +00002307 llvm::SmallString<128> TempPath;
2308 TempPath = File;
2309 TempPath += "-%%%%%%%%";
2310 int fd;
2311 if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath,
2312 /*makeAbsolute=*/false))
Argyrios Kyrtzidis55e75572011-07-21 18:44:49 +00002313 return CXSaveError_Unknown;
Argyrios Kyrtzidis55e75572011-07-21 18:44:49 +00002314
Douglas Gregore9386682010-08-13 05:36:37 +00002315 // FIXME: Can we somehow regenerate the stat cache here, or do we need to
2316 // unconditionally create a stat cache when we parse the file?
Argyrios Kyrtzidis08a2bfd2011-07-28 00:45:10 +00002317 llvm::raw_fd_ostream Out(fd, /*shouldClose=*/true);
Argyrios Kyrtzidis35dcda72011-03-09 17:21:42 +00002318
2319 serialize(Out);
2320 Out.close();
Argyrios Kyrtzidis55e75572011-07-21 18:44:49 +00002321 if (Out.has_error())
2322 return CXSaveError_Unknown;
2323
2324 if (llvm::error_code ec = llvm::sys::fs::rename(TempPath.str(), File)) {
2325 bool exists;
2326 llvm::sys::fs::remove(TempPath.str(), exists);
2327 return CXSaveError_Unknown;
2328 }
2329
2330 return CXSaveError_None;
Argyrios Kyrtzidis35dcda72011-03-09 17:21:42 +00002331}
2332
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002333bool ASTUnit::serialize(raw_ostream &OS) {
Argyrios Kyrtzidis35dcda72011-03-09 17:21:42 +00002334 if (getDiagnostics().hasErrorOccurred())
2335 return true;
2336
Douglas Gregore9386682010-08-13 05:36:37 +00002337 std::vector<unsigned char> Buffer;
2338 llvm::BitstreamWriter Stream(Buffer);
Sebastian Redl55c0ad52010-08-18 23:56:21 +00002339 ASTWriter Writer(Stream);
Douglas Gregor4a69c2e2011-09-01 17:04:32 +00002340 // FIXME: Handle modules
2341 Writer.WriteAST(getSema(), 0, std::string(), /*IsModule=*/false, "");
Douglas Gregore9386682010-08-13 05:36:37 +00002342
2343 // Write the generated bitstream to "Out".
Douglas Gregor2dd19f12010-08-18 22:29:43 +00002344 if (!Buffer.empty())
Argyrios Kyrtzidis35dcda72011-03-09 17:21:42 +00002345 OS.write((char *)&Buffer.front(), Buffer.size());
2346
2347 return false;
Douglas Gregore9386682010-08-13 05:36:37 +00002348}
Douglas Gregor925296b2011-07-19 16:10:42 +00002349
2350typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap;
2351
2352static void TranslateSLoc(SourceLocation &L, SLocRemap &Remap) {
2353 unsigned Raw = L.getRawEncoding();
2354 const unsigned MacroBit = 1U << 31;
2355 L = SourceLocation::getFromRawEncoding((Raw & MacroBit) |
2356 ((Raw & ~MacroBit) + Remap.find(Raw & ~MacroBit)->second));
2357}
2358
2359void ASTUnit::TranslateStoredDiagnostics(
2360 ASTReader *MMan,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002361 StringRef ModName,
Douglas Gregor925296b2011-07-19 16:10:42 +00002362 SourceManager &SrcMgr,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002363 const SmallVectorImpl<StoredDiagnostic> &Diags,
2364 SmallVectorImpl<StoredDiagnostic> &Out) {
Douglas Gregor925296b2011-07-19 16:10:42 +00002365 // The stored diagnostic has the old source manager in it; update
2366 // the locations to refer into the new source manager. We also need to remap
2367 // all the locations to the new view. This includes the diag location, any
2368 // associated source ranges, and the source ranges of associated fix-its.
2369 // FIXME: There should be a cleaner way to do this.
2370
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002371 SmallVector<StoredDiagnostic, 4> Result;
Douglas Gregor925296b2011-07-19 16:10:42 +00002372 Result.reserve(Diags.size());
2373 assert(MMan && "Don't have a module manager");
Jonathan D. Turnerb2b08232011-07-26 18:21:30 +00002374 serialization::Module *Mod = MMan->ModuleMgr.lookup(ModName);
Douglas Gregor925296b2011-07-19 16:10:42 +00002375 assert(Mod && "Don't have preamble module");
2376 SLocRemap &Remap = Mod->SLocRemap;
2377 for (unsigned I = 0, N = Diags.size(); I != N; ++I) {
2378 // Rebuild the StoredDiagnostic.
2379 const StoredDiagnostic &SD = Diags[I];
2380 SourceLocation L = SD.getLocation();
2381 TranslateSLoc(L, Remap);
2382 FullSourceLoc Loc(L, SrcMgr);
2383
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002384 SmallVector<CharSourceRange, 4> Ranges;
Douglas Gregor925296b2011-07-19 16:10:42 +00002385 Ranges.reserve(SD.range_size());
2386 for (StoredDiagnostic::range_iterator I = SD.range_begin(),
2387 E = SD.range_end();
2388 I != E; ++I) {
2389 SourceLocation BL = I->getBegin();
2390 TranslateSLoc(BL, Remap);
2391 SourceLocation EL = I->getEnd();
2392 TranslateSLoc(EL, Remap);
2393 Ranges.push_back(CharSourceRange(SourceRange(BL, EL), I->isTokenRange()));
2394 }
2395
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002396 SmallVector<FixItHint, 2> FixIts;
Douglas Gregor925296b2011-07-19 16:10:42 +00002397 FixIts.reserve(SD.fixit_size());
2398 for (StoredDiagnostic::fixit_iterator I = SD.fixit_begin(),
2399 E = SD.fixit_end();
2400 I != E; ++I) {
2401 FixIts.push_back(FixItHint());
2402 FixItHint &FH = FixIts.back();
2403 FH.CodeToInsert = I->CodeToInsert;
2404 SourceLocation BL = I->RemoveRange.getBegin();
2405 TranslateSLoc(BL, Remap);
2406 SourceLocation EL = I->RemoveRange.getEnd();
2407 TranslateSLoc(EL, Remap);
2408 FH.RemoveRange = CharSourceRange(SourceRange(BL, EL),
2409 I->RemoveRange.isTokenRange());
2410 }
2411
2412 Result.push_back(StoredDiagnostic(SD.getLevel(), SD.getID(),
2413 SD.getMessage(), Loc, Ranges, FixIts));
2414 }
2415 Result.swap(Out);
2416}