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