]> granicus.if.org Git - clang/blob - include/clang/AST/ExternalASTSource.h
Add an ExternalASTSource hook to complete a type on demand.
[clang] / include / clang / AST / ExternalASTSource.h
1 //===--- ExternalASTSource.h - Abstract External AST Interface --*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file defines the ExternalASTSource interface, which enables
11 //  construction of AST nodes from some external source.x
12 //
13 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
15 #define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H
16
17 #include "clang/AST/DeclBase.h"
18 #include <cassert>
19 #include <vector>
20
21 namespace llvm {
22 template <class T> class SmallVectorImpl;
23 }
24
25 namespace clang {
26
27 class ASTConsumer;
28 class CXXBaseSpecifier;
29 class Decl;
30 class DeclContext;
31 class DeclContextLookupResult;
32 class DeclarationName;
33 class ExternalSemaSource; // layering violation required for downcasting
34 class NamedDecl;
35 class Selector;
36 class Stmt;
37 class TagDecl;
38
39 /// \brief Abstract interface for external sources of AST nodes.
40 ///
41 /// External AST sources provide AST nodes constructed from some
42 /// external source, such as a precompiled header. External AST
43 /// sources can resolve types and declarations from abstract IDs into
44 /// actual type and declaration nodes, and read parts of declaration
45 /// contexts.
46 class ExternalASTSource {
47   /// \brief Whether this AST source also provides information for
48   /// semantic analysis.
49   bool SemaSource;
50
51   friend class ExternalSemaSource;
52
53 public:
54   ExternalASTSource() : SemaSource(false) { }
55
56   virtual ~ExternalASTSource();
57
58   /// \brief RAII class for safely pairing a StartedDeserializing call
59   /// with FinishedDeserializing.
60   class Deserializing {
61     ExternalASTSource *Source;
62   public:
63     explicit Deserializing(ExternalASTSource *source) : Source(source) {
64       assert(Source);
65       Source->StartedDeserializing();
66     }
67     ~Deserializing() {
68       Source->FinishedDeserializing();
69     }
70   };
71
72   /// \brief Resolve a declaration ID into a declaration, potentially
73   /// building a new declaration.
74   ///
75   /// This method only needs to be implemented if the AST source ever
76   /// passes back decl sets as VisibleDeclaration objects.
77   virtual Decl *GetExternalDecl(uint32_t ID) = 0;
78
79   /// \brief Resolve a selector ID into a selector.
80   ///
81   /// This operation only needs to be implemented if the AST source
82   /// returns non-zero for GetNumKnownSelectors().
83   virtual Selector GetExternalSelector(uint32_t ID) = 0;
84
85   /// \brief Returns the number of selectors known to the external AST
86   /// source.
87   virtual uint32_t GetNumExternalSelectors() = 0;
88
89   /// \brief Resolve the offset of a statement in the decl stream into
90   /// a statement.
91   ///
92   /// This operation is meant to be used via a LazyOffsetPtr.  It only
93   /// needs to be implemented if the AST source uses methods like
94   /// FunctionDecl::setLazyBody when building decls.
95   virtual Stmt *GetExternalDeclStmt(uint64_t Offset) = 0;
96
97   /// \brief Resolve the offset of a set of C++ base specifiers in the decl
98   /// stream into an array of specifiers.
99   virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) = 0;
100   
101   /// \brief Finds all declarations with the given name in the
102   /// given context.
103   ///
104   /// Generally the final step of this method is either to call
105   /// SetExternalVisibleDeclsForName or to recursively call lookup on
106   /// the DeclContext after calling SetExternalVisibleDecls.
107   virtual DeclContextLookupResult
108   FindExternalVisibleDeclsByName(const DeclContext *DC,
109                                  DeclarationName Name) = 0;
110
111   /// \brief Deserialize all the visible declarations from external storage.
112   ///
113   /// Name lookup deserializes visible declarations lazily, thus a DeclContext
114   /// may not have a complete name lookup table. This function deserializes
115   /// the rest of visible declarations from the external storage and completes
116   /// the name lookup table of the DeclContext.
117   virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0;
118
119   /// \brief Finds all declarations lexically contained within the given
120   /// DeclContext, after applying an optional filter predicate.
121   ///
122   /// \param isKindWeWant a predicate function that returns true if the passed
123   /// declaration kind is one we are looking for. If NULL, all declarations
124   /// are returned.
125   ///
126   /// \return true if an error occurred
127   virtual bool FindExternalLexicalDecls(const DeclContext *DC,
128                                         bool (*isKindWeWant)(Decl::Kind),
129                                       llvm::SmallVectorImpl<Decl*> &Result) = 0;
130
131   /// \brief Finds all declarations lexically contained within the given
132   /// DeclContext.
133   ///
134   /// \return true if an error occurred
135   bool FindExternalLexicalDecls(const DeclContext *DC,
136                                 llvm::SmallVectorImpl<Decl*> &Result) {
137     return FindExternalLexicalDecls(DC, 0, Result);
138   }
139
140   template <typename DeclTy>
141   bool FindExternalLexicalDeclsBy(const DeclContext *DC,
142                                 llvm::SmallVectorImpl<Decl*> &Result) {
143     return FindExternalLexicalDecls(DC, DeclTy::classofKind, Result);
144   }
145
146   /// \brief Gives the external AST source an opportunity to complete
147   /// an incomplete type.
148   virtual void CompleteType(TagDecl *Tag) {}
149
150   /// \brief Notify ExternalASTSource that we started deserialization of
151   /// a decl or type so until FinishedDeserializing is called there may be
152   /// decls that are initializing. Must be paired with FinishedDeserializing.
153   ///
154   /// The default implementation of this method is a no-op.
155   virtual void StartedDeserializing() { }
156
157   /// \brief Notify ExternalASTSource that we finished the deserialization of
158   /// a decl or type. Must be paired with StartedDeserializing.
159   ///
160   /// The default implementation of this method is a no-op.
161   virtual void FinishedDeserializing() { }
162
163   /// \brief Function that will be invoked when we begin parsing a new
164   /// translation unit involving this external AST source.
165   ///
166   /// The default implementation of this method is a no-op.
167   virtual void StartTranslationUnit(ASTConsumer *Consumer) { }
168
169   /// \brief Print any statistics that have been gathered regarding
170   /// the external AST source.
171   ///
172   /// The default implementation of this method is a no-op.
173   virtual void PrintStats();
174
175 protected:
176   static DeclContextLookupResult
177   SetExternalVisibleDeclsForName(const DeclContext *DC,
178                                  DeclarationName Name,
179                                  llvm::SmallVectorImpl<NamedDecl*> &Decls);
180
181   static DeclContextLookupResult
182   SetNoExternalVisibleDeclsForName(const DeclContext *DC,
183                                    DeclarationName Name);
184
185   void MaterializeVisibleDeclsForName(const DeclContext *DC,
186                                       DeclarationName Name,
187                                  llvm::SmallVectorImpl<NamedDecl*> &Decls);
188 };
189
190 /// \brief A lazy pointer to an AST node (of base type T) that resides
191 /// within an external AST source.
192 ///
193 /// The AST node is identified within the external AST source by a
194 /// 63-bit offset, and can be retrieved via an operation on the
195 /// external AST source itself.
196 template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
197 struct LazyOffsetPtr {
198   /// \brief Either a pointer to an AST node or the offset within the
199   /// external AST source where the AST node can be found.
200   ///
201   /// If the low bit is clear, a pointer to the AST node. If the low
202   /// bit is set, the upper 63 bits are the offset.
203   mutable uint64_t Ptr;
204
205 public:
206   LazyOffsetPtr() : Ptr(0) { }
207
208   explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { }
209   explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
210     assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
211     if (Offset == 0)
212       Ptr = 0;
213   }
214
215   LazyOffsetPtr &operator=(T *Ptr) {
216     this->Ptr = reinterpret_cast<uint64_t>(Ptr);
217     return *this;
218   }
219
220   LazyOffsetPtr &operator=(uint64_t Offset) {
221     assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
222     if (Offset == 0)
223       Ptr = 0;
224     else
225       Ptr = (Offset << 1) | 0x01;
226
227     return *this;
228   }
229
230   /// \brief Whether this pointer is non-NULL.
231   ///
232   /// This operation does not require the AST node to be deserialized.
233   operator bool() const { return Ptr != 0; }
234
235   /// \brief Whether this pointer is currently stored as an offset.
236   bool isOffset() const { return Ptr & 0x01; }
237
238   /// \brief Retrieve the pointer to the AST node that this lazy pointer
239   ///
240   /// \param Source the external AST source.
241   ///
242   /// \returns a pointer to the AST node.
243   T* get(ExternalASTSource *Source) const {
244     if (isOffset()) {
245       assert(Source &&
246              "Cannot deserialize a lazy pointer without an AST source");
247       Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));
248     }
249     return reinterpret_cast<T*>(Ptr);
250   }
251 };
252
253 /// \brief A lazy pointer to a statement.
254 typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
255   LazyDeclStmtPtr;
256
257 /// \brief A lazy pointer to a declaration.
258 typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
259   LazyDeclPtr;
260
261 /// \brief A lazy pointer to a set of CXXBaseSpecifiers.
262 typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, 
263                       &ExternalASTSource::GetExternalCXXBaseSpecifiers>
264   LazyCXXBaseSpecifiersPtr;
265   
266 } // end namespace clang
267
268 #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H