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