clang API Documentation

ExternalASTSource.h
Go to the documentation of this file.
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