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: Deserializing(ExternalASTSource * source)80 explicit Deserializing(ExternalASTSource *source) : Source(source) { 81 assert(Source); 82 Source->StartedDeserializing(); 83 } 84 ~Deserializing()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. getGeneration()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. updateOutOfDateIdentifier(IdentifierInfo & II)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. getModule(unsigned 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. FindExternalLexicalDecls(const DeclContext * DC,SmallVectorImpl<Decl * > & Result)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 MemoryBufferSizesMemoryBufferSizes282 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. getMemoryBufferSizes()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 /// \{ isA(const void * ClassID)298 virtual bool isA(const void *ClassID) const { return ClassID == &ID; } classof(const ExternalASTSource * S)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; LazyOffsetPtrLazyOffsetPtr333 explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) {} 334 LazyOffsetPtrLazyOffsetPtr335 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. isValidLazyOffsetPtr364 bool isValid() const { return Ptr != 0; } 365 366 /// Whether this pointer is currently stored as an offset. isOffsetLazyOffsetPtr367 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. getLazyOffsetPtr374 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 LazyDataLazyGenerationalUpdatePtr::LazyData396 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 LazyGenerationalUpdatePtrLazyGenerationalUpdatePtr404 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()) ValueLazyGenerationalUpdatePtr411 : 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()) ValueLazyGenerationalUpdatePtr417 : Value(Value) {} 418 419 /// Forcibly set this pointer (which must be lazy) as needing updates. markIncompleteLazyGenerationalUpdatePtr420 void markIncomplete() { 421 Value.template get<LazyData *>()->LastGeneration = 0; 422 } 423 424 /// Set the value of this pointer, in the current generation. setLazyGenerationalUpdatePtr425 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. setNotUpdatedLazyGenerationalUpdatePtr434 void setNotUpdated(T NewValue) { Value = NewValue; } 435 436 /// Get the value of this pointer, updating its owner if necessary. getLazyGenerationalUpdatePtr437 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. getNotUpdatedLazyGenerationalUpdatePtr449 T getNotUpdated() const { 450 if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) 451 return LazyVal->LastValue; 452 return Value.template get<T>(); 453 } 454 getOpaqueValueLazyGenerationalUpdatePtr455 void *getOpaqueValue() { return Value.getOpaqueValue(); } getFromOpaqueValueLazyGenerationalUpdatePtr456 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