diff options
Diffstat (limited to 'include/clang/AST/ExternalASTSource.h')
-rw-r--r-- | include/clang/AST/ExternalASTSource.h | 199 |
1 files changed, 176 insertions, 23 deletions
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index ef1f1618ba1d..96d14b29549b 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -15,11 +15,6 @@ #define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H #include "clang/AST/DeclBase.h" -#include <cassert> - -namespace llvm { -template <class T> class SmallVectorImpl; -} namespace clang { @@ -129,16 +124,6 @@ public: virtual DeclContextLookupResult FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); - /// \brief Deserialize all the visible declarations from external storage. - /// - /// Name lookup deserializes visible declarations lazily, thus a DeclContext - /// may not have a complete name lookup table. This function deserializes - /// the rest of visible declarations from the external storage and completes - /// the name lookup table of the DeclContext. - /// - /// The default implementation of this method is a no-op. - virtual void MaterializeVisibleDecls(const DeclContext *DC); - /// \brief Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. /// @@ -151,20 +136,20 @@ public: /// The default implementation of this method is a no-op. virtual ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, bool (*isKindWeWant)(Decl::Kind), - llvm::SmallVectorImpl<Decl*> &Result); + SmallVectorImpl<Decl*> &Result); /// \brief Finds all declarations lexically contained within the given /// DeclContext. /// /// \return true if an error occurred ExternalLoadResult FindExternalLexicalDecls(const DeclContext *DC, - llvm::SmallVectorImpl<Decl*> &Result) { + SmallVectorImpl<Decl*> &Result) { return FindExternalLexicalDecls(DC, 0, Result); } template <typename DeclTy> ExternalLoadResult FindExternalLexicalDeclsBy(const DeclContext *DC, - llvm::SmallVectorImpl<Decl*> &Result) { + SmallVectorImpl<Decl*> &Result) { return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result); } @@ -231,15 +216,11 @@ protected: static DeclContextLookupResult SetExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name, - llvm::SmallVectorImpl<NamedDecl*> &Decls); + ArrayRef<NamedDecl*> Decls); static DeclContextLookupResult SetNoExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name); - - void MaterializeVisibleDeclsForName(const DeclContext *DC, - DeclarationName Name, - llvm::SmallVectorImpl<NamedDecl*> &Decls); }; /// \brief A lazy pointer to an AST node (of base type T) that resides @@ -305,6 +286,178 @@ public: } }; +/// \brief Represents a lazily-loaded vector of data. +/// +/// The lazily-loaded vector of data contains data that is partially loaded +/// from an external source and partially added by local translation. The +/// items loaded from the external source are loaded lazily, when needed for +/// iteration over the complete vector. +template<typename T, typename Source, + void (Source::*Loader)(SmallVectorImpl<T>&), + unsigned LoadedStorage = 2, unsigned LocalStorage = 4> +class LazyVector { + SmallVector<T, LoadedStorage> Loaded; + SmallVector<T, LocalStorage> Local; + +public: + // Iteration over the elements in the vector. + class iterator { + LazyVector *Self; + + /// \brief Position within the vector.. + /// + /// In a complete iteration, the Position field walks the range [-M, N), + /// where negative values are used to indicate elements + /// loaded from the external source while non-negative values are used to + /// indicate elements added via \c push_back(). + /// However, to provide iteration in source order (for, e.g., chained + /// precompiled headers), dereferencing the iterator flips the negative + /// values (corresponding to loaded entities), so that position -M + /// corresponds to element 0 in the loaded entities vector, position -M+1 + /// corresponds to element 1 in the loaded entities vector, etc. This + /// gives us a reasonably efficient, source-order walk. + int Position; + + friend class LazyVector; + + public: + typedef T value_type; + typedef value_type& reference; + typedef value_type* pointer; + typedef std::random_access_iterator_tag iterator_category; + typedef int difference_type; + + iterator() : Self(0), Position(0) { } + + iterator(LazyVector *Self, int Position) + : Self(Self), Position(Position) { } + + reference operator*() const { + if (Position < 0) + return Self->Loaded.end()[Position]; + return Self->Local[Position]; + } + + pointer operator->() const { + if (Position < 0) + return &Self->Loaded.end()[Position]; + + return &Self->Local[Position]; + } + + reference operator[](difference_type D) { + return *(*this + D); + } + + iterator &operator++() { + ++Position; + return *this; + } + + iterator operator++(int) { + iterator Prev(*this); + ++Position; + return Prev; + } + + iterator &operator--() { + --Position; + return *this; + } + + iterator operator--(int) { + iterator Prev(*this); + --Position; + return Prev; + } + + friend bool operator==(const iterator &X, const iterator &Y) { + return X.Position == Y.Position; + } + + friend bool operator!=(const iterator &X, const iterator &Y) { + return X.Position != Y.Position; + } + + friend bool operator<(const iterator &X, const iterator &Y) { + return X.Position < Y.Position; + } + + friend bool operator>(const iterator &X, const iterator &Y) { + return X.Position > Y.Position; + } + + friend bool operator<=(const iterator &X, const iterator &Y) { + return X.Position < Y.Position; + } + + friend bool operator>=(const iterator &X, const iterator &Y) { + return X.Position > Y.Position; + } + + friend iterator& operator+=(iterator &X, difference_type D) { + X.Position += D; + return X; + } + + friend iterator& operator-=(iterator &X, difference_type D) { + X.Position -= D; + return X; + } + + friend iterator operator+(iterator X, difference_type D) { + X.Position += D; + return X; + } + + friend iterator operator+(difference_type D, iterator X) { + X.Position += D; + return X; + } + + friend difference_type operator-(const iterator &X, const iterator &Y) { + return X.Position - Y.Position; + } + + friend iterator operator-(iterator X, difference_type D) { + X.Position -= D; + return X; + } + }; + friend class iterator; + + iterator begin(Source *source, bool LocalOnly = false) { + if (LocalOnly) + return iterator(this, 0); + + if (source) + (source->*Loader)(Loaded); + return iterator(this, -(int)Loaded.size()); + } + + iterator end() { + return iterator(this, Local.size()); + } + + void push_back(const T& LocalValue) { + Local.push_back(LocalValue); + } + + void erase(iterator From, iterator To) { + if (From.Position < 0 && To.Position < 0) { + Loaded.erase(Loaded.end() + From.Position, Loaded.end() + To.Position); + return; + } + + if (From.Position < 0) { + Loaded.erase(Loaded.end() + From.Position, Loaded.end()); + From = begin(0, true); + } + + Local.erase(Local.begin() + From.Position, Local.begin() + To.Position); + } +}; + /// \brief A lazy pointer to a statement. typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt> LazyDeclStmtPtr; |