rename test
[clang.git] / lib / Sema / TypeLocBuilder.h
blob3d20a5273d6d2f4f85cbee0d530f6bcb3d1c830a
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.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H
16 #define LLVM_CLANG_SEMA_TYPELOCBUILDER_H
18 #include "clang/AST/TypeLoc.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "clang/AST/ASTContext.h"
22 namespace clang {
24 class TypeLocBuilder {
25 enum { InlineCapacity = 8 * sizeof(SourceLocation) };
27 /// The underlying location-data buffer. Data grows from the end
28 /// of the buffer backwards.
29 char *Buffer;
31 /// The capacity of the current buffer.
32 size_t Capacity;
34 /// The index of the first occupied byte in the buffer.
35 size_t Index;
37 #ifndef NDEBUG
38 /// The last type pushed on this builder.
39 QualType LastTy;
40 #endif
42 /// The inline buffer.
43 char InlineBuffer[InlineCapacity];
45 public:
46 TypeLocBuilder()
47 : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity)
50 ~TypeLocBuilder() {
51 if (Buffer != InlineBuffer)
52 delete[] Buffer;
55 /// Ensures that this buffer has at least as much capacity as described.
56 void reserve(size_t Requested) {
57 if (Requested > Capacity)
58 // For now, match the request exactly.
59 grow(Requested);
62 /// Pushes a copy of the given TypeLoc onto this builder. The builder
63 /// must be empty for this to work.
64 void pushFullCopy(TypeLoc L) {
65 size_t Size = L.getFullDataSize();
66 TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size);
67 memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
70 /// Pushes uninitialized space for the given type. The builder must
71 /// be empty.
72 TypeLoc pushFullUninitialized(QualType T) {
73 return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T));
76 /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
77 /// previously retrieved from this builder.
78 TypeSpecTypeLoc pushTypeSpec(QualType T) {
79 size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
80 return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize));
83 /// Resets this builder to the newly-initialized state.
84 void clear() {
85 #ifndef NDEBUG
86 LastTy = QualType();
87 #endif
88 Index = Capacity;
91 /// Pushes space for a new TypeLoc of the given type. Invalidates
92 /// any TypeLocs previously retrieved from this builder.
93 template <class TyLocType> TyLocType push(QualType T) {
94 size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
95 return cast<TyLocType>(pushImpl(T, LocalSize));
98 /// Creates a TypeSourceInfo for the given type.
99 TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
100 #ifndef NDEBUG
101 assert(T == LastTy && "type doesn't match last type pushed!");
102 #endif
104 size_t FullDataSize = Capacity - Index;
105 TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
106 memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
107 return DI;
110 private:
111 TypeLoc pushImpl(QualType T, size_t LocalSize) {
112 #ifndef NDEBUG
113 QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
114 assert(TLast == LastTy &&
115 "mismatch between last type and new type's inner type");
116 LastTy = T;
117 #endif
119 // If we need to grow, grow by a factor of 2.
120 if (LocalSize > Index) {
121 size_t RequiredCapacity = Capacity + (LocalSize - Index);
122 size_t NewCapacity = Capacity * 2;
123 while (RequiredCapacity > NewCapacity)
124 NewCapacity *= 2;
125 grow(NewCapacity);
128 Index -= LocalSize;
130 return getTypeLoc(T);
133 /// Grow to the given capacity.
134 void grow(size_t NewCapacity) {
135 assert(NewCapacity > Capacity);
137 // Allocate the new buffer and copy the old data into it.
138 char *NewBuffer = new char[NewCapacity];
139 unsigned NewIndex = Index + NewCapacity - Capacity;
140 memcpy(&NewBuffer[NewIndex],
141 &Buffer[Index],
142 Capacity - Index);
144 if (Buffer != InlineBuffer)
145 delete[] Buffer;
147 Buffer = NewBuffer;
148 Capacity = NewCapacity;
149 Index = NewIndex;
152 TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) {
153 #ifndef NDEBUG
154 assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder");
155 LastTy = T;
156 #endif
157 assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder");
159 reserve(Size);
160 Index -= Size;
162 return getTypeLoc(T);
166 // This is private because, when we kill off TypeSourceInfo in favor
167 // of TypeLoc, we'll want an interface that creates a TypeLoc given
168 // an ASTContext, and we don't want people to think they can just
169 // use this as an equivalent.
170 TypeLoc getTypeLoc(QualType T) {
171 #ifndef NDEBUG
172 assert(LastTy == T && "type doesn't match last type pushed!");
173 #endif
174 return TypeLoc(T, &Buffer[Index]);
180 #endif