1327952Sdim//===- ExternalASTSource.h - Abstract External AST Interface ----*- C++ -*-===//
2193326Sed//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6193326Sed//
7193326Sed//===----------------------------------------------------------------------===//
8193326Sed//
9193326Sed//  This file defines the ExternalASTSource interface, which enables
10221345Sdim//  construction of AST nodes from some external source.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13327952Sdim
14280031Sdim#ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H
15280031Sdim#define LLVM_CLANG_AST_EXTERNALASTSOURCE_H
16193326Sed
17249423Sdim#include "clang/AST/CharUnits.h"
18218893Sdim#include "clang/AST/DeclBase.h"
19327952Sdim#include "clang/Basic/LLVM.h"
20321369Sdim#include "clang/Basic/Module.h"
21327952Sdim#include "llvm/ADT/ArrayRef.h"
22234353Sdim#include "llvm/ADT/DenseMap.h"
23327952Sdim#include "llvm/ADT/IntrusiveRefCntPtr.h"
24327952Sdim#include "llvm/ADT/Optional.h"
25327952Sdim#include "llvm/ADT/PointerUnion.h"
26327952Sdim#include "llvm/ADT/STLExtras.h"
27327952Sdim#include "llvm/ADT/SmallVector.h"
28327952Sdim#include "llvm/ADT/StringRef.h"
29327952Sdim#include "llvm/ADT/iterator.h"
30327952Sdim#include "llvm/Support/PointerLikeTypeTraits.h"
31327952Sdim#include <cassert>
32327952Sdim#include <cstddef>
33327952Sdim#include <cstdint>
34327952Sdim#include <iterator>
35327952Sdim#include <string>
36327952Sdim#include <utility>
37212904Sdim
38193326Sednamespace clang {
39193326Sed
40193326Sedclass ASTConsumer;
41327952Sdimclass ASTContext;
42218893Sdimclass CXXBaseSpecifier;
43288943Sdimclass CXXCtorInitializer;
44327952Sdimclass CXXRecordDecl;
45212904Sdimclass DeclarationName;
46249423Sdimclass FieldDecl;
47327952Sdimclass IdentifierInfo;
48212904Sdimclass NamedDecl;
49327952Sdimclass ObjCInterfaceDecl;
50249423Sdimclass RecordDecl;
51212904Sdimclass Selector;
52193326Sedclass Stmt;
53218893Sdimclass TagDecl;
54193326Sed
55341825Sdim/// Abstract interface for external sources of AST nodes.
56193326Sed///
57193326Sed/// External AST sources provide AST nodes constructed from some
58193326Sed/// external source, such as a precompiled header. External AST
59193326Sed/// sources can resolve types and declarations from abstract IDs into
60193326Sed/// actual type and declaration nodes, and read parts of declaration
61193326Sed/// contexts.
62276479Sdimclass ExternalASTSource : public RefCountedBase<ExternalASTSource> {
63327952Sdim  friend class ExternalSemaSource;
64327952Sdim
65276479Sdim  /// Generation number for this external AST source. Must be increased
66276479Sdim  /// whenever we might have added new redeclarations for existing decls.
67327952Sdim  uint32_t CurrentGeneration = 0;
68276479Sdim
69360784Sdim  /// LLVM-style RTTI.
70360784Sdim  static char ID;
71193326Sed
72193326Sedpublic:
73327952Sdim  ExternalASTSource() = default;
74193326Sed  virtual ~ExternalASTSource();
75193326Sed
76341825Sdim  /// RAII class for safely pairing a StartedDeserializing call
77212904Sdim  /// with FinishedDeserializing.
78212904Sdim  class Deserializing {
79212904Sdim    ExternalASTSource *Source;
80327952Sdim
81212904Sdim  public:
82212904Sdim    explicit Deserializing(ExternalASTSource *source) : Source(source) {
83212904Sdim      assert(Source);
84212904Sdim      Source->StartedDeserializing();
85212904Sdim    }
86327952Sdim
87212904Sdim    ~Deserializing() {
88212904Sdim      Source->FinishedDeserializing();
89212904Sdim    }
90212904Sdim  };
91212904Sdim
92341825Sdim  /// Get the current generation of this AST source. This number
93276479Sdim  /// is incremented each time the AST source lazily extends an existing
94276479Sdim  /// entity.
95276479Sdim  uint32_t getGeneration() const { return CurrentGeneration; }
96276479Sdim
97341825Sdim  /// Resolve a declaration ID into a declaration, potentially
98193326Sed  /// building a new declaration.
99210299Sed  ///
100210299Sed  /// This method only needs to be implemented if the AST source ever
101210299Sed  /// passes back decl sets as VisibleDeclaration objects.
102221345Sdim  ///
103221345Sdim  /// The default implementation of this method is a no-op.
104221345Sdim  virtual Decl *GetExternalDecl(uint32_t ID);
105193326Sed
106341825Sdim  /// Resolve a selector ID into a selector.
107210299Sed  ///
108210299Sed  /// This operation only needs to be implemented if the AST source
109210299Sed  /// returns non-zero for GetNumKnownSelectors().
110221345Sdim  ///
111221345Sdim  /// The default implementation of this method is a no-op.
112221345Sdim  virtual Selector GetExternalSelector(uint32_t ID);
113207619Srdivacky
114341825Sdim  /// Returns the number of selectors known to the external AST
115207619Srdivacky  /// source.
116221345Sdim  ///
117221345Sdim  /// The default implementation of this method is a no-op.
118221345Sdim  virtual uint32_t GetNumExternalSelectors();
119207619Srdivacky
120341825Sdim  /// Resolve the offset of a statement in the decl stream into
121210299Sed  /// a statement.
122193326Sed  ///
123210299Sed  /// This operation is meant to be used via a LazyOffsetPtr.  It only
124210299Sed  /// needs to be implemented if the AST source uses methods like
125210299Sed  /// FunctionDecl::setLazyBody when building decls.
126221345Sdim  ///
127221345Sdim  /// The default implementation of this method is a no-op.
128221345Sdim  virtual Stmt *GetExternalDeclStmt(uint64_t Offset);
129193326Sed
130341825Sdim  /// Resolve the offset of a set of C++ constructor initializers in
131288943Sdim  /// the decl stream into an array of initializers.
132288943Sdim  ///
133288943Sdim  /// The default implementation of this method is a no-op.
134288943Sdim  virtual CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset);
135288943Sdim
136341825Sdim  /// Resolve the offset of a set of C++ base specifiers in the decl
137218893Sdim  /// stream into an array of specifiers.
138221345Sdim  ///
139221345Sdim  /// The default implementation of this method is a no-op.
140221345Sdim  virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset);
141221345Sdim
142341825Sdim  /// Update an out-of-date identifier.
143327952Sdim  virtual void updateOutOfDateIdentifier(IdentifierInfo &II) {}
144249423Sdim
145341825Sdim  /// Find all declarations with the given name in the given context,
146249423Sdim  /// and add them to the context by calling SetExternalVisibleDeclsForName
147249423Sdim  /// or SetNoExternalVisibleDeclsForName.
148249423Sdim  /// \return \c true if any declarations might have been found, \c false if
149249423Sdim  /// we definitely have no declarations with tbis name.
150193326Sed  ///
151249423Sdim  /// The default implementation of this method is a no-op returning \c false.
152249423Sdim  virtual bool
153221345Sdim  FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name);
154193326Sed
155341825Sdim  /// Ensures that the table of all visible declarations inside this
156234982Sdim  /// context is up to date.
157234982Sdim  ///
158249423Sdim  /// The default implementation of this function is a no-op.
159234982Sdim  virtual void completeVisibleDeclsMap(const DeclContext *DC);
160234982Sdim
161341825Sdim  /// Retrieve the module that corresponds to the given module ID.
162276479Sdim  virtual Module *getModule(unsigned ID) { return nullptr; }
163249423Sdim
164341825Sdim  /// Determine whether D comes from a PCH which was built with a corresponding
165341825Sdim  /// object file.
166341825Sdim  virtual bool DeclIsFromPCHWithObjectFile(const Decl *D) { return false; }
167341825Sdim
168296417Sdim  /// Abstracts clang modules and precompiled header files and holds
169296417Sdim  /// everything needed to generate debug info for an imported module
170296417Sdim  /// or PCH.
171296417Sdim  class ASTSourceDescriptor {
172296417Sdim    StringRef PCHModuleName;
173296417Sdim    StringRef Path;
174296417Sdim    StringRef ASTFile;
175321369Sdim    ASTFileSignature Signature;
176296417Sdim    const Module *ClangModule = nullptr;
177296417Sdim
178296417Sdim  public:
179327952Sdim    ASTSourceDescriptor() = default;
180296417Sdim    ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
181321369Sdim                        ASTFileSignature Signature)
182296417Sdim        : PCHModuleName(std::move(Name)), Path(std::move(Path)),
183327952Sdim          ASTFile(std::move(ASTFile)), Signature(Signature) {}
184296417Sdim    ASTSourceDescriptor(const Module &M);
185327952Sdim
186296417Sdim    std::string getModuleName() const;
187296417Sdim    StringRef getPath() const { return Path; }
188296417Sdim    StringRef getASTFile() const { return ASTFile; }
189321369Sdim    ASTFileSignature getSignature() const { return Signature; }
190296417Sdim    const Module *getModuleOrNull() const { return ClangModule; }
191288943Sdim  };
192288943Sdim
193296417Sdim  /// Return a descriptor for the corresponding module, if one exists.
194288943Sdim  virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);
195288943Sdim
196321369Sdim  enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy };
197321369Sdim
198321369Sdim  virtual ExtKind hasExternalDefinitions(const Decl *D);
199321369Sdim
200341825Sdim  /// Finds all declarations lexically contained within the given
201218893Sdim  /// DeclContext, after applying an optional filter predicate.
202193326Sed  ///
203296417Sdim  /// \param IsKindWeWant a predicate function that returns true if the passed
204296417Sdim  /// declaration kind is one we are looking for.
205218893Sdim  ///
206221345Sdim  /// The default implementation of this method is a no-op.
207296417Sdim  virtual void
208296417Sdim  FindExternalLexicalDecls(const DeclContext *DC,
209296417Sdim                           llvm::function_ref<bool(Decl::Kind)> IsKindWeWant,
210296417Sdim                           SmallVectorImpl<Decl *> &Result);
211193326Sed
212341825Sdim  /// Finds all declarations lexically contained within the given
213218893Sdim  /// DeclContext.
214296417Sdim  void FindExternalLexicalDecls(const DeclContext *DC,
215296417Sdim                                SmallVectorImpl<Decl *> &Result) {
216296417Sdim    FindExternalLexicalDecls(DC, [](Decl::Kind) { return true; }, Result);
217218893Sdim  }
218218893Sdim
219341825Sdim  /// Get the decls that are contained in a file in the Offset/Length
220243830Sdim  /// range. \p Length can be 0 to indicate a point at \p Offset instead of
221276479Sdim  /// a range.
222276479Sdim  virtual void FindFileRegionDecls(FileID File, unsigned Offset,
223276479Sdim                                   unsigned Length,
224276479Sdim                                   SmallVectorImpl<Decl *> &Decls);
225234353Sdim
226341825Sdim  /// Gives the external AST source an opportunity to complete
227276479Sdim  /// the redeclaration chain for a declaration. Called each time we
228276479Sdim  /// need the most recent declaration of a declaration after the
229276479Sdim  /// generation count is incremented.
230276479Sdim  virtual void CompleteRedeclChain(const Decl *D);
231276479Sdim
232341825Sdim  /// Gives the external AST source an opportunity to complete
233218893Sdim  /// an incomplete type.
234276479Sdim  virtual void CompleteType(TagDecl *Tag);
235218893Sdim
236341825Sdim  /// Gives the external AST source an opportunity to complete an
237218893Sdim  /// incomplete Objective-C class.
238218893Sdim  ///
239218893Sdim  /// This routine will only be invoked if the "externally completed" bit is
240276479Sdim  /// set on the ObjCInterfaceDecl via the function
241218893Sdim  /// \c ObjCInterfaceDecl::setExternallyCompleted().
242276479Sdim  virtual void CompleteType(ObjCInterfaceDecl *Class);
243221345Sdim
244341825Sdim  /// Loads comment ranges.
245276479Sdim  virtual void ReadComments();
246239462Sdim
247341825Sdim  /// Notify ExternalASTSource that we started deserialization of
248212904Sdim  /// a decl or type so until FinishedDeserializing is called there may be
249212904Sdim  /// decls that are initializing. Must be paired with FinishedDeserializing.
250212904Sdim  ///
251212904Sdim  /// The default implementation of this method is a no-op.
252276479Sdim  virtual void StartedDeserializing();
253212904Sdim
254341825Sdim  /// Notify ExternalASTSource that we finished the deserialization of
255212904Sdim  /// a decl or type. Must be paired with StartedDeserializing.
256212904Sdim  ///
257212904Sdim  /// The default implementation of this method is a no-op.
258276479Sdim  virtual void FinishedDeserializing();
259212904Sdim
260341825Sdim  /// Function that will be invoked when we begin parsing a new
261193326Sed  /// translation unit involving this external AST source.
262210299Sed  ///
263210299Sed  /// The default implementation of this method is a no-op.
264276479Sdim  virtual void StartTranslationUnit(ASTConsumer *Consumer);
265193326Sed
266341825Sdim  /// Print any statistics that have been gathered regarding
267193326Sed  /// the external AST source.
268210299Sed  ///
269210299Sed  /// The default implementation of this method is a no-op.
270193326Sed  virtual void PrintStats();
271341825Sdim
272341825Sdim  /// Perform layout on the given record.
273234353Sdim  ///
274341825Sdim  /// This routine allows the external AST source to provide an specific
275234353Sdim  /// layout for a record, overriding the layout that would normally be
276234353Sdim  /// constructed. It is intended for clients who receive specific layout
277234353Sdim  /// details rather than source code (such as LLDB). The client is expected
278234353Sdim  /// to fill in the field offsets, base offsets, virtual base offsets, and
279234353Sdim  /// complete object size.
280234353Sdim  ///
281234353Sdim  /// \param Record The record whose layout is being requested.
282234353Sdim  ///
283234353Sdim  /// \param Size The final size of the record, in bits.
284234353Sdim  ///
285234353Sdim  /// \param Alignment The final alignment of the record, in bits.
286234353Sdim  ///
287234353Sdim  /// \param FieldOffsets The offset of each of the fields within the record,
288234353Sdim  /// expressed in bits. All of the fields must be provided with offsets.
289234353Sdim  ///
290234353Sdim  /// \param BaseOffsets The offset of each of the direct, non-virtual base
291341825Sdim  /// classes. If any bases are not given offsets, the bases will be laid
292234353Sdim  /// out according to the ABI.
293234353Sdim  ///
294234353Sdim  /// \param VirtualBaseOffsets The offset of each of the virtual base classes
295341825Sdim  /// (either direct or not). If any bases are not given offsets, the bases will be laid
296234353Sdim  /// out according to the ABI.
297341825Sdim  ///
298234353Sdim  /// \returns true if the record layout was provided, false otherwise.
299276479Sdim  virtual bool layoutRecordType(
300276479Sdim      const RecordDecl *Record, uint64_t &Size, uint64_t &Alignment,
301276479Sdim      llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets,
302276479Sdim      llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets,
303276479Sdim      llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets);
304276479Sdim
305221345Sdim  //===--------------------------------------------------------------------===//
306221345Sdim  // Queries for performance analysis.
307221345Sdim  //===--------------------------------------------------------------------===//
308341825Sdim
309221345Sdim  struct MemoryBufferSizes {
310221345Sdim    size_t malloc_bytes;
311221345Sdim    size_t mmap_bytes;
312341825Sdim
313221345Sdim    MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes)
314327952Sdim        : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {}
315221345Sdim  };
316341825Sdim
317221345Sdim  /// Return the amount of memory used by memory buffers, breaking down
318221345Sdim  /// by heap-backed versus mmap'ed memory.
319221345Sdim  MemoryBufferSizes getMemoryBufferSizes() const {
320221345Sdim    MemoryBufferSizes sizes(0, 0);
321221345Sdim    getMemoryBufferSizes(sizes);
322221345Sdim    return sizes;
323221345Sdim  }
324210299Sed
325223017Sdim  virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const;
326221345Sdim
327360784Sdim  /// LLVM-style RTTI.
328360784Sdim  /// \{
329360784Sdim  virtual bool isA(const void *ClassID) const { return ClassID == &ID; }
330360784Sdim  static bool classof(const ExternalASTSource *S) { return S->isA(&ID); }
331360784Sdim  /// \}
332360784Sdim
333210299Sedprotected:
334212904Sdim  static DeclContextLookupResult
335210299Sed  SetExternalVisibleDeclsForName(const DeclContext *DC,
336210299Sed                                 DeclarationName Name,
337226633Sdim                                 ArrayRef<NamedDecl*> Decls);
338210299Sed
339212904Sdim  static DeclContextLookupResult
340210299Sed  SetNoExternalVisibleDeclsForName(const DeclContext *DC,
341210299Sed                                   DeclarationName Name);
342276479Sdim
343341825Sdim  /// Increment the current generation.
344276479Sdim  uint32_t incrementGeneration(ASTContext &C);
345193326Sed};
346193326Sed
347341825Sdim/// A lazy pointer to an AST node (of base type T) that resides
348193326Sed/// within an external AST source.
349193326Sed///
350193326Sed/// The AST node is identified within the external AST source by a
351193326Sed/// 63-bit offset, and can be retrieved via an operation on the
352193326Sed/// external AST source itself.
353212904Sdimtemplate<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
354193326Sedstruct LazyOffsetPtr {
355341825Sdim  /// Either a pointer to an AST node or the offset within the
356193326Sed  /// external AST source where the AST node can be found.
357193326Sed  ///
358193326Sed  /// If the low bit is clear, a pointer to the AST node. If the low
359193326Sed  /// bit is set, the upper 63 bits are the offset.
360327952Sdim  mutable uint64_t Ptr = 0;
361193326Sed
362193326Sedpublic:
363327952Sdim  LazyOffsetPtr() = default;
364327952Sdim  explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) {}
365193326Sed
366193326Sed  explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
367193326Sed    assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
368193326Sed    if (Offset == 0)
369193326Sed      Ptr = 0;
370193326Sed  }
371193326Sed
372193326Sed  LazyOffsetPtr &operator=(T *Ptr) {
373193326Sed    this->Ptr = reinterpret_cast<uint64_t>(Ptr);
374193326Sed    return *this;
375193326Sed  }
376198092Srdivacky
377193326Sed  LazyOffsetPtr &operator=(uint64_t Offset) {
378193326Sed    assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
379193326Sed    if (Offset == 0)
380193326Sed      Ptr = 0;
381193326Sed    else
382193326Sed      Ptr = (Offset << 1) | 0x01;
383193326Sed
384193326Sed    return *this;
385193326Sed  }
386193326Sed
387341825Sdim  /// Whether this pointer is non-NULL.
388193326Sed  ///
389193326Sed  /// This operation does not require the AST node to be deserialized.
390288943Sdim  explicit operator bool() const { return Ptr != 0; }
391193326Sed
392341825Sdim  /// Whether this pointer is non-NULL.
393261991Sdim  ///
394261991Sdim  /// This operation does not require the AST node to be deserialized.
395261991Sdim  bool isValid() const { return Ptr != 0; }
396261991Sdim
397341825Sdim  /// Whether this pointer is currently stored as an offset.
398193326Sed  bool isOffset() const { return Ptr & 0x01; }
399193326Sed
400341825Sdim  /// Retrieve the pointer to the AST node that this lazy pointer points to.
401193326Sed  ///
402193326Sed  /// \param Source the external AST source.
403193326Sed  ///
404193326Sed  /// \returns a pointer to the AST node.
405193326Sed  T* get(ExternalASTSource *Source) const {
406193326Sed    if (isOffset()) {
407198092Srdivacky      assert(Source &&
408193326Sed             "Cannot deserialize a lazy pointer without an AST source");
409193326Sed      Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));
410193326Sed    }
411193326Sed    return reinterpret_cast<T*>(Ptr);
412193326Sed  }
413193326Sed};
414193326Sed
415341825Sdim/// A lazy value (of type T) that is within an AST node of type Owner,
416276479Sdim/// where the value might change in later generations of the external AST
417276479Sdim/// source.
418276479Sdimtemplate<typename Owner, typename T, void (ExternalASTSource::*Update)(Owner)>
419276479Sdimstruct LazyGenerationalUpdatePtr {
420276479Sdim  /// A cache of the value of this pointer, in the most recent generation in
421276479Sdim  /// which we queried it.
422276479Sdim  struct LazyData {
423276479Sdim    ExternalASTSource *ExternalSource;
424327952Sdim    uint32_t LastGeneration = 0;
425276479Sdim    T LastValue;
426327952Sdim
427327952Sdim    LazyData(ExternalASTSource *Source, T Value)
428327952Sdim        : ExternalSource(Source), LastValue(Value) {}
429276479Sdim  };
430276479Sdim
431276479Sdim  // Our value is represented as simply T if there is no external AST source.
432327952Sdim  using ValueType = llvm::PointerUnion<T, LazyData*>;
433276479Sdim  ValueType Value;
434276479Sdim
435276479Sdim  LazyGenerationalUpdatePtr(ValueType V) : Value(V) {}
436276479Sdim
437276479Sdim  // Defined in ASTContext.h
438276479Sdim  static ValueType makeValue(const ASTContext &Ctx, T Value);
439276479Sdim
440276479Sdimpublic:
441276479Sdim  explicit LazyGenerationalUpdatePtr(const ASTContext &Ctx, T Value = T())
442276479Sdim      : Value(makeValue(Ctx, Value)) {}
443276479Sdim
444276479Sdim  /// Create a pointer that is not potentially updated by later generations of
445276479Sdim  /// the external AST source.
446276479Sdim  enum NotUpdatedTag { NotUpdated };
447276479Sdim  LazyGenerationalUpdatePtr(NotUpdatedTag, T Value = T())
448276479Sdim      : Value(Value) {}
449276479Sdim
450276479Sdim  /// Forcibly set this pointer (which must be lazy) as needing updates.
451276479Sdim  void markIncomplete() {
452276479Sdim    Value.template get<LazyData *>()->LastGeneration = 0;
453276479Sdim  }
454276479Sdim
455276479Sdim  /// Set the value of this pointer, in the current generation.
456276479Sdim  void set(T NewValue) {
457341825Sdim    if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) {
458276479Sdim      LazyVal->LastValue = NewValue;
459276479Sdim      return;
460276479Sdim    }
461276479Sdim    Value = NewValue;
462276479Sdim  }
463276479Sdim
464276479Sdim  /// Set the value of this pointer, for this and all future generations.
465276479Sdim  void setNotUpdated(T NewValue) { Value = NewValue; }
466276479Sdim
467276479Sdim  /// Get the value of this pointer, updating its owner if necessary.
468276479Sdim  T get(Owner O) {
469341825Sdim    if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) {
470276479Sdim      if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration()) {
471276479Sdim        LazyVal->LastGeneration = LazyVal->ExternalSource->getGeneration();
472276479Sdim        (LazyVal->ExternalSource->*Update)(O);
473276479Sdim      }
474276479Sdim      return LazyVal->LastValue;
475276479Sdim    }
476276479Sdim    return Value.template get<T>();
477276479Sdim  }
478276479Sdim
479276479Sdim  /// Get the most recently computed value of this pointer without updating it.
480276479Sdim  T getNotUpdated() const {
481341825Sdim    if (auto *LazyVal = Value.template dyn_cast<LazyData *>())
482276479Sdim      return LazyVal->LastValue;
483276479Sdim    return Value.template get<T>();
484276479Sdim  }
485276479Sdim
486276479Sdim  void *getOpaqueValue() { return Value.getOpaqueValue(); }
487276479Sdim  static LazyGenerationalUpdatePtr getFromOpaqueValue(void *Ptr) {
488276479Sdim    return LazyGenerationalUpdatePtr(ValueType::getFromOpaqueValue(Ptr));
489276479Sdim  }
490276479Sdim};
491276479Sdim
492327952Sdim} // namespace clang
493327952Sdim
494276479Sdim/// Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be
495276479Sdim/// placed into a PointerUnion.
496276479Sdimnamespace llvm {
497327952Sdim
498276479Sdimtemplate<typename Owner, typename T,
499276479Sdim         void (clang::ExternalASTSource::*Update)(Owner)>
500276479Sdimstruct PointerLikeTypeTraits<
501276479Sdim    clang::LazyGenerationalUpdatePtr<Owner, T, Update>> {
502327952Sdim  using Ptr = clang::LazyGenerationalUpdatePtr<Owner, T, Update>;
503327952Sdim
504276479Sdim  static void *getAsVoidPointer(Ptr P) { return P.getOpaqueValue(); }
505276479Sdim  static Ptr getFromVoidPointer(void *P) { return Ptr::getFromOpaqueValue(P); }
506327952Sdim
507276479Sdim  enum {
508276479Sdim    NumLowBitsAvailable = PointerLikeTypeTraits<T>::NumLowBitsAvailable - 1
509276479Sdim  };
510276479Sdim};
511276479Sdim
512327952Sdim} // namespace llvm
513327952Sdim
514276479Sdimnamespace clang {
515327952Sdim
516341825Sdim/// Represents a lazily-loaded vector of data.
517226633Sdim///
518226633Sdim/// The lazily-loaded vector of data contains data that is partially loaded
519341825Sdim/// from an external source and partially added by local translation. The
520226633Sdim/// items loaded from the external source are loaded lazily, when needed for
521226633Sdim/// iteration over the complete vector.
522341825Sdimtemplate<typename T, typename Source,
523226633Sdim         void (Source::*Loader)(SmallVectorImpl<T>&),
524226633Sdim         unsigned LoadedStorage = 2, unsigned LocalStorage = 4>
525226633Sdimclass LazyVector {
526226633Sdim  SmallVector<T, LoadedStorage> Loaded;
527226633Sdim  SmallVector<T, LocalStorage> Local;
528226633Sdim
529226633Sdimpublic:
530288943Sdim  /// Iteration over the elements in the vector.
531288943Sdim  ///
532288943Sdim  /// In a complete iteration, the iterator walks the range [-M, N),
533288943Sdim  /// where negative values are used to indicate elements
534288943Sdim  /// loaded from the external source while non-negative values are used to
535288943Sdim  /// indicate elements added via \c push_back().
536288943Sdim  /// However, to provide iteration in source order (for, e.g., chained
537288943Sdim  /// precompiled headers), dereferencing the iterator flips the negative
538288943Sdim  /// values (corresponding to loaded entities), so that position -M
539288943Sdim  /// corresponds to element 0 in the loaded entities vector, position -M+1
540288943Sdim  /// corresponds to element 1 in the loaded entities vector, etc. This
541288943Sdim  /// gives us a reasonably efficient, source-order walk.
542288943Sdim  ///
543288943Sdim  /// We define this as a wrapping iterator around an int. The
544288943Sdim  /// iterator_adaptor_base class forwards the iterator methods to basic integer
545288943Sdim  /// arithmetic.
546309124Sdim  class iterator
547309124Sdim      : public llvm::iterator_adaptor_base<
548309124Sdim            iterator, int, std::random_access_iterator_tag, T, int, T *, T &> {
549327952Sdim    friend class LazyVector;
550327952Sdim
551226633Sdim    LazyVector *Self;
552288943Sdim
553288943Sdim    iterator(LazyVector *Self, int Position)
554288943Sdim        : iterator::iterator_adaptor_base(Position), Self(Self) {}
555288943Sdim
556288943Sdim    bool isLoaded() const { return this->I < 0; }
557288943Sdim
558226633Sdim  public:
559288943Sdim    iterator() : iterator(nullptr, 0) {}
560288943Sdim
561288943Sdim    typename iterator::reference operator*() const {
562288943Sdim      if (isLoaded())
563288943Sdim        return Self->Loaded.end()[this->I];
564288943Sdim      return Self->Local.begin()[this->I];
565226633Sdim    }
566226633Sdim  };
567288943Sdim
568226633Sdim  iterator begin(Source *source, bool LocalOnly = false) {
569226633Sdim    if (LocalOnly)
570226633Sdim      return iterator(this, 0);
571341825Sdim
572226633Sdim    if (source)
573226633Sdim      (source->*Loader)(Loaded);
574226633Sdim    return iterator(this, -(int)Loaded.size());
575226633Sdim  }
576341825Sdim
577226633Sdim  iterator end() {
578226633Sdim    return iterator(this, Local.size());
579226633Sdim  }
580341825Sdim
581226633Sdim  void push_back(const T& LocalValue) {
582226633Sdim    Local.push_back(LocalValue);
583226633Sdim  }
584341825Sdim
585226633Sdim  void erase(iterator From, iterator To) {
586288943Sdim    if (From.isLoaded() && To.isLoaded()) {
587288943Sdim      Loaded.erase(&*From, &*To);
588226633Sdim      return;
589226633Sdim    }
590288943Sdim
591288943Sdim    if (From.isLoaded()) {
592288943Sdim      Loaded.erase(&*From, Loaded.end());
593276479Sdim      From = begin(nullptr, true);
594226633Sdim    }
595288943Sdim
596288943Sdim    Local.erase(&*From, &*To);
597226633Sdim  }
598226633Sdim};
599226633Sdim
600341825Sdim/// A lazy pointer to a statement.
601327952Sdimusing LazyDeclStmtPtr =
602327952Sdim    LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>;
603193326Sed
604341825Sdim/// A lazy pointer to a declaration.
605327952Sdimusing LazyDeclPtr =
606327952Sdim    LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>;
607212904Sdim
608341825Sdim/// A lazy pointer to a set of CXXCtorInitializers.
609327952Sdimusing LazyCXXCtorInitializersPtr =
610327952Sdim    LazyOffsetPtr<CXXCtorInitializer *, uint64_t,
611327952Sdim                  &ExternalASTSource::GetExternalCXXCtorInitializers>;
612288943Sdim
613341825Sdim/// A lazy pointer to a set of CXXBaseSpecifiers.
614327952Sdimusing LazyCXXBaseSpecifiersPtr =
615327952Sdim    LazyOffsetPtr<CXXBaseSpecifier, uint64_t,
616327952Sdim                  &ExternalASTSource::GetExternalCXXBaseSpecifiers>;
617221345Sdim
618327952Sdim} // namespace clang
619193326Sed
620327952Sdim#endif // LLVM_CLANG_AST_EXTERNALASTSOURCE_H
621