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