Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | //===- ExternalASTSource.h - Abstract External AST Interface ----*- 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 ExternalASTSource interface, which enables |
11 | // construction of AST nodes from some external source. |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H |
16 | #define LLVM_CLANG_AST_EXTERNALASTSOURCE_H |
17 | |
18 | #include "clang/AST/CharUnits.h" |
19 | #include "clang/AST/DeclBase.h" |
20 | #include "clang/Basic/LLVM.h" |
21 | #include "clang/Basic/Module.h" |
22 | #include "llvm/ADT/ArrayRef.h" |
23 | #include "llvm/ADT/DenseMap.h" |
24 | #include "llvm/ADT/IntrusiveRefCntPtr.h" |
25 | #include "llvm/ADT/Optional.h" |
26 | #include "llvm/ADT/PointerUnion.h" |
27 | #include "llvm/ADT/STLExtras.h" |
28 | #include "llvm/ADT/SmallVector.h" |
29 | #include "llvm/ADT/StringRef.h" |
30 | #include "llvm/ADT/iterator.h" |
31 | #include "llvm/Support/PointerLikeTypeTraits.h" |
32 | #include <cassert> |
33 | #include <cstddef> |
34 | #include <cstdint> |
35 | #include <iterator> |
36 | #include <string> |
37 | #include <utility> |
38 | |
39 | namespace clang { |
40 | |
41 | class ASTConsumer; |
42 | class ASTContext; |
43 | class CXXBaseSpecifier; |
44 | class CXXCtorInitializer; |
45 | class CXXRecordDecl; |
46 | class DeclarationName; |
47 | class FieldDecl; |
48 | class IdentifierInfo; |
49 | class NamedDecl; |
50 | class ObjCInterfaceDecl; |
51 | class RecordDecl; |
52 | class Selector; |
53 | class Stmt; |
54 | class TagDecl; |
55 | |
56 | /// Abstract interface for external sources of AST nodes. |
57 | /// |
58 | /// External AST sources provide AST nodes constructed from some |
59 | /// external source, such as a precompiled header. External AST |
60 | /// sources can resolve types and declarations from abstract IDs into |
61 | /// actual type and declaration nodes, and read parts of declaration |
62 | /// contexts. |
63 | class ExternalASTSource : public RefCountedBase<ExternalASTSource> { |
64 | friend class ExternalSemaSource; |
65 | |
66 | /// Generation number for this external AST source. Must be increased |
67 | /// whenever we might have added new redeclarations for existing decls. |
68 | uint32_t CurrentGeneration = 0; |
69 | |
70 | /// Whether this AST source also provides information for |
71 | /// semantic analysis. |
72 | bool SemaSource = false; |
73 | |
74 | public: |
75 | ExternalASTSource() = default; |
76 | virtual ~ExternalASTSource(); |
77 | |
78 | /// RAII class for safely pairing a StartedDeserializing call |
79 | /// with FinishedDeserializing. |
80 | class Deserializing { |
81 | ExternalASTSource *Source; |
82 | |
83 | public: |
84 | explicit Deserializing(ExternalASTSource *source) : Source(source) { |
85 | assert(Source); |
86 | Source->StartedDeserializing(); |
87 | } |
88 | |
89 | ~Deserializing() { |
90 | Source->FinishedDeserializing(); |
91 | } |
92 | }; |
93 | |
94 | /// Get the current generation of this AST source. This number |
95 | /// is incremented each time the AST source lazily extends an existing |
96 | /// entity. |
97 | uint32_t getGeneration() const { return CurrentGeneration; } |
98 | |
99 | /// Resolve a declaration ID into a declaration, potentially |
100 | /// building a new declaration. |
101 | /// |
102 | /// This method only needs to be implemented if the AST source ever |
103 | /// passes back decl sets as VisibleDeclaration objects. |
104 | /// |
105 | /// The default implementation of this method is a no-op. |
106 | virtual Decl *GetExternalDecl(uint32_t ID); |
107 | |
108 | /// Resolve a selector ID into a selector. |
109 | /// |
110 | /// This operation only needs to be implemented if the AST source |
111 | /// returns non-zero for GetNumKnownSelectors(). |
112 | /// |
113 | /// The default implementation of this method is a no-op. |
114 | virtual Selector GetExternalSelector(uint32_t ID); |
115 | |
116 | /// Returns the number of selectors known to the external AST |
117 | /// source. |
118 | /// |
119 | /// The default implementation of this method is a no-op. |
120 | virtual uint32_t GetNumExternalSelectors(); |
121 | |
122 | /// Resolve the offset of a statement in the decl stream into |
123 | /// a statement. |
124 | /// |
125 | /// This operation is meant to be used via a LazyOffsetPtr. It only |
126 | /// needs to be implemented if the AST source uses methods like |
127 | /// FunctionDecl::setLazyBody when building decls. |
128 | /// |
129 | /// The default implementation of this method is a no-op. |
130 | virtual Stmt *GetExternalDeclStmt(uint64_t Offset); |
131 | |
132 | /// Resolve the offset of a set of C++ constructor initializers in |
133 | /// the decl stream into an array of initializers. |
134 | /// |
135 | /// The default implementation of this method is a no-op. |
136 | virtual CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset); |
137 | |
138 | /// Resolve the offset of a set of C++ base specifiers in the decl |
139 | /// stream into an array of specifiers. |
140 | /// |
141 | /// The default implementation of this method is a no-op. |
142 | virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); |
143 | |
144 | /// Update an out-of-date identifier. |
145 | virtual void updateOutOfDateIdentifier(IdentifierInfo &II) {} |
146 | |
147 | /// Find all declarations with the given name in the given context, |
148 | /// and add them to the context by calling SetExternalVisibleDeclsForName |
149 | /// or SetNoExternalVisibleDeclsForName. |
150 | /// \return \c true if any declarations might have been found, \c false if |
151 | /// we definitely have no declarations with tbis name. |
152 | /// |
153 | /// The default implementation of this method is a no-op returning \c false. |
154 | virtual bool |
155 | FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); |
156 | |
157 | /// Ensures that the table of all visible declarations inside this |
158 | /// context is up to date. |
159 | /// |
160 | /// The default implementation of this function is a no-op. |
161 | virtual void completeVisibleDeclsMap(const DeclContext *DC); |
162 | |
163 | /// Retrieve the module that corresponds to the given module ID. |
164 | virtual Module *getModule(unsigned ID) { return nullptr; } |
165 | |
166 | /// Determine whether D comes from a PCH which was built with a corresponding |
167 | /// object file. |
168 | virtual bool DeclIsFromPCHWithObjectFile(const Decl *D) { return false; } |
169 | |
170 | /// Abstracts clang modules and precompiled header files and holds |
171 | /// everything needed to generate debug info for an imported module |
172 | /// or PCH. |
173 | class ASTSourceDescriptor { |
174 | StringRef PCHModuleName; |
175 | StringRef Path; |
176 | StringRef ASTFile; |
177 | ASTFileSignature Signature; |
178 | const Module *ClangModule = nullptr; |
179 | |
180 | public: |
181 | ASTSourceDescriptor() = default; |
182 | ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile, |
183 | ASTFileSignature Signature) |
184 | : PCHModuleName(std::move(Name)), Path(std::move(Path)), |
185 | ASTFile(std::move(ASTFile)), Signature(Signature) {} |
186 | ASTSourceDescriptor(const Module &M); |
187 | |
188 | std::string getModuleName() const; |
189 | StringRef getPath() const { return Path; } |
190 | StringRef getASTFile() const { return ASTFile; } |
191 | ASTFileSignature getSignature() const { return Signature; } |
192 | const Module *getModuleOrNull() const { return ClangModule; } |
193 | }; |
194 | |
195 | /// Return a descriptor for the corresponding module, if one exists. |
196 | virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID); |
197 | |
198 | enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy }; |
199 | |
200 | virtual ExtKind hasExternalDefinitions(const Decl *D); |
201 | |
202 | /// Finds all declarations lexically contained within the given |
203 | /// DeclContext, after applying an optional filter predicate. |
204 | /// |
205 | /// \param IsKindWeWant a predicate function that returns true if the passed |
206 | /// declaration kind is one we are looking for. |
207 | /// |
208 | /// The default implementation of this method is a no-op. |
209 | virtual void |
210 | FindExternalLexicalDecls(const DeclContext *DC, |
211 | llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, |
212 | SmallVectorImpl<Decl *> &Result); |
213 | |
214 | /// Finds all declarations lexically contained within the given |
215 | /// DeclContext. |
216 | void FindExternalLexicalDecls(const DeclContext *DC, |
217 | SmallVectorImpl<Decl *> &Result) { |
218 | FindExternalLexicalDecls(DC, [](Decl::Kind) { return true; }, Result); |
219 | } |
220 | |
221 | /// Get the decls that are contained in a file in the Offset/Length |
222 | /// range. \p Length can be 0 to indicate a point at \p Offset instead of |
223 | /// a range. |
224 | virtual void FindFileRegionDecls(FileID File, unsigned Offset, |
225 | unsigned Length, |
226 | SmallVectorImpl<Decl *> &Decls); |
227 | |
228 | /// Gives the external AST source an opportunity to complete |
229 | /// the redeclaration chain for a declaration. Called each time we |
230 | /// need the most recent declaration of a declaration after the |
231 | /// generation count is incremented. |
232 | virtual void CompleteRedeclChain(const Decl *D); |
233 | |
234 | /// Gives the external AST source an opportunity to complete |
235 | /// an incomplete type. |
236 | virtual void CompleteType(TagDecl *Tag); |
237 | |
238 | /// Gives the external AST source an opportunity to complete an |
239 | /// incomplete Objective-C class. |
240 | /// |
241 | /// This routine will only be invoked if the "externally completed" bit is |
242 | /// set on the ObjCInterfaceDecl via the function |
243 | /// \c ObjCInterfaceDecl::setExternallyCompleted(). |
244 | virtual void CompleteType(ObjCInterfaceDecl *Class); |
245 | |
246 | /// Loads comment ranges. |
247 | virtual void ReadComments(); |
248 | |
249 | /// Notify ExternalASTSource that we started deserialization of |
250 | /// a decl or type so until FinishedDeserializing is called there may be |
251 | /// decls that are initializing. Must be paired with FinishedDeserializing. |
252 | /// |
253 | /// The default implementation of this method is a no-op. |
254 | virtual void StartedDeserializing(); |
255 | |
256 | /// Notify ExternalASTSource that we finished the deserialization of |
257 | /// a decl or type. Must be paired with StartedDeserializing. |
258 | /// |
259 | /// The default implementation of this method is a no-op. |
260 | virtual void FinishedDeserializing(); |
261 | |
262 | /// Function that will be invoked when we begin parsing a new |
263 | /// translation unit involving this external AST source. |
264 | /// |
265 | /// The default implementation of this method is a no-op. |
266 | virtual void StartTranslationUnit(ASTConsumer *Consumer); |
267 | |
268 | /// Print any statistics that have been gathered regarding |
269 | /// the external AST source. |
270 | /// |
271 | /// The default implementation of this method is a no-op. |
272 | virtual void PrintStats(); |
273 | |
274 | /// Perform layout on the given record. |
275 | /// |
276 | /// This routine allows the external AST source to provide an specific |
277 | /// layout for a record, overriding the layout that would normally be |
278 | /// constructed. It is intended for clients who receive specific layout |
279 | /// details rather than source code (such as LLDB). The client is expected |
280 | /// to fill in the field offsets, base offsets, virtual base offsets, and |
281 | /// complete object size. |
282 | /// |
283 | /// \param Record The record whose layout is being requested. |
284 | /// |
285 | /// \param Size The final size of the record, in bits. |
286 | /// |
287 | /// \param Alignment The final alignment of the record, in bits. |
288 | /// |
289 | /// \param FieldOffsets The offset of each of the fields within the record, |
290 | /// expressed in bits. All of the fields must be provided with offsets. |
291 | /// |
292 | /// \param BaseOffsets The offset of each of the direct, non-virtual base |
293 | /// classes. If any bases are not given offsets, the bases will be laid |
294 | /// out according to the ABI. |
295 | /// |
296 | /// \param VirtualBaseOffsets The offset of each of the virtual base classes |
297 | /// (either direct or not). If any bases are not given offsets, the bases will be laid |
298 | /// out according to the ABI. |
299 | /// |
300 | /// \returns true if the record layout was provided, false otherwise. |
301 | virtual bool layoutRecordType( |
302 | const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment, |
303 | llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, |
304 | llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, |
305 | llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets); |
306 | |
307 | //===--------------------------------------------------------------------===// |
308 | // Queries for performance analysis. |
309 | //===--------------------------------------------------------------------===// |
310 | |
311 | struct MemoryBufferSizes { |
312 | size_t malloc_bytes; |
313 | size_t mmap_bytes; |
314 | |
315 | MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) |
316 | : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} |
317 | }; |
318 | |
319 | /// Return the amount of memory used by memory buffers, breaking down |
320 | /// by heap-backed versus mmap'ed memory. |
321 | MemoryBufferSizes getMemoryBufferSizes() const { |
322 | MemoryBufferSizes sizes(0, 0); |
323 | getMemoryBufferSizes(sizes); |
324 | return sizes; |
325 | } |
326 | |
327 | virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; |
328 | |
329 | protected: |
330 | static DeclContextLookupResult |
331 | SetExternalVisibleDeclsForName(const DeclContext *DC, |
332 | DeclarationName Name, |
333 | ArrayRef<NamedDecl*> Decls); |
334 | |
335 | static DeclContextLookupResult |
336 | SetNoExternalVisibleDeclsForName(const DeclContext *DC, |
337 | DeclarationName Name); |
338 | |
339 | /// Increment the current generation. |
340 | uint32_t incrementGeneration(ASTContext &C); |
341 | }; |
342 | |
343 | /// A lazy pointer to an AST node (of base type T) that resides |
344 | /// within an external AST source. |
345 | /// |
346 | /// The AST node is identified within the external AST source by a |
347 | /// 63-bit offset, and can be retrieved via an operation on the |
348 | /// external AST source itself. |
349 | template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)> |
350 | struct LazyOffsetPtr { |
351 | /// Either a pointer to an AST node or the offset within the |
352 | /// external AST source where the AST node can be found. |
353 | /// |
354 | /// If the low bit is clear, a pointer to the AST node. If the low |
355 | /// bit is set, the upper 63 bits are the offset. |
356 | mutable uint64_t Ptr = 0; |
357 | |
358 | public: |
359 | LazyOffsetPtr() = default; |
360 | explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) {} |
361 | |
362 | explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) { |
363 | assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); |
364 | if (Offset == 0) |
365 | Ptr = 0; |
366 | } |
367 | |
368 | LazyOffsetPtr &operator=(T *Ptr) { |
369 | this->Ptr = reinterpret_cast<uint64_t>(Ptr); |
370 | return *this; |
371 | } |
372 | |
373 | LazyOffsetPtr &operator=(uint64_t Offset) { |
374 | assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); |
375 | if (Offset == 0) |
376 | Ptr = 0; |
377 | else |
378 | Ptr = (Offset << 1) | 0x01; |
379 | |
380 | return *this; |
381 | } |
382 | |
383 | /// Whether this pointer is non-NULL. |
384 | /// |
385 | /// This operation does not require the AST node to be deserialized. |
386 | explicit operator bool() const { return Ptr != 0; } |
387 | |
388 | /// Whether this pointer is non-NULL. |
389 | /// |
390 | /// This operation does not require the AST node to be deserialized. |
391 | bool isValid() const { return Ptr != 0; } |
392 | |
393 | /// Whether this pointer is currently stored as an offset. |
394 | bool isOffset() const { return Ptr & 0x01; } |
395 | |
396 | /// Retrieve the pointer to the AST node that this lazy pointer points to. |
397 | /// |
398 | /// \param Source the external AST source. |
399 | /// |
400 | /// \returns a pointer to the AST node. |
401 | T* get(ExternalASTSource *Source) const { |
402 | if (isOffset()) { |
403 | assert(Source && |
404 | "Cannot deserialize a lazy pointer without an AST source"); |
405 | Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1)); |
406 | } |
407 | return reinterpret_cast<T*>(Ptr); |
408 | } |
409 | }; |
410 | |
411 | /// A lazy value (of type T) that is within an AST node of type Owner, |
412 | /// where the value might change in later generations of the external AST |
413 | /// source. |
414 | template<typename Owner, typename T, void (ExternalASTSource::*Update)(Owner)> |
415 | struct LazyGenerationalUpdatePtr { |
416 | /// A cache of the value of this pointer, in the most recent generation in |
417 | /// which we queried it. |
418 | struct LazyData { |
419 | ExternalASTSource *ExternalSource; |
420 | uint32_t LastGeneration = 0; |
421 | T LastValue; |
422 | |
423 | LazyData(ExternalASTSource *Source, T Value) |
424 | : ExternalSource(Source), LastValue(Value) {} |
425 | }; |
426 | |
427 | // Our value is represented as simply T if there is no external AST source. |
428 | using ValueType = llvm::PointerUnion<T, LazyData*>; |
429 | ValueType Value; |
430 | |
431 | LazyGenerationalUpdatePtr(ValueType V) : Value(V) {} |
432 | |
433 | // Defined in ASTContext.h |
434 | static ValueType makeValue(const ASTContext &Ctx, T Value); |
435 | |
436 | public: |
437 | explicit LazyGenerationalUpdatePtr(const ASTContext &Ctx, T Value = T()) |
438 | : Value(makeValue(Ctx, Value)) {} |
439 | |
440 | /// Create a pointer that is not potentially updated by later generations of |
441 | /// the external AST source. |
442 | enum NotUpdatedTag { NotUpdated }; |
443 | LazyGenerationalUpdatePtr(NotUpdatedTag, T Value = T()) |
444 | : Value(Value) {} |
445 | |
446 | /// Forcibly set this pointer (which must be lazy) as needing updates. |
447 | void markIncomplete() { |
448 | Value.template get<LazyData *>()->LastGeneration = 0; |
449 | } |
450 | |
451 | /// Set the value of this pointer, in the current generation. |
452 | void set(T NewValue) { |
453 | if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) { |
454 | LazyVal->LastValue = NewValue; |
455 | return; |
456 | } |
457 | Value = NewValue; |
458 | } |
459 | |
460 | /// Set the value of this pointer, for this and all future generations. |
461 | void setNotUpdated(T NewValue) { Value = NewValue; } |
462 | |
463 | /// Get the value of this pointer, updating its owner if necessary. |
464 | T get(Owner O) { |
465 | if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) { |
466 | if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration()) { |
467 | LazyVal->LastGeneration = LazyVal->ExternalSource->getGeneration(); |
468 | (LazyVal->ExternalSource->*Update)(O); |
469 | } |
470 | return LazyVal->LastValue; |
471 | } |
472 | return Value.template get<T>(); |
473 | } |
474 | |
475 | /// Get the most recently computed value of this pointer without updating it. |
476 | T getNotUpdated() const { |
477 | if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) |
478 | return LazyVal->LastValue; |
479 | return Value.template get<T>(); |
480 | } |
481 | |
482 | void *getOpaqueValue() { return Value.getOpaqueValue(); } |
483 | static LazyGenerationalUpdatePtr getFromOpaqueValue(void *Ptr) { |
484 | return LazyGenerationalUpdatePtr(ValueType::getFromOpaqueValue(Ptr)); |
485 | } |
486 | }; |
487 | |
488 | } // namespace clang |
489 | |
490 | /// Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be |
491 | /// placed into a PointerUnion. |
492 | namespace llvm { |
493 | |
494 | template<typename Owner, typename T, |
495 | void (clang::ExternalASTSource::*Update)(Owner)> |
496 | struct PointerLikeTypeTraits< |
497 | clang::LazyGenerationalUpdatePtr<Owner, T, Update>> { |
498 | using Ptr = clang::LazyGenerationalUpdatePtr<Owner, T, Update>; |
499 | |
500 | static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); } |
501 | static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); } |
502 | |
503 | enum { |
504 | NumLowBitsAvailable = PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1 |
505 | }; |
506 | }; |
507 | |
508 | } // namespace llvm |
509 | |
510 | namespace clang { |
511 | |
512 | /// Represents a lazily-loaded vector of data. |
513 | /// |
514 | /// The lazily-loaded vector of data contains data that is partially loaded |
515 | /// from an external source and partially added by local translation. The |
516 | /// items loaded from the external source are loaded lazily, when needed for |
517 | /// iteration over the complete vector. |
518 | template<typename T, typename Source, |
519 | void (Source::*Loader)(SmallVectorImpl<T>&), |
520 | unsigned LoadedStorage = 2, unsigned LocalStorage = 4> |
521 | class LazyVector { |
522 | SmallVector<T, LoadedStorage> Loaded; |
523 | SmallVector<T, LocalStorage> Local; |
524 | |
525 | public: |
526 | /// Iteration over the elements in the vector. |
527 | /// |
528 | /// In a complete iteration, the iterator walks the range [-M, N), |
529 | /// where negative values are used to indicate elements |
530 | /// loaded from the external source while non-negative values are used to |
531 | /// indicate elements added via \c push_back(). |
532 | /// However, to provide iteration in source order (for, e.g., chained |
533 | /// precompiled headers), dereferencing the iterator flips the negative |
534 | /// values (corresponding to loaded entities), so that position -M |
535 | /// corresponds to element 0 in the loaded entities vector, position -M+1 |
536 | /// corresponds to element 1 in the loaded entities vector, etc. This |
537 | /// gives us a reasonably efficient, source-order walk. |
538 | /// |
539 | /// We define this as a wrapping iterator around an int. The |
540 | /// iterator_adaptor_base class forwards the iterator methods to basic integer |
541 | /// arithmetic. |
542 | class iterator |
543 | : public llvm::iterator_adaptor_base< |
544 | iterator, int, std::random_access_iterator_tag, T, int, T *, T &> { |
545 | friend class LazyVector; |
546 | |
547 | LazyVector *Self; |
548 | |
549 | iterator(LazyVector *Self, int Position) |
550 | : iterator::iterator_adaptor_base(Position), Self(Self) {} |
551 | |
552 | bool isLoaded() const { return this->I < 0; } |
553 | |
554 | public: |
555 | iterator() : iterator(nullptr, 0) {} |
556 | |
557 | typename iterator::reference operator*() const { |
558 | if (isLoaded()) |
559 | return Self->Loaded.end()[this->I]; |
560 | return Self->Local.begin()[this->I]; |
561 | } |
562 | }; |
563 | |
564 | iterator begin(Source *source, bool LocalOnly = false) { |
565 | if (LocalOnly) |
566 | return iterator(this, 0); |
567 | |
568 | if (source) |
569 | (source->*Loader)(Loaded); |
570 | return iterator(this, -(int)Loaded.size()); |
571 | } |
572 | |
573 | iterator end() { |
574 | return iterator(this, Local.size()); |
575 | } |
576 | |
577 | void push_back(const T& LocalValue) { |
578 | Local.push_back(LocalValue); |
579 | } |
580 | |
581 | void erase(iterator From, iterator To) { |
582 | if (From.isLoaded() && To.isLoaded()) { |
583 | Loaded.erase(&*From, &*To); |
584 | return; |
585 | } |
586 | |
587 | if (From.isLoaded()) { |
588 | Loaded.erase(&*From, Loaded.end()); |
589 | From = begin(nullptr, true); |
590 | } |
591 | |
592 | Local.erase(&*From, &*To); |
593 | } |
594 | }; |
595 | |
596 | /// A lazy pointer to a statement. |
597 | using LazyDeclStmtPtr = |
598 | LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>; |
599 | |
600 | /// A lazy pointer to a declaration. |
601 | using LazyDeclPtr = |
602 | LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>; |
603 | |
604 | /// A lazy pointer to a set of CXXCtorInitializers. |
605 | using LazyCXXCtorInitializersPtr = |
606 | LazyOffsetPtr<CXXCtorInitializer *, uint64_t, |
607 | &ExternalASTSource::GetExternalCXXCtorInitializers>; |
608 | |
609 | /// A lazy pointer to a set of CXXBaseSpecifiers. |
610 | using LazyCXXBaseSpecifiersPtr = |
611 | LazyOffsetPtr<CXXBaseSpecifier, uint64_t, |
612 | &ExternalASTSource::GetExternalCXXBaseSpecifiers>; |
613 | |
614 | } // namespace clang |
615 | |
616 | #endif // LLVM_CLANG_AST_EXTERNALASTSOURCE_H |
617 |
Warning: That file was not part of the compilation database. It may have many parsing errors.