blob: e84f8bd6e29f0eaf2cb0c8652cf4b5e10eeb8d76 [file] [log] [blame]
Argyrios Kyrtzidis4b562cf2009-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 Kyrtzidis0853a022009-06-20 08:08:23 +000014#include "clang/Frontend/ASTUnit.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000015#include "clang/AST/ASTContext.h"
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000016#include "clang/AST/ASTConsumer.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000017#include "clang/AST/DeclVisitor.h"
Douglas Gregorf5586f62010-08-16 18:08:11 +000018#include "clang/AST/TypeOrdering.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000019#include "clang/AST/StmtVisitor.h"
Daniel Dunbar7b556682009-12-02 03:23:45 +000020#include "clang/Driver/Compilation.h"
21#include "clang/Driver/Driver.h"
22#include "clang/Driver/Job.h"
Argyrios Kyrtzidis4e03c2b2011-03-07 22:45:01 +000023#include "clang/Driver/ArgList.h"
24#include "clang/Driver/Options.h"
Daniel Dunbar7b556682009-12-02 03:23:45 +000025#include "clang/Driver/Tool.h"
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000026#include "clang/Frontend/CompilerInstance.h"
27#include "clang/Frontend/FrontendActions.h"
Daniel Dunbar7b556682009-12-02 03:23:45 +000028#include "clang/Frontend/FrontendDiagnostic.h"
Daniel Dunbar521bf9c2009-12-01 09:51:01 +000029#include "clang/Frontend/FrontendOptions.h"
Douglas Gregor32be4a52010-10-11 21:37:58 +000030#include "clang/Frontend/Utils.h"
Sebastian Redl6ab7cd82010-08-18 23:57:17 +000031#include "clang/Serialization/ASTReader.h"
Sebastian Redl7faa2ec2010-08-18 23:56:37 +000032#include "clang/Serialization/ASTWriter.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000033#include "clang/Lex/HeaderSearch.h"
34#include "clang/Lex/Preprocessor.h"
Daniel Dunbard58c03f2009-11-15 06:48:46 +000035#include "clang/Basic/TargetOptions.h"
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000036#include "clang/Basic/TargetInfo.h"
37#include "clang/Basic/Diagnostic.h"
Chris Lattner7f9fc3f2011-03-23 04:04:01 +000038#include "llvm/ADT/ArrayRef.h"
Douglas Gregor9b7db622011-02-16 18:16:54 +000039#include "llvm/ADT/StringExtras.h"
Douglas Gregor349d38c2010-08-16 23:08:34 +000040#include "llvm/ADT/StringSet.h"
Douglas Gregor1fd9e0d2010-12-07 00:05:48 +000041#include "llvm/Support/Atomic.h"
Douglas Gregor4db64a42010-01-23 00:14:00 +000042#include "llvm/Support/MemoryBuffer.h"
Michael J. Spencer03013fa2010-11-29 18:12:39 +000043#include "llvm/Support/Host.h"
44#include "llvm/Support/Path.h"
Douglas Gregordf95a132010-08-09 20:45:32 +000045#include "llvm/Support/raw_ostream.h"
Douglas Gregor385103b2010-07-30 20:58:08 +000046#include "llvm/Support/Timer.h"
Argyrios Kyrtzidis9cca68d2011-07-21 18:44:49 +000047#include "llvm/Support/FileSystem.h"
Ted Kremenekb547eeb2011-03-18 02:06:56 +000048#include "llvm/Support/CrashRecoveryContext.h"
Douglas Gregor44c181a2010-07-23 00:33:23 +000049#include <cstdlib>
Zhongxing Xuad23ebe2010-07-23 02:15:08 +000050#include <cstdio>
Douglas Gregorcc5888d2010-07-31 00:40:00 +000051#include <sys/stat.h>
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +000052using namespace clang;
53
Douglas Gregor213f18b2010-10-28 15:44:59 +000054using llvm::TimeRecord;
55
56namespace {
57 class SimpleTimer {
58 bool WantTiming;
59 TimeRecord Start;
60 std::string Output;
61
Benjamin Krameredfb7ec2010-11-09 20:00:56 +000062 public:
Douglas Gregor9dba61a2010-11-01 13:48:43 +000063 explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) {
Douglas Gregor213f18b2010-10-28 15:44:59 +000064 if (WantTiming)
Benjamin Krameredfb7ec2010-11-09 20:00:56 +000065 Start = TimeRecord::getCurrentTime();
Douglas Gregor213f18b2010-10-28 15:44:59 +000066 }
67
Chris Lattner5f9e2722011-07-23 10:55:15 +000068 void setOutput(const Twine &Output) {
Douglas Gregor213f18b2010-10-28 15:44:59 +000069 if (WantTiming)
Benjamin Krameredfb7ec2010-11-09 20:00:56 +000070 this->Output = Output.str();
Douglas Gregor213f18b2010-10-28 15:44:59 +000071 }
72
Douglas Gregor213f18b2010-10-28 15:44:59 +000073 ~SimpleTimer() {
74 if (WantTiming) {
75 TimeRecord Elapsed = TimeRecord::getCurrentTime();
76 Elapsed -= Start;
77 llvm::errs() << Output << ':';
78 Elapsed.print(Elapsed, llvm::errs());
79 llvm::errs() << '\n';
80 }
81 }
82 };
83}
84
Douglas Gregoreababfb2010-08-04 05:53:38 +000085/// \brief After failing to build a precompiled preamble (due to
86/// errors in the source that occurs in the preamble), the number of
87/// reparses during which we'll skip even trying to precompile the
88/// preamble.
89const unsigned DefaultPreambleRebuildInterval = 5;
90
Douglas Gregore3c60a72010-11-17 00:13:31 +000091/// \brief Tracks the number of ASTUnit objects that are currently active.
92///
93/// Used for debugging purposes only.
Douglas Gregor1fd9e0d2010-12-07 00:05:48 +000094static llvm::sys::cas_flag ActiveASTUnitObjects;
Douglas Gregore3c60a72010-11-17 00:13:31 +000095
Douglas Gregor3687e9d2010-04-05 21:10:19 +000096ASTUnit::ASTUnit(bool _MainFileIsAST)
Argyrios Kyrtzidisb0f4b9a2011-03-09 17:21:42 +000097 : OnlyLocalDecls(false), CaptureDiagnostics(false),
98 MainFileIsAST(_MainFileIsAST),
Douglas Gregor467dc882011-08-25 22:30:56 +000099 TUKind(TU_Complete), WantTiming(getenv("LIBCLANG_TIMING")),
Argyrios Kyrtzidis15727dd2011-03-05 01:03:48 +0000100 OwnsRemappedFileBuffers(true),
Douglas Gregor213f18b2010-10-28 15:44:59 +0000101 NumStoredDiagnosticsFromDriver(0),
Douglas Gregor4cd912a2010-10-12 00:50:20 +0000102 ConcurrencyCheckValue(CheckUnlocked),
Douglas Gregor671947b2010-08-19 01:33:06 +0000103 PreambleRebuildCounter(0), SavedMainFileBuffer(0), PreambleBuffer(0),
Douglas Gregor727d93e2010-08-17 00:40:40 +0000104 ShouldCacheCodeCompletionResults(false),
Chandler Carruthba7537f2011-07-14 09:02:10 +0000105 NestedMacroExpansions(true),
Douglas Gregor9b7db622011-02-16 18:16:54 +0000106 CompletionCacheTopLevelHashValue(0),
107 PreambleTopLevelHashValue(0),
108 CurrentTopLevelHashValue(0),
Douglas Gregor8b1540c2010-08-19 00:45:44 +0000109 UnsafeToFree(false) {
Douglas Gregore3c60a72010-11-17 00:13:31 +0000110 if (getenv("LIBCLANG_OBJTRACKING")) {
Douglas Gregor1fd9e0d2010-12-07 00:05:48 +0000111 llvm::sys::AtomicIncrement(&ActiveASTUnitObjects);
Douglas Gregore3c60a72010-11-17 00:13:31 +0000112 fprintf(stderr, "+++ %d translation units\n", ActiveASTUnitObjects);
113 }
Douglas Gregor385103b2010-07-30 20:58:08 +0000114}
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000115
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000116ASTUnit::~ASTUnit() {
Douglas Gregorbdf60622010-03-05 21:16:25 +0000117 ConcurrencyCheckValue = CheckLocked;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000118 CleanTemporaryFiles();
Douglas Gregor175c4a92010-07-23 23:58:40 +0000119 if (!PreambleFile.empty())
Douglas Gregor385103b2010-07-30 20:58:08 +0000120 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000121
122 // Free the buffers associated with remapped files. We are required to
123 // perform this operation here because we explicitly request that the
124 // compiler instance *not* free these buffers for each invocation of the
125 // parser.
Ted Kremenek4f327862011-03-21 18:40:17 +0000126 if (Invocation.getPtr() && OwnsRemappedFileBuffers) {
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000127 PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
128 for (PreprocessorOptions::remapped_file_buffer_iterator
129 FB = PPOpts.remapped_file_buffer_begin(),
130 FBEnd = PPOpts.remapped_file_buffer_end();
131 FB != FBEnd;
132 ++FB)
133 delete FB->second;
134 }
Douglas Gregor28233422010-07-27 14:52:07 +0000135
136 delete SavedMainFileBuffer;
Douglas Gregor671947b2010-08-19 01:33:06 +0000137 delete PreambleBuffer;
138
Douglas Gregor213f18b2010-10-28 15:44:59 +0000139 ClearCachedCompletionResults();
Douglas Gregore3c60a72010-11-17 00:13:31 +0000140
141 if (getenv("LIBCLANG_OBJTRACKING")) {
Douglas Gregor1fd9e0d2010-12-07 00:05:48 +0000142 llvm::sys::AtomicDecrement(&ActiveASTUnitObjects);
Douglas Gregore3c60a72010-11-17 00:13:31 +0000143 fprintf(stderr, "--- %d translation units\n", ActiveASTUnitObjects);
144 }
Douglas Gregorabc563f2010-07-19 21:46:24 +0000145}
146
147void ASTUnit::CleanTemporaryFiles() {
Douglas Gregor313e26c2010-02-18 23:35:40 +0000148 for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
149 TemporaryFiles[I].eraseFromDisk();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000150 TemporaryFiles.clear();
Steve Naroffe19944c2009-10-15 22:23:48 +0000151}
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000152
Douglas Gregor8071e422010-08-15 06:18:01 +0000153/// \brief Determine the set of code-completion contexts in which this
154/// declaration should be shown.
155static unsigned getDeclShowContexts(NamedDecl *ND,
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000156 const LangOptions &LangOpts,
157 bool &IsNestedNameSpecifier) {
158 IsNestedNameSpecifier = false;
159
Douglas Gregor8071e422010-08-15 06:18:01 +0000160 if (isa<UsingShadowDecl>(ND))
161 ND = dyn_cast<NamedDecl>(ND->getUnderlyingDecl());
162 if (!ND)
163 return 0;
164
165 unsigned Contexts = 0;
166 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) ||
167 isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND)) {
168 // Types can appear in these contexts.
169 if (LangOpts.CPlusPlus || !isa<TagDecl>(ND))
170 Contexts |= (1 << (CodeCompletionContext::CCC_TopLevel - 1))
171 | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
172 | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
173 | (1 << (CodeCompletionContext::CCC_Statement - 1))
Douglas Gregor02688102010-09-14 23:59:36 +0000174 | (1 << (CodeCompletionContext::CCC_Type - 1))
175 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1));
Douglas Gregor8071e422010-08-15 06:18:01 +0000176
177 // In C++, types can appear in expressions contexts (for functional casts).
178 if (LangOpts.CPlusPlus)
179 Contexts |= (1 << (CodeCompletionContext::CCC_Expression - 1));
180
181 // In Objective-C, message sends can send interfaces. In Objective-C++,
182 // all types are available due to functional casts.
183 if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND))
184 Contexts |= (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
Douglas Gregor3da626b2011-07-07 16:03:39 +0000185
186 // In Objective-C, you can only be a subclass of another Objective-C class
187 if (isa<ObjCInterfaceDecl>(ND))
Douglas Gregor0f91c8c2011-07-30 06:55:39 +0000188 Contexts |= (1 << (CodeCompletionContext::CCC_ObjCInterfaceName - 1));
Douglas Gregor8071e422010-08-15 06:18:01 +0000189
190 // Deal with tag names.
191 if (isa<EnumDecl>(ND)) {
192 Contexts |= (1 << (CodeCompletionContext::CCC_EnumTag - 1));
193
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000194 // Part of the nested-name-specifier in C++0x.
Douglas Gregor8071e422010-08-15 06:18:01 +0000195 if (LangOpts.CPlusPlus0x)
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000196 IsNestedNameSpecifier = true;
Douglas Gregor8071e422010-08-15 06:18:01 +0000197 } else if (RecordDecl *Record = dyn_cast<RecordDecl>(ND)) {
198 if (Record->isUnion())
199 Contexts |= (1 << (CodeCompletionContext::CCC_UnionTag - 1));
200 else
201 Contexts |= (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
202
Douglas Gregor8071e422010-08-15 06:18:01 +0000203 if (LangOpts.CPlusPlus)
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000204 IsNestedNameSpecifier = true;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000205 } else if (isa<ClassTemplateDecl>(ND))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000206 IsNestedNameSpecifier = true;
Douglas Gregor8071e422010-08-15 06:18:01 +0000207 } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {
208 // Values can appear in these contexts.
209 Contexts = (1 << (CodeCompletionContext::CCC_Statement - 1))
210 | (1 << (CodeCompletionContext::CCC_Expression - 1))
Douglas Gregor02688102010-09-14 23:59:36 +0000211 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
Douglas Gregor8071e422010-08-15 06:18:01 +0000212 | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1));
213 } else if (isa<ObjCProtocolDecl>(ND)) {
214 Contexts = (1 << (CodeCompletionContext::CCC_ObjCProtocolName - 1));
Douglas Gregor3da626b2011-07-07 16:03:39 +0000215 } else if (isa<ObjCCategoryDecl>(ND)) {
216 Contexts = (1 << (CodeCompletionContext::CCC_ObjCCategoryName - 1));
Douglas Gregor8071e422010-08-15 06:18:01 +0000217 } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) {
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000218 Contexts = (1 << (CodeCompletionContext::CCC_Namespace - 1));
Douglas Gregor8071e422010-08-15 06:18:01 +0000219
220 // Part of the nested-name-specifier.
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000221 IsNestedNameSpecifier = true;
Douglas Gregor8071e422010-08-15 06:18:01 +0000222 }
223
224 return Contexts;
225}
226
Douglas Gregor87c08a52010-08-13 22:48:40 +0000227void ASTUnit::CacheCodeCompletionResults() {
228 if (!TheSema)
229 return;
230
Douglas Gregor213f18b2010-10-28 15:44:59 +0000231 SimpleTimer Timer(WantTiming);
Benjamin Krameredfb7ec2010-11-09 20:00:56 +0000232 Timer.setOutput("Cache global code completions for " + getMainFileName());
Douglas Gregor87c08a52010-08-13 22:48:40 +0000233
234 // Clear out the previous results.
235 ClearCachedCompletionResults();
236
237 // Gather the set of global code completions.
John McCall0a2c5e22010-08-25 06:19:51 +0000238 typedef CodeCompletionResult Result;
Chris Lattner5f9e2722011-07-23 10:55:15 +0000239 SmallVector<Result, 8> Results;
Douglas Gregor48601b32011-02-16 19:08:06 +0000240 CachedCompletionAllocator = new GlobalCodeCompletionAllocator;
241 TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator, Results);
Douglas Gregor87c08a52010-08-13 22:48:40 +0000242
243 // Translate global code completions into cached completions.
Douglas Gregorf5586f62010-08-16 18:08:11 +0000244 llvm::DenseMap<CanQualType, unsigned> CompletionTypes;
245
Douglas Gregor87c08a52010-08-13 22:48:40 +0000246 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
247 switch (Results[I].Kind) {
Douglas Gregor8071e422010-08-15 06:18:01 +0000248 case Result::RK_Declaration: {
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000249 bool IsNestedNameSpecifier = false;
Douglas Gregor8071e422010-08-15 06:18:01 +0000250 CachedCodeCompletionResult CachedResult;
Douglas Gregor218937c2011-02-01 19:23:04 +0000251 CachedResult.Completion = Results[I].CreateCodeCompletionString(*TheSema,
Douglas Gregor48601b32011-02-16 19:08:06 +0000252 *CachedCompletionAllocator);
Douglas Gregor8071e422010-08-15 06:18:01 +0000253 CachedResult.ShowInContexts = getDeclShowContexts(Results[I].Declaration,
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000254 Ctx->getLangOptions(),
255 IsNestedNameSpecifier);
Douglas Gregor8071e422010-08-15 06:18:01 +0000256 CachedResult.Priority = Results[I].Priority;
257 CachedResult.Kind = Results[I].CursorKind;
Douglas Gregor58ddb602010-08-23 23:00:57 +0000258 CachedResult.Availability = Results[I].Availability;
Douglas Gregorc4421e92010-08-16 16:46:30 +0000259
Douglas Gregorf5586f62010-08-16 18:08:11 +0000260 // Keep track of the type of this completion in an ASTContext-agnostic
261 // way.
Douglas Gregorc4421e92010-08-16 16:46:30 +0000262 QualType UsageType = getDeclUsageType(*Ctx, Results[I].Declaration);
Douglas Gregorf5586f62010-08-16 18:08:11 +0000263 if (UsageType.isNull()) {
Douglas Gregorc4421e92010-08-16 16:46:30 +0000264 CachedResult.TypeClass = STC_Void;
Douglas Gregorf5586f62010-08-16 18:08:11 +0000265 CachedResult.Type = 0;
266 } else {
267 CanQualType CanUsageType
268 = Ctx->getCanonicalType(UsageType.getUnqualifiedType());
269 CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType);
270
271 // Determine whether we have already seen this type. If so, we save
272 // ourselves the work of formatting the type string by using the
273 // temporary, CanQualType-based hash table to find the associated value.
274 unsigned &TypeValue = CompletionTypes[CanUsageType];
275 if (TypeValue == 0) {
276 TypeValue = CompletionTypes.size();
277 CachedCompletionTypes[QualType(CanUsageType).getAsString()]
278 = TypeValue;
279 }
280
281 CachedResult.Type = TypeValue;
Douglas Gregorc4421e92010-08-16 16:46:30 +0000282 }
Douglas Gregorf5586f62010-08-16 18:08:11 +0000283
Douglas Gregor8071e422010-08-15 06:18:01 +0000284 CachedCompletionResults.push_back(CachedResult);
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000285
286 /// Handle nested-name-specifiers in C++.
287 if (TheSema->Context.getLangOptions().CPlusPlus &&
288 IsNestedNameSpecifier && !Results[I].StartsNestedNameSpecifier) {
289 // The contexts in which a nested-name-specifier can appear in C++.
290 unsigned NNSContexts
291 = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
292 | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
293 | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
294 | (1 << (CodeCompletionContext::CCC_Statement - 1))
295 | (1 << (CodeCompletionContext::CCC_Expression - 1))
296 | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
297 | (1 << (CodeCompletionContext::CCC_EnumTag - 1))
298 | (1 << (CodeCompletionContext::CCC_UnionTag - 1))
299 | (1 << (CodeCompletionContext::CCC_ClassOrStructTag - 1))
Douglas Gregor2ccccb32010-08-23 18:23:48 +0000300 | (1 << (CodeCompletionContext::CCC_Type - 1))
Douglas Gregor02688102010-09-14 23:59:36 +0000301 | (1 << (CodeCompletionContext::CCC_PotentiallyQualifiedName - 1))
302 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1));
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000303
304 if (isa<NamespaceDecl>(Results[I].Declaration) ||
305 isa<NamespaceAliasDecl>(Results[I].Declaration))
306 NNSContexts |= (1 << (CodeCompletionContext::CCC_Namespace - 1));
307
308 if (unsigned RemainingContexts
309 = NNSContexts & ~CachedResult.ShowInContexts) {
310 // If there any contexts where this completion can be a
311 // nested-name-specifier but isn't already an option, create a
312 // nested-name-specifier completion.
313 Results[I].StartsNestedNameSpecifier = true;
Douglas Gregor218937c2011-02-01 19:23:04 +0000314 CachedResult.Completion
315 = Results[I].CreateCodeCompletionString(*TheSema,
Douglas Gregor48601b32011-02-16 19:08:06 +0000316 *CachedCompletionAllocator);
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000317 CachedResult.ShowInContexts = RemainingContexts;
318 CachedResult.Priority = CCP_NestedNameSpecifier;
319 CachedResult.TypeClass = STC_Void;
320 CachedResult.Type = 0;
321 CachedCompletionResults.push_back(CachedResult);
322 }
323 }
Douglas Gregor87c08a52010-08-13 22:48:40 +0000324 break;
Douglas Gregor8071e422010-08-15 06:18:01 +0000325 }
326
Douglas Gregor87c08a52010-08-13 22:48:40 +0000327 case Result::RK_Keyword:
328 case Result::RK_Pattern:
329 // Ignore keywords and patterns; we don't care, since they are so
330 // easily regenerated.
331 break;
332
333 case Result::RK_Macro: {
334 CachedCodeCompletionResult CachedResult;
Douglas Gregor218937c2011-02-01 19:23:04 +0000335 CachedResult.Completion
336 = Results[I].CreateCodeCompletionString(*TheSema,
Douglas Gregor48601b32011-02-16 19:08:06 +0000337 *CachedCompletionAllocator);
Douglas Gregor87c08a52010-08-13 22:48:40 +0000338 CachedResult.ShowInContexts
339 = (1 << (CodeCompletionContext::CCC_TopLevel - 1))
340 | (1 << (CodeCompletionContext::CCC_ObjCInterface - 1))
341 | (1 << (CodeCompletionContext::CCC_ObjCImplementation - 1))
342 | (1 << (CodeCompletionContext::CCC_ObjCIvarList - 1))
343 | (1 << (CodeCompletionContext::CCC_ClassStructUnion - 1))
344 | (1 << (CodeCompletionContext::CCC_Statement - 1))
345 | (1 << (CodeCompletionContext::CCC_Expression - 1))
Douglas Gregor1fbb4472010-08-24 20:21:13 +0000346 | (1 << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
Douglas Gregorf29c5232010-08-24 22:20:20 +0000347 | (1 << (CodeCompletionContext::CCC_MacroNameUse - 1))
Douglas Gregor02688102010-09-14 23:59:36 +0000348 | (1 << (CodeCompletionContext::CCC_PreprocessorExpression - 1))
Douglas Gregor5c722c702011-02-18 23:30:37 +0000349 | (1 << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
350 | (1 << (CodeCompletionContext::CCC_OtherWithMacros - 1));
Douglas Gregor2ccccb32010-08-23 18:23:48 +0000351
Douglas Gregor87c08a52010-08-13 22:48:40 +0000352 CachedResult.Priority = Results[I].Priority;
353 CachedResult.Kind = Results[I].CursorKind;
Douglas Gregor58ddb602010-08-23 23:00:57 +0000354 CachedResult.Availability = Results[I].Availability;
Douglas Gregor1827e102010-08-16 16:18:59 +0000355 CachedResult.TypeClass = STC_Void;
Douglas Gregorf5586f62010-08-16 18:08:11 +0000356 CachedResult.Type = 0;
Douglas Gregor87c08a52010-08-13 22:48:40 +0000357 CachedCompletionResults.push_back(CachedResult);
358 break;
359 }
360 }
Douglas Gregor87c08a52010-08-13 22:48:40 +0000361 }
Douglas Gregor9b7db622011-02-16 18:16:54 +0000362
363 // Save the current top-level hash value.
364 CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue;
Douglas Gregor87c08a52010-08-13 22:48:40 +0000365}
366
367void ASTUnit::ClearCachedCompletionResults() {
Douglas Gregor87c08a52010-08-13 22:48:40 +0000368 CachedCompletionResults.clear();
Douglas Gregorf5586f62010-08-16 18:08:11 +0000369 CachedCompletionTypes.clear();
Douglas Gregor48601b32011-02-16 19:08:06 +0000370 CachedCompletionAllocator = 0;
Douglas Gregor87c08a52010-08-13 22:48:40 +0000371}
372
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000373namespace {
374
Sebastian Redlc43b54c2010-08-18 23:56:43 +0000375/// \brief Gathers information from ASTReader that will be used to initialize
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000376/// a Preprocessor.
Sebastian Redl3c7f4132010-08-18 23:57:06 +0000377class ASTInfoCollector : public ASTReaderListener {
Douglas Gregor998b3d32011-09-01 23:39:15 +0000378 Preprocessor &PP;
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000379 ASTContext &Context;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000380 LangOptions &LangOpt;
381 HeaderSearch &HSI;
Douglas Gregor998b3d32011-09-01 23:39:15 +0000382 llvm::IntrusiveRefCntPtr<TargetInfo> &Target;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000383 std::string &Predefines;
384 unsigned &Counter;
Mike Stump1eb44332009-09-09 15:08:12 +0000385
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000386 unsigned NumHeaderInfos;
Mike Stump1eb44332009-09-09 15:08:12 +0000387
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000388 bool InitializedLanguage;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000389public:
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000390 ASTInfoCollector(Preprocessor &PP, ASTContext &Context, LangOptions &LangOpt,
391 HeaderSearch &HSI,
Douglas Gregor998b3d32011-09-01 23:39:15 +0000392 llvm::IntrusiveRefCntPtr<TargetInfo> &Target,
393 std::string &Predefines,
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000394 unsigned &Counter)
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000395 : PP(PP), Context(Context), LangOpt(LangOpt), HSI(HSI), Target(Target),
Douglas Gregor998b3d32011-09-01 23:39:15 +0000396 Predefines(Predefines), Counter(Counter), NumHeaderInfos(0),
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000397 InitializedLanguage(false) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000398
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000399 virtual bool ReadLanguageOptions(const LangOptions &LangOpts) {
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000400 if (InitializedLanguage)
Douglas Gregor998b3d32011-09-01 23:39:15 +0000401 return false;
402
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000403 LangOpt = LangOpts;
Douglas Gregor998b3d32011-09-01 23:39:15 +0000404
405 // Initialize the preprocessor.
406 PP.Initialize(*Target);
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000407
408 // Initialize the ASTContext
409 Context.InitBuiltinTypes(*Target);
410
411 InitializedLanguage = true;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000412 return false;
413 }
Mike Stump1eb44332009-09-09 15:08:12 +0000414
Chris Lattner5f9e2722011-07-23 10:55:15 +0000415 virtual bool ReadTargetTriple(StringRef Triple) {
Douglas Gregor998b3d32011-09-01 23:39:15 +0000416 // If we've already initialized the target, don't do it again.
417 if (Target)
418 return false;
419
420 // FIXME: This is broken, we should store the TargetOptions in the AST file.
421 TargetOptions TargetOpts;
422 TargetOpts.ABI = "";
423 TargetOpts.CXXABI = "";
424 TargetOpts.CPU = "";
425 TargetOpts.Features.clear();
426 TargetOpts.Triple = Triple;
427 Target = TargetInfo::CreateTargetInfo(PP.getDiagnostics(), TargetOpts);
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000428 return false;
429 }
Mike Stump1eb44332009-09-09 15:08:12 +0000430
Sebastian Redlcb481aa2010-07-14 23:29:55 +0000431 virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
Chris Lattner5f9e2722011-07-23 10:55:15 +0000432 StringRef OriginalFileName,
Nick Lewycky277a6e72011-02-23 21:16:44 +0000433 std::string &SuggestedPredefines,
434 FileManager &FileMgr) {
Sebastian Redlcb481aa2010-07-14 23:29:55 +0000435 Predefines = Buffers[0].Data;
436 for (unsigned I = 1, N = Buffers.size(); I != N; ++I) {
437 Predefines += Buffers[I].Data;
438 }
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000439 return false;
440 }
Mike Stump1eb44332009-09-09 15:08:12 +0000441
Douglas Gregorec1afbf2010-03-16 19:09:18 +0000442 virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI, unsigned ID) {
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000443 HSI.setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
444 }
Mike Stump1eb44332009-09-09 15:08:12 +0000445
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000446 virtual void ReadCounter(unsigned Value) {
447 Counter = Value;
448 }
449};
450
David Blaikie26e7a902011-09-26 00:01:39 +0000451class StoredDiagnosticConsumer : public DiagnosticConsumer {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000452 SmallVectorImpl<StoredDiagnostic> &StoredDiags;
Douglas Gregora88084b2010-02-18 18:08:43 +0000453
454public:
David Blaikie26e7a902011-09-26 00:01:39 +0000455 explicit StoredDiagnosticConsumer(
Chris Lattner5f9e2722011-07-23 10:55:15 +0000456 SmallVectorImpl<StoredDiagnostic> &StoredDiags)
Douglas Gregora88084b2010-02-18 18:08:43 +0000457 : StoredDiags(StoredDiags) { }
458
David Blaikied6471f72011-09-25 23:23:43 +0000459 virtual void HandleDiagnostic(DiagnosticsEngine::Level Level,
David Blaikie40847cf2011-09-26 01:18:08 +0000460 const Diagnostic &Info);
Douglas Gregoraee526e2011-09-29 00:38:00 +0000461
462 DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
463 // Just drop any diagnostics that come from cloned consumers; they'll
464 // have different source managers anyway.
465 return new IgnoringDiagConsumer();
466 }
Douglas Gregora88084b2010-02-18 18:08:43 +0000467};
468
469/// \brief RAII object that optionally captures diagnostics, if
470/// there is no diagnostic client to capture them already.
471class CaptureDroppedDiagnostics {
David Blaikied6471f72011-09-25 23:23:43 +0000472 DiagnosticsEngine &Diags;
David Blaikie26e7a902011-09-26 00:01:39 +0000473 StoredDiagnosticConsumer Client;
David Blaikie78ad0b92011-09-25 23:39:51 +0000474 DiagnosticConsumer *PreviousClient;
Douglas Gregora88084b2010-02-18 18:08:43 +0000475
476public:
David Blaikied6471f72011-09-25 23:23:43 +0000477 CaptureDroppedDiagnostics(bool RequestCapture, DiagnosticsEngine &Diags,
Chris Lattner5f9e2722011-07-23 10:55:15 +0000478 SmallVectorImpl<StoredDiagnostic> &StoredDiags)
Douglas Gregorbdbb0042010-08-18 22:29:43 +0000479 : Diags(Diags), Client(StoredDiags), PreviousClient(0)
Douglas Gregora88084b2010-02-18 18:08:43 +0000480 {
Douglas Gregorbdbb0042010-08-18 22:29:43 +0000481 if (RequestCapture || Diags.getClient() == 0) {
482 PreviousClient = Diags.takeClient();
Douglas Gregora88084b2010-02-18 18:08:43 +0000483 Diags.setClient(&Client);
Douglas Gregorbdbb0042010-08-18 22:29:43 +0000484 }
Douglas Gregora88084b2010-02-18 18:08:43 +0000485 }
486
487 ~CaptureDroppedDiagnostics() {
Douglas Gregorbdbb0042010-08-18 22:29:43 +0000488 if (Diags.getClient() == &Client) {
489 Diags.takeClient();
490 Diags.setClient(PreviousClient);
491 }
Douglas Gregora88084b2010-02-18 18:08:43 +0000492 }
493};
494
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000495} // anonymous namespace
496
David Blaikie26e7a902011-09-26 00:01:39 +0000497void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level,
David Blaikie40847cf2011-09-26 01:18:08 +0000498 const Diagnostic &Info) {
Argyrios Kyrtzidisf2224d82010-11-18 20:06:46 +0000499 // Default implementation (Warnings/errors count).
David Blaikie78ad0b92011-09-25 23:39:51 +0000500 DiagnosticConsumer::HandleDiagnostic(Level, Info);
Argyrios Kyrtzidisf2224d82010-11-18 20:06:46 +0000501
Douglas Gregora88084b2010-02-18 18:08:43 +0000502 StoredDiags.push_back(StoredDiagnostic(Level, Info));
503}
504
Steve Naroff77accc12009-09-03 18:19:54 +0000505const std::string &ASTUnit::getOriginalSourceFileName() {
Daniel Dunbar68d40e22009-12-02 08:44:16 +0000506 return OriginalSourceFile;
Steve Naroff77accc12009-09-03 18:19:54 +0000507}
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000508
Chris Lattner5f9e2722011-07-23 10:55:15 +0000509llvm::MemoryBuffer *ASTUnit::getBufferForFile(StringRef Filename,
Chris Lattner75dfb652010-11-23 09:19:42 +0000510 std::string *ErrorStr) {
Chris Lattner39b49bc2010-11-23 08:35:12 +0000511 assert(FileMgr);
Chris Lattner75dfb652010-11-23 09:19:42 +0000512 return FileMgr->getBufferForFile(Filename, ErrorStr);
Argyrios Kyrtzidis389db162010-11-03 22:45:23 +0000513}
514
Douglas Gregore47be3e2010-11-11 00:39:14 +0000515/// \brief Configure the diagnostics object for use with ASTUnit.
David Blaikied6471f72011-09-25 23:23:43 +0000516void ASTUnit::ConfigureDiags(llvm::IntrusiveRefCntPtr<DiagnosticsEngine> &Diags,
Douglas Gregor0b53cf82011-01-19 01:02:47 +0000517 const char **ArgBegin, const char **ArgEnd,
Douglas Gregore47be3e2010-11-11 00:39:14 +0000518 ASTUnit &AST, bool CaptureDiagnostics) {
519 if (!Diags.getPtr()) {
520 // No diagnostics engine was provided, so create our own diagnostics object
521 // with the default options.
522 DiagnosticOptions DiagOpts;
David Blaikie78ad0b92011-09-25 23:39:51 +0000523 DiagnosticConsumer *Client = 0;
Douglas Gregore47be3e2010-11-11 00:39:14 +0000524 if (CaptureDiagnostics)
David Blaikie26e7a902011-09-26 00:01:39 +0000525 Client = new StoredDiagnosticConsumer(AST.StoredDiagnostics);
Douglas Gregor0b53cf82011-01-19 01:02:47 +0000526 Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd- ArgBegin,
527 ArgBegin, Client);
Douglas Gregore47be3e2010-11-11 00:39:14 +0000528 } else if (CaptureDiagnostics) {
David Blaikie26e7a902011-09-26 00:01:39 +0000529 Diags->setClient(new StoredDiagnosticConsumer(AST.StoredDiagnostics));
Douglas Gregore47be3e2010-11-11 00:39:14 +0000530 }
531}
532
Sebastian Redl3c7f4132010-08-18 23:57:06 +0000533ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename,
David Blaikied6471f72011-09-25 23:23:43 +0000534 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
Argyrios Kyrtzidis389db162010-11-03 22:45:23 +0000535 const FileSystemOptions &FileSystemOpts,
Ted Kremenek5cf48762009-10-17 00:34:24 +0000536 bool OnlyLocalDecls,
Douglas Gregor4db64a42010-01-23 00:14:00 +0000537 RemappedFile *RemappedFiles,
Douglas Gregora88084b2010-02-18 18:08:43 +0000538 unsigned NumRemappedFiles,
539 bool CaptureDiagnostics) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000540 llvm::OwningPtr<ASTUnit> AST(new ASTUnit(true));
Ted Kremenekb547eeb2011-03-18 02:06:56 +0000541
542 // Recover resources if we crash before exiting this method.
Ted Kremenek25a11e12011-03-22 01:15:24 +0000543 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
544 ASTUnitCleanup(AST.get());
David Blaikied6471f72011-09-25 23:23:43 +0000545 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
546 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
Ted Kremenek25a11e12011-03-22 01:15:24 +0000547 DiagCleanup(Diags.getPtr());
Ted Kremenekb547eeb2011-03-18 02:06:56 +0000548
Douglas Gregor0b53cf82011-01-19 01:02:47 +0000549 ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
Douglas Gregorabc563f2010-07-19 21:46:24 +0000550
Douglas Gregor7d1d49d2009-10-16 20:01:17 +0000551 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregore47be3e2010-11-11 00:39:14 +0000552 AST->CaptureDiagnostics = CaptureDiagnostics;
Douglas Gregor28019772010-04-05 23:52:57 +0000553 AST->Diagnostics = Diags;
Ted Kremenek4f327862011-03-21 18:40:17 +0000554 AST->FileMgr = new FileManager(FileSystemOpts);
555 AST->SourceMgr = new SourceManager(AST->getDiagnostics(),
556 AST->getFileManager());
Chris Lattner39b49bc2010-11-23 08:35:12 +0000557 AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));
Douglas Gregor914ed9d2010-08-13 03:15:25 +0000558
Douglas Gregor4db64a42010-01-23 00:14:00 +0000559 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
Argyrios Kyrtzidisb1c86492011-03-05 01:03:53 +0000560 FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
561 if (const llvm::MemoryBuffer *
562 memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
563 // Create the file entry for the file that we're mapping from.
564 const FileEntry *FromFile
565 = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
566 memBuf->getBufferSize(),
567 0);
568 if (!FromFile) {
569 AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
570 << RemappedFiles[I].first;
571 delete memBuf;
572 continue;
573 }
574
575 // Override the contents of the "from" file with the contents of
576 // the "to" file.
577 AST->getSourceManager().overrideFileContents(FromFile, memBuf);
578
579 } else {
580 const char *fname = fileOrBuf.get<const char *>();
581 const FileEntry *ToFile = AST->FileMgr->getFile(fname);
582 if (!ToFile) {
583 AST->getDiagnostics().Report(diag::err_fe_remap_missing_to_file)
584 << RemappedFiles[I].first << fname;
585 continue;
586 }
587
588 // Create the file entry for the file that we're mapping from.
589 const FileEntry *FromFile
590 = AST->getFileManager().getVirtualFile(RemappedFiles[I].first,
591 ToFile->getSize(),
592 0);
593 if (!FromFile) {
594 AST->getDiagnostics().Report(diag::err_fe_remap_missing_from_file)
595 << RemappedFiles[I].first;
596 delete memBuf;
597 continue;
598 }
599
600 // Override the contents of the "from" file with the contents of
601 // the "to" file.
602 AST->getSourceManager().overrideFileContents(FromFile, ToFile);
Douglas Gregor4db64a42010-01-23 00:14:00 +0000603 }
Douglas Gregor4db64a42010-01-23 00:14:00 +0000604 }
605
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000606 // Gather Info for preprocessor construction later on.
Mike Stump1eb44332009-09-09 15:08:12 +0000607
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000608 HeaderSearch &HeaderInfo = *AST->HeaderInfo.get();
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000609 std::string Predefines;
610 unsigned Counter;
611
Sebastian Redlc43b54c2010-08-18 23:56:43 +0000612 llvm::OwningPtr<ASTReader> Reader;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000613
Douglas Gregor998b3d32011-09-01 23:39:15 +0000614 AST->PP = new Preprocessor(AST->getDiagnostics(), AST->ASTFileLangOpts,
615 /*Target=*/0, AST->getSourceManager(), HeaderInfo,
616 *AST,
617 /*IILookup=*/0,
618 /*OwnsHeaderSearch=*/false,
619 /*DelayInitialization=*/true);
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000620 Preprocessor &PP = *AST->PP;
621
622 AST->Ctx = new ASTContext(AST->ASTFileLangOpts,
623 AST->getSourceManager(),
624 /*Target=*/0,
625 PP.getIdentifierTable(),
626 PP.getSelectorTable(),
627 PP.getBuiltinInfo(),
628 /* size_reserve = */0,
629 /*DelayInitialization=*/true);
630 ASTContext &Context = *AST->Ctx;
Douglas Gregor998b3d32011-09-01 23:39:15 +0000631
Douglas Gregorf8a1e512011-09-02 00:26:20 +0000632 Reader.reset(new ASTReader(PP, Context));
Ted Kremenek8c647de2011-05-04 23:27:12 +0000633
634 // Recover resources if we crash before exiting this method.
635 llvm::CrashRecoveryContextCleanupRegistrar<ASTReader>
636 ReaderCleanup(Reader.get());
637
Douglas Gregorbcfd1f52011-09-02 00:18:52 +0000638 Reader->setListener(new ASTInfoCollector(*AST->PP, Context,
Douglas Gregor998b3d32011-09-01 23:39:15 +0000639 AST->ASTFileLangOpts, HeaderInfo,
640 AST->Target, Predefines, Counter));
Daniel Dunbarcc318932009-09-03 05:59:35 +0000641
Douglas Gregor72a9ae12011-07-22 16:00:58 +0000642 switch (Reader->ReadAST(Filename, serialization::MK_MainFile)) {
Sebastian Redlc43b54c2010-08-18 23:56:43 +0000643 case ASTReader::Success:
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000644 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000645
Sebastian Redlc43b54c2010-08-18 23:56:43 +0000646 case ASTReader::Failure:
647 case ASTReader::IgnorePCH:
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000648 AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch);
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000649 return NULL;
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000650 }
Mike Stump1eb44332009-09-09 15:08:12 +0000651
Daniel Dunbar68d40e22009-12-02 08:44:16 +0000652 AST->OriginalSourceFile = Reader->getOriginalSourceFile();
653
Daniel Dunbard5b61262009-09-21 03:03:47 +0000654 PP.setPredefines(Reader->getSuggestedPredefines());
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000655 PP.setCounterValue(Counter);
Mike Stump1eb44332009-09-09 15:08:12 +0000656
Sebastian Redlc43b54c2010-08-18 23:56:43 +0000657 // Attach the AST reader to the AST context as an external AST
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000658 // source, so that declarations will be deserialized from the
Sebastian Redl3c7f4132010-08-18 23:57:06 +0000659 // AST file as needed.
Sebastian Redlc43b54c2010-08-18 23:56:43 +0000660 ASTReader *ReaderPtr = Reader.get();
Douglas Gregor914ed9d2010-08-13 03:15:25 +0000661 llvm::OwningPtr<ExternalASTSource> Source(Reader.take());
Ted Kremenek8c647de2011-05-04 23:27:12 +0000662
663 // Unregister the cleanup for ASTReader. It will get cleaned up
664 // by the ASTUnit cleanup.
665 ReaderCleanup.unregister();
666
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000667 Context.setExternalSource(Source);
668
Douglas Gregor914ed9d2010-08-13 03:15:25 +0000669 // Create an AST consumer, even though it isn't used.
670 AST->Consumer.reset(new ASTConsumer);
671
Sebastian Redlc43b54c2010-08-18 23:56:43 +0000672 // Create a semantic analysis object and tell the AST reader about it.
Douglas Gregor914ed9d2010-08-13 03:15:25 +0000673 AST->TheSema.reset(new Sema(PP, Context, *AST->Consumer));
674 AST->TheSema->Initialize();
675 ReaderPtr->InitializeSema(*AST->TheSema);
676
Mike Stump1eb44332009-09-09 15:08:12 +0000677 return AST.take();
Argyrios Kyrtzidis0853a022009-06-20 08:08:23 +0000678}
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000679
680namespace {
681
Douglas Gregor9b7db622011-02-16 18:16:54 +0000682/// \brief Preprocessor callback class that updates a hash value with the names
683/// of all macros that have been defined by the translation unit.
684class MacroDefinitionTrackerPPCallbacks : public PPCallbacks {
685 unsigned &Hash;
686
687public:
688 explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) { }
689
690 virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
691 Hash = llvm::HashString(MacroNameTok.getIdentifierInfo()->getName(), Hash);
692 }
693};
694
695/// \brief Add the given declaration to the hash of all top-level entities.
696void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) {
697 if (!D)
698 return;
699
700 DeclContext *DC = D->getDeclContext();
701 if (!DC)
702 return;
703
704 if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit()))
705 return;
706
707 if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
708 if (ND->getIdentifier())
709 Hash = llvm::HashString(ND->getIdentifier()->getName(), Hash);
710 else if (DeclarationName Name = ND->getDeclName()) {
711 std::string NameStr = Name.getAsString();
712 Hash = llvm::HashString(NameStr, Hash);
713 }
714 return;
715 }
716
717 if (ObjCForwardProtocolDecl *Forward
718 = dyn_cast<ObjCForwardProtocolDecl>(D)) {
719 for (ObjCForwardProtocolDecl::protocol_iterator
720 P = Forward->protocol_begin(),
721 PEnd = Forward->protocol_end();
722 P != PEnd; ++P)
723 AddTopLevelDeclarationToHash(*P, Hash);
724 return;
725 }
726
Chris Lattner5f9e2722011-07-23 10:55:15 +0000727 if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(D)) {
Fariborz Jahanian95ed7782011-08-27 20:50:59 +0000728 AddTopLevelDeclarationToHash(Class->getForwardInterfaceDecl(), Hash);
Douglas Gregor9b7db622011-02-16 18:16:54 +0000729 return;
730 }
731}
732
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000733class TopLevelDeclTrackerConsumer : public ASTConsumer {
734 ASTUnit &Unit;
Douglas Gregor9b7db622011-02-16 18:16:54 +0000735 unsigned &Hash;
736
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000737public:
Douglas Gregor9b7db622011-02-16 18:16:54 +0000738 TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash)
739 : Unit(_Unit), Hash(Hash) {
740 Hash = 0;
741 }
742
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000743 void HandleTopLevelDecl(DeclGroupRef D) {
Ted Kremenekda5a4282010-05-03 20:16:35 +0000744 for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
745 Decl *D = *it;
746 // FIXME: Currently ObjC method declarations are incorrectly being
747 // reported as top-level declarations, even though their DeclContext
748 // is the containing ObjC @interface/@implementation. This is a
749 // fundamental problem in the parser right now.
750 if (isa<ObjCMethodDecl>(D))
751 continue;
Douglas Gregor9b7db622011-02-16 18:16:54 +0000752
753 AddTopLevelDeclarationToHash(D, Hash);
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000754 Unit.addTopLevelDecl(D);
Ted Kremenekda5a4282010-05-03 20:16:35 +0000755 }
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000756 }
Sebastian Redl27372b42010-08-11 18:52:41 +0000757
758 // We're not interested in "interesting" decls.
759 void HandleInterestingDecl(DeclGroupRef) {}
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000760};
761
762class TopLevelDeclTrackerAction : public ASTFrontendAction {
763public:
764 ASTUnit &Unit;
765
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000766 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
Chris Lattner5f9e2722011-07-23 10:55:15 +0000767 StringRef InFile) {
Douglas Gregor9b7db622011-02-16 18:16:54 +0000768 CI.getPreprocessor().addPPCallbacks(
769 new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue()));
770 return new TopLevelDeclTrackerConsumer(Unit,
771 Unit.getCurrentTopLevelHashValue());
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000772 }
773
774public:
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000775 TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {}
776
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000777 virtual bool hasCodeCompletionSupport() const { return false; }
Douglas Gregor467dc882011-08-25 22:30:56 +0000778 virtual TranslationUnitKind getTranslationUnitKind() {
779 return Unit.getTranslationUnitKind();
Douglas Gregordf95a132010-08-09 20:45:32 +0000780 }
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000781};
782
Argyrios Kyrtzidis92ddef12011-09-19 20:40:48 +0000783class PrecompilePreambleConsumer : public PCHGenerator {
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000784 ASTUnit &Unit;
Douglas Gregor9b7db622011-02-16 18:16:54 +0000785 unsigned &Hash;
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000786 std::vector<Decl *> TopLevelDecls;
Douglas Gregor89d99802010-11-30 06:16:57 +0000787
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000788public:
Douglas Gregor9293ba82011-08-25 22:35:51 +0000789 PrecompilePreambleConsumer(ASTUnit &Unit, const Preprocessor &PP,
Chris Lattner5f9e2722011-07-23 10:55:15 +0000790 StringRef isysroot, raw_ostream *Out)
Douglas Gregor7143aab2011-09-01 17:04:32 +0000791 : PCHGenerator(PP, "", /*IsModule=*/false, isysroot, Out), Unit(Unit),
Douglas Gregor9b7db622011-02-16 18:16:54 +0000792 Hash(Unit.getCurrentTopLevelHashValue()) {
793 Hash = 0;
794 }
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000795
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000796 virtual void HandleTopLevelDecl(DeclGroupRef D) {
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000797 for (DeclGroupRef::iterator it = D.begin(), ie = D.end(); it != ie; ++it) {
798 Decl *D = *it;
799 // FIXME: Currently ObjC method declarations are incorrectly being
800 // reported as top-level declarations, even though their DeclContext
801 // is the containing ObjC @interface/@implementation. This is a
802 // fundamental problem in the parser right now.
803 if (isa<ObjCMethodDecl>(D))
804 continue;
Douglas Gregor9b7db622011-02-16 18:16:54 +0000805 AddTopLevelDeclarationToHash(D, Hash);
Douglas Gregoreb8837b2010-08-03 19:06:41 +0000806 TopLevelDecls.push_back(D);
807 }
808 }
809
810 virtual void HandleTranslationUnit(ASTContext &Ctx) {
811 PCHGenerator::HandleTranslationUnit(Ctx);
812 if (!Unit.getDiagnostics().hasErrorOccurred()) {
813 // Translate the top-level declarations we captured during
814 // parsing into declaration IDs in the precompiled
815 // preamble. This will allow us to deserialize those top-level
816 // declarations when requested.
817 for (unsigned I = 0, N = TopLevelDecls.size(); I != N; ++I)
818 Unit.addTopLevelDeclFromPreamble(
819 getWriter().getDeclID(TopLevelDecls[I]));
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000820 }
821 }
822};
823
824class PrecompilePreambleAction : public ASTFrontendAction {
825 ASTUnit &Unit;
826
827public:
828 explicit PrecompilePreambleAction(ASTUnit &Unit) : Unit(Unit) {}
829
830 virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
Chris Lattner5f9e2722011-07-23 10:55:15 +0000831 StringRef InFile) {
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000832 std::string Sysroot;
Argyrios Kyrtzidis8e3df4d2011-02-15 17:54:22 +0000833 std::string OutputFile;
Chris Lattner5f9e2722011-07-23 10:55:15 +0000834 raw_ostream *OS = 0;
Argyrios Kyrtzidis8e3df4d2011-02-15 17:54:22 +0000835 if (GeneratePCHAction::ComputeASTConsumerArguments(CI, InFile, Sysroot,
836 OutputFile,
Douglas Gregor9293ba82011-08-25 22:35:51 +0000837 OS))
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000838 return 0;
839
Douglas Gregor832d6202011-07-22 16:35:34 +0000840 if (!CI.getFrontendOpts().RelocatablePCH)
841 Sysroot.clear();
842
Douglas Gregor9b7db622011-02-16 18:16:54 +0000843 CI.getPreprocessor().addPPCallbacks(
844 new MacroDefinitionTrackerPPCallbacks(Unit.getCurrentTopLevelHashValue()));
Douglas Gregor9293ba82011-08-25 22:35:51 +0000845 return new PrecompilePreambleConsumer(Unit, CI.getPreprocessor(), Sysroot,
846 OS);
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000847 }
848
849 virtual bool hasCodeCompletionSupport() const { return false; }
850 virtual bool hasASTFileSupport() const { return false; }
Douglas Gregor467dc882011-08-25 22:30:56 +0000851 virtual TranslationUnitKind getTranslationUnitKind() { return TU_Prefix; }
Douglas Gregor1d715ac2010-08-03 08:14:03 +0000852};
853
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000854}
855
Douglas Gregorabc563f2010-07-19 21:46:24 +0000856/// Parse the source file into a translation unit using the given compiler
857/// invocation, replacing the current translation unit.
858///
859/// \returns True if a failure occurred that causes the ASTUnit not to
860/// contain any translation-unit information, false otherwise.
Douglas Gregor754f3492010-07-24 00:38:13 +0000861bool ASTUnit::Parse(llvm::MemoryBuffer *OverrideMainBuffer) {
Douglas Gregor28233422010-07-27 14:52:07 +0000862 delete SavedMainFileBuffer;
863 SavedMainFileBuffer = 0;
864
Ted Kremenek4f327862011-03-21 18:40:17 +0000865 if (!Invocation) {
Douglas Gregor671947b2010-08-19 01:33:06 +0000866 delete OverrideMainBuffer;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000867 return true;
Douglas Gregor671947b2010-08-19 01:33:06 +0000868 }
Douglas Gregorabc563f2010-07-19 21:46:24 +0000869
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000870 // Create the compiler instance to use for building the AST.
Ted Kremenek03201fb2011-03-21 18:40:07 +0000871 llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance());
872
873 // Recover resources if we crash before exiting this method.
Ted Kremenek25a11e12011-03-22 01:15:24 +0000874 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
875 CICleanup(Clang.get());
Ted Kremenek03201fb2011-03-21 18:40:07 +0000876
Argyrios Kyrtzidis26d43cd2011-09-12 18:09:38 +0000877 llvm::IntrusiveRefCntPtr<CompilerInvocation>
878 CCInvocation(new CompilerInvocation(*Invocation));
879
880 Clang->setInvocation(CCInvocation.getPtr());
Ted Kremenek03201fb2011-03-21 18:40:07 +0000881 OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000882
Douglas Gregor1abc6bc2010-08-04 16:47:14 +0000883 // Set up diagnostics, capturing any diagnostics that would
884 // otherwise be dropped.
Ted Kremenek03201fb2011-03-21 18:40:07 +0000885 Clang->setDiagnostics(&getDiagnostics());
Douglas Gregor3687e9d2010-04-05 21:10:19 +0000886
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000887 // Create the target instance.
Ted Kremenek03201fb2011-03-21 18:40:07 +0000888 Clang->getTargetOpts().Features = TargetFeatures;
889 Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
Ted Kremenek4f327862011-03-21 18:40:17 +0000890 Clang->getTargetOpts()));
Ted Kremenek03201fb2011-03-21 18:40:07 +0000891 if (!Clang->hasTarget()) {
Douglas Gregor671947b2010-08-19 01:33:06 +0000892 delete OverrideMainBuffer;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000893 return true;
Douglas Gregor671947b2010-08-19 01:33:06 +0000894 }
895
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000896 // Inform the target of the language options.
897 //
898 // FIXME: We shouldn't need to do this, the target should be immutable once
899 // created. This complexity should be lifted elsewhere.
Ted Kremenek03201fb2011-03-21 18:40:07 +0000900 Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
Douglas Gregorabc563f2010-07-19 21:46:24 +0000901
Ted Kremenek03201fb2011-03-21 18:40:07 +0000902 assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000903 "Invocation must have exactly one source file!");
Ted Kremenek03201fb2011-03-21 18:40:07 +0000904 assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000905 "FIXME: AST inputs not yet supported here!");
Ted Kremenek03201fb2011-03-21 18:40:07 +0000906 assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
Daniel Dunbarfaddc3e2010-06-07 23:26:47 +0000907 "IR inputs not support here!");
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000908
Douglas Gregorabc563f2010-07-19 21:46:24 +0000909 // Configure the various subsystems.
910 // FIXME: Should we retain the previous file manager?
Ted Kremenek03201fb2011-03-21 18:40:07 +0000911 FileSystemOpts = Clang->getFileSystemOpts();
Ted Kremenek4f327862011-03-21 18:40:17 +0000912 FileMgr = new FileManager(FileSystemOpts);
913 SourceMgr = new SourceManager(getDiagnostics(), *FileMgr);
Douglas Gregor914ed9d2010-08-13 03:15:25 +0000914 TheSema.reset();
Ted Kremenek4f327862011-03-21 18:40:17 +0000915 Ctx = 0;
916 PP = 0;
Douglas Gregorabc563f2010-07-19 21:46:24 +0000917
918 // Clear out old caches and data.
919 TopLevelDecls.clear();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000920 CleanTemporaryFiles();
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000921
Douglas Gregorf128fed2010-08-20 00:02:33 +0000922 if (!OverrideMainBuffer) {
Douglas Gregor4cd912a2010-10-12 00:50:20 +0000923 StoredDiagnostics.erase(
924 StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
925 StoredDiagnostics.end());
Douglas Gregorf128fed2010-08-20 00:02:33 +0000926 TopLevelDeclsInPreamble.clear();
927 }
928
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000929 // Create a file manager object to provide access to and cache the filesystem.
Ted Kremenek03201fb2011-03-21 18:40:07 +0000930 Clang->setFileManager(&getFileManager());
Douglas Gregorabc563f2010-07-19 21:46:24 +0000931
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000932 // Create the source manager.
Ted Kremenek03201fb2011-03-21 18:40:07 +0000933 Clang->setSourceManager(&getSourceManager());
Douglas Gregorabc563f2010-07-19 21:46:24 +0000934
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000935 // If the main file has been overridden due to the use of a preamble,
936 // make that override happen and introduce the preamble.
Ted Kremenek03201fb2011-03-21 18:40:07 +0000937 PreprocessorOptions &PreprocessorOpts = Clang->getPreprocessorOpts();
Chandler Carruthba7537f2011-07-14 09:02:10 +0000938 PreprocessorOpts.DetailedRecordIncludesNestedMacroExpansions
939 = NestedMacroExpansions;
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000940 if (OverrideMainBuffer) {
941 PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
942 PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
943 PreprocessorOpts.PrecompiledPreambleBytes.second
944 = PreambleEndsAtStartOfLine;
Douglas Gregor385103b2010-07-30 20:58:08 +0000945 PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
Douglas Gregorfae3b2f2010-07-27 00:27:13 +0000946 PreprocessorOpts.DisablePCHValidation = true;
Douglas Gregor28233422010-07-27 14:52:07 +0000947
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000948 // The stored diagnostic has the old source manager in it; update
949 // the locations to refer into the new source manager. Since we've
950 // been careful to make sure that the source manager's state
951 // before and after are identical, so that we can reuse the source
952 // location itself.
Douglas Gregor4cd912a2010-10-12 00:50:20 +0000953 for (unsigned I = NumStoredDiagnosticsFromDriver,
954 N = StoredDiagnostics.size();
955 I < N; ++I) {
Douglas Gregorc0659ec2010-08-02 20:51:39 +0000956 FullSourceLoc Loc(StoredDiagnostics[I].getLocation(),
957 getSourceManager());
958 StoredDiagnostics[I].setLocation(Loc);
959 }
Douglas Gregor4cd912a2010-10-12 00:50:20 +0000960
961 // Keep track of the override buffer;
962 SavedMainFileBuffer = OverrideMainBuffer;
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000963 }
964
Ted Kremenek25a11e12011-03-22 01:15:24 +0000965 llvm::OwningPtr<TopLevelDeclTrackerAction> Act(
966 new TopLevelDeclTrackerAction(*this));
967
968 // Recover resources if we crash before exiting this method.
969 llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
970 ActCleanup(Act.get());
971
Ted Kremenek03201fb2011-03-21 18:40:07 +0000972 if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
973 Clang->getFrontendOpts().Inputs[0].first))
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000974 goto error;
Douglas Gregorf62d43d2011-07-19 16:10:42 +0000975
976 if (OverrideMainBuffer) {
Jonathan D. Turner9461fcc2011-07-22 17:25:03 +0000977 std::string ModName = PreambleFile;
Douglas Gregorf62d43d2011-07-19 16:10:42 +0000978 TranslateStoredDiagnostics(Clang->getModuleManager(), ModName,
979 getSourceManager(), PreambleDiagnostics,
980 StoredDiagnostics);
981 }
982
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000983 Act->Execute();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000984
Ted Kremenek4f327862011-03-21 18:40:17 +0000985 // Steal the created target, context, and preprocessor.
Ted Kremenek03201fb2011-03-21 18:40:07 +0000986 TheSema.reset(Clang->takeSema());
987 Consumer.reset(Clang->takeASTConsumer());
Ted Kremenek4f327862011-03-21 18:40:17 +0000988 Ctx = &Clang->getASTContext();
989 PP = &Clang->getPreprocessor();
990 Clang->setSourceManager(0);
991 Clang->setFileManager(0);
992 Target = &Clang->getTarget();
Douglas Gregorabc563f2010-07-19 21:46:24 +0000993
Daniel Dunbarf772d1e2009-12-04 08:17:33 +0000994 Act->EndSourceFile();
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000995
Douglas Gregorabc563f2010-07-19 21:46:24 +0000996 return false;
Ted Kremenek4f327862011-03-21 18:40:17 +0000997
Daniel Dunbar521bf9c2009-12-01 09:51:01 +0000998error:
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +0000999 // Remove the overridden buffer we used for the preamble.
Douglas Gregorfae3b2f2010-07-27 00:27:13 +00001000 if (OverrideMainBuffer) {
Douglas Gregor671947b2010-08-19 01:33:06 +00001001 delete OverrideMainBuffer;
Douglas Gregor37cf6632010-10-06 21:11:08 +00001002 SavedMainFileBuffer = 0;
Douglas Gregorfae3b2f2010-07-27 00:27:13 +00001003 }
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001004
Douglas Gregord54eb442010-10-12 16:25:54 +00001005 StoredDiagnostics.clear();
Douglas Gregorabc563f2010-07-19 21:46:24 +00001006 return true;
1007}
1008
Douglas Gregor44c181a2010-07-23 00:33:23 +00001009/// \brief Simple function to retrieve a path for a preamble precompiled header.
1010static std::string GetPreamblePCHPath() {
1011 // FIXME: This is lame; sys::Path should provide this function (in particular,
1012 // it should know how to find the temporary files dir).
1013 // FIXME: This is really lame. I copied this code from the Driver!
Douglas Gregor424668c2010-09-11 18:05:19 +00001014 // FIXME: This is a hack so that we can override the preamble file during
1015 // crash-recovery testing, which is the only case where the preamble files
1016 // are not necessarily cleaned up.
1017 const char *TmpFile = ::getenv("CINDEXTEST_PREAMBLE_FILE");
1018 if (TmpFile)
1019 return TmpFile;
1020
Douglas Gregor44c181a2010-07-23 00:33:23 +00001021 std::string Error;
1022 const char *TmpDir = ::getenv("TMPDIR");
1023 if (!TmpDir)
1024 TmpDir = ::getenv("TEMP");
1025 if (!TmpDir)
1026 TmpDir = ::getenv("TMP");
Douglas Gregorc6cb2b02010-09-11 17:51:16 +00001027#ifdef LLVM_ON_WIN32
1028 if (!TmpDir)
1029 TmpDir = ::getenv("USERPROFILE");
1030#endif
Douglas Gregor44c181a2010-07-23 00:33:23 +00001031 if (!TmpDir)
1032 TmpDir = "/tmp";
1033 llvm::sys::Path P(TmpDir);
Douglas Gregorc6cb2b02010-09-11 17:51:16 +00001034 P.createDirectoryOnDisk(true);
Douglas Gregor44c181a2010-07-23 00:33:23 +00001035 P.appendComponent("preamble");
Douglas Gregor6bf18302010-08-11 13:06:56 +00001036 P.appendSuffix("pch");
Argyrios Kyrtzidisbc9d5a32011-07-21 18:44:46 +00001037 if (P.makeUnique(/*reuse_current=*/false, /*ErrMsg*/0))
Douglas Gregor44c181a2010-07-23 00:33:23 +00001038 return std::string();
1039
Douglas Gregor44c181a2010-07-23 00:33:23 +00001040 return P.str();
1041}
1042
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001043/// \brief Compute the preamble for the main file, providing the source buffer
1044/// that corresponds to the main file along with a pair (bytes, start-of-line)
1045/// that describes the preamble.
1046std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> >
Douglas Gregordf95a132010-08-09 20:45:32 +00001047ASTUnit::ComputePreamble(CompilerInvocation &Invocation,
1048 unsigned MaxLines, bool &CreatedBuffer) {
Douglas Gregor175c4a92010-07-23 23:58:40 +00001049 FrontendOptions &FrontendOpts = Invocation.getFrontendOpts();
Chris Lattner39b49bc2010-11-23 08:35:12 +00001050 PreprocessorOptions &PreprocessorOpts = Invocation.getPreprocessorOpts();
Douglas Gregor175c4a92010-07-23 23:58:40 +00001051 CreatedBuffer = false;
1052
Douglas Gregor44c181a2010-07-23 00:33:23 +00001053 // Try to determine if the main file has been remapped, either from the
1054 // command line (to another file) or directly through the compiler invocation
1055 // (to a memory buffer).
Douglas Gregor175c4a92010-07-23 23:58:40 +00001056 llvm::MemoryBuffer *Buffer = 0;
Douglas Gregor44c181a2010-07-23 00:33:23 +00001057 llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
1058 if (const llvm::sys::FileStatus *MainFileStatus = MainFilePath.getFileStatus()) {
1059 // Check whether there is a file-file remapping of the main file
1060 for (PreprocessorOptions::remapped_file_iterator
Douglas Gregor175c4a92010-07-23 23:58:40 +00001061 M = PreprocessorOpts.remapped_file_begin(),
1062 E = PreprocessorOpts.remapped_file_end();
Douglas Gregor44c181a2010-07-23 00:33:23 +00001063 M != E;
1064 ++M) {
1065 llvm::sys::PathWithStatus MPath(M->first);
1066 if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
1067 if (MainFileStatus->uniqueID == MStatus->uniqueID) {
1068 // We found a remapping. Try to load the resulting, remapped source.
Douglas Gregor175c4a92010-07-23 23:58:40 +00001069 if (CreatedBuffer) {
Douglas Gregor44c181a2010-07-23 00:33:23 +00001070 delete Buffer;
Douglas Gregor175c4a92010-07-23 23:58:40 +00001071 CreatedBuffer = false;
1072 }
1073
Argyrios Kyrtzidis389db162010-11-03 22:45:23 +00001074 Buffer = getBufferForFile(M->second);
Douglas Gregor44c181a2010-07-23 00:33:23 +00001075 if (!Buffer)
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001076 return std::make_pair((llvm::MemoryBuffer*)0,
1077 std::make_pair(0, true));
Douglas Gregor175c4a92010-07-23 23:58:40 +00001078 CreatedBuffer = true;
Douglas Gregor44c181a2010-07-23 00:33:23 +00001079 }
1080 }
1081 }
1082
1083 // Check whether there is a file-buffer remapping. It supercedes the
1084 // file-file remapping.
1085 for (PreprocessorOptions::remapped_file_buffer_iterator
1086 M = PreprocessorOpts.remapped_file_buffer_begin(),
1087 E = PreprocessorOpts.remapped_file_buffer_end();
1088 M != E;
1089 ++M) {
1090 llvm::sys::PathWithStatus MPath(M->first);
1091 if (const llvm::sys::FileStatus *MStatus = MPath.getFileStatus()) {
1092 if (MainFileStatus->uniqueID == MStatus->uniqueID) {
1093 // We found a remapping.
Douglas Gregor175c4a92010-07-23 23:58:40 +00001094 if (CreatedBuffer) {
Douglas Gregor44c181a2010-07-23 00:33:23 +00001095 delete Buffer;
Douglas Gregor175c4a92010-07-23 23:58:40 +00001096 CreatedBuffer = false;
1097 }
Douglas Gregor44c181a2010-07-23 00:33:23 +00001098
Douglas Gregor175c4a92010-07-23 23:58:40 +00001099 Buffer = const_cast<llvm::MemoryBuffer *>(M->second);
Douglas Gregor44c181a2010-07-23 00:33:23 +00001100 }
1101 }
Douglas Gregor175c4a92010-07-23 23:58:40 +00001102 }
Douglas Gregor44c181a2010-07-23 00:33:23 +00001103 }
1104
1105 // If the main source file was not remapped, load it now.
1106 if (!Buffer) {
Argyrios Kyrtzidis389db162010-11-03 22:45:23 +00001107 Buffer = getBufferForFile(FrontendOpts.Inputs[0].second);
Douglas Gregor44c181a2010-07-23 00:33:23 +00001108 if (!Buffer)
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001109 return std::make_pair((llvm::MemoryBuffer*)0, std::make_pair(0, true));
Douglas Gregor175c4a92010-07-23 23:58:40 +00001110
1111 CreatedBuffer = true;
Douglas Gregor44c181a2010-07-23 00:33:23 +00001112 }
1113
Argyrios Kyrtzidis03c107a2011-08-25 20:39:19 +00001114 return std::make_pair(Buffer, Lexer::ComputePreamble(Buffer,
1115 Invocation.getLangOpts(),
1116 MaxLines));
Douglas Gregor175c4a92010-07-23 23:58:40 +00001117}
1118
Douglas Gregor754f3492010-07-24 00:38:13 +00001119static llvm::MemoryBuffer *CreatePaddedMainFileBuffer(llvm::MemoryBuffer *Old,
Douglas Gregor754f3492010-07-24 00:38:13 +00001120 unsigned NewSize,
Chris Lattner5f9e2722011-07-23 10:55:15 +00001121 StringRef NewName) {
Douglas Gregor754f3492010-07-24 00:38:13 +00001122 llvm::MemoryBuffer *Result
1123 = llvm::MemoryBuffer::getNewUninitMemBuffer(NewSize, NewName);
1124 memcpy(const_cast<char*>(Result->getBufferStart()),
1125 Old->getBufferStart(), Old->getBufferSize());
1126 memset(const_cast<char*>(Result->getBufferStart()) + Old->getBufferSize(),
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001127 ' ', NewSize - Old->getBufferSize() - 1);
1128 const_cast<char*>(Result->getBufferEnd())[-1] = '\n';
Douglas Gregor754f3492010-07-24 00:38:13 +00001129
Douglas Gregor754f3492010-07-24 00:38:13 +00001130 return Result;
1131}
1132
Douglas Gregor175c4a92010-07-23 23:58:40 +00001133/// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing
1134/// the source file.
1135///
1136/// This routine will compute the preamble of the main source file. If a
1137/// non-trivial preamble is found, it will precompile that preamble into a
1138/// precompiled header so that the precompiled preamble can be used to reduce
1139/// reparsing time. If a precompiled preamble has already been constructed,
1140/// this routine will determine if it is still valid and, if so, avoid
1141/// rebuilding the precompiled preamble.
1142///
Douglas Gregordf95a132010-08-09 20:45:32 +00001143/// \param AllowRebuild When true (the default), this routine is
1144/// allowed to rebuild the precompiled preamble if it is found to be
1145/// out-of-date.
1146///
1147/// \param MaxLines When non-zero, the maximum number of lines that
1148/// can occur within the preamble.
1149///
Douglas Gregor754f3492010-07-24 00:38:13 +00001150/// \returns If the precompiled preamble can be used, returns a newly-allocated
1151/// buffer that should be used in place of the main file when doing so.
1152/// Otherwise, returns a NULL pointer.
Douglas Gregordf95a132010-08-09 20:45:32 +00001153llvm::MemoryBuffer *ASTUnit::getMainBufferWithPrecompiledPreamble(
Douglas Gregor01b6e312011-07-01 18:22:13 +00001154 const CompilerInvocation &PreambleInvocationIn,
Douglas Gregordf95a132010-08-09 20:45:32 +00001155 bool AllowRebuild,
1156 unsigned MaxLines) {
Douglas Gregor01b6e312011-07-01 18:22:13 +00001157
1158 llvm::IntrusiveRefCntPtr<CompilerInvocation>
1159 PreambleInvocation(new CompilerInvocation(PreambleInvocationIn));
1160 FrontendOptions &FrontendOpts = PreambleInvocation->getFrontendOpts();
Douglas Gregor175c4a92010-07-23 23:58:40 +00001161 PreprocessorOptions &PreprocessorOpts
Douglas Gregor01b6e312011-07-01 18:22:13 +00001162 = PreambleInvocation->getPreprocessorOpts();
Douglas Gregor175c4a92010-07-23 23:58:40 +00001163
1164 bool CreatedPreambleBuffer = false;
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001165 std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > NewPreamble
Douglas Gregor01b6e312011-07-01 18:22:13 +00001166 = ComputePreamble(*PreambleInvocation, MaxLines, CreatedPreambleBuffer);
Douglas Gregor175c4a92010-07-23 23:58:40 +00001167
Douglas Gregorf62d43d2011-07-19 16:10:42 +00001168 // If ComputePreamble() Take ownership of the preamble buffer.
Douglas Gregor73fc9122010-11-16 20:45:51 +00001169 llvm::OwningPtr<llvm::MemoryBuffer> OwnedPreambleBuffer;
1170 if (CreatedPreambleBuffer)
1171 OwnedPreambleBuffer.reset(NewPreamble.first);
1172
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001173 if (!NewPreamble.second.first) {
Douglas Gregor175c4a92010-07-23 23:58:40 +00001174 // We couldn't find a preamble in the main source. Clear out the current
1175 // preamble, if we have one. It's obviously no good any more.
1176 Preamble.clear();
1177 if (!PreambleFile.empty()) {
Douglas Gregor385103b2010-07-30 20:58:08 +00001178 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregor175c4a92010-07-23 23:58:40 +00001179 PreambleFile.clear();
1180 }
Douglas Gregoreababfb2010-08-04 05:53:38 +00001181
1182 // The next time we actually see a preamble, precompile it.
1183 PreambleRebuildCounter = 1;
Douglas Gregor754f3492010-07-24 00:38:13 +00001184 return 0;
Douglas Gregor175c4a92010-07-23 23:58:40 +00001185 }
1186
1187 if (!Preamble.empty()) {
1188 // We've previously computed a preamble. Check whether we have the same
1189 // preamble now that we did before, and that there's enough space in
1190 // the main-file buffer within the precompiled preamble to fit the
1191 // new main file.
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001192 if (Preamble.size() == NewPreamble.second.first &&
1193 PreambleEndsAtStartOfLine == NewPreamble.second.second &&
Douglas Gregor592508e2010-07-24 00:42:07 +00001194 NewPreamble.first->getBufferSize() < PreambleReservedSize-2 &&
Argyrios Kyrtzidis507097e2011-09-19 20:40:35 +00001195 memcmp(Preamble.getBufferStart(), NewPreamble.first->getBufferStart(),
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001196 NewPreamble.second.first) == 0) {
Douglas Gregor175c4a92010-07-23 23:58:40 +00001197 // The preamble has not changed. We may be able to re-use the precompiled
1198 // preamble.
Douglas Gregorc0659ec2010-08-02 20:51:39 +00001199
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001200 // Check that none of the files used by the preamble have changed.
1201 bool AnyFileChanged = false;
1202
1203 // First, make a record of those files that have been overridden via
1204 // remapping or unsaved_files.
1205 llvm::StringMap<std::pair<off_t, time_t> > OverriddenFiles;
1206 for (PreprocessorOptions::remapped_file_iterator
1207 R = PreprocessorOpts.remapped_file_begin(),
1208 REnd = PreprocessorOpts.remapped_file_end();
1209 !AnyFileChanged && R != REnd;
1210 ++R) {
1211 struct stat StatBuf;
Anders Carlsson340415c2011-03-18 19:23:38 +00001212 if (FileMgr->getNoncachedStatValue(R->second, StatBuf)) {
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001213 // If we can't stat the file we're remapping to, assume that something
1214 // horrible happened.
1215 AnyFileChanged = true;
1216 break;
1217 }
Douglas Gregor754f3492010-07-24 00:38:13 +00001218
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001219 OverriddenFiles[R->first] = std::make_pair(StatBuf.st_size,
1220 StatBuf.st_mtime);
1221 }
1222 for (PreprocessorOptions::remapped_file_buffer_iterator
1223 R = PreprocessorOpts.remapped_file_buffer_begin(),
1224 REnd = PreprocessorOpts.remapped_file_buffer_end();
1225 !AnyFileChanged && R != REnd;
1226 ++R) {
1227 // FIXME: Should we actually compare the contents of file->buffer
1228 // remappings?
1229 OverriddenFiles[R->first] = std::make_pair(R->second->getBufferSize(),
1230 0);
1231 }
1232
1233 // Check whether anything has changed.
1234 for (llvm::StringMap<std::pair<off_t, time_t> >::iterator
1235 F = FilesInPreamble.begin(), FEnd = FilesInPreamble.end();
1236 !AnyFileChanged && F != FEnd;
1237 ++F) {
1238 llvm::StringMap<std::pair<off_t, time_t> >::iterator Overridden
1239 = OverriddenFiles.find(F->first());
1240 if (Overridden != OverriddenFiles.end()) {
1241 // This file was remapped; check whether the newly-mapped file
1242 // matches up with the previous mapping.
1243 if (Overridden->second != F->second)
1244 AnyFileChanged = true;
1245 continue;
1246 }
1247
1248 // The file was not remapped; check whether it has changed on disk.
1249 struct stat StatBuf;
Anders Carlsson340415c2011-03-18 19:23:38 +00001250 if (FileMgr->getNoncachedStatValue(F->first(), StatBuf)) {
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001251 // If we can't stat the file, assume that something horrible happened.
1252 AnyFileChanged = true;
1253 } else if (StatBuf.st_size != F->second.first ||
1254 StatBuf.st_mtime != F->second.second)
1255 AnyFileChanged = true;
1256 }
1257
1258 if (!AnyFileChanged) {
Douglas Gregorc0659ec2010-08-02 20:51:39 +00001259 // Okay! We can re-use the precompiled preamble.
1260
1261 // Set the state of the diagnostic object to mimic its state
1262 // after parsing the preamble.
Douglas Gregor32be4a52010-10-11 21:37:58 +00001263 // FIXME: This won't catch any #pragma push warning changes that
1264 // have occurred in the preamble.
Douglas Gregorc0659ec2010-08-02 20:51:39 +00001265 getDiagnostics().Reset();
Douglas Gregor32be4a52010-10-11 21:37:58 +00001266 ProcessWarningOptions(getDiagnostics(),
Douglas Gregor01b6e312011-07-01 18:22:13 +00001267 PreambleInvocation->getDiagnosticOpts());
Douglas Gregorc0659ec2010-08-02 20:51:39 +00001268 getDiagnostics().setNumWarnings(NumWarningsInPreamble);
Douglas Gregorc0659ec2010-08-02 20:51:39 +00001269
1270 // Create a version of the main file buffer that is padded to
1271 // buffer size we reserved when creating the preamble.
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001272 return CreatePaddedMainFileBuffer(NewPreamble.first,
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001273 PreambleReservedSize,
1274 FrontendOpts.Inputs[0].second);
1275 }
Douglas Gregor175c4a92010-07-23 23:58:40 +00001276 }
Douglas Gregordf95a132010-08-09 20:45:32 +00001277
1278 // If we aren't allowed to rebuild the precompiled preamble, just
1279 // return now.
1280 if (!AllowRebuild)
1281 return 0;
Douglas Gregoraa3e6ba2010-10-08 04:03:57 +00001282
Douglas Gregor175c4a92010-07-23 23:58:40 +00001283 // We can't reuse the previously-computed preamble. Build a new one.
1284 Preamble.clear();
Douglas Gregorf62d43d2011-07-19 16:10:42 +00001285 PreambleDiagnostics.clear();
Douglas Gregor385103b2010-07-30 20:58:08 +00001286 llvm::sys::Path(PreambleFile).eraseFromDisk();
Douglas Gregoreababfb2010-08-04 05:53:38 +00001287 PreambleRebuildCounter = 1;
Douglas Gregordf95a132010-08-09 20:45:32 +00001288 } else if (!AllowRebuild) {
1289 // We aren't allowed to rebuild the precompiled preamble; just
1290 // return now.
1291 return 0;
1292 }
Douglas Gregoreababfb2010-08-04 05:53:38 +00001293
1294 // If the preamble rebuild counter > 1, it's because we previously
1295 // failed to build a preamble and we're not yet ready to try
1296 // again. Decrement the counter and return a failure.
1297 if (PreambleRebuildCounter > 1) {
1298 --PreambleRebuildCounter;
1299 return 0;
1300 }
1301
Douglas Gregor2cd4fd42010-09-11 17:56:52 +00001302 // Create a temporary file for the precompiled preamble. In rare
1303 // circumstances, this can fail.
1304 std::string PreamblePCHPath = GetPreamblePCHPath();
1305 if (PreamblePCHPath.empty()) {
1306 // Try again next time.
1307 PreambleRebuildCounter = 1;
1308 return 0;
1309 }
1310
Douglas Gregor175c4a92010-07-23 23:58:40 +00001311 // We did not previously compute a preamble, or it can't be reused anyway.
Douglas Gregor213f18b2010-10-28 15:44:59 +00001312 SimpleTimer PreambleTimer(WantTiming);
Benjamin Krameredfb7ec2010-11-09 20:00:56 +00001313 PreambleTimer.setOutput("Precompiling preamble");
Douglas Gregor44c181a2010-07-23 00:33:23 +00001314
1315 // Create a new buffer that stores the preamble. The buffer also contains
1316 // extra space for the original contents of the file (which will be present
1317 // when we actually parse the file) along with more room in case the file
Douglas Gregor175c4a92010-07-23 23:58:40 +00001318 // grows.
1319 PreambleReservedSize = NewPreamble.first->getBufferSize();
1320 if (PreambleReservedSize < 4096)
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001321 PreambleReservedSize = 8191;
Douglas Gregor44c181a2010-07-23 00:33:23 +00001322 else
Douglas Gregor175c4a92010-07-23 23:58:40 +00001323 PreambleReservedSize *= 2;
1324
Douglas Gregorc0659ec2010-08-02 20:51:39 +00001325 // Save the preamble text for later; we'll need to compare against it for
1326 // subsequent reparses.
Argyrios Kyrtzidis507097e2011-09-19 20:40:35 +00001327 StringRef MainFilename = PreambleInvocation->getFrontendOpts().Inputs[0].second;
1328 Preamble.assign(FileMgr->getFile(MainFilename),
1329 NewPreamble.first->getBufferStart(),
Douglas Gregorc0659ec2010-08-02 20:51:39 +00001330 NewPreamble.first->getBufferStart()
1331 + NewPreamble.second.first);
1332 PreambleEndsAtStartOfLine = NewPreamble.second.second;
1333
Douglas Gregor671947b2010-08-19 01:33:06 +00001334 delete PreambleBuffer;
1335 PreambleBuffer
Douglas Gregor175c4a92010-07-23 23:58:40 +00001336 = llvm::MemoryBuffer::getNewUninitMemBuffer(PreambleReservedSize,
Douglas Gregor44c181a2010-07-23 00:33:23 +00001337 FrontendOpts.Inputs[0].second);
1338 memcpy(const_cast<char*>(PreambleBuffer->getBufferStart()),
Douglas Gregor175c4a92010-07-23 23:58:40 +00001339 NewPreamble.first->getBufferStart(), Preamble.size());
1340 memset(const_cast<char*>(PreambleBuffer->getBufferStart()) + Preamble.size(),
Douglas Gregorf4f6c9d2010-07-26 21:36:20 +00001341 ' ', PreambleReservedSize - Preamble.size() - 1);
1342 const_cast<char*>(PreambleBuffer->getBufferEnd())[-1] = '\n';
Douglas Gregor44c181a2010-07-23 00:33:23 +00001343
1344 // Remap the main source file to the preamble buffer.
Douglas Gregor175c4a92010-07-23 23:58:40 +00001345 llvm::sys::PathWithStatus MainFilePath(FrontendOpts.Inputs[0].second);
Douglas Gregor44c181a2010-07-23 00:33:23 +00001346 PreprocessorOpts.addRemappedFile(MainFilePath.str(), PreambleBuffer);
1347
1348 // Tell the compiler invocation to generate a temporary precompiled header.
1349 FrontendOpts.ProgramAction = frontend::GeneratePCH;
Douglas Gregor44c181a2010-07-23 00:33:23 +00001350 // FIXME: Generate the precompiled header into memory?
Douglas Gregor2cd4fd42010-09-11 17:56:52 +00001351 FrontendOpts.OutputFile = PreamblePCHPath;
Douglas Gregoraa3e6ba2010-10-08 04:03:57 +00001352 PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
1353 PreprocessorOpts.PrecompiledPreambleBytes.second = false;
Douglas Gregor44c181a2010-07-23 00:33:23 +00001354
1355 // Create the compiler instance to use for building the precompiled preamble.
Ted Kremenek03201fb2011-03-21 18:40:07 +00001356 llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance());
1357
1358 // Recover resources if we crash before exiting this method.
Ted Kremenek25a11e12011-03-22 01:15:24 +00001359 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
1360 CICleanup(Clang.get());
Ted Kremenek03201fb2011-03-21 18:40:07 +00001361
Douglas Gregor01b6e312011-07-01 18:22:13 +00001362 Clang->setInvocation(&*PreambleInvocation);
Ted Kremenek03201fb2011-03-21 18:40:07 +00001363 OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
Douglas Gregor44c181a2010-07-23 00:33:23 +00001364
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00001365 // Set up diagnostics, capturing all of the diagnostics produced.
Ted Kremenek03201fb2011-03-21 18:40:07 +00001366 Clang->setDiagnostics(&getDiagnostics());
Douglas Gregor44c181a2010-07-23 00:33:23 +00001367
1368 // Create the target instance.
Ted Kremenek03201fb2011-03-21 18:40:07 +00001369 Clang->getTargetOpts().Features = TargetFeatures;
1370 Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
1371 Clang->getTargetOpts()));
1372 if (!Clang->hasTarget()) {
Douglas Gregor175c4a92010-07-23 23:58:40 +00001373 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
1374 Preamble.clear();
Douglas Gregoreababfb2010-08-04 05:53:38 +00001375 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregor671947b2010-08-19 01:33:06 +00001376 PreprocessorOpts.eraseRemappedFile(
1377 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor754f3492010-07-24 00:38:13 +00001378 return 0;
Douglas Gregor44c181a2010-07-23 00:33:23 +00001379 }
1380
1381 // Inform the target of the language options.
1382 //
1383 // FIXME: We shouldn't need to do this, the target should be immutable once
1384 // created. This complexity should be lifted elsewhere.
Ted Kremenek03201fb2011-03-21 18:40:07 +00001385 Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
Douglas Gregor44c181a2010-07-23 00:33:23 +00001386
Ted Kremenek03201fb2011-03-21 18:40:07 +00001387 assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
Douglas Gregor44c181a2010-07-23 00:33:23 +00001388 "Invocation must have exactly one source file!");
Ted Kremenek03201fb2011-03-21 18:40:07 +00001389 assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
Douglas Gregor44c181a2010-07-23 00:33:23 +00001390 "FIXME: AST inputs not yet supported here!");
Ted Kremenek03201fb2011-03-21 18:40:07 +00001391 assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
Douglas Gregor44c181a2010-07-23 00:33:23 +00001392 "IR inputs not support here!");
1393
1394 // Clear out old caches and data.
Douglas Gregoraa3e6ba2010-10-08 04:03:57 +00001395 getDiagnostics().Reset();
Ted Kremenek03201fb2011-03-21 18:40:07 +00001396 ProcessWarningOptions(getDiagnostics(), Clang->getDiagnosticOpts());
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001397 StoredDiagnostics.erase(
1398 StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
1399 StoredDiagnostics.end());
Douglas Gregoreb8837b2010-08-03 19:06:41 +00001400 TopLevelDecls.clear();
1401 TopLevelDeclsInPreamble.clear();
Douglas Gregor44c181a2010-07-23 00:33:23 +00001402
1403 // Create a file manager object to provide access to and cache the filesystem.
Ted Kremenek03201fb2011-03-21 18:40:07 +00001404 Clang->setFileManager(new FileManager(Clang->getFileSystemOpts()));
Douglas Gregor44c181a2010-07-23 00:33:23 +00001405
1406 // Create the source manager.
Ted Kremenek03201fb2011-03-21 18:40:07 +00001407 Clang->setSourceManager(new SourceManager(getDiagnostics(),
Ted Kremenek4f327862011-03-21 18:40:17 +00001408 Clang->getFileManager()));
Douglas Gregor44c181a2010-07-23 00:33:23 +00001409
Douglas Gregor1d715ac2010-08-03 08:14:03 +00001410 llvm::OwningPtr<PrecompilePreambleAction> Act;
1411 Act.reset(new PrecompilePreambleAction(*this));
Ted Kremenek03201fb2011-03-21 18:40:07 +00001412 if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
1413 Clang->getFrontendOpts().Inputs[0].first)) {
Douglas Gregor175c4a92010-07-23 23:58:40 +00001414 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
1415 Preamble.clear();
Douglas Gregoreababfb2010-08-04 05:53:38 +00001416 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregor671947b2010-08-19 01:33:06 +00001417 PreprocessorOpts.eraseRemappedFile(
1418 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor754f3492010-07-24 00:38:13 +00001419 return 0;
Douglas Gregor44c181a2010-07-23 00:33:23 +00001420 }
1421
1422 Act->Execute();
1423 Act->EndSourceFile();
Ted Kremenek4f327862011-03-21 18:40:17 +00001424
Douglas Gregoreb8837b2010-08-03 19:06:41 +00001425 if (Diagnostics->hasErrorOccurred()) {
Douglas Gregor175c4a92010-07-23 23:58:40 +00001426 // There were errors parsing the preamble, so no precompiled header was
1427 // generated. Forget that we even tried.
Douglas Gregor06e50442010-09-27 16:43:25 +00001428 // FIXME: Should we leave a note for ourselves to try again?
Douglas Gregor175c4a92010-07-23 23:58:40 +00001429 llvm::sys::Path(FrontendOpts.OutputFile).eraseFromDisk();
1430 Preamble.clear();
Douglas Gregoreb8837b2010-08-03 19:06:41 +00001431 TopLevelDeclsInPreamble.clear();
Douglas Gregoreababfb2010-08-04 05:53:38 +00001432 PreambleRebuildCounter = DefaultPreambleRebuildInterval;
Douglas Gregor671947b2010-08-19 01:33:06 +00001433 PreprocessorOpts.eraseRemappedFile(
1434 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor754f3492010-07-24 00:38:13 +00001435 return 0;
Douglas Gregor175c4a92010-07-23 23:58:40 +00001436 }
1437
Douglas Gregorf62d43d2011-07-19 16:10:42 +00001438 // Transfer any diagnostics generated when parsing the preamble into the set
1439 // of preamble diagnostics.
1440 PreambleDiagnostics.clear();
1441 PreambleDiagnostics.insert(PreambleDiagnostics.end(),
1442 StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
1443 StoredDiagnostics.end());
1444 StoredDiagnostics.erase(
1445 StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver,
1446 StoredDiagnostics.end());
1447
Douglas Gregor175c4a92010-07-23 23:58:40 +00001448 // Keep track of the preamble we precompiled.
1449 PreambleFile = FrontendOpts.OutputFile;
Douglas Gregorc0659ec2010-08-02 20:51:39 +00001450 NumWarningsInPreamble = getDiagnostics().getNumWarnings();
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001451
1452 // Keep track of all of the files that the source manager knows about,
1453 // so we can verify whether they have changed or not.
1454 FilesInPreamble.clear();
Ted Kremenek03201fb2011-03-21 18:40:07 +00001455 SourceManager &SourceMgr = Clang->getSourceManager();
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001456 const llvm::MemoryBuffer *MainFileBuffer
1457 = SourceMgr.getBuffer(SourceMgr.getMainFileID());
1458 for (SourceManager::fileinfo_iterator F = SourceMgr.fileinfo_begin(),
1459 FEnd = SourceMgr.fileinfo_end();
1460 F != FEnd;
1461 ++F) {
Argyrios Kyrtzidisb1c86492011-03-05 01:03:53 +00001462 const FileEntry *File = F->second->OrigEntry;
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001463 if (!File || F->second->getRawBuffer() == MainFileBuffer)
1464 continue;
1465
1466 FilesInPreamble[File->getName()]
1467 = std::make_pair(F->second->getSize(), File->getModificationTime());
1468 }
1469
Douglas Gregoreababfb2010-08-04 05:53:38 +00001470 PreambleRebuildCounter = 1;
Douglas Gregor671947b2010-08-19 01:33:06 +00001471 PreprocessorOpts.eraseRemappedFile(
1472 PreprocessorOpts.remapped_file_buffer_end() - 1);
Douglas Gregor9b7db622011-02-16 18:16:54 +00001473
1474 // If the hash of top-level entities differs from the hash of the top-level
1475 // entities the last time we rebuilt the preamble, clear out the completion
1476 // cache.
1477 if (CurrentTopLevelHashValue != PreambleTopLevelHashValue) {
1478 CompletionCacheTopLevelHashValue = 0;
1479 PreambleTopLevelHashValue = CurrentTopLevelHashValue;
1480 }
1481
Douglas Gregor754f3492010-07-24 00:38:13 +00001482 return CreatePaddedMainFileBuffer(NewPreamble.first,
Douglas Gregor754f3492010-07-24 00:38:13 +00001483 PreambleReservedSize,
1484 FrontendOpts.Inputs[0].second);
Douglas Gregor44c181a2010-07-23 00:33:23 +00001485}
Douglas Gregorabc563f2010-07-19 21:46:24 +00001486
Douglas Gregoreb8837b2010-08-03 19:06:41 +00001487void ASTUnit::RealizeTopLevelDeclsFromPreamble() {
1488 std::vector<Decl *> Resolved;
1489 Resolved.reserve(TopLevelDeclsInPreamble.size());
1490 ExternalASTSource &Source = *getASTContext().getExternalSource();
1491 for (unsigned I = 0, N = TopLevelDeclsInPreamble.size(); I != N; ++I) {
1492 // Resolve the declaration ID to an actual declaration, possibly
1493 // deserializing the declaration in the process.
1494 Decl *D = Source.GetExternalDecl(TopLevelDeclsInPreamble[I]);
1495 if (D)
1496 Resolved.push_back(D);
1497 }
1498 TopLevelDeclsInPreamble.clear();
1499 TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end());
1500}
1501
Chris Lattner5f9e2722011-07-23 10:55:15 +00001502StringRef ASTUnit::getMainFileName() const {
Douglas Gregor213f18b2010-10-28 15:44:59 +00001503 return Invocation->getFrontendOpts().Inputs[0].second;
1504}
1505
Argyrios Kyrtzidisb0f4b9a2011-03-09 17:21:42 +00001506ASTUnit *ASTUnit::create(CompilerInvocation *CI,
David Blaikied6471f72011-09-25 23:23:43 +00001507 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags) {
Argyrios Kyrtzidisb0f4b9a2011-03-09 17:21:42 +00001508 llvm::OwningPtr<ASTUnit> AST;
1509 AST.reset(new ASTUnit(false));
1510 ConfigureDiags(Diags, 0, 0, *AST, /*CaptureDiagnostics=*/false);
1511 AST->Diagnostics = Diags;
Ted Kremenek4f327862011-03-21 18:40:17 +00001512 AST->Invocation = CI;
Anders Carlsson0d8d7e62011-03-18 18:22:40 +00001513 AST->FileSystemOpts = CI->getFileSystemOpts();
Ted Kremenek4f327862011-03-21 18:40:17 +00001514 AST->FileMgr = new FileManager(AST->FileSystemOpts);
1515 AST->SourceMgr = new SourceManager(*Diags, *AST->FileMgr);
Argyrios Kyrtzidisb0f4b9a2011-03-09 17:21:42 +00001516
1517 return AST.take();
1518}
1519
Argyrios Kyrtzidisd808bd22011-05-03 23:26:34 +00001520ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(CompilerInvocation *CI,
David Blaikied6471f72011-09-25 23:23:43 +00001521 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
Argyrios Kyrtzidisd808bd22011-05-03 23:26:34 +00001522 ASTFrontendAction *Action) {
1523 assert(CI && "A CompilerInvocation is required");
1524
1525 // Create the AST unit.
1526 llvm::OwningPtr<ASTUnit> AST;
1527 AST.reset(new ASTUnit(false));
1528 ConfigureDiags(Diags, 0, 0, *AST, /*CaptureDiagnostics*/false);
1529 AST->Diagnostics = Diags;
1530 AST->OnlyLocalDecls = false;
1531 AST->CaptureDiagnostics = false;
Douglas Gregor467dc882011-08-25 22:30:56 +00001532 AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete;
Argyrios Kyrtzidisd808bd22011-05-03 23:26:34 +00001533 AST->ShouldCacheCodeCompletionResults = false;
1534 AST->Invocation = CI;
1535
1536 // Recover resources if we crash before exiting this method.
1537 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
1538 ASTUnitCleanup(AST.get());
David Blaikied6471f72011-09-25 23:23:43 +00001539 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
1540 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
Argyrios Kyrtzidisd808bd22011-05-03 23:26:34 +00001541 DiagCleanup(Diags.getPtr());
1542
1543 // We'll manage file buffers ourselves.
1544 CI->getPreprocessorOpts().RetainRemappedFileBuffers = true;
1545 CI->getFrontendOpts().DisableFree = false;
1546 ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts());
1547
1548 // Save the target features.
1549 AST->TargetFeatures = CI->getTargetOpts().Features;
1550
1551 // Create the compiler instance to use for building the AST.
1552 llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance());
1553
1554 // Recover resources if we crash before exiting this method.
1555 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
1556 CICleanup(Clang.get());
1557
1558 Clang->setInvocation(CI);
1559 AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
1560
1561 // Set up diagnostics, capturing any diagnostics that would
1562 // otherwise be dropped.
1563 Clang->setDiagnostics(&AST->getDiagnostics());
1564
1565 // Create the target instance.
1566 Clang->getTargetOpts().Features = AST->TargetFeatures;
1567 Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
1568 Clang->getTargetOpts()));
1569 if (!Clang->hasTarget())
1570 return 0;
1571
1572 // Inform the target of the language options.
1573 //
1574 // FIXME: We shouldn't need to do this, the target should be immutable once
1575 // created. This complexity should be lifted elsewhere.
1576 Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
1577
1578 assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
1579 "Invocation must have exactly one source file!");
1580 assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
1581 "FIXME: AST inputs not yet supported here!");
1582 assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
1583 "IR inputs not supported here!");
1584
1585 // Configure the various subsystems.
1586 AST->FileSystemOpts = Clang->getFileSystemOpts();
1587 AST->FileMgr = new FileManager(AST->FileSystemOpts);
1588 AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr);
1589 AST->TheSema.reset();
1590 AST->Ctx = 0;
1591 AST->PP = 0;
1592
1593 // Create a file manager object to provide access to and cache the filesystem.
1594 Clang->setFileManager(&AST->getFileManager());
1595
1596 // Create the source manager.
1597 Clang->setSourceManager(&AST->getSourceManager());
1598
1599 ASTFrontendAction *Act = Action;
1600
1601 llvm::OwningPtr<TopLevelDeclTrackerAction> TrackerAct;
1602 if (!Act) {
1603 TrackerAct.reset(new TopLevelDeclTrackerAction(*AST));
1604 Act = TrackerAct.get();
1605 }
1606
1607 // Recover resources if we crash before exiting this method.
1608 llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction>
1609 ActCleanup(TrackerAct.get());
1610
1611 if (!Act->BeginSourceFile(*Clang.get(),
1612 Clang->getFrontendOpts().Inputs[0].second,
1613 Clang->getFrontendOpts().Inputs[0].first))
1614 return 0;
1615
1616 Act->Execute();
1617
1618 // Steal the created target, context, and preprocessor.
1619 AST->TheSema.reset(Clang->takeSema());
1620 AST->Consumer.reset(Clang->takeASTConsumer());
1621 AST->Ctx = &Clang->getASTContext();
1622 AST->PP = &Clang->getPreprocessor();
1623 Clang->setSourceManager(0);
1624 Clang->setFileManager(0);
1625 AST->Target = &Clang->getTarget();
1626
1627 Act->EndSourceFile();
1628
1629 return AST.take();
1630}
1631
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001632bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
1633 if (!Invocation)
1634 return true;
1635
1636 // We'll manage file buffers ourselves.
1637 Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true;
1638 Invocation->getFrontendOpts().DisableFree = false;
Douglas Gregor0b53cf82011-01-19 01:02:47 +00001639 ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001640
Douglas Gregor1aa27302011-01-27 18:02:58 +00001641 // Save the target features.
1642 TargetFeatures = Invocation->getTargetOpts().Features;
1643
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001644 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregor99ba2022010-10-27 17:24:53 +00001645 if (PrecompilePreamble) {
Douglas Gregor08bb4c62010-11-15 23:00:34 +00001646 PreambleRebuildCounter = 2;
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001647 OverrideMainBuffer
1648 = getMainBufferWithPrecompiledPreamble(*Invocation);
1649 }
1650
Douglas Gregor213f18b2010-10-28 15:44:59 +00001651 SimpleTimer ParsingTimer(WantTiming);
Benjamin Krameredfb7ec2010-11-09 20:00:56 +00001652 ParsingTimer.setOutput("Parsing " + getMainFileName());
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001653
Ted Kremenek25a11e12011-03-22 01:15:24 +00001654 // Recover resources if we crash before exiting this method.
1655 llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer>
1656 MemBufferCleanup(OverrideMainBuffer);
1657
Douglas Gregor213f18b2010-10-28 15:44:59 +00001658 return Parse(OverrideMainBuffer);
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001659}
1660
Douglas Gregorabc563f2010-07-19 21:46:24 +00001661ASTUnit *ASTUnit::LoadFromCompilerInvocation(CompilerInvocation *CI,
David Blaikied6471f72011-09-25 23:23:43 +00001662 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
Douglas Gregorabc563f2010-07-19 21:46:24 +00001663 bool OnlyLocalDecls,
Douglas Gregor44c181a2010-07-23 00:33:23 +00001664 bool CaptureDiagnostics,
Douglas Gregordf95a132010-08-09 20:45:32 +00001665 bool PrecompilePreamble,
Douglas Gregor467dc882011-08-25 22:30:56 +00001666 TranslationUnitKind TUKind,
Douglas Gregordca8ee82011-05-06 16:33:08 +00001667 bool CacheCodeCompletionResults,
Chandler Carruthba7537f2011-07-14 09:02:10 +00001668 bool NestedMacroExpansions) {
Douglas Gregorabc563f2010-07-19 21:46:24 +00001669 // Create the AST unit.
1670 llvm::OwningPtr<ASTUnit> AST;
1671 AST.reset(new ASTUnit(false));
Douglas Gregor0b53cf82011-01-19 01:02:47 +00001672 ConfigureDiags(Diags, 0, 0, *AST, CaptureDiagnostics);
Douglas Gregorabc563f2010-07-19 21:46:24 +00001673 AST->Diagnostics = Diags;
Douglas Gregorabc563f2010-07-19 21:46:24 +00001674 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregore47be3e2010-11-11 00:39:14 +00001675 AST->CaptureDiagnostics = CaptureDiagnostics;
Douglas Gregor467dc882011-08-25 22:30:56 +00001676 AST->TUKind = TUKind;
Douglas Gregor87c08a52010-08-13 22:48:40 +00001677 AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
Ted Kremenek4f327862011-03-21 18:40:17 +00001678 AST->Invocation = CI;
Chandler Carruthba7537f2011-07-14 09:02:10 +00001679 AST->NestedMacroExpansions = NestedMacroExpansions;
Douglas Gregorabc563f2010-07-19 21:46:24 +00001680
Ted Kremenekb547eeb2011-03-18 02:06:56 +00001681 // Recover resources if we crash before exiting this method.
Ted Kremenek25a11e12011-03-22 01:15:24 +00001682 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
1683 ASTUnitCleanup(AST.get());
David Blaikied6471f72011-09-25 23:23:43 +00001684 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
1685 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
Ted Kremenek25a11e12011-03-22 01:15:24 +00001686 DiagCleanup(Diags.getPtr());
Ted Kremenekb547eeb2011-03-18 02:06:56 +00001687
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001688 return AST->LoadFromCompilerInvocation(PrecompilePreamble)? 0 : AST.take();
Daniel Dunbar521bf9c2009-12-01 09:51:01 +00001689}
Daniel Dunbar7b556682009-12-02 03:23:45 +00001690
1691ASTUnit *ASTUnit::LoadFromCommandLine(const char **ArgBegin,
1692 const char **ArgEnd,
David Blaikied6471f72011-09-25 23:23:43 +00001693 llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
Chris Lattner5f9e2722011-07-23 10:55:15 +00001694 StringRef ResourceFilesPath,
Daniel Dunbar7b556682009-12-02 03:23:45 +00001695 bool OnlyLocalDecls,
Douglas Gregore47be3e2010-11-11 00:39:14 +00001696 bool CaptureDiagnostics,
Douglas Gregor4db64a42010-01-23 00:14:00 +00001697 RemappedFile *RemappedFiles,
Douglas Gregora88084b2010-02-18 18:08:43 +00001698 unsigned NumRemappedFiles,
Argyrios Kyrtzidis299a4a92011-03-08 23:35:24 +00001699 bool RemappedFilesKeepOriginalName,
Douglas Gregordf95a132010-08-09 20:45:32 +00001700 bool PrecompilePreamble,
Douglas Gregor467dc882011-08-25 22:30:56 +00001701 TranslationUnitKind TUKind,
Douglas Gregor99ba2022010-10-27 17:24:53 +00001702 bool CacheCodeCompletionResults,
Chandler Carruthba7537f2011-07-14 09:02:10 +00001703 bool NestedMacroExpansions) {
Douglas Gregor28019772010-04-05 23:52:57 +00001704 if (!Diags.getPtr()) {
Douglas Gregor3687e9d2010-04-05 21:10:19 +00001705 // No diagnostics engine was provided, so create our own diagnostics object
1706 // with the default options.
1707 DiagnosticOptions DiagOpts;
Douglas Gregor0b53cf82011-01-19 01:02:47 +00001708 Diags = CompilerInstance::createDiagnostics(DiagOpts, ArgEnd - ArgBegin,
1709 ArgBegin);
Douglas Gregor3687e9d2010-04-05 21:10:19 +00001710 }
Daniel Dunbar7b556682009-12-02 03:23:45 +00001711
Chris Lattner5f9e2722011-07-23 10:55:15 +00001712 SmallVector<StoredDiagnostic, 4> StoredDiagnostics;
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001713
Ted Kremenek4f327862011-03-21 18:40:17 +00001714 llvm::IntrusiveRefCntPtr<CompilerInvocation> CI;
Douglas Gregore47be3e2010-11-11 00:39:14 +00001715
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001716 {
Douglas Gregorf62d43d2011-07-19 16:10:42 +00001717
Douglas Gregore47be3e2010-11-11 00:39:14 +00001718 CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags,
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001719 StoredDiagnostics);
Daniel Dunbar3bd54cc2010-01-25 00:44:02 +00001720
Argyrios Kyrtzidis832316e2011-04-04 23:11:45 +00001721 CI = clang::createInvocationFromCommandLine(
Frits van Bommele9c02652011-07-18 12:00:32 +00001722 llvm::makeArrayRef(ArgBegin, ArgEnd),
1723 Diags);
Argyrios Kyrtzidis054e4f52011-04-04 21:38:51 +00001724 if (!CI)
Argyrios Kyrtzidis4e03c2b2011-03-07 22:45:01 +00001725 return 0;
Daniel Dunbar7b556682009-12-02 03:23:45 +00001726 }
Douglas Gregore47be3e2010-11-11 00:39:14 +00001727
Douglas Gregor4db64a42010-01-23 00:14:00 +00001728 // Override any files that need remapping
Argyrios Kyrtzidisb1c86492011-03-05 01:03:53 +00001729 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
1730 FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
1731 if (const llvm::MemoryBuffer *
1732 memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
1733 CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, memBuf);
1734 } else {
1735 const char *fname = fileOrBuf.get<const char *>();
1736 CI->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first, fname);
1737 }
1738 }
Argyrios Kyrtzidis299a4a92011-03-08 23:35:24 +00001739 CI->getPreprocessorOpts().RemappedFilesKeepOriginalName =
1740 RemappedFilesKeepOriginalName;
Douglas Gregor4db64a42010-01-23 00:14:00 +00001741
Daniel Dunbar8b9adfe2009-12-15 00:06:45 +00001742 // Override the resources path.
Daniel Dunbar807b0612010-01-30 21:47:16 +00001743 CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath;
Daniel Dunbar7b556682009-12-02 03:23:45 +00001744
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001745 // Create the AST unit.
1746 llvm::OwningPtr<ASTUnit> AST;
1747 AST.reset(new ASTUnit(false));
Douglas Gregor0b53cf82011-01-19 01:02:47 +00001748 ConfigureDiags(Diags, ArgBegin, ArgEnd, *AST, CaptureDiagnostics);
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001749 AST->Diagnostics = Diags;
Anders Carlsson0d8d7e62011-03-18 18:22:40 +00001750
1751 AST->FileSystemOpts = CI->getFileSystemOpts();
Ted Kremenek4f327862011-03-21 18:40:17 +00001752 AST->FileMgr = new FileManager(AST->FileSystemOpts);
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001753 AST->OnlyLocalDecls = OnlyLocalDecls;
Douglas Gregore47be3e2010-11-11 00:39:14 +00001754 AST->CaptureDiagnostics = CaptureDiagnostics;
Douglas Gregor467dc882011-08-25 22:30:56 +00001755 AST->TUKind = TUKind;
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001756 AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults;
1757 AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size();
Douglas Gregor4cd912a2010-10-12 00:50:20 +00001758 AST->StoredDiagnostics.swap(StoredDiagnostics);
Ted Kremenek4f327862011-03-21 18:40:17 +00001759 AST->Invocation = CI;
Chandler Carruthba7537f2011-07-14 09:02:10 +00001760 AST->NestedMacroExpansions = NestedMacroExpansions;
Ted Kremenekb547eeb2011-03-18 02:06:56 +00001761
1762 // Recover resources if we crash before exiting this method.
Ted Kremenek25a11e12011-03-22 01:15:24 +00001763 llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
1764 ASTUnitCleanup(AST.get());
1765 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInvocation,
1766 llvm::CrashRecoveryContextReleaseRefCleanup<CompilerInvocation> >
1767 CICleanup(CI.getPtr());
David Blaikied6471f72011-09-25 23:23:43 +00001768 llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine,
1769 llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
Ted Kremenek25a11e12011-03-22 01:15:24 +00001770 DiagCleanup(Diags.getPtr());
Ted Kremenekb547eeb2011-03-18 02:06:56 +00001771
Chris Lattner39b49bc2010-11-23 08:35:12 +00001772 return AST->LoadFromCompilerInvocation(PrecompilePreamble) ? 0 : AST.take();
Daniel Dunbar7b556682009-12-02 03:23:45 +00001773}
Douglas Gregorabc563f2010-07-19 21:46:24 +00001774
1775bool ASTUnit::Reparse(RemappedFile *RemappedFiles, unsigned NumRemappedFiles) {
Ted Kremenek4f327862011-03-21 18:40:17 +00001776 if (!Invocation)
Douglas Gregorabc563f2010-07-19 21:46:24 +00001777 return true;
1778
Douglas Gregor213f18b2010-10-28 15:44:59 +00001779 SimpleTimer ParsingTimer(WantTiming);
Benjamin Krameredfb7ec2010-11-09 20:00:56 +00001780 ParsingTimer.setOutput("Reparsing " + getMainFileName());
Douglas Gregor213f18b2010-10-28 15:44:59 +00001781
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001782 // Remap files.
Douglas Gregorf128fed2010-08-20 00:02:33 +00001783 PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts();
Douglas Gregor8ef6c8c2011-02-05 19:42:43 +00001784 PPOpts.DisableStatCache = true;
Douglas Gregorf128fed2010-08-20 00:02:33 +00001785 for (PreprocessorOptions::remapped_file_buffer_iterator
1786 R = PPOpts.remapped_file_buffer_begin(),
1787 REnd = PPOpts.remapped_file_buffer_end();
1788 R != REnd;
1789 ++R) {
1790 delete R->second;
1791 }
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001792 Invocation->getPreprocessorOpts().clearRemappedFiles();
Argyrios Kyrtzidisb1c86492011-03-05 01:03:53 +00001793 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
1794 FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
1795 if (const llvm::MemoryBuffer *
1796 memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
1797 Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1798 memBuf);
1799 } else {
1800 const char *fname = fileOrBuf.get<const char *>();
1801 Invocation->getPreprocessorOpts().addRemappedFile(RemappedFiles[I].first,
1802 fname);
1803 }
1804 }
Douglas Gregorcc5888d2010-07-31 00:40:00 +00001805
Douglas Gregoreababfb2010-08-04 05:53:38 +00001806 // If we have a preamble file lying around, or if we might try to
1807 // build a precompiled preamble, do so now.
Douglas Gregor754f3492010-07-24 00:38:13 +00001808 llvm::MemoryBuffer *OverrideMainBuffer = 0;
Douglas Gregoreababfb2010-08-04 05:53:38 +00001809 if (!PreambleFile.empty() || PreambleRebuildCounter > 0)
Douglas Gregor2283d792010-08-20 00:59:43 +00001810 OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation);
Douglas Gregor175c4a92010-07-23 23:58:40 +00001811
Douglas Gregorabc563f2010-07-19 21:46:24 +00001812 // Clear out the diagnostics state.
Douglas Gregor32be4a52010-10-11 21:37:58 +00001813 if (!OverrideMainBuffer) {
Douglas Gregorc0659ec2010-08-02 20:51:39 +00001814 getDiagnostics().Reset();
Douglas Gregor32be4a52010-10-11 21:37:58 +00001815 ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts());
1816 }
Douglas Gregorabc563f2010-07-19 21:46:24 +00001817
Douglas Gregor175c4a92010-07-23 23:58:40 +00001818 // Parse the sources
Douglas Gregor9b7db622011-02-16 18:16:54 +00001819 bool Result = Parse(OverrideMainBuffer);
1820
1821 // If we're caching global code-completion results, and the top-level
1822 // declarations have changed, clear out the code-completion cache.
1823 if (!Result && ShouldCacheCodeCompletionResults &&
1824 CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue)
1825 CacheCodeCompletionResults();
1826
Douglas Gregor8fa0a802011-08-04 20:04:59 +00001827 // We now need to clear out the completion allocator for
1828 // clang_getCursorCompletionString; it'll be recreated if necessary.
1829 CursorCompletionAllocator = 0;
1830
Douglas Gregor175c4a92010-07-23 23:58:40 +00001831 return Result;
Douglas Gregorabc563f2010-07-19 21:46:24 +00001832}
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00001833
Douglas Gregor87c08a52010-08-13 22:48:40 +00001834//----------------------------------------------------------------------------//
1835// Code completion
1836//----------------------------------------------------------------------------//
1837
1838namespace {
1839 /// \brief Code completion consumer that combines the cached code-completion
1840 /// results from an ASTUnit with the code-completion results provided to it,
1841 /// then passes the result on to
1842 class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer {
Douglas Gregor3da626b2011-07-07 16:03:39 +00001843 unsigned long long NormalContexts;
Douglas Gregor87c08a52010-08-13 22:48:40 +00001844 ASTUnit &AST;
1845 CodeCompleteConsumer &Next;
1846
1847 public:
1848 AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next,
Douglas Gregor8071e422010-08-15 06:18:01 +00001849 bool IncludeMacros, bool IncludeCodePatterns,
1850 bool IncludeGlobals)
1851 : CodeCompleteConsumer(IncludeMacros, IncludeCodePatterns, IncludeGlobals,
Douglas Gregor87c08a52010-08-13 22:48:40 +00001852 Next.isOutputBinary()), AST(AST), Next(Next)
1853 {
1854 // Compute the set of contexts in which we will look when we don't have
1855 // any information about the specific context.
1856 NormalContexts
Douglas Gregor3da626b2011-07-07 16:03:39 +00001857 = (1LL << (CodeCompletionContext::CCC_TopLevel - 1))
1858 | (1LL << (CodeCompletionContext::CCC_ObjCInterface - 1))
1859 | (1LL << (CodeCompletionContext::CCC_ObjCImplementation - 1))
1860 | (1LL << (CodeCompletionContext::CCC_ObjCIvarList - 1))
1861 | (1LL << (CodeCompletionContext::CCC_Statement - 1))
1862 | (1LL << (CodeCompletionContext::CCC_Expression - 1))
1863 | (1LL << (CodeCompletionContext::CCC_ObjCMessageReceiver - 1))
1864 | (1LL << (CodeCompletionContext::CCC_DotMemberAccess - 1))
1865 | (1LL << (CodeCompletionContext::CCC_ArrowMemberAccess - 1))
1866 | (1LL << (CodeCompletionContext::CCC_ObjCPropertyAccess - 1))
1867 | (1LL << (CodeCompletionContext::CCC_ObjCProtocolName - 1))
1868 | (1LL << (CodeCompletionContext::CCC_ParenthesizedExpression - 1))
1869 | (1LL << (CodeCompletionContext::CCC_Recovery - 1));
Douglas Gregor02688102010-09-14 23:59:36 +00001870
Douglas Gregor87c08a52010-08-13 22:48:40 +00001871 if (AST.getASTContext().getLangOptions().CPlusPlus)
Douglas Gregor3da626b2011-07-07 16:03:39 +00001872 NormalContexts |= (1LL << (CodeCompletionContext::CCC_EnumTag - 1))
1873 | (1LL << (CodeCompletionContext::CCC_UnionTag - 1))
1874 | (1LL << (CodeCompletionContext::CCC_ClassOrStructTag - 1));
Douglas Gregor87c08a52010-08-13 22:48:40 +00001875 }
1876
1877 virtual void ProcessCodeCompleteResults(Sema &S,
1878 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00001879 CodeCompletionResult *Results,
Douglas Gregor697ca6d2010-08-16 20:01:48 +00001880 unsigned NumResults);
Douglas Gregor87c08a52010-08-13 22:48:40 +00001881
1882 virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg,
1883 OverloadCandidate *Candidates,
1884 unsigned NumCandidates) {
1885 Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates);
1886 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001887
Douglas Gregordae68752011-02-01 22:57:45 +00001888 virtual CodeCompletionAllocator &getAllocator() {
Douglas Gregor218937c2011-02-01 19:23:04 +00001889 return Next.getAllocator();
1890 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00001891 };
1892}
Douglas Gregor697ca6d2010-08-16 20:01:48 +00001893
Douglas Gregor5f808c22010-08-16 21:18:39 +00001894/// \brief Helper function that computes which global names are hidden by the
1895/// local code-completion results.
Ted Kremenekc198f612010-11-07 06:11:36 +00001896static void CalculateHiddenNames(const CodeCompletionContext &Context,
1897 CodeCompletionResult *Results,
1898 unsigned NumResults,
1899 ASTContext &Ctx,
1900 llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){
Douglas Gregor5f808c22010-08-16 21:18:39 +00001901 bool OnlyTagNames = false;
1902 switch (Context.getKind()) {
Douglas Gregor52779fb2010-09-23 23:01:17 +00001903 case CodeCompletionContext::CCC_Recovery:
Douglas Gregor5f808c22010-08-16 21:18:39 +00001904 case CodeCompletionContext::CCC_TopLevel:
1905 case CodeCompletionContext::CCC_ObjCInterface:
1906 case CodeCompletionContext::CCC_ObjCImplementation:
1907 case CodeCompletionContext::CCC_ObjCIvarList:
1908 case CodeCompletionContext::CCC_ClassStructUnion:
1909 case CodeCompletionContext::CCC_Statement:
1910 case CodeCompletionContext::CCC_Expression:
1911 case CodeCompletionContext::CCC_ObjCMessageReceiver:
Douglas Gregor3da626b2011-07-07 16:03:39 +00001912 case CodeCompletionContext::CCC_DotMemberAccess:
1913 case CodeCompletionContext::CCC_ArrowMemberAccess:
1914 case CodeCompletionContext::CCC_ObjCPropertyAccess:
Douglas Gregor5f808c22010-08-16 21:18:39 +00001915 case CodeCompletionContext::CCC_Namespace:
1916 case CodeCompletionContext::CCC_Type:
Douglas Gregor2ccccb32010-08-23 18:23:48 +00001917 case CodeCompletionContext::CCC_Name:
1918 case CodeCompletionContext::CCC_PotentiallyQualifiedName:
Douglas Gregor02688102010-09-14 23:59:36 +00001919 case CodeCompletionContext::CCC_ParenthesizedExpression:
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00001920 case CodeCompletionContext::CCC_ObjCInterfaceName:
Douglas Gregor5f808c22010-08-16 21:18:39 +00001921 break;
1922
1923 case CodeCompletionContext::CCC_EnumTag:
1924 case CodeCompletionContext::CCC_UnionTag:
1925 case CodeCompletionContext::CCC_ClassOrStructTag:
1926 OnlyTagNames = true;
1927 break;
1928
1929 case CodeCompletionContext::CCC_ObjCProtocolName:
Douglas Gregor1fbb4472010-08-24 20:21:13 +00001930 case CodeCompletionContext::CCC_MacroName:
1931 case CodeCompletionContext::CCC_MacroNameUse:
Douglas Gregorf29c5232010-08-24 22:20:20 +00001932 case CodeCompletionContext::CCC_PreprocessorExpression:
Douglas Gregor721f3592010-08-25 18:41:16 +00001933 case CodeCompletionContext::CCC_PreprocessorDirective:
Douglas Gregor59a66942010-08-25 18:04:30 +00001934 case CodeCompletionContext::CCC_NaturalLanguage:
Douglas Gregor458433d2010-08-26 15:07:07 +00001935 case CodeCompletionContext::CCC_SelectorName:
Douglas Gregor1a480c42010-08-27 17:35:51 +00001936 case CodeCompletionContext::CCC_TypeQualifiers:
Douglas Gregor52779fb2010-09-23 23:01:17 +00001937 case CodeCompletionContext::CCC_Other:
Douglas Gregor5c722c702011-02-18 23:30:37 +00001938 case CodeCompletionContext::CCC_OtherWithMacros:
Douglas Gregor3da626b2011-07-07 16:03:39 +00001939 case CodeCompletionContext::CCC_ObjCInstanceMessage:
1940 case CodeCompletionContext::CCC_ObjCClassMessage:
1941 case CodeCompletionContext::CCC_ObjCCategoryName:
Douglas Gregor721f3592010-08-25 18:41:16 +00001942 // We're looking for nothing, or we're looking for names that cannot
1943 // be hidden.
Douglas Gregor5f808c22010-08-16 21:18:39 +00001944 return;
1945 }
1946
John McCall0a2c5e22010-08-25 06:19:51 +00001947 typedef CodeCompletionResult Result;
Douglas Gregor5f808c22010-08-16 21:18:39 +00001948 for (unsigned I = 0; I != NumResults; ++I) {
1949 if (Results[I].Kind != Result::RK_Declaration)
1950 continue;
1951
1952 unsigned IDNS
1953 = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace();
1954
1955 bool Hiding = false;
1956 if (OnlyTagNames)
1957 Hiding = (IDNS & Decl::IDNS_Tag);
1958 else {
1959 unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member |
Douglas Gregora5fb7c32010-08-16 23:05:20 +00001960 Decl::IDNS_Namespace | Decl::IDNS_Ordinary |
1961 Decl::IDNS_NonMemberOperator);
Douglas Gregor5f808c22010-08-16 21:18:39 +00001962 if (Ctx.getLangOptions().CPlusPlus)
1963 HiddenIDNS |= Decl::IDNS_Tag;
1964 Hiding = (IDNS & HiddenIDNS);
1965 }
1966
1967 if (!Hiding)
1968 continue;
1969
1970 DeclarationName Name = Results[I].Declaration->getDeclName();
1971 if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo())
1972 HiddenNames.insert(Identifier->getName());
1973 else
1974 HiddenNames.insert(Name.getAsString());
1975 }
1976}
1977
1978
Douglas Gregor697ca6d2010-08-16 20:01:48 +00001979void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S,
1980 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00001981 CodeCompletionResult *Results,
Douglas Gregor697ca6d2010-08-16 20:01:48 +00001982 unsigned NumResults) {
1983 // Merge the results we were given with the results we cached.
1984 bool AddedResult = false;
Douglas Gregor5f808c22010-08-16 21:18:39 +00001985 unsigned InContexts
Douglas Gregor52779fb2010-09-23 23:01:17 +00001986 = (Context.getKind() == CodeCompletionContext::CCC_Recovery? NormalContexts
NAKAMURA Takumi01a429a2011-08-17 01:46:16 +00001987 : (1ULL << (Context.getKind() - 1)));
Douglas Gregor5f808c22010-08-16 21:18:39 +00001988 // Contains the set of names that are hidden by "local" completion results.
Ted Kremenekc198f612010-11-07 06:11:36 +00001989 llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames;
John McCall0a2c5e22010-08-25 06:19:51 +00001990 typedef CodeCompletionResult Result;
Chris Lattner5f9e2722011-07-23 10:55:15 +00001991 SmallVector<Result, 8> AllResults;
Douglas Gregor697ca6d2010-08-16 20:01:48 +00001992 for (ASTUnit::cached_completion_iterator
Douglas Gregor5535d572010-08-16 21:23:13 +00001993 C = AST.cached_completion_begin(),
1994 CEnd = AST.cached_completion_end();
Douglas Gregor697ca6d2010-08-16 20:01:48 +00001995 C != CEnd; ++C) {
1996 // If the context we are in matches any of the contexts we are
1997 // interested in, we'll add this result.
1998 if ((C->ShowInContexts & InContexts) == 0)
1999 continue;
2000
2001 // If we haven't added any results previously, do so now.
2002 if (!AddedResult) {
Douglas Gregor5f808c22010-08-16 21:18:39 +00002003 CalculateHiddenNames(Context, Results, NumResults, S.Context,
2004 HiddenNames);
Douglas Gregor697ca6d2010-08-16 20:01:48 +00002005 AllResults.insert(AllResults.end(), Results, Results + NumResults);
2006 AddedResult = true;
2007 }
2008
Douglas Gregor5f808c22010-08-16 21:18:39 +00002009 // Determine whether this global completion result is hidden by a local
2010 // completion result. If so, skip it.
2011 if (C->Kind != CXCursor_MacroDefinition &&
2012 HiddenNames.count(C->Completion->getTypedText()))
2013 continue;
2014
Douglas Gregor697ca6d2010-08-16 20:01:48 +00002015 // Adjust priority based on similar type classes.
2016 unsigned Priority = C->Priority;
Douglas Gregor4125c372010-08-25 18:03:13 +00002017 CXCursorKind CursorKind = C->Kind;
Douglas Gregor1fbb4472010-08-24 20:21:13 +00002018 CodeCompletionString *Completion = C->Completion;
Douglas Gregor697ca6d2010-08-16 20:01:48 +00002019 if (!Context.getPreferredType().isNull()) {
2020 if (C->Kind == CXCursor_MacroDefinition) {
2021 Priority = getMacroUsagePriority(C->Completion->getTypedText(),
Douglas Gregorb05496d2010-09-20 21:11:48 +00002022 S.getLangOptions(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00002023 Context.getPreferredType()->isAnyPointerType());
Douglas Gregor697ca6d2010-08-16 20:01:48 +00002024 } else if (C->Type) {
2025 CanQualType Expected
Douglas Gregor5535d572010-08-16 21:23:13 +00002026 = S.Context.getCanonicalType(
Douglas Gregor697ca6d2010-08-16 20:01:48 +00002027 Context.getPreferredType().getUnqualifiedType());
2028 SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected);
2029 if (ExpectedSTC == C->TypeClass) {
2030 // We know this type is similar; check for an exact match.
2031 llvm::StringMap<unsigned> &CachedCompletionTypes
Douglas Gregor5535d572010-08-16 21:23:13 +00002032 = AST.getCachedCompletionTypes();
Douglas Gregor697ca6d2010-08-16 20:01:48 +00002033 llvm::StringMap<unsigned>::iterator Pos
Douglas Gregor5535d572010-08-16 21:23:13 +00002034 = CachedCompletionTypes.find(QualType(Expected).getAsString());
Douglas Gregor697ca6d2010-08-16 20:01:48 +00002035 if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type)
2036 Priority /= CCF_ExactTypeMatch;
2037 else
2038 Priority /= CCF_SimilarTypeMatch;
2039 }
2040 }
2041 }
2042
Douglas Gregor1fbb4472010-08-24 20:21:13 +00002043 // Adjust the completion string, if required.
2044 if (C->Kind == CXCursor_MacroDefinition &&
2045 Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) {
2046 // Create a new code-completion string that just contains the
2047 // macro name, without its arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00002048 CodeCompletionBuilder Builder(getAllocator(), CCP_CodePattern,
2049 C->Availability);
2050 Builder.AddTypedTextChunk(C->Completion->getTypedText());
Douglas Gregor4125c372010-08-25 18:03:13 +00002051 CursorKind = CXCursor_NotImplemented;
2052 Priority = CCP_CodePattern;
Douglas Gregor218937c2011-02-01 19:23:04 +00002053 Completion = Builder.TakeString();
Douglas Gregor1fbb4472010-08-24 20:21:13 +00002054 }
2055
Douglas Gregor4125c372010-08-25 18:03:13 +00002056 AllResults.push_back(Result(Completion, Priority, CursorKind,
Douglas Gregor58ddb602010-08-23 23:00:57 +00002057 C->Availability));
Douglas Gregor697ca6d2010-08-16 20:01:48 +00002058 }
2059
2060 // If we did not add any cached completion results, just forward the
2061 // results we were given to the next consumer.
2062 if (!AddedResult) {
2063 Next.ProcessCodeCompleteResults(S, Context, Results, NumResults);
2064 return;
2065 }
Douglas Gregor1e5e6682010-08-26 13:48:20 +00002066
Douglas Gregor697ca6d2010-08-16 20:01:48 +00002067 Next.ProcessCodeCompleteResults(S, Context, AllResults.data(),
2068 AllResults.size());
2069}
2070
2071
2072
Chris Lattner5f9e2722011-07-23 10:55:15 +00002073void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column,
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002074 RemappedFile *RemappedFiles,
2075 unsigned NumRemappedFiles,
Douglas Gregorcee235c2010-08-05 09:09:23 +00002076 bool IncludeMacros,
2077 bool IncludeCodePatterns,
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002078 CodeCompleteConsumer &Consumer,
David Blaikied6471f72011-09-25 23:23:43 +00002079 DiagnosticsEngine &Diag, LangOptions &LangOpts,
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002080 SourceManager &SourceMgr, FileManager &FileMgr,
Chris Lattner5f9e2722011-07-23 10:55:15 +00002081 SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
2082 SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
Ted Kremenek4f327862011-03-21 18:40:17 +00002083 if (!Invocation)
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002084 return;
2085
Douglas Gregor213f18b2010-10-28 15:44:59 +00002086 SimpleTimer CompletionTimer(WantTiming);
Benjamin Krameredfb7ec2010-11-09 20:00:56 +00002087 CompletionTimer.setOutput("Code completion @ " + File + ":" +
Chris Lattner5f9e2722011-07-23 10:55:15 +00002088 Twine(Line) + ":" + Twine(Column));
Douglas Gregordf95a132010-08-09 20:45:32 +00002089
Ted Kremenek4f327862011-03-21 18:40:17 +00002090 llvm::IntrusiveRefCntPtr<CompilerInvocation>
2091 CCInvocation(new CompilerInvocation(*Invocation));
2092
2093 FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts();
2094 PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts();
Douglas Gregorcee235c2010-08-05 09:09:23 +00002095
Douglas Gregor87c08a52010-08-13 22:48:40 +00002096 FrontendOpts.ShowMacrosInCodeCompletion
2097 = IncludeMacros && CachedCompletionResults.empty();
Douglas Gregorcee235c2010-08-05 09:09:23 +00002098 FrontendOpts.ShowCodePatternsInCodeCompletion = IncludeCodePatterns;
Douglas Gregor8071e422010-08-15 06:18:01 +00002099 FrontendOpts.ShowGlobalSymbolsInCodeCompletion
2100 = CachedCompletionResults.empty();
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002101 FrontendOpts.CodeCompletionAt.FileName = File;
2102 FrontendOpts.CodeCompletionAt.Line = Line;
2103 FrontendOpts.CodeCompletionAt.Column = Column;
2104
2105 // Set the language options appropriately.
Ted Kremenek4f327862011-03-21 18:40:17 +00002106 LangOpts = CCInvocation->getLangOpts();
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002107
Ted Kremenek03201fb2011-03-21 18:40:07 +00002108 llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance());
2109
2110 // Recover resources if we crash before exiting this method.
Ted Kremenek25a11e12011-03-22 01:15:24 +00002111 llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
2112 CICleanup(Clang.get());
Ted Kremenek03201fb2011-03-21 18:40:07 +00002113
Ted Kremenek4f327862011-03-21 18:40:17 +00002114 Clang->setInvocation(&*CCInvocation);
Ted Kremenek03201fb2011-03-21 18:40:07 +00002115 OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].second;
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002116
2117 // Set up diagnostics, capturing any diagnostics produced.
Ted Kremenek03201fb2011-03-21 18:40:07 +00002118 Clang->setDiagnostics(&Diag);
Ted Kremenek4f327862011-03-21 18:40:17 +00002119 ProcessWarningOptions(Diag, CCInvocation->getDiagnosticOpts());
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002120 CaptureDroppedDiagnostics Capture(true,
Ted Kremenek03201fb2011-03-21 18:40:07 +00002121 Clang->getDiagnostics(),
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002122 StoredDiagnostics);
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002123
2124 // Create the target instance.
Ted Kremenek03201fb2011-03-21 18:40:07 +00002125 Clang->getTargetOpts().Features = TargetFeatures;
2126 Clang->setTarget(TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),
2127 Clang->getTargetOpts()));
2128 if (!Clang->hasTarget()) {
Ted Kremenek4f327862011-03-21 18:40:17 +00002129 Clang->setInvocation(0);
Douglas Gregorbdbb0042010-08-18 22:29:43 +00002130 return;
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002131 }
2132
2133 // Inform the target of the language options.
2134 //
2135 // FIXME: We shouldn't need to do this, the target should be immutable once
2136 // created. This complexity should be lifted elsewhere.
Ted Kremenek03201fb2011-03-21 18:40:07 +00002137 Clang->getTarget().setForcedLangOptions(Clang->getLangOpts());
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002138
Ted Kremenek03201fb2011-03-21 18:40:07 +00002139 assert(Clang->getFrontendOpts().Inputs.size() == 1 &&
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002140 "Invocation must have exactly one source file!");
Ted Kremenek03201fb2011-03-21 18:40:07 +00002141 assert(Clang->getFrontendOpts().Inputs[0].first != IK_AST &&
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002142 "FIXME: AST inputs not yet supported here!");
Ted Kremenek03201fb2011-03-21 18:40:07 +00002143 assert(Clang->getFrontendOpts().Inputs[0].first != IK_LLVM_IR &&
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002144 "IR inputs not support here!");
2145
2146
2147 // Use the source and file managers that we were given.
Ted Kremenek03201fb2011-03-21 18:40:07 +00002148 Clang->setFileManager(&FileMgr);
2149 Clang->setSourceManager(&SourceMgr);
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002150
2151 // Remap files.
2152 PreprocessorOpts.clearRemappedFiles();
Douglas Gregorb75d3df2010-08-04 17:07:00 +00002153 PreprocessorOpts.RetainRemappedFileBuffers = true;
Douglas Gregor2283d792010-08-20 00:59:43 +00002154 for (unsigned I = 0; I != NumRemappedFiles; ++I) {
Argyrios Kyrtzidisb1c86492011-03-05 01:03:53 +00002155 FilenameOrMemBuf fileOrBuf = RemappedFiles[I].second;
2156 if (const llvm::MemoryBuffer *
2157 memBuf = fileOrBuf.dyn_cast<const llvm::MemoryBuffer *>()) {
2158 PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, memBuf);
2159 OwnedBuffers.push_back(memBuf);
2160 } else {
2161 const char *fname = fileOrBuf.get<const char *>();
2162 PreprocessorOpts.addRemappedFile(RemappedFiles[I].first, fname);
2163 }
Douglas Gregor2283d792010-08-20 00:59:43 +00002164 }
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002165
Douglas Gregor87c08a52010-08-13 22:48:40 +00002166 // Use the code completion consumer we were given, but adding any cached
2167 // code-completion results.
Douglas Gregor7f946ad2010-11-29 16:13:56 +00002168 AugmentedCodeCompleteConsumer *AugmentedConsumer
2169 = new AugmentedCodeCompleteConsumer(*this, Consumer,
2170 FrontendOpts.ShowMacrosInCodeCompletion,
2171 FrontendOpts.ShowCodePatternsInCodeCompletion,
2172 FrontendOpts.ShowGlobalSymbolsInCodeCompletion);
Ted Kremenek03201fb2011-03-21 18:40:07 +00002173 Clang->setCodeCompletionConsumer(AugmentedConsumer);
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002174
Douglas Gregordf95a132010-08-09 20:45:32 +00002175 // If we have a precompiled preamble, try to use it. We only allow
2176 // the use of the precompiled preamble if we're if the completion
2177 // point is within the main file, after the end of the precompiled
2178 // preamble.
2179 llvm::MemoryBuffer *OverrideMainBuffer = 0;
2180 if (!PreambleFile.empty()) {
2181 using llvm::sys::FileStatus;
2182 llvm::sys::PathWithStatus CompleteFilePath(File);
2183 llvm::sys::PathWithStatus MainPath(OriginalSourceFile);
2184 if (const FileStatus *CompleteFileStatus = CompleteFilePath.getFileStatus())
2185 if (const FileStatus *MainStatus = MainPath.getFileStatus())
Argyrios Kyrtzidisc8c97a02011-09-04 03:32:04 +00002186 if (CompleteFileStatus->getUniqueID() == MainStatus->getUniqueID() &&
2187 Line > 1)
Douglas Gregor2283d792010-08-20 00:59:43 +00002188 OverrideMainBuffer
Ted Kremenek4f327862011-03-21 18:40:17 +00002189 = getMainBufferWithPrecompiledPreamble(*CCInvocation, false,
Douglas Gregorc9c29a82010-08-25 18:04:15 +00002190 Line - 1);
Douglas Gregordf95a132010-08-09 20:45:32 +00002191 }
2192
2193 // If the main file has been overridden due to the use of a preamble,
2194 // make that override happen and introduce the preamble.
Douglas Gregor8ef6c8c2011-02-05 19:42:43 +00002195 PreprocessorOpts.DisableStatCache = true;
Douglas Gregor4cd912a2010-10-12 00:50:20 +00002196 StoredDiagnostics.insert(StoredDiagnostics.end(),
2197 this->StoredDiagnostics.begin(),
2198 this->StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver);
Douglas Gregordf95a132010-08-09 20:45:32 +00002199 if (OverrideMainBuffer) {
2200 PreprocessorOpts.addRemappedFile(OriginalSourceFile, OverrideMainBuffer);
2201 PreprocessorOpts.PrecompiledPreambleBytes.first = Preamble.size();
2202 PreprocessorOpts.PrecompiledPreambleBytes.second
2203 = PreambleEndsAtStartOfLine;
2204 PreprocessorOpts.ImplicitPCHInclude = PreambleFile;
2205 PreprocessorOpts.DisablePCHValidation = true;
2206
Douglas Gregor2283d792010-08-20 00:59:43 +00002207 OwnedBuffers.push_back(OverrideMainBuffer);
Douglas Gregorf128fed2010-08-20 00:02:33 +00002208 } else {
2209 PreprocessorOpts.PrecompiledPreambleBytes.first = 0;
2210 PreprocessorOpts.PrecompiledPreambleBytes.second = false;
Douglas Gregordf95a132010-08-09 20:45:32 +00002211 }
2212
Douglas Gregordca8ee82011-05-06 16:33:08 +00002213 // Disable the preprocessing record
2214 PreprocessorOpts.DetailedRecord = false;
2215
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002216 llvm::OwningPtr<SyntaxOnlyAction> Act;
2217 Act.reset(new SyntaxOnlyAction);
Ted Kremenek03201fb2011-03-21 18:40:07 +00002218 if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0].second,
2219 Clang->getFrontendOpts().Inputs[0].first)) {
Douglas Gregorf62d43d2011-07-19 16:10:42 +00002220 if (OverrideMainBuffer) {
Jonathan D. Turner9461fcc2011-07-22 17:25:03 +00002221 std::string ModName = PreambleFile;
Douglas Gregorf62d43d2011-07-19 16:10:42 +00002222 TranslateStoredDiagnostics(Clang->getModuleManager(), ModName,
2223 getSourceManager(), PreambleDiagnostics,
2224 StoredDiagnostics);
2225 }
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002226 Act->Execute();
2227 Act->EndSourceFile();
2228 }
Douglas Gregor1abc6bc2010-08-04 16:47:14 +00002229}
Douglas Gregor7ae2faa2010-08-13 05:36:37 +00002230
Chris Lattner5f9e2722011-07-23 10:55:15 +00002231CXSaveError ASTUnit::Save(StringRef File) {
Douglas Gregor85bea972011-07-06 17:40:26 +00002232 if (getDiagnostics().hasUnrecoverableErrorOccurred())
Douglas Gregor39c411f2011-07-06 16:43:36 +00002233 return CXSaveError_TranslationErrors;
Argyrios Kyrtzidis9cca68d2011-07-21 18:44:49 +00002234
2235 // Write to a temporary file and later rename it to the actual file, to avoid
2236 // possible race conditions.
Argyrios Kyrtzidis7e909852011-07-28 00:45:10 +00002237 llvm::SmallString<128> TempPath;
2238 TempPath = File;
2239 TempPath += "-%%%%%%%%";
2240 int fd;
2241 if (llvm::sys::fs::unique_file(TempPath.str(), fd, TempPath,
2242 /*makeAbsolute=*/false))
Argyrios Kyrtzidis9cca68d2011-07-21 18:44:49 +00002243 return CXSaveError_Unknown;
Argyrios Kyrtzidis9cca68d2011-07-21 18:44:49 +00002244
Douglas Gregor7ae2faa2010-08-13 05:36:37 +00002245 // FIXME: Can we somehow regenerate the stat cache here, or do we need to
2246 // unconditionally create a stat cache when we parse the file?
Argyrios Kyrtzidis7e909852011-07-28 00:45:10 +00002247 llvm::raw_fd_ostream Out(fd, /*shouldClose=*/true);
Argyrios Kyrtzidisb0f4b9a2011-03-09 17:21:42 +00002248
2249 serialize(Out);
2250 Out.close();
Argyrios Kyrtzidis9cca68d2011-07-21 18:44:49 +00002251 if (Out.has_error())
2252 return CXSaveError_Unknown;
2253
2254 if (llvm::error_code ec = llvm::sys::fs::rename(TempPath.str(), File)) {
2255 bool exists;
2256 llvm::sys::fs::remove(TempPath.str(), exists);
2257 return CXSaveError_Unknown;
2258 }
2259
2260 return CXSaveError_None;
Argyrios Kyrtzidisb0f4b9a2011-03-09 17:21:42 +00002261}
2262
Chris Lattner5f9e2722011-07-23 10:55:15 +00002263bool ASTUnit::serialize(raw_ostream &OS) {
Argyrios Kyrtzidisb0f4b9a2011-03-09 17:21:42 +00002264 if (getDiagnostics().hasErrorOccurred())
2265 return true;
2266
Douglas Gregor7ae2faa2010-08-13 05:36:37 +00002267 std::vector<unsigned char> Buffer;
2268 llvm::BitstreamWriter Stream(Buffer);
Sebastian Redla4232eb2010-08-18 23:56:21 +00002269 ASTWriter Writer(Stream);
Douglas Gregor7143aab2011-09-01 17:04:32 +00002270 // FIXME: Handle modules
2271 Writer.WriteAST(getSema(), 0, std::string(), /*IsModule=*/false, "");
Douglas Gregor7ae2faa2010-08-13 05:36:37 +00002272
2273 // Write the generated bitstream to "Out".
Douglas Gregorbdbb0042010-08-18 22:29:43 +00002274 if (!Buffer.empty())
Argyrios Kyrtzidisb0f4b9a2011-03-09 17:21:42 +00002275 OS.write((char *)&Buffer.front(), Buffer.size());
2276
2277 return false;
Douglas Gregor7ae2faa2010-08-13 05:36:37 +00002278}
Douglas Gregorf62d43d2011-07-19 16:10:42 +00002279
2280typedef ContinuousRangeMap<unsigned, int, 2> SLocRemap;
2281
2282static void TranslateSLoc(SourceLocation &L, SLocRemap &Remap) {
2283 unsigned Raw = L.getRawEncoding();
2284 const unsigned MacroBit = 1U << 31;
2285 L = SourceLocation::getFromRawEncoding((Raw & MacroBit) |
2286 ((Raw & ~MacroBit) + Remap.find(Raw & ~MacroBit)->second));
2287}
2288
2289void ASTUnit::TranslateStoredDiagnostics(
2290 ASTReader *MMan,
Chris Lattner5f9e2722011-07-23 10:55:15 +00002291 StringRef ModName,
Douglas Gregorf62d43d2011-07-19 16:10:42 +00002292 SourceManager &SrcMgr,
Chris Lattner5f9e2722011-07-23 10:55:15 +00002293 const SmallVectorImpl<StoredDiagnostic> &Diags,
2294 SmallVectorImpl<StoredDiagnostic> &Out) {
Douglas Gregorf62d43d2011-07-19 16:10:42 +00002295 // The stored diagnostic has the old source manager in it; update
2296 // the locations to refer into the new source manager. We also need to remap
2297 // all the locations to the new view. This includes the diag location, any
2298 // associated source ranges, and the source ranges of associated fix-its.
2299 // FIXME: There should be a cleaner way to do this.
2300
Chris Lattner5f9e2722011-07-23 10:55:15 +00002301 SmallVector<StoredDiagnostic, 4> Result;
Douglas Gregorf62d43d2011-07-19 16:10:42 +00002302 Result.reserve(Diags.size());
2303 assert(MMan && "Don't have a module manager");
Jonathan D. Turner48d2c3f2011-07-26 18:21:30 +00002304 serialization::Module *Mod = MMan->ModuleMgr.lookup(ModName);
Douglas Gregorf62d43d2011-07-19 16:10:42 +00002305 assert(Mod && "Don't have preamble module");
2306 SLocRemap &Remap = Mod->SLocRemap;
2307 for (unsigned I = 0, N = Diags.size(); I != N; ++I) {
2308 // Rebuild the StoredDiagnostic.
2309 const StoredDiagnostic &SD = Diags[I];
2310 SourceLocation L = SD.getLocation();
2311 TranslateSLoc(L, Remap);
2312 FullSourceLoc Loc(L, SrcMgr);
2313
Chris Lattner5f9e2722011-07-23 10:55:15 +00002314 SmallVector<CharSourceRange, 4> Ranges;
Douglas Gregorf62d43d2011-07-19 16:10:42 +00002315 Ranges.reserve(SD.range_size());
2316 for (StoredDiagnostic::range_iterator I = SD.range_begin(),
2317 E = SD.range_end();
2318 I != E; ++I) {
2319 SourceLocation BL = I->getBegin();
2320 TranslateSLoc(BL, Remap);
2321 SourceLocation EL = I->getEnd();
2322 TranslateSLoc(EL, Remap);
2323 Ranges.push_back(CharSourceRange(SourceRange(BL, EL), I->isTokenRange()));
2324 }
2325
Chris Lattner5f9e2722011-07-23 10:55:15 +00002326 SmallVector<FixItHint, 2> FixIts;
Douglas Gregorf62d43d2011-07-19 16:10:42 +00002327 FixIts.reserve(SD.fixit_size());
2328 for (StoredDiagnostic::fixit_iterator I = SD.fixit_begin(),
2329 E = SD.fixit_end();
2330 I != E; ++I) {
2331 FixIts.push_back(FixItHint());
2332 FixItHint &FH = FixIts.back();
2333 FH.CodeToInsert = I->CodeToInsert;
2334 SourceLocation BL = I->RemoveRange.getBegin();
2335 TranslateSLoc(BL, Remap);
2336 SourceLocation EL = I->RemoveRange.getEnd();
2337 TranslateSLoc(EL, Remap);
2338 FH.RemoveRange = CharSourceRange(SourceRange(BL, EL),
2339 I->RemoveRange.isTokenRange());
2340 }
2341
2342 Result.push_back(StoredDiagnostic(SD.getLevel(), SD.getID(),
2343 SD.getMessage(), Loc, Ranges, FixIts));
2344 }
2345 Result.swap(Out);
2346}
Argyrios Kyrtzidis507097e2011-09-19 20:40:35 +00002347
2348SourceLocation ASTUnit::getLocation(const FileEntry *File,
2349 unsigned Line, unsigned Col) const {
2350 const SourceManager &SM = getSourceManager();
Argyrios Kyrtzidisee0f84f2011-09-26 08:01:41 +00002351 SourceLocation Loc = SM.translateFileLineCol(File, Line, Col);
Argyrios Kyrtzidis507097e2011-09-19 20:40:35 +00002352 return SM.getMacroArgExpandedLocation(Loc);
2353}
2354
2355SourceLocation ASTUnit::getLocation(const FileEntry *File,
2356 unsigned Offset) const {
2357 const SourceManager &SM = getSourceManager();
Argyrios Kyrtzidisee0f84f2011-09-26 08:01:41 +00002358 SourceLocation FileLoc = SM.translateFileLineCol(File, 1, 1);
Argyrios Kyrtzidis507097e2011-09-19 20:40:35 +00002359 return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset));
2360}
2361
Argyrios Kyrtzidisee0f84f2011-09-26 08:01:41 +00002362/// \brief If \arg Loc is a loaded location from the preamble, returns
2363/// the corresponding local location of the main file, otherwise it returns
2364/// \arg Loc.
2365SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) {
2366 FileID PreambleID;
2367 if (SourceMgr)
2368 PreambleID = SourceMgr->getPreambleFileID();
2369
2370 if (Loc.isInvalid() || Preamble.empty() || PreambleID.isInvalid())
2371 return Loc;
2372
2373 unsigned Offs;
2374 if (SourceMgr->isInFileID(Loc, PreambleID, &Offs) && Offs < Preamble.size()) {
2375 SourceLocation FileLoc
2376 = SourceMgr->getLocForStartOfFile(SourceMgr->getMainFileID());
2377 return FileLoc.getLocWithOffset(Offs);
2378 }
2379
2380 return Loc;
2381}
2382
2383/// \brief If \arg Loc is a local location of the main file but inside the
2384/// preamble chunk, returns the corresponding loaded location from the
2385/// preamble, otherwise it returns \arg Loc.
2386SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) {
2387 FileID PreambleID;
2388 if (SourceMgr)
2389 PreambleID = SourceMgr->getPreambleFileID();
2390
2391 if (Loc.isInvalid() || Preamble.empty() || PreambleID.isInvalid())
2392 return Loc;
2393
2394 unsigned Offs;
2395 if (SourceMgr->isInFileID(Loc, SourceMgr->getMainFileID(), &Offs) &&
2396 Offs < Preamble.size()) {
2397 SourceLocation FileLoc = SourceMgr->getLocForStartOfFile(PreambleID);
2398 return FileLoc.getLocWithOffset(Offs);
2399 }
2400
2401 return Loc;
2402}
2403
Argyrios Kyrtzidis507097e2011-09-19 20:40:35 +00002404void ASTUnit::PreambleData::countLines() const {
2405 NumLines = 0;
2406 if (empty())
2407 return;
2408
2409 for (std::vector<char>::const_iterator
2410 I = Buffer.begin(), E = Buffer.end(); I != E; ++I) {
2411 if (*I == '\n')
2412 ++NumLines;
2413 }
2414 if (Buffer.back() != '\n')
2415 ++NumLines;
2416}