clang API Documentation
00001 //===--- ExternalASTSource.h - Abstract External AST Interface --*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the ExternalASTSource interface, which enables 00011 // construction of AST nodes from some external source. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H 00015 #define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H 00016 00017 #include "clang/AST/DeclBase.h" 00018 #include "clang/AST/CharUnits.h" 00019 #include "llvm/ADT/DenseMap.h" 00020 00021 namespace clang { 00022 00023 class ASTConsumer; 00024 class CXXBaseSpecifier; 00025 class DeclarationName; 00026 class ExternalSemaSource; // layering violation required for downcasting 00027 class NamedDecl; 00028 class Selector; 00029 class Stmt; 00030 class TagDecl; 00031 00032 /// \brief Enumeration describing the result of loading information from 00033 /// an external source. 00034 enum ExternalLoadResult { 00035 /// \brief Loading the external information has succeeded. 00036 ELR_Success, 00037 00038 /// \brief Loading the external information has failed. 00039 ELR_Failure, 00040 00041 /// \brief The external information has already been loaded, and therefore 00042 /// no additional processing is required. 00043 ELR_AlreadyLoaded 00044 }; 00045 00046 /// \brief Abstract interface for external sources of AST nodes. 00047 /// 00048 /// External AST sources provide AST nodes constructed from some 00049 /// external source, such as a precompiled header. External AST 00050 /// sources can resolve types and declarations from abstract IDs into 00051 /// actual type and declaration nodes, and read parts of declaration 00052 /// contexts. 00053 class ExternalASTSource { 00054 /// \brief Whether this AST source also provides information for 00055 /// semantic analysis. 00056 bool SemaSource; 00057 00058 friend class ExternalSemaSource; 00059 00060 public: 00061 ExternalASTSource() : SemaSource(false) { } 00062 00063 virtual ~ExternalASTSource(); 00064 00065 /// \brief RAII class for safely pairing a StartedDeserializing call 00066 /// with FinishedDeserializing. 00067 class Deserializing { 00068 ExternalASTSource *Source; 00069 public: 00070 explicit Deserializing(ExternalASTSource *source) : Source(source) { 00071 assert(Source); 00072 Source->StartedDeserializing(); 00073 } 00074 ~Deserializing() { 00075 Source->FinishedDeserializing(); 00076 } 00077 }; 00078 00079 /// \brief Resolve a declaration ID into a declaration, potentially 00080 /// building a new declaration. 00081 /// 00082 /// This method only needs to be implemented if the AST source ever 00083 /// passes back decl sets as VisibleDeclaration objects. 00084 /// 00085 /// The default implementation of this method is a no-op. 00086 virtual Decl *GetExternalDecl(uint32_t ID); 00087 00088 /// \brief Resolve a selector ID into a selector. 00089 /// 00090 /// This operation only needs to be implemented if the AST source 00091 /// returns non-zero for GetNumKnownSelectors(). 00092 /// 00093 /// The default implementation of this method is a no-op. 00094 virtual Selector GetExternalSelector(uint32_t ID); 00095 00096 /// \brief Returns the number of selectors known to the external AST 00097 /// source. 00098 /// 00099 /// The default implementation of this method is a no-op. 00100 virtual uint32_t GetNumExternalSelectors(); 00101 00102 /// \brief Resolve the offset of a statement in the decl stream into 00103 /// a statement. 00104 /// 00105 /// This operation is meant to be used via a LazyOffsetPtr. It only 00106 /// needs to be implemented if the AST source uses methods like 00107 /// FunctionDecl::setLazyBody when building decls. 00108 /// 00109 /// The default implementation of this method is a no-op. 00110 virtual Stmt *GetExternalDeclStmt(uint64_t Offset); 00111 00112 /// \brief Resolve the offset of a set of C++ base specifiers in the decl 00113 /// stream into an array of specifiers. 00114 /// 00115 /// The default implementation of this method is a no-op. 00116 virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); 00117 00118 /// \brief Finds all declarations with the given name in the 00119 /// given context. 00120 /// 00121 /// Generally the final step of this method is either to call 00122 /// SetExternalVisibleDeclsForName or to recursively call lookup on 00123 /// the DeclContext after calling SetExternalVisibleDecls. 00124 /// 00125 /// The default implementation of this method is a no-op. 00126 virtual DeclContextLookupResult 00127 FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); 00128 00129 /// \brief Ensures that the table of all visible declarations inside this 00130 /// context is up to date. 00131 /// 00132 /// The default implementation of this functino is a no-op. 00133 virtual void completeVisibleDeclsMap(const DeclContext *DC); 00134 00135 /// \brief Finds all declarations lexically contained within the given 00136 /// DeclContext, after applying an optional filter predicate. 00137 /// 00138 /// \param isKindWeWant a predicate function that returns true if the passed 00139 /// declaration kind is one we are looking for. If NULL, all declarations 00140 /// are returned. 00141 /// 00142 /// \return an indication of whether the load succeeded or failed. 00143 /// 00144 /// The default implementation of this method is a no-op. 00145 virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, 00146 bool (*isKindWeWant)(Decl::Kind), 00147 SmallVectorImpl<Decl*> &Result); 00148 00149 /// \brief Finds all declarations lexically contained within the given 00150 /// DeclContext. 00151 /// 00152 /// \return true if an error occurred 00153 ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, 00154 SmallVectorImpl<Decl*> &Result) { 00155 return FindExternalLexicalDecls(DC, 0, Result); 00156 } 00157 00158 template <typename DeclTy> 00159 ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC, 00160 SmallVectorImpl<Decl*> &Result) { 00161 return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result); 00162 } 00163 00164 /// \brief Get the decls that are contained in a file in the Offset/Length 00165 /// range. \arg Length can be 0 to indicate a point at \arg Offset instead of 00166 /// a range. 00167 virtual void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, 00168 SmallVectorImpl<Decl *> &Decls) {} 00169 00170 /// \brief Gives the external AST source an opportunity to complete 00171 /// an incomplete type. 00172 virtual void CompleteType(TagDecl *Tag) {} 00173 00174 /// \brief Gives the external AST source an opportunity to complete an 00175 /// incomplete Objective-C class. 00176 /// 00177 /// This routine will only be invoked if the "externally completed" bit is 00178 /// set on the ObjCInterfaceDecl via the function 00179 /// \c ObjCInterfaceDecl::setExternallyCompleted(). 00180 virtual void CompleteType(ObjCInterfaceDecl *Class) { } 00181 00182 /// \brief Notify ExternalASTSource that we started deserialization of 00183 /// a decl or type so until FinishedDeserializing is called there may be 00184 /// decls that are initializing. Must be paired with FinishedDeserializing. 00185 /// 00186 /// The default implementation of this method is a no-op. 00187 virtual void StartedDeserializing() { } 00188 00189 /// \brief Notify ExternalASTSource that we finished the deserialization of 00190 /// a decl or type. Must be paired with StartedDeserializing. 00191 /// 00192 /// The default implementation of this method is a no-op. 00193 virtual void FinishedDeserializing() { } 00194 00195 /// \brief Function that will be invoked when we begin parsing a new 00196 /// translation unit involving this external AST source. 00197 /// 00198 /// The default implementation of this method is a no-op. 00199 virtual void StartTranslationUnit(ASTConsumer *Consumer) { } 00200 00201 /// \brief Print any statistics that have been gathered regarding 00202 /// the external AST source. 00203 /// 00204 /// The default implementation of this method is a no-op. 00205 virtual void PrintStats(); 00206 00207 00208 /// \brief Perform layout on the given record. 00209 /// 00210 /// This routine allows the external AST source to provide an specific 00211 /// layout for a record, overriding the layout that would normally be 00212 /// constructed. It is intended for clients who receive specific layout 00213 /// details rather than source code (such as LLDB). The client is expected 00214 /// to fill in the field offsets, base offsets, virtual base offsets, and 00215 /// complete object size. 00216 /// 00217 /// \param Record The record whose layout is being requested. 00218 /// 00219 /// \param Size The final size of the record, in bits. 00220 /// 00221 /// \param Alignment The final alignment of the record, in bits. 00222 /// 00223 /// \param FieldOffsets The offset of each of the fields within the record, 00224 /// expressed in bits. All of the fields must be provided with offsets. 00225 /// 00226 /// \param BaseOffsets The offset of each of the direct, non-virtual base 00227 /// classes. If any bases are not given offsets, the bases will be laid 00228 /// out according to the ABI. 00229 /// 00230 /// \param VirtualBaseOffsets The offset of each of the virtual base classes 00231 /// (either direct or not). If any bases are not given offsets, the bases will be laid 00232 /// out according to the ABI. 00233 /// 00234 /// \returns true if the record layout was provided, false otherwise. 00235 virtual bool 00236 layoutRecordType(const RecordDecl *Record, 00237 uint64_t &Size, uint64_t &Alignment, 00238 llvm::DenseMap<const FieldDecl *, uint64_t> &FieldOffsets, 00239 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &BaseOffsets, 00240 llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets) 00241 { 00242 return false; 00243 } 00244 00245 //===--------------------------------------------------------------------===// 00246 // Queries for performance analysis. 00247 //===--------------------------------------------------------------------===// 00248 00249 struct MemoryBufferSizes { 00250 size_t malloc_bytes; 00251 size_t mmap_bytes; 00252 00253 MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) 00254 : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} 00255 }; 00256 00257 /// Return the amount of memory used by memory buffers, breaking down 00258 /// by heap-backed versus mmap'ed memory. 00259 MemoryBufferSizes getMemoryBufferSizes() const { 00260 MemoryBufferSizes sizes(0, 0); 00261 getMemoryBufferSizes(sizes); 00262 return sizes; 00263 } 00264 00265 virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; 00266 00267 protected: 00268 static DeclContextLookupResult 00269 SetExternalVisibleDeclsForName(const DeclContext *DC, 00270 DeclarationName Name, 00271 ArrayRef<NamedDecl*> Decls); 00272 00273 static DeclContextLookupResult 00274 SetNoExternalVisibleDeclsForName(const DeclContext *DC, 00275 DeclarationName Name); 00276 }; 00277 00278 /// \brief A lazy pointer to an AST node (of base type T) that resides 00279 /// within an external AST source. 00280 /// 00281 /// The AST node is identified within the external AST source by a 00282 /// 63-bit offset, and can be retrieved via an operation on the 00283 /// external AST source itself. 00284 template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)> 00285 struct LazyOffsetPtr { 00286 /// \brief Either a pointer to an AST node or the offset within the 00287 /// external AST source where the AST node can be found. 00288 /// 00289 /// If the low bit is clear, a pointer to the AST node. If the low 00290 /// bit is set, the upper 63 bits are the offset. 00291 mutable uint64_t Ptr; 00292 00293 public: 00294 LazyOffsetPtr() : Ptr(0) { } 00295 00296 explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { } 00297 explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) { 00298 assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); 00299 if (Offset == 0) 00300 Ptr = 0; 00301 } 00302 00303 LazyOffsetPtr &operator=(T *Ptr) { 00304 this->Ptr = reinterpret_cast<uint64_t>(Ptr); 00305 return *this; 00306 } 00307 00308 LazyOffsetPtr &operator=(uint64_t Offset) { 00309 assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits"); 00310 if (Offset == 0) 00311 Ptr = 0; 00312 else 00313 Ptr = (Offset << 1) | 0x01; 00314 00315 return *this; 00316 } 00317 00318 /// \brief Whether this pointer is non-NULL. 00319 /// 00320 /// This operation does not require the AST node to be deserialized. 00321 operator bool() const { return Ptr != 0; } 00322 00323 /// \brief Whether this pointer is currently stored as an offset. 00324 bool isOffset() const { return Ptr & 0x01; } 00325 00326 /// \brief Retrieve the pointer to the AST node that this lazy pointer 00327 /// 00328 /// \param Source the external AST source. 00329 /// 00330 /// \returns a pointer to the AST node. 00331 T* get(ExternalASTSource *Source) const { 00332 if (isOffset()) { 00333 assert(Source && 00334 "Cannot deserialize a lazy pointer without an AST source"); 00335 Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1)); 00336 } 00337 return reinterpret_cast<T*>(Ptr); 00338 } 00339 }; 00340 00341 /// \brief Represents a lazily-loaded vector of data. 00342 /// 00343 /// The lazily-loaded vector of data contains data that is partially loaded 00344 /// from an external source and partially added by local translation. The 00345 /// items loaded from the external source are loaded lazily, when needed for 00346 /// iteration over the complete vector. 00347 template<typename T, typename Source, 00348 void (Source::*Loader)(SmallVectorImpl<T>&), 00349 unsigned LoadedStorage = 2, unsigned LocalStorage = 4> 00350 class LazyVector { 00351 SmallVector<T, LoadedStorage> Loaded; 00352 SmallVector<T, LocalStorage> Local; 00353 00354 public: 00355 // Iteration over the elements in the vector. 00356 class iterator { 00357 LazyVector *Self; 00358 00359 /// \brief Position within the vector.. 00360 /// 00361 /// In a complete iteration, the Position field walks the range [-M, N), 00362 /// where negative values are used to indicate elements 00363 /// loaded from the external source while non-negative values are used to 00364 /// indicate elements added via \c push_back(). 00365 /// However, to provide iteration in source order (for, e.g., chained 00366 /// precompiled headers), dereferencing the iterator flips the negative 00367 /// values (corresponding to loaded entities), so that position -M 00368 /// corresponds to element 0 in the loaded entities vector, position -M+1 00369 /// corresponds to element 1 in the loaded entities vector, etc. This 00370 /// gives us a reasonably efficient, source-order walk. 00371 int Position; 00372 00373 friend class LazyVector; 00374 00375 public: 00376 typedef T value_type; 00377 typedef value_type& reference; 00378 typedef value_type* pointer; 00379 typedef std::random_access_iterator_tag iterator_category; 00380 typedef int difference_type; 00381 00382 iterator() : Self(0), Position(0) { } 00383 00384 iterator(LazyVector *Self, int Position) 00385 : Self(Self), Position(Position) { } 00386 00387 reference operator*() const { 00388 if (Position < 0) 00389 return Self->Loaded.end()[Position]; 00390 return Self->Local[Position]; 00391 } 00392 00393 pointer operator->() const { 00394 if (Position < 0) 00395 return &Self->Loaded.end()[Position]; 00396 00397 return &Self->Local[Position]; 00398 } 00399 00400 reference operator[](difference_type D) { 00401 return *(*this + D); 00402 } 00403 00404 iterator &operator++() { 00405 ++Position; 00406 return *this; 00407 } 00408 00409 iterator operator++(int) { 00410 iterator Prev(*this); 00411 ++Position; 00412 return Prev; 00413 } 00414 00415 iterator &operator--() { 00416 --Position; 00417 return *this; 00418 } 00419 00420 iterator operator--(int) { 00421 iterator Prev(*this); 00422 --Position; 00423 return Prev; 00424 } 00425 00426 friend bool operator==(const iterator &X, const iterator &Y) { 00427 return X.Position == Y.Position; 00428 } 00429 00430 friend bool operator!=(const iterator &X, const iterator &Y) { 00431 return X.Position != Y.Position; 00432 } 00433 00434 friend bool operator<(const iterator &X, const iterator &Y) { 00435 return X.Position < Y.Position; 00436 } 00437 00438 friend bool operator>(const iterator &X, const iterator &Y) { 00439 return X.Position > Y.Position; 00440 } 00441 00442 friend bool operator<=(const iterator &X, const iterator &Y) { 00443 return X.Position < Y.Position; 00444 } 00445 00446 friend bool operator>=(const iterator &X, const iterator &Y) { 00447 return X.Position > Y.Position; 00448 } 00449 00450 friend iterator& operator+=(iterator &X, difference_type D) { 00451 X.Position += D; 00452 return X; 00453 } 00454 00455 friend iterator& operator-=(iterator &X, difference_type D) { 00456 X.Position -= D; 00457 return X; 00458 } 00459 00460 friend iterator operator+(iterator X, difference_type D) { 00461 X.Position += D; 00462 return X; 00463 } 00464 00465 friend iterator operator+(difference_type D, iterator X) { 00466 X.Position += D; 00467 return X; 00468 } 00469 00470 friend difference_type operator-(const iterator &X, const iterator &Y) { 00471 return X.Position - Y.Position; 00472 } 00473 00474 friend iterator operator-(iterator X, difference_type D) { 00475 X.Position -= D; 00476 return X; 00477 } 00478 }; 00479 friend class iterator; 00480 00481 iterator begin(Source *source, bool LocalOnly = false) { 00482 if (LocalOnly) 00483 return iterator(this, 0); 00484 00485 if (source) 00486 (source->*Loader)(Loaded); 00487 return iterator(this, -(int)Loaded.size()); 00488 } 00489 00490 iterator end() { 00491 return iterator(this, Local.size()); 00492 } 00493 00494 void push_back(const T& LocalValue) { 00495 Local.push_back(LocalValue); 00496 } 00497 00498 void erase(iterator From, iterator To) { 00499 if (From.Position < 0 && To.Position < 0) { 00500 Loaded.erase(Loaded.end() + From.Position, Loaded.end() + To.Position); 00501 return; 00502 } 00503 00504 if (From.Position < 0) { 00505 Loaded.erase(Loaded.end() + From.Position, Loaded.end()); 00506 From = begin(0, true); 00507 } 00508 00509 Local.erase(Local.begin() + From.Position, Local.begin() + To.Position); 00510 } 00511 }; 00512 00513 /// \brief A lazy pointer to a statement. 00514 typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> 00515 LazyDeclStmtPtr; 00516 00517 /// \brief A lazy pointer to a declaration. 00518 typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> 00519 LazyDeclPtr; 00520 00521 /// \brief A lazy pointer to a set of CXXBaseSpecifiers. 00522 typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, 00523 &ExternalASTSource::GetExternalCXXBaseSpecifiers> 00524 LazyCXXBaseSpecifiersPtr; 00525 00526 } // end namespace clang 00527 00528 #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H