]> granicus.if.org Git - clang/blob - include/clang/AST/ExternalASTSource.h
Read/write in PCH Sema's StdNamespace and StdBadAlloc and use a LazyDeclPtr for them...
[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/DeclarationName.h"
18 #include "clang/AST/Type.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include <cassert>
21 #include <vector>
22 namespace clang {
23
24 class ASTConsumer;
25 class Decl;
26 class DeclContext;
27 class ExternalSemaSource; // layering violation required for downcasting
28 class Stmt;
29
30 /// \brief The deserialized representation of a set of declarations
31 /// with the same name that are visible in a given context.
32 struct VisibleDeclaration {
33   /// \brief The name of the declarations.
34   DeclarationName Name;
35
36   /// \brief The ID numbers of all of the declarations with this name.
37   ///
38   /// These declarations have not necessarily been de-serialized.
39   llvm::SmallVector<unsigned, 4> Declarations;
40 };
41
42 /// \brief Abstract interface for external sources of AST nodes.
43 ///
44 /// External AST sources provide AST nodes constructed from some
45 /// external source, such as a precompiled header. External AST
46 /// sources can resolve types and declarations from abstract IDs into
47 /// actual type and declaration nodes, and read parts of declaration
48 /// contexts.
49 class ExternalASTSource {
50   /// \brief Whether this AST source also provides information for
51   /// semantic analysis.
52   bool SemaSource;
53
54   friend class ExternalSemaSource;
55
56 public:
57   ExternalASTSource() : SemaSource(false) { }
58
59   virtual ~ExternalASTSource();
60
61   /// \brief RAII class for safely pairing a StartedDeserializing call
62   /// with FinishedDeserializing.
63   class Deserializing {
64     ExternalASTSource *Source;
65   public:
66     explicit Deserializing(ExternalASTSource *source) : Source(source) {
67       assert(Source);
68       Source->StartedDeserializing();
69     }
70     ~Deserializing() {
71       Source->FinishedDeserializing();
72     }
73   };
74
75   /// \brief Resolve a declaration ID into a declaration, potentially
76   /// building a new declaration.
77   ///
78   /// This method only needs to be implemented if the AST source ever
79   /// passes back decl sets as VisibleDeclaration objects.
80   virtual Decl *GetExternalDecl(uint32_t ID) = 0;
81
82   /// \brief Resolve a selector ID into a selector.
83   ///
84   /// This operation only needs to be implemented if the AST source
85   /// returns non-zero for GetNumKnownSelectors().
86   virtual Selector GetExternalSelector(uint32_t ID) = 0;
87
88   /// \brief Returns the number of selectors known to the external AST
89   /// source.
90   virtual uint32_t GetNumExternalSelectors() = 0;
91
92   /// \brief Resolve the offset of a statement in the decl stream into
93   /// a statement.
94   ///
95   /// This operation is meant to be used via a LazyOffsetPtr.  It only
96   /// needs to be implemented if the AST source uses methods like
97   /// FunctionDecl::setLazyBody when building decls.
98   virtual Stmt *GetExternalDeclStmt(uint64_t Offset) = 0;
99
100   /// \brief Finds all declarations with the given name in the
101   /// given context.
102   ///
103   /// Generally the final step of this method is either to call
104   /// SetExternalVisibleDeclsForName or to recursively call lookup on
105   /// the DeclContext after calling SetExternalVisibleDecls.
106   virtual DeclContext::lookup_result
107   FindExternalVisibleDeclsByName(const DeclContext *DC,
108                                  DeclarationName Name) = 0;
109
110   /// \brief Finds all declarations lexically contained within the given
111   /// DeclContext.
112   ///
113   /// \return true if an error occurred
114   virtual bool FindExternalLexicalDecls(const DeclContext *DC,
115                                 llvm::SmallVectorImpl<Decl*> &Result) = 0;
116
117   /// \brief Notify ExternalASTSource that we started deserialization of
118   /// a decl or type so until FinishedDeserializing is called there may be
119   /// decls that are initializing. Must be paired with FinishedDeserializing.
120   ///
121   /// The default implementation of this method is a no-op.
122   virtual void StartedDeserializing() { }
123
124   /// \brief Notify ExternalASTSource that we finished the deserialization of
125   /// a decl or type. Must be paired with StartedDeserializing.
126   ///
127   /// The default implementation of this method is a no-op.
128   virtual void FinishedDeserializing() { }
129
130   /// \brief Function that will be invoked when we begin parsing a new
131   /// translation unit involving this external AST source.
132   ///
133   /// The default implementation of this method is a no-op.
134   virtual void StartTranslationUnit(ASTConsumer *Consumer) { }
135
136   /// \brief Print any statistics that have been gathered regarding
137   /// the external AST source.
138   ///
139   /// The default implementation of this method is a no-op.
140   virtual void PrintStats();
141
142 protected:
143   /// \brief Initialize the context's lookup map with the given decls.
144   /// It is assumed that none of the declarations are redeclarations of
145   /// each other.
146   static void SetExternalVisibleDecls(const DeclContext *DC,
147                   const llvm::SmallVectorImpl<VisibleDeclaration> &Decls);
148
149   /// \brief Initialize the context's lookup map with the given decls.
150   /// It is assumed that none of the declarations are redeclarations of
151   /// each other.
152   static void SetExternalVisibleDecls(const DeclContext *DC,
153                               const llvm::SmallVectorImpl<NamedDecl*> &Decls);
154
155   static DeclContext::lookup_result
156   SetExternalVisibleDeclsForName(const DeclContext *DC,
157                                  const VisibleDeclaration &VD);
158
159   static DeclContext::lookup_result
160   SetExternalVisibleDeclsForName(const DeclContext *DC,
161                                  DeclarationName Name,
162                                  llvm::SmallVectorImpl<NamedDecl*> &Decls);
163
164   static DeclContext::lookup_result
165   SetNoExternalVisibleDeclsForName(const DeclContext *DC,
166                                    DeclarationName Name);
167 };
168
169 /// \brief A lazy pointer to an AST node (of base type T) that resides
170 /// within an external AST source.
171 ///
172 /// The AST node is identified within the external AST source by a
173 /// 63-bit offset, and can be retrieved via an operation on the
174 /// external AST source itself.
175 template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)>
176 struct LazyOffsetPtr {
177   /// \brief Either a pointer to an AST node or the offset within the
178   /// external AST source where the AST node can be found.
179   ///
180   /// If the low bit is clear, a pointer to the AST node. If the low
181   /// bit is set, the upper 63 bits are the offset.
182   mutable uint64_t Ptr;
183
184 public:
185   LazyOffsetPtr() : Ptr(0) { }
186
187   explicit LazyOffsetPtr(T *Ptr) : Ptr(reinterpret_cast<uint64_t>(Ptr)) { }
188   explicit LazyOffsetPtr(uint64_t Offset) : Ptr((Offset << 1) | 0x01) {
189     assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
190     if (Offset == 0)
191       Ptr = 0;
192   }
193
194   LazyOffsetPtr &operator=(T *Ptr) {
195     this->Ptr = reinterpret_cast<uint64_t>(Ptr);
196     return *this;
197   }
198
199   LazyOffsetPtr &operator=(uint64_t Offset) {
200     assert((Offset << 1 >> 1) == Offset && "Offsets must require < 63 bits");
201     if (Offset == 0)
202       Ptr = 0;
203     else
204       Ptr = (Offset << 1) | 0x01;
205
206     return *this;
207   }
208
209   /// \brief Whether this pointer is non-NULL.
210   ///
211   /// This operation does not require the AST node to be deserialized.
212   operator bool() const { return Ptr != 0; }
213
214   /// \brief Whether this pointer is currently stored as an offset.
215   bool isOffset() const { return Ptr & 0x01; }
216
217   /// \brief Retrieve the pointer to the AST node that this lazy pointer
218   ///
219   /// \param Source the external AST source.
220   ///
221   /// \returns a pointer to the AST node.
222   T* get(ExternalASTSource *Source) const {
223     if (isOffset()) {
224       assert(Source &&
225              "Cannot deserialize a lazy pointer without an AST source");
226       Ptr = reinterpret_cast<uint64_t>((Source->*Get)(Ptr >> 1));
227     }
228     return reinterpret_cast<T*>(Ptr);
229   }
230 };
231
232 /// \brief A lazy pointer to a statement.
233 typedef LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>
234   LazyDeclStmtPtr;
235
236 /// \brief A lazy pointer to a declaration.
237 typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>
238   LazyDeclPtr;
239
240 } // end namespace clang
241
242 #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H