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