]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/clang/lib/Sema/TypeLocBuilder.h
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / clang / lib / Sema / TypeLocBuilder.h
1 //===--- TypeLocBuilder.h - Type Source Info collector ----------*- 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 files defines TypeLocBuilder, a class for building TypeLocs
11 //  bottom-up.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H
16 #define LLVM_CLANG_SEMA_TYPELOCBUILDER_H
17
18 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/TypeLoc.h"
20
21 namespace clang {
22
23 class TypeLocBuilder {
24   enum { InlineCapacity = 8 * sizeof(SourceLocation) };
25
26   /// The underlying location-data buffer.  Data grows from the end
27   /// of the buffer backwards.
28   char *Buffer;
29
30   /// The capacity of the current buffer.
31   size_t Capacity;
32
33   /// The index of the first occupied byte in the buffer.
34   size_t Index;
35
36 #ifndef NDEBUG
37   /// The last type pushed on this builder.
38   QualType LastTy;
39 #endif
40     
41   /// The inline buffer.
42   char InlineBuffer[InlineCapacity];
43
44  public:
45   TypeLocBuilder()
46     : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {}
47
48   ~TypeLocBuilder() {
49     if (Buffer != InlineBuffer)
50       delete[] Buffer;
51   }
52
53   /// Ensures that this buffer has at least as much capacity as described.
54   void reserve(size_t Requested) {
55     if (Requested > Capacity)
56       // For now, match the request exactly.
57       grow(Requested);
58   }
59
60   /// Pushes a copy of the given TypeLoc onto this builder.  The builder
61   /// must be empty for this to work.
62   void pushFullCopy(TypeLoc L) {
63     size_t Size = L.getFullDataSize();
64     TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size);
65     memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
66   }
67
68   /// Pushes uninitialized space for the given type.  The builder must
69   /// be empty.
70   TypeLoc pushFullUninitialized(QualType T) {
71     return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T));
72   }
73
74   /// Pushes space for a typespec TypeLoc.  Invalidates any TypeLocs
75   /// previously retrieved from this builder.
76   TypeSpecTypeLoc pushTypeSpec(QualType T) {
77     size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
78     return pushImpl(T, LocalSize).castAs<TypeSpecTypeLoc>();
79   }
80
81   /// Resets this builder to the newly-initialized state.
82   void clear() {
83 #ifndef NDEBUG
84     LastTy = QualType();
85 #endif
86     Index = Capacity;
87   }  
88
89   /// \brief Tell the TypeLocBuilder that the type it is storing has been
90   /// modified in some safe way that doesn't affect type-location information.
91   void TypeWasModifiedSafely(QualType T) {
92 #ifndef NDEBUG
93     LastTy = T;
94 #endif
95   }
96   
97   /// Pushes space for a new TypeLoc of the given type.  Invalidates
98   /// any TypeLocs previously retrieved from this builder.
99   template <class TyLocType> TyLocType push(QualType T) {
100     size_t LocalSize = TypeLoc(T, 0).castAs<TyLocType>().getLocalDataSize();
101     return pushImpl(T, LocalSize).castAs<TyLocType>();
102   }
103
104   /// Creates a TypeSourceInfo for the given type.
105   TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
106 #ifndef NDEBUG
107     assert(T == LastTy && "type doesn't match last type pushed!");
108 #endif
109
110     size_t FullDataSize = Capacity - Index;
111     TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
112     memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
113     return DI;
114   }
115
116   /// \brief Copies the type-location information to the given AST context and 
117   /// returns a \c TypeLoc referring into the AST context.
118   TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
119 #ifndef NDEBUG
120     assert(T == LastTy && "type doesn't match last type pushed!");
121 #endif
122     
123     size_t FullDataSize = Capacity - Index;
124     void *Mem = Context.Allocate(FullDataSize);
125     memcpy(Mem, &Buffer[Index], FullDataSize);
126     return TypeLoc(T, Mem);
127   }
128
129 private:
130   TypeLoc pushImpl(QualType T, size_t LocalSize) {
131 #ifndef NDEBUG
132     QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
133     assert(TLast == LastTy &&
134            "mismatch between last type and new type's inner type");
135     LastTy = T;
136 #endif
137
138     // If we need to grow, grow by a factor of 2.
139     if (LocalSize > Index) {
140       size_t RequiredCapacity = Capacity + (LocalSize - Index);
141       size_t NewCapacity = Capacity * 2;
142       while (RequiredCapacity > NewCapacity)
143         NewCapacity *= 2;
144       grow(NewCapacity);
145     }
146
147     Index -= LocalSize;
148
149     return getTemporaryTypeLoc(T);
150   }
151
152   /// Grow to the given capacity.
153   void grow(size_t NewCapacity) {
154     assert(NewCapacity > Capacity);
155
156     // Allocate the new buffer and copy the old data into it.
157     char *NewBuffer = new char[NewCapacity];
158     unsigned NewIndex = Index + NewCapacity - Capacity;
159     memcpy(&NewBuffer[NewIndex],
160            &Buffer[Index],
161            Capacity - Index);
162
163     if (Buffer != InlineBuffer)
164       delete[] Buffer;
165
166     Buffer = NewBuffer;
167     Capacity = NewCapacity;
168     Index = NewIndex;
169   }
170
171   TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) {
172 #ifndef NDEBUG
173     assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder");
174     LastTy = T;
175 #endif
176     assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder");
177
178     reserve(Size);
179     Index -= Size;
180
181     return getTemporaryTypeLoc(T);
182   }
183
184 public:
185   /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
186   /// object.
187   ///
188   /// The resulting \c TypeLoc should only be used so long as the 
189   /// \c TypeLocBuilder is active and has not had more type information
190   /// pushed into it.
191   TypeLoc getTemporaryTypeLoc(QualType T) {
192 #ifndef NDEBUG
193     assert(LastTy == T && "type doesn't match last type pushed!");
194 #endif
195     return TypeLoc(T, &Buffer[Index]);
196   }
197 };
198
199 }
200
201 #endif