File: | tools/clang/lib/Frontend/ASTUnit.cpp |
Warning: | line 157, column 38 Potential leak of memory pointed to by field 'Obj' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- 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 | ||||
14 | #include "clang/Frontend/ASTUnit.h" | |||
15 | #include "clang/AST/ASTConsumer.h" | |||
16 | #include "clang/AST/ASTContext.h" | |||
17 | #include "clang/AST/CommentCommandTraits.h" | |||
18 | #include "clang/AST/Decl.h" | |||
19 | #include "clang/AST/DeclBase.h" | |||
20 | #include "clang/AST/DeclCXX.h" | |||
21 | #include "clang/AST/DeclGroup.h" | |||
22 | #include "clang/AST/DeclObjC.h" | |||
23 | #include "clang/AST/DeclTemplate.h" | |||
24 | #include "clang/AST/DeclarationName.h" | |||
25 | #include "clang/AST/ExternalASTSource.h" | |||
26 | #include "clang/AST/PrettyPrinter.h" | |||
27 | #include "clang/AST/Type.h" | |||
28 | #include "clang/AST/TypeOrdering.h" | |||
29 | #include "clang/Basic/Diagnostic.h" | |||
30 | #include "clang/Basic/FileManager.h" | |||
31 | #include "clang/Basic/IdentifierTable.h" | |||
32 | #include "clang/Basic/LLVM.h" | |||
33 | #include "clang/Basic/LangOptions.h" | |||
34 | #include "clang/Basic/MemoryBufferCache.h" | |||
35 | #include "clang/Basic/Module.h" | |||
36 | #include "clang/Basic/SourceLocation.h" | |||
37 | #include "clang/Basic/SourceManager.h" | |||
38 | #include "clang/Basic/TargetInfo.h" | |||
39 | #include "clang/Basic/TargetOptions.h" | |||
40 | #include "clang/Basic/VirtualFileSystem.h" | |||
41 | #include "clang/Frontend/CompilerInstance.h" | |||
42 | #include "clang/Frontend/CompilerInvocation.h" | |||
43 | #include "clang/Frontend/FrontendAction.h" | |||
44 | #include "clang/Frontend/FrontendActions.h" | |||
45 | #include "clang/Frontend/FrontendDiagnostic.h" | |||
46 | #include "clang/Frontend/FrontendOptions.h" | |||
47 | #include "clang/Frontend/MultiplexConsumer.h" | |||
48 | #include "clang/Frontend/PCHContainerOperations.h" | |||
49 | #include "clang/Frontend/PrecompiledPreamble.h" | |||
50 | #include "clang/Frontend/Utils.h" | |||
51 | #include "clang/Lex/HeaderSearch.h" | |||
52 | #include "clang/Lex/HeaderSearchOptions.h" | |||
53 | #include "clang/Lex/Lexer.h" | |||
54 | #include "clang/Lex/PPCallbacks.h" | |||
55 | #include "clang/Lex/PreprocessingRecord.h" | |||
56 | #include "clang/Lex/Preprocessor.h" | |||
57 | #include "clang/Lex/PreprocessorOptions.h" | |||
58 | #include "clang/Lex/Token.h" | |||
59 | #include "clang/Sema/CodeCompleteConsumer.h" | |||
60 | #include "clang/Sema/CodeCompleteOptions.h" | |||
61 | #include "clang/Sema/Sema.h" | |||
62 | #include "clang/Serialization/ASTBitCodes.h" | |||
63 | #include "clang/Serialization/ASTReader.h" | |||
64 | #include "clang/Serialization/ASTWriter.h" | |||
65 | #include "clang/Serialization/ContinuousRangeMap.h" | |||
66 | #include "clang/Serialization/Module.h" | |||
67 | #include "llvm/ADT/ArrayRef.h" | |||
68 | #include "llvm/ADT/DenseMap.h" | |||
69 | #include "llvm/ADT/IntrusiveRefCntPtr.h" | |||
70 | #include "llvm/ADT/None.h" | |||
71 | #include "llvm/ADT/Optional.h" | |||
72 | #include "llvm/ADT/STLExtras.h" | |||
73 | #include "llvm/ADT/SmallString.h" | |||
74 | #include "llvm/ADT/SmallVector.h" | |||
75 | #include "llvm/ADT/StringMap.h" | |||
76 | #include "llvm/ADT/StringRef.h" | |||
77 | #include "llvm/ADT/StringSet.h" | |||
78 | #include "llvm/ADT/Twine.h" | |||
79 | #include "llvm/ADT/iterator_range.h" | |||
80 | #include "llvm/Bitcode/BitstreamWriter.h" | |||
81 | #include "llvm/Support/Allocator.h" | |||
82 | #include "llvm/Support/Casting.h" | |||
83 | #include "llvm/Support/CrashRecoveryContext.h" | |||
84 | #include "llvm/Support/DJB.h" | |||
85 | #include "llvm/Support/ErrorHandling.h" | |||
86 | #include "llvm/Support/ErrorOr.h" | |||
87 | #include "llvm/Support/FileSystem.h" | |||
88 | #include "llvm/Support/MemoryBuffer.h" | |||
89 | #include "llvm/Support/Mutex.h" | |||
90 | #include "llvm/Support/Timer.h" | |||
91 | #include "llvm/Support/raw_ostream.h" | |||
92 | #include <algorithm> | |||
93 | #include <atomic> | |||
94 | #include <cassert> | |||
95 | #include <cstdint> | |||
96 | #include <cstdio> | |||
97 | #include <cstdlib> | |||
98 | #include <memory> | |||
99 | #include <string> | |||
100 | #include <tuple> | |||
101 | #include <utility> | |||
102 | #include <vector> | |||
103 | ||||
104 | using namespace clang; | |||
105 | ||||
106 | using llvm::TimeRecord; | |||
107 | ||||
108 | namespace { | |||
109 | ||||
110 | class SimpleTimer { | |||
111 | bool WantTiming; | |||
112 | TimeRecord Start; | |||
113 | std::string Output; | |||
114 | ||||
115 | public: | |||
116 | explicit SimpleTimer(bool WantTiming) : WantTiming(WantTiming) { | |||
117 | if (WantTiming) | |||
118 | Start = TimeRecord::getCurrentTime(); | |||
119 | } | |||
120 | ||||
121 | ~SimpleTimer() { | |||
122 | if (WantTiming) { | |||
123 | TimeRecord Elapsed = TimeRecord::getCurrentTime(); | |||
124 | Elapsed -= Start; | |||
125 | llvm::errs() << Output << ':'; | |||
126 | Elapsed.print(Elapsed, llvm::errs()); | |||
127 | llvm::errs() << '\n'; | |||
128 | } | |||
129 | } | |||
130 | ||||
131 | void setOutput(const Twine &Output) { | |||
132 | if (WantTiming) | |||
133 | this->Output = Output.str(); | |||
134 | } | |||
135 | }; | |||
136 | ||||
137 | } // namespace | |||
138 | ||||
139 | template <class T> | |||
140 | static std::unique_ptr<T> valueOrNull(llvm::ErrorOr<std::unique_ptr<T>> Val) { | |||
141 | if (!Val) | |||
142 | return nullptr; | |||
143 | return std::move(*Val); | |||
144 | } | |||
145 | ||||
146 | template <class T> | |||
147 | static bool moveOnNoError(llvm::ErrorOr<T> Val, T &Output) { | |||
148 | if (!Val) | |||
149 | return false; | |||
150 | Output = std::move(*Val); | |||
151 | return true; | |||
152 | } | |||
153 | ||||
154 | /// \brief Get a source buffer for \p MainFilePath, handling all file-to-file | |||
155 | /// and file-to-buffer remappings inside \p Invocation. | |||
156 | static std::unique_ptr<llvm::MemoryBuffer> | |||
157 | getBufferForFileHandlingRemapping(const CompilerInvocation &Invocation, | |||
158 | vfs::FileSystem *VFS, | |||
159 | StringRef FilePath) { | |||
160 | const auto &PreprocessorOpts = Invocation.getPreprocessorOpts(); | |||
161 | ||||
162 | // Try to determine if the main file has been remapped, either from the | |||
163 | // command line (to another file) or directly through the compiler | |||
164 | // invocation (to a memory buffer). | |||
165 | llvm::MemoryBuffer *Buffer = nullptr; | |||
166 | std::unique_ptr<llvm::MemoryBuffer> BufferOwner; | |||
167 | auto FileStatus = VFS->status(FilePath); | |||
168 | if (FileStatus) { | |||
169 | llvm::sys::fs::UniqueID MainFileID = FileStatus->getUniqueID(); | |||
170 | ||||
171 | // Check whether there is a file-file remapping of the main file | |||
172 | for (const auto &RF : PreprocessorOpts.RemappedFiles) { | |||
173 | std::string MPath(RF.first); | |||
174 | auto MPathStatus = VFS->status(MPath); | |||
175 | if (MPathStatus) { | |||
176 | llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID(); | |||
177 | if (MainFileID == MID) { | |||
178 | // We found a remapping. Try to load the resulting, remapped source. | |||
179 | BufferOwner = valueOrNull(VFS->getBufferForFile(RF.second)); | |||
180 | if (!BufferOwner) | |||
181 | return nullptr; | |||
182 | } | |||
183 | } | |||
184 | } | |||
185 | ||||
186 | // Check whether there is a file-buffer remapping. It supercedes the | |||
187 | // file-file remapping. | |||
188 | for (const auto &RB : PreprocessorOpts.RemappedFileBuffers) { | |||
189 | std::string MPath(RB.first); | |||
190 | auto MPathStatus = VFS->status(MPath); | |||
191 | if (MPathStatus) { | |||
192 | llvm::sys::fs::UniqueID MID = MPathStatus->getUniqueID(); | |||
193 | if (MainFileID == MID) { | |||
194 | // We found a remapping. | |||
195 | BufferOwner.reset(); | |||
196 | Buffer = const_cast<llvm::MemoryBuffer *>(RB.second); | |||
197 | } | |||
198 | } | |||
199 | } | |||
200 | } | |||
201 | ||||
202 | // If the main source file was not remapped, load it now. | |||
203 | if (!Buffer && !BufferOwner) { | |||
204 | BufferOwner = valueOrNull(VFS->getBufferForFile(FilePath)); | |||
205 | if (!BufferOwner) | |||
206 | return nullptr; | |||
207 | } | |||
208 | ||||
209 | if (BufferOwner) | |||
210 | return BufferOwner; | |||
211 | if (!Buffer) | |||
212 | return nullptr; | |||
213 | return llvm::MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(), FilePath); | |||
214 | } | |||
215 | ||||
216 | struct ASTUnit::ASTWriterData { | |||
217 | SmallString<128> Buffer; | |||
218 | llvm::BitstreamWriter Stream; | |||
219 | ASTWriter Writer; | |||
220 | ||||
221 | ASTWriterData(MemoryBufferCache &PCMCache) | |||
222 | : Stream(Buffer), Writer(Stream, Buffer, PCMCache, {}) {} | |||
223 | }; | |||
224 | ||||
225 | void ASTUnit::clearFileLevelDecls() { | |||
226 | llvm::DeleteContainerSeconds(FileDecls); | |||
227 | } | |||
228 | ||||
229 | /// \brief After failing to build a precompiled preamble (due to | |||
230 | /// errors in the source that occurs in the preamble), the number of | |||
231 | /// reparses during which we'll skip even trying to precompile the | |||
232 | /// preamble. | |||
233 | const unsigned DefaultPreambleRebuildInterval = 5; | |||
234 | ||||
235 | /// \brief Tracks the number of ASTUnit objects that are currently active. | |||
236 | /// | |||
237 | /// Used for debugging purposes only. | |||
238 | static std::atomic<unsigned> ActiveASTUnitObjects; | |||
239 | ||||
240 | ASTUnit::ASTUnit(bool _MainFileIsAST) | |||
241 | : MainFileIsAST(_MainFileIsAST), WantTiming(getenv("LIBCLANG_TIMING")), | |||
242 | ShouldCacheCodeCompletionResults(false), | |||
243 | IncludeBriefCommentsInCodeCompletion(false), UserFilesAreVolatile(false), | |||
244 | UnsafeToFree(false) { | |||
245 | if (getenv("LIBCLANG_OBJTRACKING")) | |||
246 | fprintf(stderrstderr, "+++ %u translation units\n", ++ActiveASTUnitObjects); | |||
247 | } | |||
248 | ||||
249 | ASTUnit::~ASTUnit() { | |||
250 | // If we loaded from an AST file, balance out the BeginSourceFile call. | |||
251 | if (MainFileIsAST && getDiagnostics().getClient()) { | |||
252 | getDiagnostics().getClient()->EndSourceFile(); | |||
253 | } | |||
254 | ||||
255 | clearFileLevelDecls(); | |||
256 | ||||
257 | // Free the buffers associated with remapped files. We are required to | |||
258 | // perform this operation here because we explicitly request that the | |||
259 | // compiler instance *not* free these buffers for each invocation of the | |||
260 | // parser. | |||
261 | if (Invocation && OwnsRemappedFileBuffers) { | |||
262 | PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); | |||
263 | for (const auto &RB : PPOpts.RemappedFileBuffers) | |||
264 | delete RB.second; | |||
265 | } | |||
266 | ||||
267 | ClearCachedCompletionResults(); | |||
268 | ||||
269 | if (getenv("LIBCLANG_OBJTRACKING")) | |||
270 | fprintf(stderrstderr, "--- %u translation units\n", --ActiveASTUnitObjects); | |||
271 | } | |||
272 | ||||
273 | void ASTUnit::setPreprocessor(std::shared_ptr<Preprocessor> PP) { | |||
274 | this->PP = std::move(PP); | |||
275 | } | |||
276 | ||||
277 | /// \brief Determine the set of code-completion contexts in which this | |||
278 | /// declaration should be shown. | |||
279 | static unsigned getDeclShowContexts(const NamedDecl *ND, | |||
280 | const LangOptions &LangOpts, | |||
281 | bool &IsNestedNameSpecifier) { | |||
282 | IsNestedNameSpecifier = false; | |||
283 | ||||
284 | if (isa<UsingShadowDecl>(ND)) | |||
285 | ND = ND->getUnderlyingDecl(); | |||
286 | if (!ND) | |||
287 | return 0; | |||
288 | ||||
289 | uint64_t Contexts = 0; | |||
290 | if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND) || | |||
291 | isa<ClassTemplateDecl>(ND) || isa<TemplateTemplateParmDecl>(ND) || | |||
292 | isa<TypeAliasTemplateDecl>(ND)) { | |||
293 | // Types can appear in these contexts. | |||
294 | if (LangOpts.CPlusPlus || !isa<TagDecl>(ND)) | |||
295 | Contexts |= (1LL << CodeCompletionContext::CCC_TopLevel) | |||
296 | | (1LL << CodeCompletionContext::CCC_ObjCIvarList) | |||
297 | | (1LL << CodeCompletionContext::CCC_ClassStructUnion) | |||
298 | | (1LL << CodeCompletionContext::CCC_Statement) | |||
299 | | (1LL << CodeCompletionContext::CCC_Type) | |||
300 | | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression); | |||
301 | ||||
302 | // In C++, types can appear in expressions contexts (for functional casts). | |||
303 | if (LangOpts.CPlusPlus) | |||
304 | Contexts |= (1LL << CodeCompletionContext::CCC_Expression); | |||
305 | ||||
306 | // In Objective-C, message sends can send interfaces. In Objective-C++, | |||
307 | // all types are available due to functional casts. | |||
308 | if (LangOpts.CPlusPlus || isa<ObjCInterfaceDecl>(ND)) | |||
309 | Contexts |= (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver); | |||
310 | ||||
311 | // In Objective-C, you can only be a subclass of another Objective-C class | |||
312 | if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) { | |||
313 | // Objective-C interfaces can be used in a class property expression. | |||
314 | if (ID->getDefinition()) | |||
315 | Contexts |= (1LL << CodeCompletionContext::CCC_Expression); | |||
316 | Contexts |= (1LL << CodeCompletionContext::CCC_ObjCInterfaceName); | |||
317 | } | |||
318 | ||||
319 | // Deal with tag names. | |||
320 | if (isa<EnumDecl>(ND)) { | |||
321 | Contexts |= (1LL << CodeCompletionContext::CCC_EnumTag); | |||
322 | ||||
323 | // Part of the nested-name-specifier in C++0x. | |||
324 | if (LangOpts.CPlusPlus11) | |||
325 | IsNestedNameSpecifier = true; | |||
326 | } else if (const auto *Record = dyn_cast<RecordDecl>(ND)) { | |||
327 | if (Record->isUnion()) | |||
328 | Contexts |= (1LL << CodeCompletionContext::CCC_UnionTag); | |||
329 | else | |||
330 | Contexts |= (1LL << CodeCompletionContext::CCC_ClassOrStructTag); | |||
331 | ||||
332 | if (LangOpts.CPlusPlus) | |||
333 | IsNestedNameSpecifier = true; | |||
334 | } else if (isa<ClassTemplateDecl>(ND)) | |||
335 | IsNestedNameSpecifier = true; | |||
336 | } else if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) { | |||
337 | // Values can appear in these contexts. | |||
338 | Contexts = (1LL << CodeCompletionContext::CCC_Statement) | |||
339 | | (1LL << CodeCompletionContext::CCC_Expression) | |||
340 | | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression) | |||
341 | | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver); | |||
342 | } else if (isa<ObjCProtocolDecl>(ND)) { | |||
343 | Contexts = (1LL << CodeCompletionContext::CCC_ObjCProtocolName); | |||
344 | } else if (isa<ObjCCategoryDecl>(ND)) { | |||
345 | Contexts = (1LL << CodeCompletionContext::CCC_ObjCCategoryName); | |||
346 | } else if (isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) { | |||
347 | Contexts = (1LL << CodeCompletionContext::CCC_Namespace); | |||
348 | ||||
349 | // Part of the nested-name-specifier. | |||
350 | IsNestedNameSpecifier = true; | |||
351 | } | |||
352 | ||||
353 | return Contexts; | |||
354 | } | |||
355 | ||||
356 | void ASTUnit::CacheCodeCompletionResults() { | |||
357 | if (!TheSema) | |||
358 | return; | |||
359 | ||||
360 | SimpleTimer Timer(WantTiming); | |||
361 | Timer.setOutput("Cache global code completions for " + getMainFileName()); | |||
362 | ||||
363 | // Clear out the previous results. | |||
364 | ClearCachedCompletionResults(); | |||
365 | ||||
366 | // Gather the set of global code completions. | |||
367 | using Result = CodeCompletionResult; | |||
368 | SmallVector<Result, 8> Results; | |||
369 | CachedCompletionAllocator = std::make_shared<GlobalCodeCompletionAllocator>(); | |||
370 | CodeCompletionTUInfo CCTUInfo(CachedCompletionAllocator); | |||
371 | TheSema->GatherGlobalCodeCompletions(*CachedCompletionAllocator, | |||
372 | CCTUInfo, Results); | |||
373 | ||||
374 | // Translate global code completions into cached completions. | |||
375 | llvm::DenseMap<CanQualType, unsigned> CompletionTypes; | |||
376 | CodeCompletionContext CCContext(CodeCompletionContext::CCC_TopLevel); | |||
377 | ||||
378 | for (auto &R : Results) { | |||
379 | switch (R.Kind) { | |||
380 | case Result::RK_Declaration: { | |||
381 | bool IsNestedNameSpecifier = false; | |||
382 | CachedCodeCompletionResult CachedResult; | |||
383 | CachedResult.Completion = R.CreateCodeCompletionString( | |||
384 | *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo, | |||
385 | IncludeBriefCommentsInCodeCompletion); | |||
386 | CachedResult.ShowInContexts = getDeclShowContexts( | |||
387 | R.Declaration, Ctx->getLangOpts(), IsNestedNameSpecifier); | |||
388 | CachedResult.Priority = R.Priority; | |||
389 | CachedResult.Kind = R.CursorKind; | |||
390 | CachedResult.Availability = R.Availability; | |||
391 | ||||
392 | // Keep track of the type of this completion in an ASTContext-agnostic | |||
393 | // way. | |||
394 | QualType UsageType = getDeclUsageType(*Ctx, R.Declaration); | |||
395 | if (UsageType.isNull()) { | |||
396 | CachedResult.TypeClass = STC_Void; | |||
397 | CachedResult.Type = 0; | |||
398 | } else { | |||
399 | CanQualType CanUsageType | |||
400 | = Ctx->getCanonicalType(UsageType.getUnqualifiedType()); | |||
401 | CachedResult.TypeClass = getSimplifiedTypeClass(CanUsageType); | |||
402 | ||||
403 | // Determine whether we have already seen this type. If so, we save | |||
404 | // ourselves the work of formatting the type string by using the | |||
405 | // temporary, CanQualType-based hash table to find the associated value. | |||
406 | unsigned &TypeValue = CompletionTypes[CanUsageType]; | |||
407 | if (TypeValue == 0) { | |||
408 | TypeValue = CompletionTypes.size(); | |||
409 | CachedCompletionTypes[QualType(CanUsageType).getAsString()] | |||
410 | = TypeValue; | |||
411 | } | |||
412 | ||||
413 | CachedResult.Type = TypeValue; | |||
414 | } | |||
415 | ||||
416 | CachedCompletionResults.push_back(CachedResult); | |||
417 | ||||
418 | /// Handle nested-name-specifiers in C++. | |||
419 | if (TheSema->Context.getLangOpts().CPlusPlus && IsNestedNameSpecifier && | |||
420 | !R.StartsNestedNameSpecifier) { | |||
421 | // The contexts in which a nested-name-specifier can appear in C++. | |||
422 | uint64_t NNSContexts | |||
423 | = (1LL << CodeCompletionContext::CCC_TopLevel) | |||
424 | | (1LL << CodeCompletionContext::CCC_ObjCIvarList) | |||
425 | | (1LL << CodeCompletionContext::CCC_ClassStructUnion) | |||
426 | | (1LL << CodeCompletionContext::CCC_Statement) | |||
427 | | (1LL << CodeCompletionContext::CCC_Expression) | |||
428 | | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver) | |||
429 | | (1LL << CodeCompletionContext::CCC_EnumTag) | |||
430 | | (1LL << CodeCompletionContext::CCC_UnionTag) | |||
431 | | (1LL << CodeCompletionContext::CCC_ClassOrStructTag) | |||
432 | | (1LL << CodeCompletionContext::CCC_Type) | |||
433 | | (1LL << CodeCompletionContext::CCC_PotentiallyQualifiedName) | |||
434 | | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression); | |||
435 | ||||
436 | if (isa<NamespaceDecl>(R.Declaration) || | |||
437 | isa<NamespaceAliasDecl>(R.Declaration)) | |||
438 | NNSContexts |= (1LL << CodeCompletionContext::CCC_Namespace); | |||
439 | ||||
440 | if (unsigned RemainingContexts | |||
441 | = NNSContexts & ~CachedResult.ShowInContexts) { | |||
442 | // If there any contexts where this completion can be a | |||
443 | // nested-name-specifier but isn't already an option, create a | |||
444 | // nested-name-specifier completion. | |||
445 | R.StartsNestedNameSpecifier = true; | |||
446 | CachedResult.Completion = R.CreateCodeCompletionString( | |||
447 | *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo, | |||
448 | IncludeBriefCommentsInCodeCompletion); | |||
449 | CachedResult.ShowInContexts = RemainingContexts; | |||
450 | CachedResult.Priority = CCP_NestedNameSpecifier; | |||
451 | CachedResult.TypeClass = STC_Void; | |||
452 | CachedResult.Type = 0; | |||
453 | CachedCompletionResults.push_back(CachedResult); | |||
454 | } | |||
455 | } | |||
456 | break; | |||
457 | } | |||
458 | ||||
459 | case Result::RK_Keyword: | |||
460 | case Result::RK_Pattern: | |||
461 | // Ignore keywords and patterns; we don't care, since they are so | |||
462 | // easily regenerated. | |||
463 | break; | |||
464 | ||||
465 | case Result::RK_Macro: { | |||
466 | CachedCodeCompletionResult CachedResult; | |||
467 | CachedResult.Completion = R.CreateCodeCompletionString( | |||
468 | *TheSema, CCContext, *CachedCompletionAllocator, CCTUInfo, | |||
469 | IncludeBriefCommentsInCodeCompletion); | |||
470 | CachedResult.ShowInContexts | |||
471 | = (1LL << CodeCompletionContext::CCC_TopLevel) | |||
472 | | (1LL << CodeCompletionContext::CCC_ObjCInterface) | |||
473 | | (1LL << CodeCompletionContext::CCC_ObjCImplementation) | |||
474 | | (1LL << CodeCompletionContext::CCC_ObjCIvarList) | |||
475 | | (1LL << CodeCompletionContext::CCC_ClassStructUnion) | |||
476 | | (1LL << CodeCompletionContext::CCC_Statement) | |||
477 | | (1LL << CodeCompletionContext::CCC_Expression) | |||
478 | | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver) | |||
479 | | (1LL << CodeCompletionContext::CCC_MacroNameUse) | |||
480 | | (1LL << CodeCompletionContext::CCC_PreprocessorExpression) | |||
481 | | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression) | |||
482 | | (1LL << CodeCompletionContext::CCC_OtherWithMacros); | |||
483 | ||||
484 | CachedResult.Priority = R.Priority; | |||
485 | CachedResult.Kind = R.CursorKind; | |||
486 | CachedResult.Availability = R.Availability; | |||
487 | CachedResult.TypeClass = STC_Void; | |||
488 | CachedResult.Type = 0; | |||
489 | CachedCompletionResults.push_back(CachedResult); | |||
490 | break; | |||
491 | } | |||
492 | } | |||
493 | } | |||
494 | ||||
495 | // Save the current top-level hash value. | |||
496 | CompletionCacheTopLevelHashValue = CurrentTopLevelHashValue; | |||
497 | } | |||
498 | ||||
499 | void ASTUnit::ClearCachedCompletionResults() { | |||
500 | CachedCompletionResults.clear(); | |||
501 | CachedCompletionTypes.clear(); | |||
502 | CachedCompletionAllocator = nullptr; | |||
503 | } | |||
504 | ||||
505 | namespace { | |||
506 | ||||
507 | /// \brief Gathers information from ASTReader that will be used to initialize | |||
508 | /// a Preprocessor. | |||
509 | class ASTInfoCollector : public ASTReaderListener { | |||
510 | Preprocessor &PP; | |||
511 | ASTContext *Context; | |||
512 | HeaderSearchOptions &HSOpts; | |||
513 | PreprocessorOptions &PPOpts; | |||
514 | LangOptions &LangOpt; | |||
515 | std::shared_ptr<TargetOptions> &TargetOpts; | |||
516 | IntrusiveRefCntPtr<TargetInfo> &Target; | |||
517 | unsigned &Counter; | |||
518 | bool InitializedLanguage = false; | |||
519 | ||||
520 | public: | |||
521 | ASTInfoCollector(Preprocessor &PP, ASTContext *Context, | |||
522 | HeaderSearchOptions &HSOpts, PreprocessorOptions &PPOpts, | |||
523 | LangOptions &LangOpt, | |||
524 | std::shared_ptr<TargetOptions> &TargetOpts, | |||
525 | IntrusiveRefCntPtr<TargetInfo> &Target, unsigned &Counter) | |||
526 | : PP(PP), Context(Context), HSOpts(HSOpts), PPOpts(PPOpts), | |||
527 | LangOpt(LangOpt), TargetOpts(TargetOpts), Target(Target), | |||
528 | Counter(Counter) {} | |||
529 | ||||
530 | bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, | |||
531 | bool AllowCompatibleDifferences) override { | |||
532 | if (InitializedLanguage) | |||
533 | return false; | |||
534 | ||||
535 | LangOpt = LangOpts; | |||
536 | InitializedLanguage = true; | |||
537 | ||||
538 | updated(); | |||
539 | return false; | |||
540 | } | |||
541 | ||||
542 | bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, | |||
543 | StringRef SpecificModuleCachePath, | |||
544 | bool Complain) override { | |||
545 | this->HSOpts = HSOpts; | |||
546 | return false; | |||
547 | } | |||
548 | ||||
549 | bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain, | |||
550 | std::string &SuggestedPredefines) override { | |||
551 | this->PPOpts = PPOpts; | |||
552 | return false; | |||
553 | } | |||
554 | ||||
555 | bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain, | |||
556 | bool AllowCompatibleDifferences) override { | |||
557 | // If we've already initialized the target, don't do it again. | |||
558 | if (Target) | |||
559 | return false; | |||
560 | ||||
561 | this->TargetOpts = std::make_shared<TargetOptions>(TargetOpts); | |||
562 | Target = | |||
563 | TargetInfo::CreateTargetInfo(PP.getDiagnostics(), this->TargetOpts); | |||
564 | ||||
565 | updated(); | |||
566 | return false; | |||
567 | } | |||
568 | ||||
569 | void ReadCounter(const serialization::ModuleFile &M, | |||
570 | unsigned Value) override { | |||
571 | Counter = Value; | |||
572 | } | |||
573 | ||||
574 | private: | |||
575 | void updated() { | |||
576 | if (!Target || !InitializedLanguage) | |||
577 | return; | |||
578 | ||||
579 | // Inform the target of the language options. | |||
580 | // | |||
581 | // FIXME: We shouldn't need to do this, the target should be immutable once | |||
582 | // created. This complexity should be lifted elsewhere. | |||
583 | Target->adjust(LangOpt); | |||
584 | ||||
585 | // Initialize the preprocessor. | |||
586 | PP.Initialize(*Target); | |||
587 | ||||
588 | if (!Context) | |||
589 | return; | |||
590 | ||||
591 | // Initialize the ASTContext | |||
592 | Context->InitBuiltinTypes(*Target); | |||
593 | ||||
594 | // Adjust printing policy based on language options. | |||
595 | Context->setPrintingPolicy(PrintingPolicy(LangOpt)); | |||
596 | ||||
597 | // We didn't have access to the comment options when the ASTContext was | |||
598 | // constructed, so register them now. | |||
599 | Context->getCommentCommandTraits().registerCommentOptions( | |||
600 | LangOpt.CommentOpts); | |||
601 | } | |||
602 | }; | |||
603 | ||||
604 | /// \brief Diagnostic consumer that saves each diagnostic it is given. | |||
605 | class StoredDiagnosticConsumer : public DiagnosticConsumer { | |||
606 | SmallVectorImpl<StoredDiagnostic> *StoredDiags; | |||
607 | SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags; | |||
608 | const LangOptions *LangOpts = nullptr; | |||
609 | SourceManager *SourceMgr = nullptr; | |||
610 | ||||
611 | public: | |||
612 | StoredDiagnosticConsumer( | |||
613 | SmallVectorImpl<StoredDiagnostic> *StoredDiags, | |||
614 | SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags) | |||
615 | : StoredDiags(StoredDiags), StandaloneDiags(StandaloneDiags) { | |||
616 | assert((StoredDiags || StandaloneDiags) &&(static_cast <bool> ((StoredDiags || StandaloneDiags) && "No output collections were passed to StoredDiagnosticConsumer." ) ? void (0) : __assert_fail ("(StoredDiags || StandaloneDiags) && \"No output collections were passed to StoredDiagnosticConsumer.\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 617, __extension__ __PRETTY_FUNCTION__)) | |||
617 | "No output collections were passed to StoredDiagnosticConsumer.")(static_cast <bool> ((StoredDiags || StandaloneDiags) && "No output collections were passed to StoredDiagnosticConsumer." ) ? void (0) : __assert_fail ("(StoredDiags || StandaloneDiags) && \"No output collections were passed to StoredDiagnosticConsumer.\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 617, __extension__ __PRETTY_FUNCTION__)); | |||
618 | } | |||
619 | ||||
620 | void BeginSourceFile(const LangOptions &LangOpts, | |||
621 | const Preprocessor *PP = nullptr) override { | |||
622 | this->LangOpts = &LangOpts; | |||
623 | if (PP) | |||
624 | SourceMgr = &PP->getSourceManager(); | |||
625 | } | |||
626 | ||||
627 | void HandleDiagnostic(DiagnosticsEngine::Level Level, | |||
628 | const Diagnostic &Info) override; | |||
629 | }; | |||
630 | ||||
631 | /// \brief RAII object that optionally captures diagnostics, if | |||
632 | /// there is no diagnostic client to capture them already. | |||
633 | class CaptureDroppedDiagnostics { | |||
634 | DiagnosticsEngine &Diags; | |||
635 | StoredDiagnosticConsumer Client; | |||
636 | DiagnosticConsumer *PreviousClient = nullptr; | |||
637 | std::unique_ptr<DiagnosticConsumer> OwningPreviousClient; | |||
638 | ||||
639 | public: | |||
640 | CaptureDroppedDiagnostics( | |||
641 | bool RequestCapture, DiagnosticsEngine &Diags, | |||
642 | SmallVectorImpl<StoredDiagnostic> *StoredDiags, | |||
643 | SmallVectorImpl<ASTUnit::StandaloneDiagnostic> *StandaloneDiags) | |||
644 | : Diags(Diags), Client(StoredDiags, StandaloneDiags) { | |||
645 | if (RequestCapture || Diags.getClient() == nullptr) { | |||
646 | OwningPreviousClient = Diags.takeClient(); | |||
647 | PreviousClient = Diags.getClient(); | |||
648 | Diags.setClient(&Client, false); | |||
649 | } | |||
650 | } | |||
651 | ||||
652 | ~CaptureDroppedDiagnostics() { | |||
653 | if (Diags.getClient() == &Client) | |||
654 | Diags.setClient(PreviousClient, !!OwningPreviousClient.release()); | |||
655 | } | |||
656 | }; | |||
657 | ||||
658 | } // namespace | |||
659 | ||||
660 | static ASTUnit::StandaloneDiagnostic | |||
661 | makeStandaloneDiagnostic(const LangOptions &LangOpts, | |||
662 | const StoredDiagnostic &InDiag); | |||
663 | ||||
664 | void StoredDiagnosticConsumer::HandleDiagnostic(DiagnosticsEngine::Level Level, | |||
665 | const Diagnostic &Info) { | |||
666 | // Default implementation (Warnings/errors count). | |||
667 | DiagnosticConsumer::HandleDiagnostic(Level, Info); | |||
668 | ||||
669 | // Only record the diagnostic if it's part of the source manager we know | |||
670 | // about. This effectively drops diagnostics from modules we're building. | |||
671 | // FIXME: In the long run, ee don't want to drop source managers from modules. | |||
672 | if (!Info.hasSourceManager() || &Info.getSourceManager() == SourceMgr) { | |||
673 | StoredDiagnostic *ResultDiag = nullptr; | |||
674 | if (StoredDiags) { | |||
675 | StoredDiags->emplace_back(Level, Info); | |||
676 | ResultDiag = &StoredDiags->back(); | |||
677 | } | |||
678 | ||||
679 | if (StandaloneDiags) { | |||
680 | llvm::Optional<StoredDiagnostic> StoredDiag = None; | |||
681 | if (!ResultDiag) { | |||
682 | StoredDiag.emplace(Level, Info); | |||
683 | ResultDiag = StoredDiag.getPointer(); | |||
684 | } | |||
685 | StandaloneDiags->push_back( | |||
686 | makeStandaloneDiagnostic(*LangOpts, *ResultDiag)); | |||
687 | } | |||
688 | } | |||
689 | } | |||
690 | ||||
691 | IntrusiveRefCntPtr<ASTReader> ASTUnit::getASTReader() const { | |||
692 | return Reader; | |||
693 | } | |||
694 | ||||
695 | ASTMutationListener *ASTUnit::getASTMutationListener() { | |||
696 | if (WriterData) | |||
697 | return &WriterData->Writer; | |||
698 | return nullptr; | |||
699 | } | |||
700 | ||||
701 | ASTDeserializationListener *ASTUnit::getDeserializationListener() { | |||
702 | if (WriterData) | |||
703 | return &WriterData->Writer; | |||
704 | return nullptr; | |||
705 | } | |||
706 | ||||
707 | std::unique_ptr<llvm::MemoryBuffer> | |||
708 | ASTUnit::getBufferForFile(StringRef Filename, std::string *ErrorStr) { | |||
709 | assert(FileMgr)(static_cast <bool> (FileMgr) ? void (0) : __assert_fail ("FileMgr", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 709, __extension__ __PRETTY_FUNCTION__)); | |||
710 | auto Buffer = FileMgr->getBufferForFile(Filename); | |||
711 | if (Buffer) | |||
712 | return std::move(*Buffer); | |||
713 | if (ErrorStr) | |||
714 | *ErrorStr = Buffer.getError().message(); | |||
715 | return nullptr; | |||
716 | } | |||
717 | ||||
718 | /// \brief Configure the diagnostics object for use with ASTUnit. | |||
719 | void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags, | |||
720 | ASTUnit &AST, bool CaptureDiagnostics) { | |||
721 | assert(Diags.get() && "no DiagnosticsEngine was provided")(static_cast <bool> (Diags.get() && "no DiagnosticsEngine was provided" ) ? void (0) : __assert_fail ("Diags.get() && \"no DiagnosticsEngine was provided\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 721, __extension__ __PRETTY_FUNCTION__)); | |||
722 | if (CaptureDiagnostics) | |||
723 | Diags->setClient(new StoredDiagnosticConsumer(&AST.StoredDiagnostics, nullptr)); | |||
724 | } | |||
725 | ||||
726 | std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile( | |||
727 | const std::string &Filename, const PCHContainerReader &PCHContainerRdr, | |||
728 | WhatToLoad ToLoad, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, | |||
729 | const FileSystemOptions &FileSystemOpts, bool UseDebugInfo, | |||
730 | bool OnlyLocalDecls, ArrayRef<RemappedFile> RemappedFiles, | |||
731 | bool CaptureDiagnostics, bool AllowPCHWithCompilerErrors, | |||
732 | bool UserFilesAreVolatile) { | |||
733 | std::unique_ptr<ASTUnit> AST(new ASTUnit(true)); | |||
734 | ||||
735 | // Recover resources if we crash before exiting this method. | |||
736 | llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> | |||
737 | ASTUnitCleanup(AST.get()); | |||
738 | llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, | |||
739 | llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>> | |||
740 | DiagCleanup(Diags.get()); | |||
741 | ||||
742 | ConfigureDiags(Diags, *AST, CaptureDiagnostics); | |||
743 | ||||
744 | AST->LangOpts = std::make_shared<LangOptions>(); | |||
745 | AST->OnlyLocalDecls = OnlyLocalDecls; | |||
746 | AST->CaptureDiagnostics = CaptureDiagnostics; | |||
747 | AST->Diagnostics = Diags; | |||
748 | IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem(); | |||
749 | AST->FileMgr = new FileManager(FileSystemOpts, VFS); | |||
750 | AST->UserFilesAreVolatile = UserFilesAreVolatile; | |||
751 | AST->SourceMgr = new SourceManager(AST->getDiagnostics(), | |||
752 | AST->getFileManager(), | |||
753 | UserFilesAreVolatile); | |||
754 | AST->PCMCache = new MemoryBufferCache; | |||
755 | AST->HSOpts = std::make_shared<HeaderSearchOptions>(); | |||
756 | AST->HSOpts->ModuleFormat = PCHContainerRdr.getFormat(); | |||
757 | AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts, | |||
758 | AST->getSourceManager(), | |||
759 | AST->getDiagnostics(), | |||
760 | AST->getLangOpts(), | |||
761 | /*Target=*/nullptr)); | |||
762 | AST->PPOpts = std::make_shared<PreprocessorOptions>(); | |||
763 | ||||
764 | for (const auto &RemappedFile : RemappedFiles) | |||
765 | AST->PPOpts->addRemappedFile(RemappedFile.first, RemappedFile.second); | |||
766 | ||||
767 | // Gather Info for preprocessor construction later on. | |||
768 | ||||
769 | HeaderSearch &HeaderInfo = *AST->HeaderInfo; | |||
770 | unsigned Counter; | |||
771 | ||||
772 | AST->PP = std::make_shared<Preprocessor>( | |||
773 | AST->PPOpts, AST->getDiagnostics(), *AST->LangOpts, | |||
774 | AST->getSourceManager(), *AST->PCMCache, HeaderInfo, AST->ModuleLoader, | |||
775 | /*IILookup=*/nullptr, | |||
776 | /*OwnsHeaderSearch=*/false); | |||
777 | Preprocessor &PP = *AST->PP; | |||
778 | ||||
779 | if (ToLoad >= LoadASTOnly) | |||
780 | AST->Ctx = new ASTContext(*AST->LangOpts, AST->getSourceManager(), | |||
781 | PP.getIdentifierTable(), PP.getSelectorTable(), | |||
782 | PP.getBuiltinInfo()); | |||
783 | ||||
784 | bool disableValid = false; | |||
785 | if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION")) | |||
786 | disableValid = true; | |||
787 | AST->Reader = new ASTReader(PP, AST->Ctx.get(), PCHContainerRdr, {}, | |||
788 | /*isysroot=*/"", | |||
789 | /*DisableValidation=*/disableValid, | |||
790 | AllowPCHWithCompilerErrors); | |||
791 | ||||
792 | AST->Reader->setListener(llvm::make_unique<ASTInfoCollector>( | |||
793 | *AST->PP, AST->Ctx.get(), *AST->HSOpts, *AST->PPOpts, *AST->LangOpts, | |||
794 | AST->TargetOpts, AST->Target, Counter)); | |||
795 | ||||
796 | // Attach the AST reader to the AST context as an external AST | |||
797 | // source, so that declarations will be deserialized from the | |||
798 | // AST file as needed. | |||
799 | // We need the external source to be set up before we read the AST, because | |||
800 | // eagerly-deserialized declarations may use it. | |||
801 | if (AST->Ctx) | |||
802 | AST->Ctx->setExternalSource(AST->Reader); | |||
803 | ||||
804 | switch (AST->Reader->ReadAST(Filename, serialization::MK_MainFile, | |||
805 | SourceLocation(), ASTReader::ARR_None)) { | |||
806 | case ASTReader::Success: | |||
807 | break; | |||
808 | ||||
809 | case ASTReader::Failure: | |||
810 | case ASTReader::Missing: | |||
811 | case ASTReader::OutOfDate: | |||
812 | case ASTReader::VersionMismatch: | |||
813 | case ASTReader::ConfigurationMismatch: | |||
814 | case ASTReader::HadErrors: | |||
815 | AST->getDiagnostics().Report(diag::err_fe_unable_to_load_pch); | |||
816 | return nullptr; | |||
817 | } | |||
818 | ||||
819 | AST->OriginalSourceFile = AST->Reader->getOriginalSourceFile(); | |||
820 | ||||
821 | PP.setCounterValue(Counter); | |||
822 | ||||
823 | // Create an AST consumer, even though it isn't used. | |||
824 | if (ToLoad >= LoadASTOnly) | |||
825 | AST->Consumer.reset(new ASTConsumer); | |||
826 | ||||
827 | // Create a semantic analysis object and tell the AST reader about it. | |||
828 | if (ToLoad >= LoadEverything) { | |||
829 | AST->TheSema.reset(new Sema(PP, *AST->Ctx, *AST->Consumer)); | |||
830 | AST->TheSema->Initialize(); | |||
831 | AST->Reader->InitializeSema(*AST->TheSema); | |||
832 | } | |||
833 | ||||
834 | // Tell the diagnostic client that we have started a source file. | |||
835 | AST->getDiagnostics().getClient()->BeginSourceFile(PP.getLangOpts(), &PP); | |||
836 | ||||
837 | return AST; | |||
838 | } | |||
839 | ||||
840 | /// \brief Add the given macro to the hash of all top-level entities. | |||
841 | static void AddDefinedMacroToHash(const Token &MacroNameTok, unsigned &Hash) { | |||
842 | Hash = llvm::djbHash(MacroNameTok.getIdentifierInfo()->getName(), Hash); | |||
843 | } | |||
844 | ||||
845 | namespace { | |||
846 | ||||
847 | /// \brief Preprocessor callback class that updates a hash value with the names | |||
848 | /// of all macros that have been defined by the translation unit. | |||
849 | class MacroDefinitionTrackerPPCallbacks : public PPCallbacks { | |||
850 | unsigned &Hash; | |||
851 | ||||
852 | public: | |||
853 | explicit MacroDefinitionTrackerPPCallbacks(unsigned &Hash) : Hash(Hash) {} | |||
854 | ||||
855 | void MacroDefined(const Token &MacroNameTok, | |||
856 | const MacroDirective *MD) override { | |||
857 | AddDefinedMacroToHash(MacroNameTok, Hash); | |||
858 | } | |||
859 | }; | |||
860 | ||||
861 | } // namespace | |||
862 | ||||
863 | /// \brief Add the given declaration to the hash of all top-level entities. | |||
864 | static void AddTopLevelDeclarationToHash(Decl *D, unsigned &Hash) { | |||
865 | if (!D) | |||
866 | return; | |||
867 | ||||
868 | DeclContext *DC = D->getDeclContext(); | |||
869 | if (!DC) | |||
870 | return; | |||
871 | ||||
872 | if (!(DC->isTranslationUnit() || DC->getLookupParent()->isTranslationUnit())) | |||
873 | return; | |||
874 | ||||
875 | if (const auto *ND = dyn_cast<NamedDecl>(D)) { | |||
876 | if (const auto *EnumD = dyn_cast<EnumDecl>(D)) { | |||
877 | // For an unscoped enum include the enumerators in the hash since they | |||
878 | // enter the top-level namespace. | |||
879 | if (!EnumD->isScoped()) { | |||
880 | for (const auto *EI : EnumD->enumerators()) { | |||
881 | if (EI->getIdentifier()) | |||
882 | Hash = llvm::djbHash(EI->getIdentifier()->getName(), Hash); | |||
883 | } | |||
884 | } | |||
885 | } | |||
886 | ||||
887 | if (ND->getIdentifier()) | |||
888 | Hash = llvm::djbHash(ND->getIdentifier()->getName(), Hash); | |||
889 | else if (DeclarationName Name = ND->getDeclName()) { | |||
890 | std::string NameStr = Name.getAsString(); | |||
891 | Hash = llvm::djbHash(NameStr, Hash); | |||
892 | } | |||
893 | return; | |||
894 | } | |||
895 | ||||
896 | if (const auto *ImportD = dyn_cast<ImportDecl>(D)) { | |||
897 | if (const Module *Mod = ImportD->getImportedModule()) { | |||
898 | std::string ModName = Mod->getFullModuleName(); | |||
899 | Hash = llvm::djbHash(ModName, Hash); | |||
900 | } | |||
901 | return; | |||
902 | } | |||
903 | } | |||
904 | ||||
905 | namespace { | |||
906 | ||||
907 | class TopLevelDeclTrackerConsumer : public ASTConsumer { | |||
908 | ASTUnit &Unit; | |||
909 | unsigned &Hash; | |||
910 | ||||
911 | public: | |||
912 | TopLevelDeclTrackerConsumer(ASTUnit &_Unit, unsigned &Hash) | |||
913 | : Unit(_Unit), Hash(Hash) { | |||
914 | Hash = 0; | |||
915 | } | |||
916 | ||||
917 | void handleTopLevelDecl(Decl *D) { | |||
918 | if (!D) | |||
919 | return; | |||
920 | ||||
921 | // FIXME: Currently ObjC method declarations are incorrectly being | |||
922 | // reported as top-level declarations, even though their DeclContext | |||
923 | // is the containing ObjC @interface/@implementation. This is a | |||
924 | // fundamental problem in the parser right now. | |||
925 | if (isa<ObjCMethodDecl>(D)) | |||
926 | return; | |||
927 | ||||
928 | AddTopLevelDeclarationToHash(D, Hash); | |||
929 | Unit.addTopLevelDecl(D); | |||
930 | ||||
931 | handleFileLevelDecl(D); | |||
932 | } | |||
933 | ||||
934 | void handleFileLevelDecl(Decl *D) { | |||
935 | Unit.addFileLevelDecl(D); | |||
936 | if (auto *NSD = dyn_cast<NamespaceDecl>(D)) { | |||
937 | for (auto *I : NSD->decls()) | |||
938 | handleFileLevelDecl(I); | |||
939 | } | |||
940 | } | |||
941 | ||||
942 | bool HandleTopLevelDecl(DeclGroupRef D) override { | |||
943 | for (auto *TopLevelDecl : D) | |||
944 | handleTopLevelDecl(TopLevelDecl); | |||
945 | return true; | |||
946 | } | |||
947 | ||||
948 | // We're not interested in "interesting" decls. | |||
949 | void HandleInterestingDecl(DeclGroupRef) override {} | |||
950 | ||||
951 | void HandleTopLevelDeclInObjCContainer(DeclGroupRef D) override { | |||
952 | for (auto *TopLevelDecl : D) | |||
953 | handleTopLevelDecl(TopLevelDecl); | |||
954 | } | |||
955 | ||||
956 | ASTMutationListener *GetASTMutationListener() override { | |||
957 | return Unit.getASTMutationListener(); | |||
958 | } | |||
959 | ||||
960 | ASTDeserializationListener *GetASTDeserializationListener() override { | |||
961 | return Unit.getDeserializationListener(); | |||
962 | } | |||
963 | }; | |||
964 | ||||
965 | class TopLevelDeclTrackerAction : public ASTFrontendAction { | |||
966 | public: | |||
967 | ASTUnit &Unit; | |||
968 | ||||
969 | std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, | |||
970 | StringRef InFile) override { | |||
971 | CI.getPreprocessor().addPPCallbacks( | |||
972 | llvm::make_unique<MacroDefinitionTrackerPPCallbacks>( | |||
973 | Unit.getCurrentTopLevelHashValue())); | |||
974 | return llvm::make_unique<TopLevelDeclTrackerConsumer>( | |||
975 | Unit, Unit.getCurrentTopLevelHashValue()); | |||
976 | } | |||
977 | ||||
978 | public: | |||
979 | TopLevelDeclTrackerAction(ASTUnit &_Unit) : Unit(_Unit) {} | |||
980 | ||||
981 | bool hasCodeCompletionSupport() const override { return false; } | |||
982 | ||||
983 | TranslationUnitKind getTranslationUnitKind() override { | |||
984 | return Unit.getTranslationUnitKind(); | |||
985 | } | |||
986 | }; | |||
987 | ||||
988 | class ASTUnitPreambleCallbacks : public PreambleCallbacks { | |||
989 | public: | |||
990 | unsigned getHash() const { return Hash; } | |||
991 | ||||
992 | std::vector<Decl *> takeTopLevelDecls() { return std::move(TopLevelDecls); } | |||
993 | ||||
994 | std::vector<serialization::DeclID> takeTopLevelDeclIDs() { | |||
995 | return std::move(TopLevelDeclIDs); | |||
996 | } | |||
997 | ||||
998 | void AfterPCHEmitted(ASTWriter &Writer) override { | |||
999 | TopLevelDeclIDs.reserve(TopLevelDecls.size()); | |||
1000 | for (const auto *D : TopLevelDecls) { | |||
1001 | // Invalid top-level decls may not have been serialized. | |||
1002 | if (D->isInvalidDecl()) | |||
1003 | continue; | |||
1004 | TopLevelDeclIDs.push_back(Writer.getDeclID(D)); | |||
1005 | } | |||
1006 | } | |||
1007 | ||||
1008 | void HandleTopLevelDecl(DeclGroupRef DG) override { | |||
1009 | for (auto *D : DG) { | |||
1010 | // FIXME: Currently ObjC method declarations are incorrectly being | |||
1011 | // reported as top-level declarations, even though their DeclContext | |||
1012 | // is the containing ObjC @interface/@implementation. This is a | |||
1013 | // fundamental problem in the parser right now. | |||
1014 | if (isa<ObjCMethodDecl>(D)) | |||
1015 | continue; | |||
1016 | AddTopLevelDeclarationToHash(D, Hash); | |||
1017 | TopLevelDecls.push_back(D); | |||
1018 | } | |||
1019 | } | |||
1020 | ||||
1021 | std::unique_ptr<PPCallbacks> createPPCallbacks() override { | |||
1022 | return llvm::make_unique<MacroDefinitionTrackerPPCallbacks>(Hash); | |||
1023 | } | |||
1024 | ||||
1025 | private: | |||
1026 | unsigned Hash = 0; | |||
1027 | std::vector<Decl *> TopLevelDecls; | |||
1028 | std::vector<serialization::DeclID> TopLevelDeclIDs; | |||
1029 | llvm::SmallVector<ASTUnit::StandaloneDiagnostic, 4> PreambleDiags; | |||
1030 | }; | |||
1031 | ||||
1032 | } // namespace | |||
1033 | ||||
1034 | static bool isNonDriverDiag(const StoredDiagnostic &StoredDiag) { | |||
1035 | return StoredDiag.getLocation().isValid(); | |||
1036 | } | |||
1037 | ||||
1038 | static void | |||
1039 | checkAndRemoveNonDriverDiags(SmallVectorImpl<StoredDiagnostic> &StoredDiags) { | |||
1040 | // Get rid of stored diagnostics except the ones from the driver which do not | |||
1041 | // have a source location. | |||
1042 | StoredDiags.erase( | |||
1043 | std::remove_if(StoredDiags.begin(), StoredDiags.end(), isNonDriverDiag), | |||
1044 | StoredDiags.end()); | |||
1045 | } | |||
1046 | ||||
1047 | static void checkAndSanitizeDiags(SmallVectorImpl<StoredDiagnostic> & | |||
1048 | StoredDiagnostics, | |||
1049 | SourceManager &SM) { | |||
1050 | // The stored diagnostic has the old source manager in it; update | |||
1051 | // the locations to refer into the new source manager. Since we've | |||
1052 | // been careful to make sure that the source manager's state | |||
1053 | // before and after are identical, so that we can reuse the source | |||
1054 | // location itself. | |||
1055 | for (auto &SD : StoredDiagnostics) { | |||
1056 | if (SD.getLocation().isValid()) { | |||
1057 | FullSourceLoc Loc(SD.getLocation(), SM); | |||
1058 | SD.setLocation(Loc); | |||
1059 | } | |||
1060 | } | |||
1061 | } | |||
1062 | ||||
1063 | /// Parse the source file into a translation unit using the given compiler | |||
1064 | /// invocation, replacing the current translation unit. | |||
1065 | /// | |||
1066 | /// \returns True if a failure occurred that causes the ASTUnit not to | |||
1067 | /// contain any translation-unit information, false otherwise. | |||
1068 | bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, | |||
1069 | std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer, | |||
1070 | IntrusiveRefCntPtr<vfs::FileSystem> VFS) { | |||
1071 | if (!Invocation) | |||
1072 | return true; | |||
1073 | ||||
1074 | auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation); | |||
1075 | if (OverrideMainBuffer) { | |||
1076 | assert(Preamble &&(static_cast <bool> (Preamble && "No preamble was built, but OverrideMainBuffer is not null" ) ? void (0) : __assert_fail ("Preamble && \"No preamble was built, but OverrideMainBuffer is not null\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1077, __extension__ __PRETTY_FUNCTION__)) | |||
1077 | "No preamble was built, but OverrideMainBuffer is not null")(static_cast <bool> (Preamble && "No preamble was built, but OverrideMainBuffer is not null" ) ? void (0) : __assert_fail ("Preamble && \"No preamble was built, but OverrideMainBuffer is not null\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1077, __extension__ __PRETTY_FUNCTION__)); | |||
1078 | IntrusiveRefCntPtr<vfs::FileSystem> OldVFS = VFS; | |||
1079 | Preamble->AddImplicitPreamble(*CCInvocation, VFS, OverrideMainBuffer.get()); | |||
1080 | if (OldVFS != VFS && FileMgr) { | |||
1081 | assert(OldVFS == FileMgr->getVirtualFileSystem() &&(static_cast <bool> (OldVFS == FileMgr->getVirtualFileSystem () && "VFS passed to Parse and VFS in FileMgr are different" ) ? void (0) : __assert_fail ("OldVFS == FileMgr->getVirtualFileSystem() && \"VFS passed to Parse and VFS in FileMgr are different\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1082, __extension__ __PRETTY_FUNCTION__)) | |||
1082 | "VFS passed to Parse and VFS in FileMgr are different")(static_cast <bool> (OldVFS == FileMgr->getVirtualFileSystem () && "VFS passed to Parse and VFS in FileMgr are different" ) ? void (0) : __assert_fail ("OldVFS == FileMgr->getVirtualFileSystem() && \"VFS passed to Parse and VFS in FileMgr are different\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1082, __extension__ __PRETTY_FUNCTION__)); | |||
1083 | FileMgr = new FileManager(FileMgr->getFileSystemOpts(), VFS); | |||
1084 | } | |||
1085 | } | |||
1086 | ||||
1087 | // Create the compiler instance to use for building the AST. | |||
1088 | std::unique_ptr<CompilerInstance> Clang( | |||
1089 | new CompilerInstance(std::move(PCHContainerOps))); | |||
1090 | if (FileMgr && VFS) { | |||
1091 | assert(VFS == FileMgr->getVirtualFileSystem() &&(static_cast <bool> (VFS == FileMgr->getVirtualFileSystem () && "VFS passed to Parse and VFS in FileMgr are different" ) ? void (0) : __assert_fail ("VFS == FileMgr->getVirtualFileSystem() && \"VFS passed to Parse and VFS in FileMgr are different\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1092, __extension__ __PRETTY_FUNCTION__)) | |||
1092 | "VFS passed to Parse and VFS in FileMgr are different")(static_cast <bool> (VFS == FileMgr->getVirtualFileSystem () && "VFS passed to Parse and VFS in FileMgr are different" ) ? void (0) : __assert_fail ("VFS == FileMgr->getVirtualFileSystem() && \"VFS passed to Parse and VFS in FileMgr are different\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1092, __extension__ __PRETTY_FUNCTION__)); | |||
1093 | } else if (VFS) { | |||
1094 | Clang->setVirtualFileSystem(VFS); | |||
1095 | } | |||
1096 | ||||
1097 | // Recover resources if we crash before exiting this method. | |||
1098 | llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> | |||
1099 | CICleanup(Clang.get()); | |||
1100 | ||||
1101 | Clang->setInvocation(CCInvocation); | |||
1102 | OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile(); | |||
1103 | ||||
1104 | // Set up diagnostics, capturing any diagnostics that would | |||
1105 | // otherwise be dropped. | |||
1106 | Clang->setDiagnostics(&getDiagnostics()); | |||
1107 | ||||
1108 | // Create the target instance. | |||
1109 | Clang->setTarget(TargetInfo::CreateTargetInfo( | |||
1110 | Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); | |||
1111 | if (!Clang->hasTarget()) | |||
1112 | return true; | |||
1113 | ||||
1114 | // Inform the target of the language options. | |||
1115 | // | |||
1116 | // FIXME: We shouldn't need to do this, the target should be immutable once | |||
1117 | // created. This complexity should be lifted elsewhere. | |||
1118 | Clang->getTarget().adjust(Clang->getLangOpts()); | |||
1119 | ||||
1120 | assert(Clang->getFrontendOpts().Inputs.size() == 1 &&(static_cast <bool> (Clang->getFrontendOpts().Inputs .size() == 1 && "Invocation must have exactly one source file!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs.size() == 1 && \"Invocation must have exactly one source file!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1121, __extension__ __PRETTY_FUNCTION__)) | |||
1121 | "Invocation must have exactly one source file!")(static_cast <bool> (Clang->getFrontendOpts().Inputs .size() == 1 && "Invocation must have exactly one source file!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs.size() == 1 && \"Invocation must have exactly one source file!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1121, __extension__ __PRETTY_FUNCTION__)); | |||
1122 | assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getFormat() == InputKind::Source && "FIXME: AST inputs not yet supported here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == InputKind::Source && \"FIXME: AST inputs not yet supported here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1124, __extension__ __PRETTY_FUNCTION__)) | |||
1123 | InputKind::Source &&(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getFormat() == InputKind::Source && "FIXME: AST inputs not yet supported here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == InputKind::Source && \"FIXME: AST inputs not yet supported here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1124, __extension__ __PRETTY_FUNCTION__)) | |||
1124 | "FIXME: AST inputs not yet supported here!")(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getFormat() == InputKind::Source && "FIXME: AST inputs not yet supported here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == InputKind::Source && \"FIXME: AST inputs not yet supported here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1124, __extension__ __PRETTY_FUNCTION__)); | |||
1125 | assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getLanguage() != InputKind::LLVM_IR && "IR inputs not support here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != InputKind::LLVM_IR && \"IR inputs not support here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1127, __extension__ __PRETTY_FUNCTION__)) | |||
1126 | InputKind::LLVM_IR &&(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getLanguage() != InputKind::LLVM_IR && "IR inputs not support here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != InputKind::LLVM_IR && \"IR inputs not support here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1127, __extension__ __PRETTY_FUNCTION__)) | |||
1127 | "IR inputs not support here!")(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getLanguage() != InputKind::LLVM_IR && "IR inputs not support here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != InputKind::LLVM_IR && \"IR inputs not support here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1127, __extension__ __PRETTY_FUNCTION__)); | |||
1128 | ||||
1129 | // Configure the various subsystems. | |||
1130 | LangOpts = Clang->getInvocation().LangOpts; | |||
1131 | FileSystemOpts = Clang->getFileSystemOpts(); | |||
1132 | if (!FileMgr) { | |||
1133 | Clang->createFileManager(); | |||
1134 | FileMgr = &Clang->getFileManager(); | |||
1135 | } | |||
1136 | ||||
1137 | ResetForParse(); | |||
1138 | ||||
1139 | SourceMgr = new SourceManager(getDiagnostics(), *FileMgr, | |||
1140 | UserFilesAreVolatile); | |||
1141 | if (!OverrideMainBuffer) { | |||
1142 | checkAndRemoveNonDriverDiags(StoredDiagnostics); | |||
1143 | TopLevelDeclsInPreamble.clear(); | |||
1144 | } | |||
1145 | ||||
1146 | // Create a file manager object to provide access to and cache the filesystem. | |||
1147 | Clang->setFileManager(&getFileManager()); | |||
1148 | ||||
1149 | // Create the source manager. | |||
1150 | Clang->setSourceManager(&getSourceManager()); | |||
1151 | ||||
1152 | // If the main file has been overridden due to the use of a preamble, | |||
1153 | // make that override happen and introduce the preamble. | |||
1154 | if (OverrideMainBuffer) { | |||
1155 | // The stored diagnostic has the old source manager in it; update | |||
1156 | // the locations to refer into the new source manager. Since we've | |||
1157 | // been careful to make sure that the source manager's state | |||
1158 | // before and after are identical, so that we can reuse the source | |||
1159 | // location itself. | |||
1160 | checkAndSanitizeDiags(StoredDiagnostics, getSourceManager()); | |||
1161 | ||||
1162 | // Keep track of the override buffer; | |||
1163 | SavedMainFileBuffer = std::move(OverrideMainBuffer); | |||
1164 | } | |||
1165 | ||||
1166 | std::unique_ptr<TopLevelDeclTrackerAction> Act( | |||
1167 | new TopLevelDeclTrackerAction(*this)); | |||
1168 | ||||
1169 | // Recover resources if we crash before exiting this method. | |||
1170 | llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction> | |||
1171 | ActCleanup(Act.get()); | |||
1172 | ||||
1173 | if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) | |||
1174 | goto error; | |||
1175 | ||||
1176 | if (SavedMainFileBuffer) | |||
1177 | TranslateStoredDiagnostics(getFileManager(), getSourceManager(), | |||
1178 | PreambleDiagnostics, StoredDiagnostics); | |||
1179 | else | |||
1180 | PreambleSrcLocCache.clear(); | |||
1181 | ||||
1182 | if (!Act->Execute()) | |||
1183 | goto error; | |||
1184 | ||||
1185 | transferASTDataFromCompilerInstance(*Clang); | |||
1186 | ||||
1187 | Act->EndSourceFile(); | |||
1188 | ||||
1189 | FailedParseDiagnostics.clear(); | |||
1190 | ||||
1191 | return false; | |||
1192 | ||||
1193 | error: | |||
1194 | // Remove the overridden buffer we used for the preamble. | |||
1195 | SavedMainFileBuffer = nullptr; | |||
1196 | ||||
1197 | // Keep the ownership of the data in the ASTUnit because the client may | |||
1198 | // want to see the diagnostics. | |||
1199 | transferASTDataFromCompilerInstance(*Clang); | |||
1200 | FailedParseDiagnostics.swap(StoredDiagnostics); | |||
1201 | StoredDiagnostics.clear(); | |||
1202 | NumStoredDiagnosticsFromDriver = 0; | |||
1203 | return true; | |||
1204 | } | |||
1205 | ||||
1206 | static std::pair<unsigned, unsigned> | |||
1207 | makeStandaloneRange(CharSourceRange Range, const SourceManager &SM, | |||
1208 | const LangOptions &LangOpts) { | |||
1209 | CharSourceRange FileRange = Lexer::makeFileCharRange(Range, SM, LangOpts); | |||
1210 | unsigned Offset = SM.getFileOffset(FileRange.getBegin()); | |||
1211 | unsigned EndOffset = SM.getFileOffset(FileRange.getEnd()); | |||
1212 | return std::make_pair(Offset, EndOffset); | |||
1213 | } | |||
1214 | ||||
1215 | static ASTUnit::StandaloneFixIt makeStandaloneFixIt(const SourceManager &SM, | |||
1216 | const LangOptions &LangOpts, | |||
1217 | const FixItHint &InFix) { | |||
1218 | ASTUnit::StandaloneFixIt OutFix; | |||
1219 | OutFix.RemoveRange = makeStandaloneRange(InFix.RemoveRange, SM, LangOpts); | |||
1220 | OutFix.InsertFromRange = makeStandaloneRange(InFix.InsertFromRange, SM, | |||
1221 | LangOpts); | |||
1222 | OutFix.CodeToInsert = InFix.CodeToInsert; | |||
1223 | OutFix.BeforePreviousInsertions = InFix.BeforePreviousInsertions; | |||
1224 | return OutFix; | |||
1225 | } | |||
1226 | ||||
1227 | static ASTUnit::StandaloneDiagnostic | |||
1228 | makeStandaloneDiagnostic(const LangOptions &LangOpts, | |||
1229 | const StoredDiagnostic &InDiag) { | |||
1230 | ASTUnit::StandaloneDiagnostic OutDiag; | |||
1231 | OutDiag.ID = InDiag.getID(); | |||
1232 | OutDiag.Level = InDiag.getLevel(); | |||
1233 | OutDiag.Message = InDiag.getMessage(); | |||
1234 | OutDiag.LocOffset = 0; | |||
1235 | if (InDiag.getLocation().isInvalid()) | |||
1236 | return OutDiag; | |||
1237 | const SourceManager &SM = InDiag.getLocation().getManager(); | |||
1238 | SourceLocation FileLoc = SM.getFileLoc(InDiag.getLocation()); | |||
1239 | OutDiag.Filename = SM.getFilename(FileLoc); | |||
1240 | if (OutDiag.Filename.empty()) | |||
1241 | return OutDiag; | |||
1242 | OutDiag.LocOffset = SM.getFileOffset(FileLoc); | |||
1243 | for (const auto &Range : InDiag.getRanges()) | |||
1244 | OutDiag.Ranges.push_back(makeStandaloneRange(Range, SM, LangOpts)); | |||
1245 | for (const auto &FixIt : InDiag.getFixIts()) | |||
1246 | OutDiag.FixIts.push_back(makeStandaloneFixIt(SM, LangOpts, FixIt)); | |||
1247 | ||||
1248 | return OutDiag; | |||
1249 | } | |||
1250 | ||||
1251 | /// \brief Attempt to build or re-use a precompiled preamble when (re-)parsing | |||
1252 | /// the source file. | |||
1253 | /// | |||
1254 | /// This routine will compute the preamble of the main source file. If a | |||
1255 | /// non-trivial preamble is found, it will precompile that preamble into a | |||
1256 | /// precompiled header so that the precompiled preamble can be used to reduce | |||
1257 | /// reparsing time. If a precompiled preamble has already been constructed, | |||
1258 | /// this routine will determine if it is still valid and, if so, avoid | |||
1259 | /// rebuilding the precompiled preamble. | |||
1260 | /// | |||
1261 | /// \param AllowRebuild When true (the default), this routine is | |||
1262 | /// allowed to rebuild the precompiled preamble if it is found to be | |||
1263 | /// out-of-date. | |||
1264 | /// | |||
1265 | /// \param MaxLines When non-zero, the maximum number of lines that | |||
1266 | /// can occur within the preamble. | |||
1267 | /// | |||
1268 | /// \returns If the precompiled preamble can be used, returns a newly-allocated | |||
1269 | /// buffer that should be used in place of the main file when doing so. | |||
1270 | /// Otherwise, returns a NULL pointer. | |||
1271 | std::unique_ptr<llvm::MemoryBuffer> | |||
1272 | ASTUnit::getMainBufferWithPrecompiledPreamble( | |||
1273 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, | |||
1274 | const CompilerInvocation &PreambleInvocationIn, | |||
1275 | IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild, | |||
1276 | unsigned MaxLines) { | |||
1277 | auto MainFilePath = | |||
1278 | PreambleInvocationIn.getFrontendOpts().Inputs[0].getFile(); | |||
1279 | std::unique_ptr<llvm::MemoryBuffer> MainFileBuffer = | |||
1280 | getBufferForFileHandlingRemapping(PreambleInvocationIn, VFS.get(), | |||
1281 | MainFilePath); | |||
1282 | if (!MainFileBuffer) | |||
1283 | return nullptr; | |||
1284 | ||||
1285 | PreambleBounds Bounds = | |||
1286 | ComputePreambleBounds(*PreambleInvocationIn.getLangOpts(), | |||
1287 | MainFileBuffer.get(), MaxLines); | |||
1288 | if (!Bounds.Size) | |||
1289 | return nullptr; | |||
1290 | ||||
1291 | if (Preamble) { | |||
1292 | if (Preamble->CanReuse(PreambleInvocationIn, MainFileBuffer.get(), Bounds, | |||
1293 | VFS.get())) { | |||
1294 | // Okay! We can re-use the precompiled preamble. | |||
1295 | ||||
1296 | // Set the state of the diagnostic object to mimic its state | |||
1297 | // after parsing the preamble. | |||
1298 | getDiagnostics().Reset(); | |||
1299 | ProcessWarningOptions(getDiagnostics(), | |||
1300 | PreambleInvocationIn.getDiagnosticOpts()); | |||
1301 | getDiagnostics().setNumWarnings(NumWarningsInPreamble); | |||
1302 | ||||
1303 | PreambleRebuildCounter = 1; | |||
1304 | return MainFileBuffer; | |||
1305 | } else { | |||
1306 | Preamble.reset(); | |||
1307 | PreambleDiagnostics.clear(); | |||
1308 | TopLevelDeclsInPreamble.clear(); | |||
1309 | PreambleSrcLocCache.clear(); | |||
1310 | PreambleRebuildCounter = 1; | |||
1311 | } | |||
1312 | } | |||
1313 | ||||
1314 | // If the preamble rebuild counter > 1, it's because we previously | |||
1315 | // failed to build a preamble and we're not yet ready to try | |||
1316 | // again. Decrement the counter and return a failure. | |||
1317 | if (PreambleRebuildCounter > 1) { | |||
1318 | --PreambleRebuildCounter; | |||
1319 | return nullptr; | |||
1320 | } | |||
1321 | ||||
1322 | assert(!Preamble && "No Preamble should be stored at that point")(static_cast <bool> (!Preamble && "No Preamble should be stored at that point" ) ? void (0) : __assert_fail ("!Preamble && \"No Preamble should be stored at that point\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1322, __extension__ __PRETTY_FUNCTION__)); | |||
1323 | // If we aren't allowed to rebuild the precompiled preamble, just | |||
1324 | // return now. | |||
1325 | if (!AllowRebuild) | |||
1326 | return nullptr; | |||
1327 | ||||
1328 | SmallVector<StandaloneDiagnostic, 4> NewPreambleDiagsStandalone; | |||
1329 | SmallVector<StoredDiagnostic, 4> NewPreambleDiags; | |||
1330 | ASTUnitPreambleCallbacks Callbacks; | |||
1331 | { | |||
1332 | llvm::Optional<CaptureDroppedDiagnostics> Capture; | |||
1333 | if (CaptureDiagnostics) | |||
1334 | Capture.emplace(/*RequestCapture=*/true, *Diagnostics, &NewPreambleDiags, | |||
1335 | &NewPreambleDiagsStandalone); | |||
1336 | ||||
1337 | // We did not previously compute a preamble, or it can't be reused anyway. | |||
1338 | SimpleTimer PreambleTimer(WantTiming); | |||
1339 | PreambleTimer.setOutput("Precompiling preamble"); | |||
1340 | ||||
1341 | llvm::ErrorOr<PrecompiledPreamble> NewPreamble = PrecompiledPreamble::Build( | |||
1342 | PreambleInvocationIn, MainFileBuffer.get(), Bounds, *Diagnostics, VFS, | |||
1343 | PCHContainerOps, /*StoreInMemory=*/false, Callbacks); | |||
1344 | if (NewPreamble) { | |||
1345 | Preamble = std::move(*NewPreamble); | |||
1346 | PreambleRebuildCounter = 1; | |||
1347 | } else { | |||
1348 | switch (static_cast<BuildPreambleError>(NewPreamble.getError().value())) { | |||
1349 | case BuildPreambleError::CouldntCreateTempFile: | |||
1350 | case BuildPreambleError::PreambleIsEmpty: | |||
1351 | // Try again next time. | |||
1352 | PreambleRebuildCounter = 1; | |||
1353 | return nullptr; | |||
1354 | case BuildPreambleError::CouldntCreateTargetInfo: | |||
1355 | case BuildPreambleError::BeginSourceFileFailed: | |||
1356 | case BuildPreambleError::CouldntEmitPCH: | |||
1357 | // These erros are more likely to repeat, retry after some period. | |||
1358 | PreambleRebuildCounter = DefaultPreambleRebuildInterval; | |||
1359 | return nullptr; | |||
1360 | } | |||
1361 | llvm_unreachable("unexpected BuildPreambleError")::llvm::llvm_unreachable_internal("unexpected BuildPreambleError" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1361); | |||
1362 | } | |||
1363 | } | |||
1364 | ||||
1365 | assert(Preamble && "Preamble wasn't built")(static_cast <bool> (Preamble && "Preamble wasn't built" ) ? void (0) : __assert_fail ("Preamble && \"Preamble wasn't built\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1365, __extension__ __PRETTY_FUNCTION__)); | |||
1366 | ||||
1367 | TopLevelDecls.clear(); | |||
1368 | TopLevelDeclsInPreamble = Callbacks.takeTopLevelDeclIDs(); | |||
1369 | PreambleTopLevelHashValue = Callbacks.getHash(); | |||
1370 | ||||
1371 | NumWarningsInPreamble = getDiagnostics().getNumWarnings(); | |||
1372 | ||||
1373 | checkAndRemoveNonDriverDiags(NewPreambleDiags); | |||
1374 | StoredDiagnostics = std::move(NewPreambleDiags); | |||
1375 | PreambleDiagnostics = std::move(NewPreambleDiagsStandalone); | |||
1376 | ||||
1377 | // If the hash of top-level entities differs from the hash of the top-level | |||
1378 | // entities the last time we rebuilt the preamble, clear out the completion | |||
1379 | // cache. | |||
1380 | if (CurrentTopLevelHashValue != PreambleTopLevelHashValue) { | |||
1381 | CompletionCacheTopLevelHashValue = 0; | |||
1382 | PreambleTopLevelHashValue = CurrentTopLevelHashValue; | |||
1383 | } | |||
1384 | ||||
1385 | return MainFileBuffer; | |||
1386 | } | |||
1387 | ||||
1388 | void ASTUnit::RealizeTopLevelDeclsFromPreamble() { | |||
1389 | assert(Preamble && "Should only be called when preamble was built")(static_cast <bool> (Preamble && "Should only be called when preamble was built" ) ? void (0) : __assert_fail ("Preamble && \"Should only be called when preamble was built\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1389, __extension__ __PRETTY_FUNCTION__)); | |||
1390 | ||||
1391 | std::vector<Decl *> Resolved; | |||
1392 | Resolved.reserve(TopLevelDeclsInPreamble.size()); | |||
1393 | ExternalASTSource &Source = *getASTContext().getExternalSource(); | |||
1394 | for (const auto TopLevelDecl : TopLevelDeclsInPreamble) { | |||
1395 | // Resolve the declaration ID to an actual declaration, possibly | |||
1396 | // deserializing the declaration in the process. | |||
1397 | if (Decl *D = Source.GetExternalDecl(TopLevelDecl)) | |||
1398 | Resolved.push_back(D); | |||
1399 | } | |||
1400 | TopLevelDeclsInPreamble.clear(); | |||
1401 | TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end()); | |||
1402 | } | |||
1403 | ||||
1404 | void ASTUnit::transferASTDataFromCompilerInstance(CompilerInstance &CI) { | |||
1405 | // Steal the created target, context, and preprocessor if they have been | |||
1406 | // created. | |||
1407 | assert(CI.hasInvocation() && "missing invocation")(static_cast <bool> (CI.hasInvocation() && "missing invocation" ) ? void (0) : __assert_fail ("CI.hasInvocation() && \"missing invocation\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1407, __extension__ __PRETTY_FUNCTION__)); | |||
1408 | LangOpts = CI.getInvocation().LangOpts; | |||
1409 | TheSema = CI.takeSema(); | |||
1410 | Consumer = CI.takeASTConsumer(); | |||
1411 | if (CI.hasASTContext()) | |||
1412 | Ctx = &CI.getASTContext(); | |||
1413 | if (CI.hasPreprocessor()) | |||
1414 | PP = CI.getPreprocessorPtr(); | |||
1415 | CI.setSourceManager(nullptr); | |||
1416 | CI.setFileManager(nullptr); | |||
1417 | if (CI.hasTarget()) | |||
1418 | Target = &CI.getTarget(); | |||
1419 | Reader = CI.getModuleManager(); | |||
1420 | HadModuleLoaderFatalFailure = CI.hadModuleLoaderFatalFailure(); | |||
1421 | } | |||
1422 | ||||
1423 | StringRef ASTUnit::getMainFileName() const { | |||
1424 | if (Invocation && !Invocation->getFrontendOpts().Inputs.empty()) { | |||
1425 | const FrontendInputFile &Input = Invocation->getFrontendOpts().Inputs[0]; | |||
1426 | if (Input.isFile()) | |||
1427 | return Input.getFile(); | |||
1428 | else | |||
1429 | return Input.getBuffer()->getBufferIdentifier(); | |||
1430 | } | |||
1431 | ||||
1432 | if (SourceMgr) { | |||
1433 | if (const FileEntry * | |||
1434 | FE = SourceMgr->getFileEntryForID(SourceMgr->getMainFileID())) | |||
1435 | return FE->getName(); | |||
1436 | } | |||
1437 | ||||
1438 | return {}; | |||
1439 | } | |||
1440 | ||||
1441 | StringRef ASTUnit::getASTFileName() const { | |||
1442 | if (!isMainFileAST()) | |||
1443 | return {}; | |||
1444 | ||||
1445 | serialization::ModuleFile & | |||
1446 | Mod = Reader->getModuleManager().getPrimaryModule(); | |||
1447 | return Mod.FileName; | |||
1448 | } | |||
1449 | ||||
1450 | std::unique_ptr<ASTUnit> | |||
1451 | ASTUnit::create(std::shared_ptr<CompilerInvocation> CI, | |||
1452 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags, | |||
1453 | bool CaptureDiagnostics, bool UserFilesAreVolatile) { | |||
1454 | std::unique_ptr<ASTUnit> AST(new ASTUnit(false)); | |||
1455 | ConfigureDiags(Diags, *AST, CaptureDiagnostics); | |||
1456 | IntrusiveRefCntPtr<vfs::FileSystem> VFS = | |||
1457 | createVFSFromCompilerInvocation(*CI, *Diags); | |||
1458 | AST->Diagnostics = Diags; | |||
1459 | AST->FileSystemOpts = CI->getFileSystemOpts(); | |||
1460 | AST->Invocation = std::move(CI); | |||
1461 | AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); | |||
1462 | AST->UserFilesAreVolatile = UserFilesAreVolatile; | |||
1463 | AST->SourceMgr = new SourceManager(AST->getDiagnostics(), *AST->FileMgr, | |||
1464 | UserFilesAreVolatile); | |||
1465 | AST->PCMCache = new MemoryBufferCache; | |||
1466 | ||||
1467 | return AST; | |||
1468 | } | |||
1469 | ||||
1470 | ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( | |||
1471 | std::shared_ptr<CompilerInvocation> CI, | |||
1472 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, | |||
1473 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FrontendAction *Action, | |||
1474 | ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath, | |||
1475 | bool OnlyLocalDecls, bool CaptureDiagnostics, | |||
1476 | unsigned PrecompilePreambleAfterNParses, bool CacheCodeCompletionResults, | |||
1477 | bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile, | |||
1478 | std::unique_ptr<ASTUnit> *ErrAST) { | |||
1479 | assert(CI && "A CompilerInvocation is required")(static_cast <bool> (CI && "A CompilerInvocation is required" ) ? void (0) : __assert_fail ("CI && \"A CompilerInvocation is required\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1479, __extension__ __PRETTY_FUNCTION__)); | |||
1480 | ||||
1481 | std::unique_ptr<ASTUnit> OwnAST; | |||
1482 | ASTUnit *AST = Unit; | |||
1483 | if (!AST) { | |||
| ||||
1484 | // Create the AST unit. | |||
1485 | OwnAST = create(CI, Diags, CaptureDiagnostics, UserFilesAreVolatile); | |||
1486 | AST = OwnAST.get(); | |||
1487 | if (!AST) | |||
1488 | return nullptr; | |||
1489 | } | |||
1490 | ||||
1491 | if (!ResourceFilesPath.empty()) { | |||
1492 | // Override the resources path. | |||
1493 | CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; | |||
1494 | } | |||
1495 | AST->OnlyLocalDecls = OnlyLocalDecls; | |||
1496 | AST->CaptureDiagnostics = CaptureDiagnostics; | |||
1497 | if (PrecompilePreambleAfterNParses > 0) | |||
1498 | AST->PreambleRebuildCounter = PrecompilePreambleAfterNParses; | |||
1499 | AST->TUKind = Action ? Action->getTranslationUnitKind() : TU_Complete; | |||
1500 | AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; | |||
1501 | AST->IncludeBriefCommentsInCodeCompletion | |||
1502 | = IncludeBriefCommentsInCodeCompletion; | |||
1503 | ||||
1504 | // Recover resources if we crash before exiting this method. | |||
1505 | llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> | |||
1506 | ASTUnitCleanup(OwnAST.get()); | |||
1507 | llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, | |||
1508 | llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>> | |||
1509 | DiagCleanup(Diags.get()); | |||
1510 | ||||
1511 | // We'll manage file buffers ourselves. | |||
1512 | CI->getPreprocessorOpts().RetainRemappedFileBuffers = true; | |||
1513 | CI->getFrontendOpts().DisableFree = false; | |||
1514 | ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts()); | |||
1515 | ||||
1516 | // Create the compiler instance to use for building the AST. | |||
1517 | std::unique_ptr<CompilerInstance> Clang( | |||
1518 | new CompilerInstance(std::move(PCHContainerOps))); | |||
1519 | ||||
1520 | // Recover resources if we crash before exiting this method. | |||
1521 | llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> | |||
1522 | CICleanup(Clang.get()); | |||
1523 | ||||
1524 | Clang->setInvocation(std::move(CI)); | |||
1525 | AST->OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile(); | |||
1526 | ||||
1527 | // Set up diagnostics, capturing any diagnostics that would | |||
1528 | // otherwise be dropped. | |||
1529 | Clang->setDiagnostics(&AST->getDiagnostics()); | |||
1530 | ||||
1531 | // Create the target instance. | |||
1532 | Clang->setTarget(TargetInfo::CreateTargetInfo( | |||
1533 | Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); | |||
1534 | if (!Clang->hasTarget()) | |||
1535 | return nullptr; | |||
1536 | ||||
1537 | // Inform the target of the language options. | |||
1538 | // | |||
1539 | // FIXME: We shouldn't need to do this, the target should be immutable once | |||
1540 | // created. This complexity should be lifted elsewhere. | |||
1541 | Clang->getTarget().adjust(Clang->getLangOpts()); | |||
1542 | ||||
1543 | assert(Clang->getFrontendOpts().Inputs.size() == 1 &&(static_cast <bool> (Clang->getFrontendOpts().Inputs .size() == 1 && "Invocation must have exactly one source file!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs.size() == 1 && \"Invocation must have exactly one source file!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1544, __extension__ __PRETTY_FUNCTION__)) | |||
1544 | "Invocation must have exactly one source file!")(static_cast <bool> (Clang->getFrontendOpts().Inputs .size() == 1 && "Invocation must have exactly one source file!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs.size() == 1 && \"Invocation must have exactly one source file!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1544, __extension__ __PRETTY_FUNCTION__)); | |||
1545 | assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getFormat() == InputKind::Source && "FIXME: AST inputs not yet supported here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == InputKind::Source && \"FIXME: AST inputs not yet supported here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1547, __extension__ __PRETTY_FUNCTION__)) | |||
1546 | InputKind::Source &&(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getFormat() == InputKind::Source && "FIXME: AST inputs not yet supported here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == InputKind::Source && \"FIXME: AST inputs not yet supported here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1547, __extension__ __PRETTY_FUNCTION__)) | |||
1547 | "FIXME: AST inputs not yet supported here!")(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getFormat() == InputKind::Source && "FIXME: AST inputs not yet supported here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == InputKind::Source && \"FIXME: AST inputs not yet supported here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1547, __extension__ __PRETTY_FUNCTION__)); | |||
1548 | assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getLanguage() != InputKind::LLVM_IR && "IR inputs not support here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != InputKind::LLVM_IR && \"IR inputs not support here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1550, __extension__ __PRETTY_FUNCTION__)) | |||
1549 | InputKind::LLVM_IR &&(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getLanguage() != InputKind::LLVM_IR && "IR inputs not support here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != InputKind::LLVM_IR && \"IR inputs not support here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1550, __extension__ __PRETTY_FUNCTION__)) | |||
1550 | "IR inputs not support here!")(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getLanguage() != InputKind::LLVM_IR && "IR inputs not support here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != InputKind::LLVM_IR && \"IR inputs not support here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1550, __extension__ __PRETTY_FUNCTION__)); | |||
1551 | ||||
1552 | // Configure the various subsystems. | |||
1553 | AST->TheSema.reset(); | |||
1554 | AST->Ctx = nullptr; | |||
1555 | AST->PP = nullptr; | |||
1556 | AST->Reader = nullptr; | |||
1557 | ||||
1558 | // Create a file manager object to provide access to and cache the filesystem. | |||
1559 | Clang->setFileManager(&AST->getFileManager()); | |||
1560 | ||||
1561 | // Create the source manager. | |||
1562 | Clang->setSourceManager(&AST->getSourceManager()); | |||
1563 | ||||
1564 | FrontendAction *Act = Action; | |||
1565 | ||||
1566 | std::unique_ptr<TopLevelDeclTrackerAction> TrackerAct; | |||
1567 | if (!Act) { | |||
1568 | TrackerAct.reset(new TopLevelDeclTrackerAction(*AST)); | |||
1569 | Act = TrackerAct.get(); | |||
1570 | } | |||
1571 | ||||
1572 | // Recover resources if we crash before exiting this method. | |||
1573 | llvm::CrashRecoveryContextCleanupRegistrar<TopLevelDeclTrackerAction> | |||
1574 | ActCleanup(TrackerAct.get()); | |||
1575 | ||||
1576 | if (!Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) { | |||
1577 | AST->transferASTDataFromCompilerInstance(*Clang); | |||
1578 | if (OwnAST && ErrAST) | |||
1579 | ErrAST->swap(OwnAST); | |||
1580 | ||||
1581 | return nullptr; | |||
1582 | } | |||
1583 | ||||
1584 | if (Persistent && !TrackerAct) { | |||
1585 | Clang->getPreprocessor().addPPCallbacks( | |||
1586 | llvm::make_unique<MacroDefinitionTrackerPPCallbacks>( | |||
1587 | AST->getCurrentTopLevelHashValue())); | |||
1588 | std::vector<std::unique_ptr<ASTConsumer>> Consumers; | |||
1589 | if (Clang->hasASTConsumer()) | |||
1590 | Consumers.push_back(Clang->takeASTConsumer()); | |||
1591 | Consumers.push_back(llvm::make_unique<TopLevelDeclTrackerConsumer>( | |||
1592 | *AST, AST->getCurrentTopLevelHashValue())); | |||
1593 | Clang->setASTConsumer( | |||
1594 | llvm::make_unique<MultiplexConsumer>(std::move(Consumers))); | |||
1595 | } | |||
1596 | if (!Act->Execute()) { | |||
1597 | AST->transferASTDataFromCompilerInstance(*Clang); | |||
1598 | if (OwnAST && ErrAST) | |||
1599 | ErrAST->swap(OwnAST); | |||
1600 | ||||
1601 | return nullptr; | |||
1602 | } | |||
1603 | ||||
1604 | // Steal the created target, context, and preprocessor. | |||
1605 | AST->transferASTDataFromCompilerInstance(*Clang); | |||
1606 | ||||
1607 | Act->EndSourceFile(); | |||
1608 | ||||
1609 | if (OwnAST) | |||
1610 | return OwnAST.release(); | |||
1611 | else | |||
1612 | return AST; | |||
1613 | } | |||
1614 | ||||
1615 | bool ASTUnit::LoadFromCompilerInvocation( | |||
1616 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, | |||
1617 | unsigned PrecompilePreambleAfterNParses, | |||
1618 | IntrusiveRefCntPtr<vfs::FileSystem> VFS) { | |||
1619 | if (!Invocation) | |||
1620 | return true; | |||
1621 | ||||
1622 | assert(VFS && "VFS is null")(static_cast <bool> (VFS && "VFS is null") ? void (0) : __assert_fail ("VFS && \"VFS is null\"", "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1622, __extension__ __PRETTY_FUNCTION__)); | |||
1623 | ||||
1624 | // We'll manage file buffers ourselves. | |||
1625 | Invocation->getPreprocessorOpts().RetainRemappedFileBuffers = true; | |||
1626 | Invocation->getFrontendOpts().DisableFree = false; | |||
1627 | getDiagnostics().Reset(); | |||
1628 | ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); | |||
1629 | ||||
1630 | std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; | |||
1631 | if (PrecompilePreambleAfterNParses > 0) { | |||
1632 | PreambleRebuildCounter = PrecompilePreambleAfterNParses; | |||
1633 | OverrideMainBuffer = | |||
1634 | getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS); | |||
1635 | getDiagnostics().Reset(); | |||
1636 | ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); | |||
1637 | } | |||
1638 | ||||
1639 | SimpleTimer ParsingTimer(WantTiming); | |||
1640 | ParsingTimer.setOutput("Parsing " + getMainFileName()); | |||
1641 | ||||
1642 | // Recover resources if we crash before exiting this method. | |||
1643 | llvm::CrashRecoveryContextCleanupRegistrar<llvm::MemoryBuffer> | |||
1644 | MemBufferCleanup(OverrideMainBuffer.get()); | |||
1645 | ||||
1646 | return Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS); | |||
1647 | } | |||
1648 | ||||
1649 | std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation( | |||
1650 | std::shared_ptr<CompilerInvocation> CI, | |||
1651 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, | |||
1652 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags, FileManager *FileMgr, | |||
1653 | bool OnlyLocalDecls, bool CaptureDiagnostics, | |||
1654 | unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind, | |||
1655 | bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, | |||
1656 | bool UserFilesAreVolatile) { | |||
1657 | // Create the AST unit. | |||
1658 | std::unique_ptr<ASTUnit> AST(new ASTUnit(false)); | |||
1659 | ConfigureDiags(Diags, *AST, CaptureDiagnostics); | |||
1660 | AST->Diagnostics = Diags; | |||
1661 | AST->OnlyLocalDecls = OnlyLocalDecls; | |||
1662 | AST->CaptureDiagnostics = CaptureDiagnostics; | |||
1663 | AST->TUKind = TUKind; | |||
1664 | AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; | |||
1665 | AST->IncludeBriefCommentsInCodeCompletion | |||
1666 | = IncludeBriefCommentsInCodeCompletion; | |||
1667 | AST->Invocation = std::move(CI); | |||
1668 | AST->FileSystemOpts = FileMgr->getFileSystemOpts(); | |||
1669 | AST->FileMgr = FileMgr; | |||
1670 | AST->UserFilesAreVolatile = UserFilesAreVolatile; | |||
1671 | ||||
1672 | // Recover resources if we crash before exiting this method. | |||
1673 | llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> | |||
1674 | ASTUnitCleanup(AST.get()); | |||
1675 | llvm::CrashRecoveryContextCleanupRegistrar<DiagnosticsEngine, | |||
1676 | llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine>> | |||
1677 | DiagCleanup(Diags.get()); | |||
1678 | ||||
1679 | if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), | |||
1680 | PrecompilePreambleAfterNParses, | |||
1681 | AST->FileMgr->getVirtualFileSystem())) | |||
1682 | return nullptr; | |||
1683 | return AST; | |||
1684 | } | |||
1685 | ||||
1686 | ASTUnit *ASTUnit::LoadFromCommandLine( | |||
1687 | const char **ArgBegin, const char **ArgEnd, | |||
1688 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, | |||
1689 | IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath, | |||
1690 | bool OnlyLocalDecls, bool CaptureDiagnostics, | |||
1691 | ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName, | |||
1692 | unsigned PrecompilePreambleAfterNParses, TranslationUnitKind TUKind, | |||
1693 | bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, | |||
1694 | bool AllowPCHWithCompilerErrors, bool SkipFunctionBodies, | |||
1695 | bool SingleFileParse, bool UserFilesAreVolatile, bool ForSerialization, | |||
1696 | llvm::Optional<StringRef> ModuleFormat, std::unique_ptr<ASTUnit> *ErrAST, | |||
1697 | IntrusiveRefCntPtr<vfs::FileSystem> VFS) { | |||
1698 | assert(Diags.get() && "no DiagnosticsEngine was provided")(static_cast <bool> (Diags.get() && "no DiagnosticsEngine was provided" ) ? void (0) : __assert_fail ("Diags.get() && \"no DiagnosticsEngine was provided\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1698, __extension__ __PRETTY_FUNCTION__)); | |||
1699 | ||||
1700 | SmallVector<StoredDiagnostic, 4> StoredDiagnostics; | |||
1701 | ||||
1702 | std::shared_ptr<CompilerInvocation> CI; | |||
1703 | ||||
1704 | { | |||
1705 | CaptureDroppedDiagnostics Capture(CaptureDiagnostics, *Diags, | |||
1706 | &StoredDiagnostics, nullptr); | |||
1707 | ||||
1708 | CI = createInvocationFromCommandLine( | |||
1709 | llvm::makeArrayRef(ArgBegin, ArgEnd), Diags, VFS); | |||
1710 | if (!CI) | |||
1711 | return nullptr; | |||
1712 | } | |||
1713 | ||||
1714 | // Override any files that need remapping | |||
1715 | for (const auto &RemappedFile : RemappedFiles) { | |||
1716 | CI->getPreprocessorOpts().addRemappedFile(RemappedFile.first, | |||
1717 | RemappedFile.second); | |||
1718 | } | |||
1719 | PreprocessorOptions &PPOpts = CI->getPreprocessorOpts(); | |||
1720 | PPOpts.RemappedFilesKeepOriginalName = RemappedFilesKeepOriginalName; | |||
1721 | PPOpts.AllowPCHWithCompilerErrors = AllowPCHWithCompilerErrors; | |||
1722 | PPOpts.SingleFileParseMode = SingleFileParse; | |||
1723 | ||||
1724 | // Override the resources path. | |||
1725 | CI->getHeaderSearchOpts().ResourceDir = ResourceFilesPath; | |||
1726 | ||||
1727 | CI->getFrontendOpts().SkipFunctionBodies = SkipFunctionBodies; | |||
1728 | ||||
1729 | if (ModuleFormat) | |||
1730 | CI->getHeaderSearchOpts().ModuleFormat = ModuleFormat.getValue(); | |||
1731 | ||||
1732 | // Create the AST unit. | |||
1733 | std::unique_ptr<ASTUnit> AST; | |||
1734 | AST.reset(new ASTUnit(false)); | |||
1735 | AST->NumStoredDiagnosticsFromDriver = StoredDiagnostics.size(); | |||
1736 | AST->StoredDiagnostics.swap(StoredDiagnostics); | |||
1737 | ConfigureDiags(Diags, *AST, CaptureDiagnostics); | |||
1738 | AST->Diagnostics = Diags; | |||
1739 | AST->FileSystemOpts = CI->getFileSystemOpts(); | |||
1740 | if (!VFS) | |||
1741 | VFS = vfs::getRealFileSystem(); | |||
1742 | VFS = createVFSFromCompilerInvocation(*CI, *Diags, VFS); | |||
1743 | AST->FileMgr = new FileManager(AST->FileSystemOpts, VFS); | |||
1744 | AST->PCMCache = new MemoryBufferCache; | |||
1745 | AST->OnlyLocalDecls = OnlyLocalDecls; | |||
1746 | AST->CaptureDiagnostics = CaptureDiagnostics; | |||
1747 | AST->TUKind = TUKind; | |||
1748 | AST->ShouldCacheCodeCompletionResults = CacheCodeCompletionResults; | |||
1749 | AST->IncludeBriefCommentsInCodeCompletion | |||
1750 | = IncludeBriefCommentsInCodeCompletion; | |||
1751 | AST->UserFilesAreVolatile = UserFilesAreVolatile; | |||
1752 | AST->Invocation = CI; | |||
1753 | if (ForSerialization) | |||
1754 | AST->WriterData.reset(new ASTWriterData(*AST->PCMCache)); | |||
1755 | // Zero out now to ease cleanup during crash recovery. | |||
1756 | CI = nullptr; | |||
1757 | Diags = nullptr; | |||
1758 | ||||
1759 | // Recover resources if we crash before exiting this method. | |||
1760 | llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit> | |||
1761 | ASTUnitCleanup(AST.get()); | |||
1762 | ||||
1763 | if (AST->LoadFromCompilerInvocation(std::move(PCHContainerOps), | |||
1764 | PrecompilePreambleAfterNParses, | |||
1765 | VFS)) { | |||
1766 | // Some error occurred, if caller wants to examine diagnostics, pass it the | |||
1767 | // ASTUnit. | |||
1768 | if (ErrAST) { | |||
1769 | AST->StoredDiagnostics.swap(AST->FailedParseDiagnostics); | |||
1770 | ErrAST->swap(AST); | |||
1771 | } | |||
1772 | return nullptr; | |||
1773 | } | |||
1774 | ||||
1775 | return AST.release(); | |||
1776 | } | |||
1777 | ||||
1778 | bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, | |||
1779 | ArrayRef<RemappedFile> RemappedFiles, | |||
1780 | IntrusiveRefCntPtr<vfs::FileSystem> VFS) { | |||
1781 | if (!Invocation) | |||
1782 | return true; | |||
1783 | ||||
1784 | if (!VFS) { | |||
1785 | assert(FileMgr && "FileMgr is null on Reparse call")(static_cast <bool> (FileMgr && "FileMgr is null on Reparse call" ) ? void (0) : __assert_fail ("FileMgr && \"FileMgr is null on Reparse call\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 1785, __extension__ __PRETTY_FUNCTION__)); | |||
1786 | VFS = FileMgr->getVirtualFileSystem(); | |||
1787 | } | |||
1788 | ||||
1789 | clearFileLevelDecls(); | |||
1790 | ||||
1791 | SimpleTimer ParsingTimer(WantTiming); | |||
1792 | ParsingTimer.setOutput("Reparsing " + getMainFileName()); | |||
1793 | ||||
1794 | // Remap files. | |||
1795 | PreprocessorOptions &PPOpts = Invocation->getPreprocessorOpts(); | |||
1796 | for (const auto &RB : PPOpts.RemappedFileBuffers) | |||
1797 | delete RB.second; | |||
1798 | ||||
1799 | Invocation->getPreprocessorOpts().clearRemappedFiles(); | |||
1800 | for (const auto &RemappedFile : RemappedFiles) { | |||
1801 | Invocation->getPreprocessorOpts().addRemappedFile(RemappedFile.first, | |||
1802 | RemappedFile.second); | |||
1803 | } | |||
1804 | ||||
1805 | // If we have a preamble file lying around, or if we might try to | |||
1806 | // build a precompiled preamble, do so now. | |||
1807 | std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; | |||
1808 | if (Preamble || PreambleRebuildCounter > 0) | |||
1809 | OverrideMainBuffer = | |||
1810 | getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation, VFS); | |||
1811 | ||||
1812 | // Clear out the diagnostics state. | |||
1813 | FileMgr.reset(); | |||
1814 | getDiagnostics().Reset(); | |||
1815 | ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); | |||
1816 | if (OverrideMainBuffer) | |||
1817 | getDiagnostics().setNumWarnings(NumWarningsInPreamble); | |||
1818 | ||||
1819 | // Parse the sources | |||
1820 | bool Result = | |||
1821 | Parse(std::move(PCHContainerOps), std::move(OverrideMainBuffer), VFS); | |||
1822 | ||||
1823 | // If we're caching global code-completion results, and the top-level | |||
1824 | // declarations have changed, clear out the code-completion cache. | |||
1825 | if (!Result && ShouldCacheCodeCompletionResults && | |||
1826 | CurrentTopLevelHashValue != CompletionCacheTopLevelHashValue) | |||
1827 | CacheCodeCompletionResults(); | |||
1828 | ||||
1829 | // We now need to clear out the completion info related to this translation | |||
1830 | // unit; it'll be recreated if necessary. | |||
1831 | CCTUInfo.reset(); | |||
1832 | ||||
1833 | return Result; | |||
1834 | } | |||
1835 | ||||
1836 | void ASTUnit::ResetForParse() { | |||
1837 | SavedMainFileBuffer.reset(); | |||
1838 | ||||
1839 | SourceMgr.reset(); | |||
1840 | TheSema.reset(); | |||
1841 | Ctx.reset(); | |||
1842 | PP.reset(); | |||
1843 | Reader.reset(); | |||
1844 | ||||
1845 | TopLevelDecls.clear(); | |||
1846 | clearFileLevelDecls(); | |||
1847 | } | |||
1848 | ||||
1849 | //----------------------------------------------------------------------------// | |||
1850 | // Code completion | |||
1851 | //----------------------------------------------------------------------------// | |||
1852 | ||||
1853 | namespace { | |||
1854 | ||||
1855 | /// \brief Code completion consumer that combines the cached code-completion | |||
1856 | /// results from an ASTUnit with the code-completion results provided to it, | |||
1857 | /// then passes the result on to | |||
1858 | class AugmentedCodeCompleteConsumer : public CodeCompleteConsumer { | |||
1859 | uint64_t NormalContexts; | |||
1860 | ASTUnit &AST; | |||
1861 | CodeCompleteConsumer &Next; | |||
1862 | ||||
1863 | public: | |||
1864 | AugmentedCodeCompleteConsumer(ASTUnit &AST, CodeCompleteConsumer &Next, | |||
1865 | const CodeCompleteOptions &CodeCompleteOpts) | |||
1866 | : CodeCompleteConsumer(CodeCompleteOpts, Next.isOutputBinary()), | |||
1867 | AST(AST), Next(Next) { | |||
1868 | // Compute the set of contexts in which we will look when we don't have | |||
1869 | // any information about the specific context. | |||
1870 | NormalContexts | |||
1871 | = (1LL << CodeCompletionContext::CCC_TopLevel) | |||
1872 | | (1LL << CodeCompletionContext::CCC_ObjCInterface) | |||
1873 | | (1LL << CodeCompletionContext::CCC_ObjCImplementation) | |||
1874 | | (1LL << CodeCompletionContext::CCC_ObjCIvarList) | |||
1875 | | (1LL << CodeCompletionContext::CCC_Statement) | |||
1876 | | (1LL << CodeCompletionContext::CCC_Expression) | |||
1877 | | (1LL << CodeCompletionContext::CCC_ObjCMessageReceiver) | |||
1878 | | (1LL << CodeCompletionContext::CCC_DotMemberAccess) | |||
1879 | | (1LL << CodeCompletionContext::CCC_ArrowMemberAccess) | |||
1880 | | (1LL << CodeCompletionContext::CCC_ObjCPropertyAccess) | |||
1881 | | (1LL << CodeCompletionContext::CCC_ObjCProtocolName) | |||
1882 | | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression) | |||
1883 | | (1LL << CodeCompletionContext::CCC_Recovery); | |||
1884 | ||||
1885 | if (AST.getASTContext().getLangOpts().CPlusPlus) | |||
1886 | NormalContexts |= (1LL << CodeCompletionContext::CCC_EnumTag) | |||
1887 | | (1LL << CodeCompletionContext::CCC_UnionTag) | |||
1888 | | (1LL << CodeCompletionContext::CCC_ClassOrStructTag); | |||
1889 | } | |||
1890 | ||||
1891 | void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, | |||
1892 | CodeCompletionResult *Results, | |||
1893 | unsigned NumResults) override; | |||
1894 | ||||
1895 | void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, | |||
1896 | OverloadCandidate *Candidates, | |||
1897 | unsigned NumCandidates) override { | |||
1898 | Next.ProcessOverloadCandidates(S, CurrentArg, Candidates, NumCandidates); | |||
1899 | } | |||
1900 | ||||
1901 | CodeCompletionAllocator &getAllocator() override { | |||
1902 | return Next.getAllocator(); | |||
1903 | } | |||
1904 | ||||
1905 | CodeCompletionTUInfo &getCodeCompletionTUInfo() override { | |||
1906 | return Next.getCodeCompletionTUInfo(); | |||
1907 | } | |||
1908 | }; | |||
1909 | ||||
1910 | } // namespace | |||
1911 | ||||
1912 | /// \brief Helper function that computes which global names are hidden by the | |||
1913 | /// local code-completion results. | |||
1914 | static void CalculateHiddenNames(const CodeCompletionContext &Context, | |||
1915 | CodeCompletionResult *Results, | |||
1916 | unsigned NumResults, | |||
1917 | ASTContext &Ctx, | |||
1918 | llvm::StringSet<llvm::BumpPtrAllocator> &HiddenNames){ | |||
1919 | bool OnlyTagNames = false; | |||
1920 | switch (Context.getKind()) { | |||
1921 | case CodeCompletionContext::CCC_Recovery: | |||
1922 | case CodeCompletionContext::CCC_TopLevel: | |||
1923 | case CodeCompletionContext::CCC_ObjCInterface: | |||
1924 | case CodeCompletionContext::CCC_ObjCImplementation: | |||
1925 | case CodeCompletionContext::CCC_ObjCIvarList: | |||
1926 | case CodeCompletionContext::CCC_ClassStructUnion: | |||
1927 | case CodeCompletionContext::CCC_Statement: | |||
1928 | case CodeCompletionContext::CCC_Expression: | |||
1929 | case CodeCompletionContext::CCC_ObjCMessageReceiver: | |||
1930 | case CodeCompletionContext::CCC_DotMemberAccess: | |||
1931 | case CodeCompletionContext::CCC_ArrowMemberAccess: | |||
1932 | case CodeCompletionContext::CCC_ObjCPropertyAccess: | |||
1933 | case CodeCompletionContext::CCC_Namespace: | |||
1934 | case CodeCompletionContext::CCC_Type: | |||
1935 | case CodeCompletionContext::CCC_Name: | |||
1936 | case CodeCompletionContext::CCC_PotentiallyQualifiedName: | |||
1937 | case CodeCompletionContext::CCC_ParenthesizedExpression: | |||
1938 | case CodeCompletionContext::CCC_ObjCInterfaceName: | |||
1939 | break; | |||
1940 | ||||
1941 | case CodeCompletionContext::CCC_EnumTag: | |||
1942 | case CodeCompletionContext::CCC_UnionTag: | |||
1943 | case CodeCompletionContext::CCC_ClassOrStructTag: | |||
1944 | OnlyTagNames = true; | |||
1945 | break; | |||
1946 | ||||
1947 | case CodeCompletionContext::CCC_ObjCProtocolName: | |||
1948 | case CodeCompletionContext::CCC_MacroName: | |||
1949 | case CodeCompletionContext::CCC_MacroNameUse: | |||
1950 | case CodeCompletionContext::CCC_PreprocessorExpression: | |||
1951 | case CodeCompletionContext::CCC_PreprocessorDirective: | |||
1952 | case CodeCompletionContext::CCC_NaturalLanguage: | |||
1953 | case CodeCompletionContext::CCC_SelectorName: | |||
1954 | case CodeCompletionContext::CCC_TypeQualifiers: | |||
1955 | case CodeCompletionContext::CCC_Other: | |||
1956 | case CodeCompletionContext::CCC_OtherWithMacros: | |||
1957 | case CodeCompletionContext::CCC_ObjCInstanceMessage: | |||
1958 | case CodeCompletionContext::CCC_ObjCClassMessage: | |||
1959 | case CodeCompletionContext::CCC_ObjCCategoryName: | |||
1960 | // We're looking for nothing, or we're looking for names that cannot | |||
1961 | // be hidden. | |||
1962 | return; | |||
1963 | } | |||
1964 | ||||
1965 | using Result = CodeCompletionResult; | |||
1966 | for (unsigned I = 0; I != NumResults; ++I) { | |||
1967 | if (Results[I].Kind != Result::RK_Declaration) | |||
1968 | continue; | |||
1969 | ||||
1970 | unsigned IDNS | |||
1971 | = Results[I].Declaration->getUnderlyingDecl()->getIdentifierNamespace(); | |||
1972 | ||||
1973 | bool Hiding = false; | |||
1974 | if (OnlyTagNames) | |||
1975 | Hiding = (IDNS & Decl::IDNS_Tag); | |||
1976 | else { | |||
1977 | unsigned HiddenIDNS = (Decl::IDNS_Type | Decl::IDNS_Member | | |||
1978 | Decl::IDNS_Namespace | Decl::IDNS_Ordinary | | |||
1979 | Decl::IDNS_NonMemberOperator); | |||
1980 | if (Ctx.getLangOpts().CPlusPlus) | |||
1981 | HiddenIDNS |= Decl::IDNS_Tag; | |||
1982 | Hiding = (IDNS & HiddenIDNS); | |||
1983 | } | |||
1984 | ||||
1985 | if (!Hiding) | |||
1986 | continue; | |||
1987 | ||||
1988 | DeclarationName Name = Results[I].Declaration->getDeclName(); | |||
1989 | if (IdentifierInfo *Identifier = Name.getAsIdentifierInfo()) | |||
1990 | HiddenNames.insert(Identifier->getName()); | |||
1991 | else | |||
1992 | HiddenNames.insert(Name.getAsString()); | |||
1993 | } | |||
1994 | } | |||
1995 | ||||
1996 | void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, | |||
1997 | CodeCompletionContext Context, | |||
1998 | CodeCompletionResult *Results, | |||
1999 | unsigned NumResults) { | |||
2000 | // Merge the results we were given with the results we cached. | |||
2001 | bool AddedResult = false; | |||
2002 | uint64_t InContexts = | |||
2003 | Context.getKind() == CodeCompletionContext::CCC_Recovery | |||
2004 | ? NormalContexts : (1LL << Context.getKind()); | |||
2005 | // Contains the set of names that are hidden by "local" completion results. | |||
2006 | llvm::StringSet<llvm::BumpPtrAllocator> HiddenNames; | |||
2007 | using Result = CodeCompletionResult; | |||
2008 | SmallVector<Result, 8> AllResults; | |||
2009 | for (ASTUnit::cached_completion_iterator | |||
2010 | C = AST.cached_completion_begin(), | |||
2011 | CEnd = AST.cached_completion_end(); | |||
2012 | C != CEnd; ++C) { | |||
2013 | // If the context we are in matches any of the contexts we are | |||
2014 | // interested in, we'll add this result. | |||
2015 | if ((C->ShowInContexts & InContexts) == 0) | |||
2016 | continue; | |||
2017 | ||||
2018 | // If we haven't added any results previously, do so now. | |||
2019 | if (!AddedResult) { | |||
2020 | CalculateHiddenNames(Context, Results, NumResults, S.Context, | |||
2021 | HiddenNames); | |||
2022 | AllResults.insert(AllResults.end(), Results, Results + NumResults); | |||
2023 | AddedResult = true; | |||
2024 | } | |||
2025 | ||||
2026 | // Determine whether this global completion result is hidden by a local | |||
2027 | // completion result. If so, skip it. | |||
2028 | if (C->Kind != CXCursor_MacroDefinition && | |||
2029 | HiddenNames.count(C->Completion->getTypedText())) | |||
2030 | continue; | |||
2031 | ||||
2032 | // Adjust priority based on similar type classes. | |||
2033 | unsigned Priority = C->Priority; | |||
2034 | CodeCompletionString *Completion = C->Completion; | |||
2035 | if (!Context.getPreferredType().isNull()) { | |||
2036 | if (C->Kind == CXCursor_MacroDefinition) { | |||
2037 | Priority = getMacroUsagePriority(C->Completion->getTypedText(), | |||
2038 | S.getLangOpts(), | |||
2039 | Context.getPreferredType()->isAnyPointerType()); | |||
2040 | } else if (C->Type) { | |||
2041 | CanQualType Expected | |||
2042 | = S.Context.getCanonicalType( | |||
2043 | Context.getPreferredType().getUnqualifiedType()); | |||
2044 | SimplifiedTypeClass ExpectedSTC = getSimplifiedTypeClass(Expected); | |||
2045 | if (ExpectedSTC == C->TypeClass) { | |||
2046 | // We know this type is similar; check for an exact match. | |||
2047 | llvm::StringMap<unsigned> &CachedCompletionTypes | |||
2048 | = AST.getCachedCompletionTypes(); | |||
2049 | llvm::StringMap<unsigned>::iterator Pos | |||
2050 | = CachedCompletionTypes.find(QualType(Expected).getAsString()); | |||
2051 | if (Pos != CachedCompletionTypes.end() && Pos->second == C->Type) | |||
2052 | Priority /= CCF_ExactTypeMatch; | |||
2053 | else | |||
2054 | Priority /= CCF_SimilarTypeMatch; | |||
2055 | } | |||
2056 | } | |||
2057 | } | |||
2058 | ||||
2059 | // Adjust the completion string, if required. | |||
2060 | if (C->Kind == CXCursor_MacroDefinition && | |||
2061 | Context.getKind() == CodeCompletionContext::CCC_MacroNameUse) { | |||
2062 | // Create a new code-completion string that just contains the | |||
2063 | // macro name, without its arguments. | |||
2064 | CodeCompletionBuilder Builder(getAllocator(), getCodeCompletionTUInfo(), | |||
2065 | CCP_CodePattern, C->Availability); | |||
2066 | Builder.AddTypedTextChunk(C->Completion->getTypedText()); | |||
2067 | Priority = CCP_CodePattern; | |||
2068 | Completion = Builder.TakeString(); | |||
2069 | } | |||
2070 | ||||
2071 | AllResults.push_back(Result(Completion, Priority, C->Kind, | |||
2072 | C->Availability)); | |||
2073 | } | |||
2074 | ||||
2075 | // If we did not add any cached completion results, just forward the | |||
2076 | // results we were given to the next consumer. | |||
2077 | if (!AddedResult) { | |||
2078 | Next.ProcessCodeCompleteResults(S, Context, Results, NumResults); | |||
2079 | return; | |||
2080 | } | |||
2081 | ||||
2082 | Next.ProcessCodeCompleteResults(S, Context, AllResults.data(), | |||
2083 | AllResults.size()); | |||
2084 | } | |||
2085 | ||||
2086 | void ASTUnit::CodeComplete( | |||
2087 | StringRef File, unsigned Line, unsigned Column, | |||
2088 | ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros, | |||
2089 | bool IncludeCodePatterns, bool IncludeBriefComments, | |||
2090 | CodeCompleteConsumer &Consumer, | |||
2091 | std::shared_ptr<PCHContainerOperations> PCHContainerOps, | |||
2092 | DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr, | |||
2093 | FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, | |||
2094 | SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) { | |||
2095 | if (!Invocation) | |||
2096 | return; | |||
2097 | ||||
2098 | SimpleTimer CompletionTimer(WantTiming); | |||
2099 | CompletionTimer.setOutput("Code completion @ " + File + ":" + | |||
2100 | Twine(Line) + ":" + Twine(Column)); | |||
2101 | ||||
2102 | auto CCInvocation = std::make_shared<CompilerInvocation>(*Invocation); | |||
2103 | ||||
2104 | FrontendOptions &FrontendOpts = CCInvocation->getFrontendOpts(); | |||
2105 | CodeCompleteOptions &CodeCompleteOpts = FrontendOpts.CodeCompleteOpts; | |||
2106 | PreprocessorOptions &PreprocessorOpts = CCInvocation->getPreprocessorOpts(); | |||
2107 | ||||
2108 | CodeCompleteOpts.IncludeMacros = IncludeMacros && | |||
2109 | CachedCompletionResults.empty(); | |||
2110 | CodeCompleteOpts.IncludeCodePatterns = IncludeCodePatterns; | |||
2111 | CodeCompleteOpts.IncludeGlobals = CachedCompletionResults.empty(); | |||
2112 | CodeCompleteOpts.IncludeBriefComments = IncludeBriefComments; | |||
2113 | CodeCompleteOpts.LoadExternal = Consumer.loadExternal(); | |||
2114 | ||||
2115 | assert(IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion)(static_cast <bool> (IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion ) ? void (0) : __assert_fail ("IncludeBriefComments == this->IncludeBriefCommentsInCodeCompletion" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2115, __extension__ __PRETTY_FUNCTION__)); | |||
2116 | ||||
2117 | FrontendOpts.CodeCompletionAt.FileName = File; | |||
2118 | FrontendOpts.CodeCompletionAt.Line = Line; | |||
2119 | FrontendOpts.CodeCompletionAt.Column = Column; | |||
2120 | ||||
2121 | // Set the language options appropriately. | |||
2122 | LangOpts = *CCInvocation->getLangOpts(); | |||
2123 | ||||
2124 | // Spell-checking and warnings are wasteful during code-completion. | |||
2125 | LangOpts.SpellChecking = false; | |||
2126 | CCInvocation->getDiagnosticOpts().IgnoreWarnings = true; | |||
2127 | ||||
2128 | std::unique_ptr<CompilerInstance> Clang( | |||
2129 | new CompilerInstance(PCHContainerOps)); | |||
2130 | ||||
2131 | // Recover resources if we crash before exiting this method. | |||
2132 | llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance> | |||
2133 | CICleanup(Clang.get()); | |||
2134 | ||||
2135 | auto &Inv = *CCInvocation; | |||
2136 | Clang->setInvocation(std::move(CCInvocation)); | |||
2137 | OriginalSourceFile = Clang->getFrontendOpts().Inputs[0].getFile(); | |||
2138 | ||||
2139 | // Set up diagnostics, capturing any diagnostics produced. | |||
2140 | Clang->setDiagnostics(&Diag); | |||
2141 | CaptureDroppedDiagnostics Capture(true, | |||
2142 | Clang->getDiagnostics(), | |||
2143 | &StoredDiagnostics, nullptr); | |||
2144 | ProcessWarningOptions(Diag, Inv.getDiagnosticOpts()); | |||
2145 | ||||
2146 | // Create the target instance. | |||
2147 | Clang->setTarget(TargetInfo::CreateTargetInfo( | |||
2148 | Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); | |||
2149 | if (!Clang->hasTarget()) { | |||
2150 | Clang->setInvocation(nullptr); | |||
2151 | return; | |||
2152 | } | |||
2153 | ||||
2154 | // Inform the target of the language options. | |||
2155 | // | |||
2156 | // FIXME: We shouldn't need to do this, the target should be immutable once | |||
2157 | // created. This complexity should be lifted elsewhere. | |||
2158 | Clang->getTarget().adjust(Clang->getLangOpts()); | |||
2159 | ||||
2160 | assert(Clang->getFrontendOpts().Inputs.size() == 1 &&(static_cast <bool> (Clang->getFrontendOpts().Inputs .size() == 1 && "Invocation must have exactly one source file!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs.size() == 1 && \"Invocation must have exactly one source file!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2161, __extension__ __PRETTY_FUNCTION__)) | |||
2161 | "Invocation must have exactly one source file!")(static_cast <bool> (Clang->getFrontendOpts().Inputs .size() == 1 && "Invocation must have exactly one source file!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs.size() == 1 && \"Invocation must have exactly one source file!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2161, __extension__ __PRETTY_FUNCTION__)); | |||
2162 | assert(Clang->getFrontendOpts().Inputs[0].getKind().getFormat() ==(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getFormat() == InputKind::Source && "FIXME: AST inputs not yet supported here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == InputKind::Source && \"FIXME: AST inputs not yet supported here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2164, __extension__ __PRETTY_FUNCTION__)) | |||
2163 | InputKind::Source &&(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getFormat() == InputKind::Source && "FIXME: AST inputs not yet supported here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == InputKind::Source && \"FIXME: AST inputs not yet supported here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2164, __extension__ __PRETTY_FUNCTION__)) | |||
2164 | "FIXME: AST inputs not yet supported here!")(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getFormat() == InputKind::Source && "FIXME: AST inputs not yet supported here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getFormat() == InputKind::Source && \"FIXME: AST inputs not yet supported here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2164, __extension__ __PRETTY_FUNCTION__)); | |||
2165 | assert(Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() !=(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getLanguage() != InputKind::LLVM_IR && "IR inputs not support here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != InputKind::LLVM_IR && \"IR inputs not support here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2167, __extension__ __PRETTY_FUNCTION__)) | |||
2166 | InputKind::LLVM_IR &&(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getLanguage() != InputKind::LLVM_IR && "IR inputs not support here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != InputKind::LLVM_IR && \"IR inputs not support here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2167, __extension__ __PRETTY_FUNCTION__)) | |||
2167 | "IR inputs not support here!")(static_cast <bool> (Clang->getFrontendOpts().Inputs [0].getKind().getLanguage() != InputKind::LLVM_IR && "IR inputs not support here!" ) ? void (0) : __assert_fail ("Clang->getFrontendOpts().Inputs[0].getKind().getLanguage() != InputKind::LLVM_IR && \"IR inputs not support here!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2167, __extension__ __PRETTY_FUNCTION__)); | |||
2168 | ||||
2169 | // Use the source and file managers that we were given. | |||
2170 | Clang->setFileManager(&FileMgr); | |||
2171 | Clang->setSourceManager(&SourceMgr); | |||
2172 | ||||
2173 | // Remap files. | |||
2174 | PreprocessorOpts.clearRemappedFiles(); | |||
2175 | PreprocessorOpts.RetainRemappedFileBuffers = true; | |||
2176 | for (const auto &RemappedFile : RemappedFiles) { | |||
2177 | PreprocessorOpts.addRemappedFile(RemappedFile.first, RemappedFile.second); | |||
2178 | OwnedBuffers.push_back(RemappedFile.second); | |||
2179 | } | |||
2180 | ||||
2181 | // Use the code completion consumer we were given, but adding any cached | |||
2182 | // code-completion results. | |||
2183 | AugmentedCodeCompleteConsumer *AugmentedConsumer | |||
2184 | = new AugmentedCodeCompleteConsumer(*this, Consumer, CodeCompleteOpts); | |||
2185 | Clang->setCodeCompletionConsumer(AugmentedConsumer); | |||
2186 | ||||
2187 | // If we have a precompiled preamble, try to use it. We only allow | |||
2188 | // the use of the precompiled preamble if we're if the completion | |||
2189 | // point is within the main file, after the end of the precompiled | |||
2190 | // preamble. | |||
2191 | std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer; | |||
2192 | if (Preamble) { | |||
2193 | std::string CompleteFilePath(File); | |||
2194 | ||||
2195 | auto VFS = FileMgr.getVirtualFileSystem(); | |||
2196 | auto CompleteFileStatus = VFS->status(CompleteFilePath); | |||
2197 | if (CompleteFileStatus) { | |||
2198 | llvm::sys::fs::UniqueID CompleteFileID = CompleteFileStatus->getUniqueID(); | |||
2199 | ||||
2200 | std::string MainPath(OriginalSourceFile); | |||
2201 | auto MainStatus = VFS->status(MainPath); | |||
2202 | if (MainStatus) { | |||
2203 | llvm::sys::fs::UniqueID MainID = MainStatus->getUniqueID(); | |||
2204 | if (CompleteFileID == MainID && Line > 1) | |||
2205 | OverrideMainBuffer = getMainBufferWithPrecompiledPreamble( | |||
2206 | PCHContainerOps, Inv, VFS, false, Line - 1); | |||
2207 | } | |||
2208 | } | |||
2209 | } | |||
2210 | ||||
2211 | // If the main file has been overridden due to the use of a preamble, | |||
2212 | // make that override happen and introduce the preamble. | |||
2213 | if (OverrideMainBuffer) { | |||
2214 | assert(Preamble &&(static_cast <bool> (Preamble && "No preamble was built, but OverrideMainBuffer is not null" ) ? void (0) : __assert_fail ("Preamble && \"No preamble was built, but OverrideMainBuffer is not null\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2215, __extension__ __PRETTY_FUNCTION__)) | |||
2215 | "No preamble was built, but OverrideMainBuffer is not null")(static_cast <bool> (Preamble && "No preamble was built, but OverrideMainBuffer is not null" ) ? void (0) : __assert_fail ("Preamble && \"No preamble was built, but OverrideMainBuffer is not null\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2215, __extension__ __PRETTY_FUNCTION__)); | |||
2216 | ||||
2217 | auto VFS = FileMgr.getVirtualFileSystem(); | |||
2218 | Preamble->AddImplicitPreamble(Clang->getInvocation(), VFS, | |||
2219 | OverrideMainBuffer.get()); | |||
2220 | // FIXME: there is no way to update VFS if it was changed by | |||
2221 | // AddImplicitPreamble as FileMgr is accepted as a parameter by this method. | |||
2222 | // We use on-disk preambles instead and rely on FileMgr's VFS to ensure the | |||
2223 | // PCH files are always readable. | |||
2224 | OwnedBuffers.push_back(OverrideMainBuffer.release()); | |||
2225 | } else { | |||
2226 | PreprocessorOpts.PrecompiledPreambleBytes.first = 0; | |||
2227 | PreprocessorOpts.PrecompiledPreambleBytes.second = false; | |||
2228 | } | |||
2229 | ||||
2230 | // Disable the preprocessing record if modules are not enabled. | |||
2231 | if (!Clang->getLangOpts().Modules) | |||
2232 | PreprocessorOpts.DetailedRecord = false; | |||
2233 | ||||
2234 | std::unique_ptr<SyntaxOnlyAction> Act; | |||
2235 | Act.reset(new SyntaxOnlyAction); | |||
2236 | if (Act->BeginSourceFile(*Clang.get(), Clang->getFrontendOpts().Inputs[0])) { | |||
2237 | Act->Execute(); | |||
2238 | Act->EndSourceFile(); | |||
2239 | } | |||
2240 | } | |||
2241 | ||||
2242 | bool ASTUnit::Save(StringRef File) { | |||
2243 | if (HadModuleLoaderFatalFailure) | |||
2244 | return true; | |||
2245 | ||||
2246 | // Write to a temporary file and later rename it to the actual file, to avoid | |||
2247 | // possible race conditions. | |||
2248 | SmallString<128> TempPath; | |||
2249 | TempPath = File; | |||
2250 | TempPath += "-%%%%%%%%"; | |||
2251 | int fd; | |||
2252 | if (llvm::sys::fs::createUniqueFile(TempPath, fd, TempPath)) | |||
2253 | return true; | |||
2254 | ||||
2255 | // FIXME: Can we somehow regenerate the stat cache here, or do we need to | |||
2256 | // unconditionally create a stat cache when we parse the file? | |||
2257 | llvm::raw_fd_ostream Out(fd, /*shouldClose=*/true); | |||
2258 | ||||
2259 | serialize(Out); | |||
2260 | Out.close(); | |||
2261 | if (Out.has_error()) { | |||
2262 | Out.clear_error(); | |||
2263 | return true; | |||
2264 | } | |||
2265 | ||||
2266 | if (llvm::sys::fs::rename(TempPath, File)) { | |||
2267 | llvm::sys::fs::remove(TempPath); | |||
2268 | return true; | |||
2269 | } | |||
2270 | ||||
2271 | return false; | |||
2272 | } | |||
2273 | ||||
2274 | static bool serializeUnit(ASTWriter &Writer, | |||
2275 | SmallVectorImpl<char> &Buffer, | |||
2276 | Sema &S, | |||
2277 | bool hasErrors, | |||
2278 | raw_ostream &OS) { | |||
2279 | Writer.WriteAST(S, std::string(), nullptr, "", hasErrors); | |||
2280 | ||||
2281 | // Write the generated bitstream to "Out". | |||
2282 | if (!Buffer.empty()) | |||
2283 | OS.write(Buffer.data(), Buffer.size()); | |||
2284 | ||||
2285 | return false; | |||
2286 | } | |||
2287 | ||||
2288 | bool ASTUnit::serialize(raw_ostream &OS) { | |||
2289 | // For serialization we are lenient if the errors were only warn-as-error kind. | |||
2290 | bool hasErrors = getDiagnostics().hasUncompilableErrorOccurred(); | |||
2291 | ||||
2292 | if (WriterData) | |||
2293 | return serializeUnit(WriterData->Writer, WriterData->Buffer, | |||
2294 | getSema(), hasErrors, OS); | |||
2295 | ||||
2296 | SmallString<128> Buffer; | |||
2297 | llvm::BitstreamWriter Stream(Buffer); | |||
2298 | MemoryBufferCache PCMCache; | |||
2299 | ASTWriter Writer(Stream, Buffer, PCMCache, {}); | |||
2300 | return serializeUnit(Writer, Buffer, getSema(), hasErrors, OS); | |||
2301 | } | |||
2302 | ||||
2303 | using SLocRemap = ContinuousRangeMap<unsigned, int, 2>; | |||
2304 | ||||
2305 | void ASTUnit::TranslateStoredDiagnostics( | |||
2306 | FileManager &FileMgr, | |||
2307 | SourceManager &SrcMgr, | |||
2308 | const SmallVectorImpl<StandaloneDiagnostic> &Diags, | |||
2309 | SmallVectorImpl<StoredDiagnostic> &Out) { | |||
2310 | // Map the standalone diagnostic into the new source manager. We also need to | |||
2311 | // remap all the locations to the new view. This includes the diag location, | |||
2312 | // any associated source ranges, and the source ranges of associated fix-its. | |||
2313 | // FIXME: There should be a cleaner way to do this. | |||
2314 | SmallVector<StoredDiagnostic, 4> Result; | |||
2315 | Result.reserve(Diags.size()); | |||
2316 | ||||
2317 | for (const auto &SD : Diags) { | |||
2318 | // Rebuild the StoredDiagnostic. | |||
2319 | if (SD.Filename.empty()) | |||
2320 | continue; | |||
2321 | const FileEntry *FE = FileMgr.getFile(SD.Filename); | |||
2322 | if (!FE) | |||
2323 | continue; | |||
2324 | SourceLocation FileLoc; | |||
2325 | auto ItFileID = PreambleSrcLocCache.find(SD.Filename); | |||
2326 | if (ItFileID == PreambleSrcLocCache.end()) { | |||
2327 | FileID FID = SrcMgr.translateFile(FE); | |||
2328 | FileLoc = SrcMgr.getLocForStartOfFile(FID); | |||
2329 | PreambleSrcLocCache[SD.Filename] = FileLoc; | |||
2330 | } else { | |||
2331 | FileLoc = ItFileID->getValue(); | |||
2332 | } | |||
2333 | ||||
2334 | if (FileLoc.isInvalid()) | |||
2335 | continue; | |||
2336 | SourceLocation L = FileLoc.getLocWithOffset(SD.LocOffset); | |||
2337 | FullSourceLoc Loc(L, SrcMgr); | |||
2338 | ||||
2339 | SmallVector<CharSourceRange, 4> Ranges; | |||
2340 | Ranges.reserve(SD.Ranges.size()); | |||
2341 | for (const auto &Range : SD.Ranges) { | |||
2342 | SourceLocation BL = FileLoc.getLocWithOffset(Range.first); | |||
2343 | SourceLocation EL = FileLoc.getLocWithOffset(Range.second); | |||
2344 | Ranges.push_back(CharSourceRange::getCharRange(BL, EL)); | |||
2345 | } | |||
2346 | ||||
2347 | SmallVector<FixItHint, 2> FixIts; | |||
2348 | FixIts.reserve(SD.FixIts.size()); | |||
2349 | for (const auto &FixIt : SD.FixIts) { | |||
2350 | FixIts.push_back(FixItHint()); | |||
2351 | FixItHint &FH = FixIts.back(); | |||
2352 | FH.CodeToInsert = FixIt.CodeToInsert; | |||
2353 | SourceLocation BL = FileLoc.getLocWithOffset(FixIt.RemoveRange.first); | |||
2354 | SourceLocation EL = FileLoc.getLocWithOffset(FixIt.RemoveRange.second); | |||
2355 | FH.RemoveRange = CharSourceRange::getCharRange(BL, EL); | |||
2356 | } | |||
2357 | ||||
2358 | Result.push_back(StoredDiagnostic(SD.Level, SD.ID, | |||
2359 | SD.Message, Loc, Ranges, FixIts)); | |||
2360 | } | |||
2361 | Result.swap(Out); | |||
2362 | } | |||
2363 | ||||
2364 | void ASTUnit::addFileLevelDecl(Decl *D) { | |||
2365 | assert(D)(static_cast <bool> (D) ? void (0) : __assert_fail ("D" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2365, __extension__ __PRETTY_FUNCTION__)); | |||
2366 | ||||
2367 | // We only care about local declarations. | |||
2368 | if (D->isFromASTFile()) | |||
2369 | return; | |||
2370 | ||||
2371 | SourceManager &SM = *SourceMgr; | |||
2372 | SourceLocation Loc = D->getLocation(); | |||
2373 | if (Loc.isInvalid() || !SM.isLocalSourceLocation(Loc)) | |||
2374 | return; | |||
2375 | ||||
2376 | // We only keep track of the file-level declarations of each file. | |||
2377 | if (!D->getLexicalDeclContext()->isFileContext()) | |||
2378 | return; | |||
2379 | ||||
2380 | SourceLocation FileLoc = SM.getFileLoc(Loc); | |||
2381 | assert(SM.isLocalSourceLocation(FileLoc))(static_cast <bool> (SM.isLocalSourceLocation(FileLoc)) ? void (0) : __assert_fail ("SM.isLocalSourceLocation(FileLoc)" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2381, __extension__ __PRETTY_FUNCTION__)); | |||
2382 | FileID FID; | |||
2383 | unsigned Offset; | |||
2384 | std::tie(FID, Offset) = SM.getDecomposedLoc(FileLoc); | |||
2385 | if (FID.isInvalid()) | |||
2386 | return; | |||
2387 | ||||
2388 | LocDeclsTy *&Decls = FileDecls[FID]; | |||
2389 | if (!Decls) | |||
2390 | Decls = new LocDeclsTy(); | |||
2391 | ||||
2392 | std::pair<unsigned, Decl *> LocDecl(Offset, D); | |||
2393 | ||||
2394 | if (Decls->empty() || Decls->back().first <= Offset) { | |||
2395 | Decls->push_back(LocDecl); | |||
2396 | return; | |||
2397 | } | |||
2398 | ||||
2399 | LocDeclsTy::iterator I = std::upper_bound(Decls->begin(), Decls->end(), | |||
2400 | LocDecl, llvm::less_first()); | |||
2401 | ||||
2402 | Decls->insert(I, LocDecl); | |||
2403 | } | |||
2404 | ||||
2405 | void ASTUnit::findFileRegionDecls(FileID File, unsigned Offset, unsigned Length, | |||
2406 | SmallVectorImpl<Decl *> &Decls) { | |||
2407 | if (File.isInvalid()) | |||
2408 | return; | |||
2409 | ||||
2410 | if (SourceMgr->isLoadedFileID(File)) { | |||
2411 | assert(Ctx->getExternalSource() && "No external source!")(static_cast <bool> (Ctx->getExternalSource() && "No external source!") ? void (0) : __assert_fail ("Ctx->getExternalSource() && \"No external source!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2411, __extension__ __PRETTY_FUNCTION__)); | |||
2412 | return Ctx->getExternalSource()->FindFileRegionDecls(File, Offset, Length, | |||
2413 | Decls); | |||
2414 | } | |||
2415 | ||||
2416 | FileDeclsTy::iterator I = FileDecls.find(File); | |||
2417 | if (I == FileDecls.end()) | |||
2418 | return; | |||
2419 | ||||
2420 | LocDeclsTy &LocDecls = *I->second; | |||
2421 | if (LocDecls.empty()) | |||
2422 | return; | |||
2423 | ||||
2424 | LocDeclsTy::iterator BeginIt = | |||
2425 | std::lower_bound(LocDecls.begin(), LocDecls.end(), | |||
2426 | std::make_pair(Offset, (Decl *)nullptr), | |||
2427 | llvm::less_first()); | |||
2428 | if (BeginIt != LocDecls.begin()) | |||
2429 | --BeginIt; | |||
2430 | ||||
2431 | // If we are pointing at a top-level decl inside an objc container, we need | |||
2432 | // to backtrack until we find it otherwise we will fail to report that the | |||
2433 | // region overlaps with an objc container. | |||
2434 | while (BeginIt != LocDecls.begin() && | |||
2435 | BeginIt->second->isTopLevelDeclInObjCContainer()) | |||
2436 | --BeginIt; | |||
2437 | ||||
2438 | LocDeclsTy::iterator EndIt = std::upper_bound( | |||
2439 | LocDecls.begin(), LocDecls.end(), | |||
2440 | std::make_pair(Offset + Length, (Decl *)nullptr), llvm::less_first()); | |||
2441 | if (EndIt != LocDecls.end()) | |||
2442 | ++EndIt; | |||
2443 | ||||
2444 | for (LocDeclsTy::iterator DIt = BeginIt; DIt != EndIt; ++DIt) | |||
2445 | Decls.push_back(DIt->second); | |||
2446 | } | |||
2447 | ||||
2448 | SourceLocation ASTUnit::getLocation(const FileEntry *File, | |||
2449 | unsigned Line, unsigned Col) const { | |||
2450 | const SourceManager &SM = getSourceManager(); | |||
2451 | SourceLocation Loc = SM.translateFileLineCol(File, Line, Col); | |||
2452 | return SM.getMacroArgExpandedLocation(Loc); | |||
2453 | } | |||
2454 | ||||
2455 | SourceLocation ASTUnit::getLocation(const FileEntry *File, | |||
2456 | unsigned Offset) const { | |||
2457 | const SourceManager &SM = getSourceManager(); | |||
2458 | SourceLocation FileLoc = SM.translateFileLineCol(File, 1, 1); | |||
2459 | return SM.getMacroArgExpandedLocation(FileLoc.getLocWithOffset(Offset)); | |||
2460 | } | |||
2461 | ||||
2462 | /// \brief If \arg Loc is a loaded location from the preamble, returns | |||
2463 | /// the corresponding local location of the main file, otherwise it returns | |||
2464 | /// \arg Loc. | |||
2465 | SourceLocation ASTUnit::mapLocationFromPreamble(SourceLocation Loc) const { | |||
2466 | FileID PreambleID; | |||
2467 | if (SourceMgr) | |||
2468 | PreambleID = SourceMgr->getPreambleFileID(); | |||
2469 | ||||
2470 | if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid()) | |||
2471 | return Loc; | |||
2472 | ||||
2473 | unsigned Offs; | |||
2474 | if (SourceMgr->isInFileID(Loc, PreambleID, &Offs) && Offs < Preamble->getBounds().Size) { | |||
2475 | SourceLocation FileLoc | |||
2476 | = SourceMgr->getLocForStartOfFile(SourceMgr->getMainFileID()); | |||
2477 | return FileLoc.getLocWithOffset(Offs); | |||
2478 | } | |||
2479 | ||||
2480 | return Loc; | |||
2481 | } | |||
2482 | ||||
2483 | /// \brief If \arg Loc is a local location of the main file but inside the | |||
2484 | /// preamble chunk, returns the corresponding loaded location from the | |||
2485 | /// preamble, otherwise it returns \arg Loc. | |||
2486 | SourceLocation ASTUnit::mapLocationToPreamble(SourceLocation Loc) const { | |||
2487 | FileID PreambleID; | |||
2488 | if (SourceMgr) | |||
2489 | PreambleID = SourceMgr->getPreambleFileID(); | |||
2490 | ||||
2491 | if (Loc.isInvalid() || !Preamble || PreambleID.isInvalid()) | |||
2492 | return Loc; | |||
2493 | ||||
2494 | unsigned Offs; | |||
2495 | if (SourceMgr->isInFileID(Loc, SourceMgr->getMainFileID(), &Offs) && | |||
2496 | Offs < Preamble->getBounds().Size) { | |||
2497 | SourceLocation FileLoc = SourceMgr->getLocForStartOfFile(PreambleID); | |||
2498 | return FileLoc.getLocWithOffset(Offs); | |||
2499 | } | |||
2500 | ||||
2501 | return Loc; | |||
2502 | } | |||
2503 | ||||
2504 | bool ASTUnit::isInPreambleFileID(SourceLocation Loc) const { | |||
2505 | FileID FID; | |||
2506 | if (SourceMgr) | |||
2507 | FID = SourceMgr->getPreambleFileID(); | |||
2508 | ||||
2509 | if (Loc.isInvalid() || FID.isInvalid()) | |||
2510 | return false; | |||
2511 | ||||
2512 | return SourceMgr->isInFileID(Loc, FID); | |||
2513 | } | |||
2514 | ||||
2515 | bool ASTUnit::isInMainFileID(SourceLocation Loc) const { | |||
2516 | FileID FID; | |||
2517 | if (SourceMgr) | |||
2518 | FID = SourceMgr->getMainFileID(); | |||
2519 | ||||
2520 | if (Loc.isInvalid() || FID.isInvalid()) | |||
2521 | return false; | |||
2522 | ||||
2523 | return SourceMgr->isInFileID(Loc, FID); | |||
2524 | } | |||
2525 | ||||
2526 | SourceLocation ASTUnit::getEndOfPreambleFileID() const { | |||
2527 | FileID FID; | |||
2528 | if (SourceMgr) | |||
2529 | FID = SourceMgr->getPreambleFileID(); | |||
2530 | ||||
2531 | if (FID.isInvalid()) | |||
2532 | return {}; | |||
2533 | ||||
2534 | return SourceMgr->getLocForEndOfFile(FID); | |||
2535 | } | |||
2536 | ||||
2537 | SourceLocation ASTUnit::getStartOfMainFileID() const { | |||
2538 | FileID FID; | |||
2539 | if (SourceMgr) | |||
2540 | FID = SourceMgr->getMainFileID(); | |||
2541 | ||||
2542 | if (FID.isInvalid()) | |||
2543 | return {}; | |||
2544 | ||||
2545 | return SourceMgr->getLocForStartOfFile(FID); | |||
2546 | } | |||
2547 | ||||
2548 | llvm::iterator_range<PreprocessingRecord::iterator> | |||
2549 | ASTUnit::getLocalPreprocessingEntities() const { | |||
2550 | if (isMainFileAST()) { | |||
2551 | serialization::ModuleFile & | |||
2552 | Mod = Reader->getModuleManager().getPrimaryModule(); | |||
2553 | return Reader->getModulePreprocessedEntities(Mod); | |||
2554 | } | |||
2555 | ||||
2556 | if (PreprocessingRecord *PPRec = PP->getPreprocessingRecord()) | |||
2557 | return llvm::make_range(PPRec->local_begin(), PPRec->local_end()); | |||
2558 | ||||
2559 | return llvm::make_range(PreprocessingRecord::iterator(), | |||
2560 | PreprocessingRecord::iterator()); | |||
2561 | } | |||
2562 | ||||
2563 | bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) { | |||
2564 | if (isMainFileAST()) { | |||
2565 | serialization::ModuleFile & | |||
2566 | Mod = Reader->getModuleManager().getPrimaryModule(); | |||
2567 | for (const auto *D : Reader->getModuleFileLevelDecls(Mod)) { | |||
2568 | if (!Fn(context, D)) | |||
2569 | return false; | |||
2570 | } | |||
2571 | ||||
2572 | return true; | |||
2573 | } | |||
2574 | ||||
2575 | for (ASTUnit::top_level_iterator TL = top_level_begin(), | |||
2576 | TLEnd = top_level_end(); | |||
2577 | TL != TLEnd; ++TL) { | |||
2578 | if (!Fn(context, *TL)) | |||
2579 | return false; | |||
2580 | } | |||
2581 | ||||
2582 | return true; | |||
2583 | } | |||
2584 | ||||
2585 | const FileEntry *ASTUnit::getPCHFile() { | |||
2586 | if (!Reader) | |||
2587 | return nullptr; | |||
2588 | ||||
2589 | serialization::ModuleFile *Mod = nullptr; | |||
2590 | Reader->getModuleManager().visit([&Mod](serialization::ModuleFile &M) { | |||
2591 | switch (M.Kind) { | |||
2592 | case serialization::MK_ImplicitModule: | |||
2593 | case serialization::MK_ExplicitModule: | |||
2594 | case serialization::MK_PrebuiltModule: | |||
2595 | return true; // skip dependencies. | |||
2596 | case serialization::MK_PCH: | |||
2597 | Mod = &M; | |||
2598 | return true; // found it. | |||
2599 | case serialization::MK_Preamble: | |||
2600 | return false; // look in dependencies. | |||
2601 | case serialization::MK_MainFile: | |||
2602 | return false; // look in dependencies. | |||
2603 | } | |||
2604 | ||||
2605 | return true; | |||
2606 | }); | |||
2607 | if (Mod) | |||
2608 | return Mod->File; | |||
2609 | ||||
2610 | return nullptr; | |||
2611 | } | |||
2612 | ||||
2613 | bool ASTUnit::isModuleFile() const { | |||
2614 | return isMainFileAST() && getLangOpts().isCompilingModule(); | |||
2615 | } | |||
2616 | ||||
2617 | InputKind ASTUnit::getInputKind() const { | |||
2618 | auto &LangOpts = getLangOpts(); | |||
2619 | ||||
2620 | InputKind::Language Lang; | |||
2621 | if (LangOpts.OpenCL) | |||
2622 | Lang = InputKind::OpenCL; | |||
2623 | else if (LangOpts.CUDA) | |||
2624 | Lang = InputKind::CUDA; | |||
2625 | else if (LangOpts.RenderScript) | |||
2626 | Lang = InputKind::RenderScript; | |||
2627 | else if (LangOpts.CPlusPlus) | |||
2628 | Lang = LangOpts.ObjC1 ? InputKind::ObjCXX : InputKind::CXX; | |||
2629 | else | |||
2630 | Lang = LangOpts.ObjC1 ? InputKind::ObjC : InputKind::C; | |||
2631 | ||||
2632 | InputKind::Format Fmt = InputKind::Source; | |||
2633 | if (LangOpts.getCompilingModule() == LangOptions::CMK_ModuleMap) | |||
2634 | Fmt = InputKind::ModuleMap; | |||
2635 | ||||
2636 | // We don't know if input was preprocessed. Assume not. | |||
2637 | bool PP = false; | |||
2638 | ||||
2639 | return InputKind(Lang, Fmt, PP); | |||
2640 | } | |||
2641 | ||||
2642 | #ifndef NDEBUG | |||
2643 | ASTUnit::ConcurrencyState::ConcurrencyState() { | |||
2644 | Mutex = new llvm::sys::MutexImpl(/*recursive=*/true); | |||
2645 | } | |||
2646 | ||||
2647 | ASTUnit::ConcurrencyState::~ConcurrencyState() { | |||
2648 | delete static_cast<llvm::sys::MutexImpl *>(Mutex); | |||
2649 | } | |||
2650 | ||||
2651 | void ASTUnit::ConcurrencyState::start() { | |||
2652 | bool acquired = static_cast<llvm::sys::MutexImpl *>(Mutex)->tryacquire(); | |||
2653 | assert(acquired && "Concurrent access to ASTUnit!")(static_cast <bool> (acquired && "Concurrent access to ASTUnit!" ) ? void (0) : __assert_fail ("acquired && \"Concurrent access to ASTUnit!\"" , "/build/llvm-toolchain-snapshot-7~svn329677/tools/clang/lib/Frontend/ASTUnit.cpp" , 2653, __extension__ __PRETTY_FUNCTION__)); | |||
2654 | } | |||
2655 | ||||
2656 | void ASTUnit::ConcurrencyState::finish() { | |||
2657 | static_cast<llvm::sys::MutexImpl *>(Mutex)->release(); | |||
2658 | } | |||
2659 | ||||
2660 | #else // NDEBUG | |||
2661 | ||||
2662 | ASTUnit::ConcurrencyState::ConcurrencyState() { Mutex = nullptr; } | |||
2663 | ASTUnit::ConcurrencyState::~ConcurrencyState() {} | |||
2664 | void ASTUnit::ConcurrencyState::start() {} | |||
2665 | void ASTUnit::ConcurrencyState::finish() {} | |||
2666 | ||||
2667 | #endif // NDEBUG |
1 | //==- llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer --*- C++ -*-==// | |||
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 | // This file defines the RefCountedBase, ThreadSafeRefCountedBase, and | |||
11 | // IntrusiveRefCntPtr classes. | |||
12 | // | |||
13 | // IntrusiveRefCntPtr is a smart pointer to an object which maintains a | |||
14 | // reference count. (ThreadSafe)RefCountedBase is a mixin class that adds a | |||
15 | // refcount member variable and methods for updating the refcount. An object | |||
16 | // that inherits from (ThreadSafe)RefCountedBase deletes itself when its | |||
17 | // refcount hits zero. | |||
18 | // | |||
19 | // For example: | |||
20 | // | |||
21 | // class MyClass : public RefCountedBase<MyClass> {}; | |||
22 | // | |||
23 | // void foo() { | |||
24 | // // Constructing an IntrusiveRefCntPtr increases the pointee's refcount by | |||
25 | // // 1 (from 0 in this case). | |||
26 | // IntrusiveRefCntPtr<MyClass> Ptr1(new MyClass()); | |||
27 | // | |||
28 | // // Copying an IntrusiveRefCntPtr increases the pointee's refcount by 1. | |||
29 | // IntrusiveRefCntPtr<MyClass> Ptr2(Ptr1); | |||
30 | // | |||
31 | // // Constructing an IntrusiveRefCntPtr has no effect on the object's | |||
32 | // // refcount. After a move, the moved-from pointer is null. | |||
33 | // IntrusiveRefCntPtr<MyClass> Ptr3(std::move(Ptr1)); | |||
34 | // assert(Ptr1 == nullptr); | |||
35 | // | |||
36 | // // Clearing an IntrusiveRefCntPtr decreases the pointee's refcount by 1. | |||
37 | // Ptr2.reset(); | |||
38 | // | |||
39 | // // The object deletes itself when we return from the function, because | |||
40 | // // Ptr3's destructor decrements its refcount to 0. | |||
41 | // } | |||
42 | // | |||
43 | // You can use IntrusiveRefCntPtr with isa<T>(), dyn_cast<T>(), etc.: | |||
44 | // | |||
45 | // IntrusiveRefCntPtr<MyClass> Ptr(new MyClass()); | |||
46 | // OtherClass *Other = dyn_cast<OtherClass>(Ptr); // Ptr.get() not required | |||
47 | // | |||
48 | // IntrusiveRefCntPtr works with any class that | |||
49 | // | |||
50 | // - inherits from (ThreadSafe)RefCountedBase, | |||
51 | // - has Retain() and Release() methods, or | |||
52 | // - specializes IntrusiveRefCntPtrInfo. | |||
53 | // | |||
54 | //===----------------------------------------------------------------------===// | |||
55 | ||||
56 | #ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H | |||
57 | #define LLVM_ADT_INTRUSIVEREFCNTPTR_H | |||
58 | ||||
59 | #include <atomic> | |||
60 | #include <cassert> | |||
61 | #include <cstddef> | |||
62 | ||||
63 | namespace llvm { | |||
64 | ||||
65 | /// A CRTP mixin class that adds reference counting to a type. | |||
66 | /// | |||
67 | /// The lifetime of an object which inherits from RefCountedBase is managed by | |||
68 | /// calls to Release() and Retain(), which increment and decrement the object's | |||
69 | /// refcount, respectively. When a Release() call decrements the refcount to 0, | |||
70 | /// the object deletes itself. | |||
71 | template <class Derived> class RefCountedBase { | |||
72 | mutable unsigned RefCount = 0; | |||
73 | ||||
74 | public: | |||
75 | RefCountedBase() = default; | |||
76 | RefCountedBase(const RefCountedBase &) {} | |||
77 | ||||
78 | void Retain() const { ++RefCount; } | |||
79 | ||||
80 | void Release() const { | |||
81 | assert(RefCount > 0 && "Reference count is already zero.")(static_cast <bool> (RefCount > 0 && "Reference count is already zero." ) ? void (0) : __assert_fail ("RefCount > 0 && \"Reference count is already zero.\"" , "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/ADT/IntrusiveRefCntPtr.h" , 81, __extension__ __PRETTY_FUNCTION__)); | |||
82 | if (--RefCount == 0) | |||
83 | delete static_cast<const Derived *>(this); | |||
84 | } | |||
85 | }; | |||
86 | ||||
87 | /// A thread-safe version of \c RefCountedBase. | |||
88 | template <class Derived> class ThreadSafeRefCountedBase { | |||
89 | mutable std::atomic<int> RefCount; | |||
90 | ||||
91 | protected: | |||
92 | ThreadSafeRefCountedBase() : RefCount(0) {} | |||
93 | ||||
94 | public: | |||
95 | void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); } | |||
96 | ||||
97 | void Release() const { | |||
98 | int NewRefCount = RefCount.fetch_sub(1, std::memory_order_acq_rel) - 1; | |||
99 | assert(NewRefCount >= 0 && "Reference count was already zero.")(static_cast <bool> (NewRefCount >= 0 && "Reference count was already zero." ) ? void (0) : __assert_fail ("NewRefCount >= 0 && \"Reference count was already zero.\"" , "/build/llvm-toolchain-snapshot-7~svn329677/include/llvm/ADT/IntrusiveRefCntPtr.h" , 99, __extension__ __PRETTY_FUNCTION__)); | |||
100 | if (NewRefCount == 0) | |||
101 | delete static_cast<const Derived *>(this); | |||
102 | } | |||
103 | }; | |||
104 | ||||
105 | /// Class you can specialize to provide custom retain/release functionality for | |||
106 | /// a type. | |||
107 | /// | |||
108 | /// Usually specializing this class is not necessary, as IntrusiveRefCntPtr | |||
109 | /// works with any type which defines Retain() and Release() functions -- you | |||
110 | /// can define those functions yourself if RefCountedBase doesn't work for you. | |||
111 | /// | |||
112 | /// One case when you might want to specialize this type is if you have | |||
113 | /// - Foo.h defines type Foo and includes Bar.h, and | |||
114 | /// - Bar.h uses IntrusiveRefCntPtr<Foo> in inline functions. | |||
115 | /// | |||
116 | /// Because Foo.h includes Bar.h, Bar.h can't include Foo.h in order to pull in | |||
117 | /// the declaration of Foo. Without the declaration of Foo, normally Bar.h | |||
118 | /// wouldn't be able to use IntrusiveRefCntPtr<Foo>, which wants to call | |||
119 | /// T::Retain and T::Release. | |||
120 | /// | |||
121 | /// To resolve this, Bar.h could include a third header, FooFwd.h, which | |||
122 | /// forward-declares Foo and specializes IntrusiveRefCntPtrInfo<Foo>. Then | |||
123 | /// Bar.h could use IntrusiveRefCntPtr<Foo>, although it still couldn't call any | |||
124 | /// functions on Foo itself, because Foo would be an incomplete type. | |||
125 | template <typename T> struct IntrusiveRefCntPtrInfo { | |||
126 | static void retain(T *obj) { obj->Retain(); } | |||
127 | static void release(T *obj) { obj->Release(); } | |||
128 | }; | |||
129 | ||||
130 | /// A smart pointer to a reference-counted object that inherits from | |||
131 | /// RefCountedBase or ThreadSafeRefCountedBase. | |||
132 | /// | |||
133 | /// This class increments its pointee's reference count when it is created, and | |||
134 | /// decrements its refcount when it's destroyed (or is changed to point to a | |||
135 | /// different object). | |||
136 | template <typename T> class IntrusiveRefCntPtr { | |||
137 | T *Obj = nullptr; | |||
138 | ||||
139 | public: | |||
140 | using element_type = T; | |||
141 | ||||
142 | explicit IntrusiveRefCntPtr() = default; | |||
143 | IntrusiveRefCntPtr(T *obj) : Obj(obj) { retain(); } | |||
144 | IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.Obj) { retain(); } | |||
145 | IntrusiveRefCntPtr(IntrusiveRefCntPtr &&S) : Obj(S.Obj) { S.Obj = nullptr; } | |||
146 | ||||
147 | template <class X> | |||
148 | IntrusiveRefCntPtr(IntrusiveRefCntPtr<X> &&S) : Obj(S.get()) { | |||
149 | S.Obj = nullptr; | |||
150 | } | |||
151 | ||||
152 | template <class X> | |||
153 | IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X> &S) : Obj(S.get()) { | |||
154 | retain(); | |||
155 | } | |||
156 | ||||
157 | ~IntrusiveRefCntPtr() { release(); } | |||
| ||||
158 | ||||
159 | IntrusiveRefCntPtr &operator=(IntrusiveRefCntPtr S) { | |||
160 | swap(S); | |||
161 | return *this; | |||
162 | } | |||
163 | ||||
164 | T &operator*() const { return *Obj; } | |||
165 | T *operator->() const { return Obj; } | |||
166 | T *get() const { return Obj; } | |||
167 | explicit operator bool() const { return Obj; } | |||
168 | ||||
169 | void swap(IntrusiveRefCntPtr &other) { | |||
170 | T *tmp = other.Obj; | |||
171 | other.Obj = Obj; | |||
172 | Obj = tmp; | |||
173 | } | |||
174 | ||||
175 | void reset() { | |||
176 | release(); | |||
177 | Obj = nullptr; | |||
178 | } | |||
179 | ||||
180 | void resetWithoutRelease() { Obj = nullptr; } | |||
181 | ||||
182 | private: | |||
183 | void retain() { | |||
184 | if (Obj) | |||
185 | IntrusiveRefCntPtrInfo<T>::retain(Obj); | |||
186 | } | |||
187 | ||||
188 | void release() { | |||
189 | if (Obj) | |||
190 | IntrusiveRefCntPtrInfo<T>::release(Obj); | |||
191 | } | |||
192 | ||||
193 | template <typename X> friend class IntrusiveRefCntPtr; | |||
194 | }; | |||
195 | ||||
196 | template <class T, class U> | |||
197 | inline bool operator==(const IntrusiveRefCntPtr<T> &A, | |||
198 | const IntrusiveRefCntPtr<U> &B) { | |||
199 | return A.get() == B.get(); | |||
200 | } | |||
201 | ||||
202 | template <class T, class U> | |||
203 | inline bool operator!=(const IntrusiveRefCntPtr<T> &A, | |||
204 | const IntrusiveRefCntPtr<U> &B) { | |||
205 | return A.get() != B.get(); | |||
206 | } | |||
207 | ||||
208 | template <class T, class U> | |||
209 | inline bool operator==(const IntrusiveRefCntPtr<T> &A, U *B) { | |||
210 | return A.get() == B; | |||
211 | } | |||
212 | ||||
213 | template <class T, class U> | |||
214 | inline bool operator!=(const IntrusiveRefCntPtr<T> &A, U *B) { | |||
215 | return A.get() != B; | |||
216 | } | |||
217 | ||||
218 | template <class T, class U> | |||
219 | inline bool operator==(T *A, const IntrusiveRefCntPtr<U> &B) { | |||
220 | return A == B.get(); | |||
221 | } | |||
222 | ||||
223 | template <class T, class U> | |||
224 | inline bool operator!=(T *A, const IntrusiveRefCntPtr<U> &B) { | |||
225 | return A != B.get(); | |||
226 | } | |||
227 | ||||
228 | template <class T> | |||
229 | bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { | |||
230 | return !B; | |||
231 | } | |||
232 | ||||
233 | template <class T> | |||
234 | bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { | |||
235 | return B == A; | |||
236 | } | |||
237 | ||||
238 | template <class T> | |||
239 | bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) { | |||
240 | return !(A == B); | |||
241 | } | |||
242 | ||||
243 | template <class T> | |||
244 | bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) { | |||
245 | return !(A == B); | |||
246 | } | |||
247 | ||||
248 | // Make IntrusiveRefCntPtr work with dyn_cast, isa, and the other idioms from | |||
249 | // Casting.h. | |||
250 | template <typename From> struct simplify_type; | |||
251 | ||||
252 | template <class T> struct simplify_type<IntrusiveRefCntPtr<T>> { | |||
253 | using SimpleType = T *; | |||
254 | ||||
255 | static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T> &Val) { | |||
256 | return Val.get(); | |||
257 | } | |||
258 | }; | |||
259 | ||||
260 | template <class T> struct simplify_type<const IntrusiveRefCntPtr<T>> { | |||
261 | using SimpleType = /*const*/ T *; | |||
262 | ||||
263 | static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T> &Val) { | |||
264 | return Val.get(); | |||
265 | } | |||
266 | }; | |||
267 | ||||
268 | } // end namespace llvm | |||
269 | ||||
270 | #endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H |