Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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