blob: 7a5e43e25dc99fba13f30eddd51013724e6b3d91 [file] [log] [blame]
John McCall109de5e2009-10-21 00:23:54 +00001//===--- 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
Douglas Gregor7e44e3f2010-12-02 00:05:49 +000015#ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H
16#define LLVM_CLANG_SEMA_TYPELOCBUILDER_H
John McCall109de5e2009-10-21 00:23:54 +000017
18#include "clang/AST/TypeLoc.h"
Douglas Gregor7745cab2009-11-15 06:34:37 +000019#include "clang/AST/ASTContext.h"
John McCall109de5e2009-10-21 00:23:54 +000020
21namespace clang {
22
23class 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()
Ted Kremenekb995e042011-03-22 01:15:21 +000046 : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {}
John McCall109de5e2009-10-21 00:23:54 +000047
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
John McCallc12c5bb2010-05-15 11:32:37 +000060 /// 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) {
John McCall41bafb12010-11-12 07:35:56 +000063 size_t Size = L.getFullDataSize();
64 TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size);
John McCallc12c5bb2010-05-15 11:32:37 +000065 memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
66 }
67
John McCall41bafb12010-11-12 07:35:56 +000068 /// 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
John McCalled976492009-12-04 22:46:56 +000074 /// 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 cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize));
79 }
John McCall480076c2010-06-11 00:26:38 +000080
81 /// Resets this builder to the newly-initialized state.
82 void clear() {
83#ifndef NDEBUG
84 LastTy = QualType();
85#endif
86 Index = Capacity;
87 }
John McCalled976492009-12-04 22:46:56 +000088
John McCallf85e1932011-06-15 23:02:42 +000089 /// \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
John McCallf85e1932011-06-15 23:02:42 +000093 LastTy = T;
94#endif
95 }
96
John McCalled976492009-12-04 22:46:56 +000097 /// Pushes space for a new TypeLoc of the given type. Invalidates
John McCall109de5e2009-10-21 00:23:54 +000098 /// any TypeLocs previously retrieved from this builder.
99 template <class TyLocType> TyLocType push(QualType T) {
John McCall109de5e2009-10-21 00:23:54 +0000100 size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
John McCalled976492009-12-04 22:46:56 +0000101 return cast<TyLocType>(pushImpl(T, LocalSize));
John McCall109de5e2009-10-21 00:23:54 +0000102 }
103
John McCalla93c9342009-12-07 02:54:59 +0000104 /// Creates a TypeSourceInfo for the given type.
105 TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
John McCall109de5e2009-10-21 00:23:54 +0000106#ifndef NDEBUG
107 assert(T == LastTy && "type doesn't match last type pushed!");
108#endif
109
110 size_t FullDataSize = Capacity - Index;
John McCalla93c9342009-12-07 02:54:59 +0000111 TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
John McCall109de5e2009-10-21 00:23:54 +0000112 memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
113 return DI;
114 }
115
Douglas Gregor2e4c34a2011-02-24 00:17:56 +0000116 /// \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
John McCalled976492009-12-04 22:46:56 +0000129private:
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
Douglas Gregor4020cae2011-06-17 23:16:24 +0000149 return getTemporaryTypeLoc(T);
John McCalled976492009-12-04 22:46:56 +0000150 }
151
John McCall109de5e2009-10-21 00:23:54 +0000152 /// 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 }
John McCall41bafb12010-11-12 07:35:56 +0000170
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
Douglas Gregor4020cae2011-06-17 23:16:24 +0000181 return getTemporaryTypeLoc(T);
John McCall41bafb12010-11-12 07:35:56 +0000182 }
183
Douglas Gregor4020cae2011-06-17 23:16:24 +0000184public:
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) {
John McCall41bafb12010-11-12 07:35:56 +0000192#ifndef NDEBUG
193 assert(LastTy == T && "type doesn't match last type pushed!");
194#endif
195 return TypeLoc(T, &Buffer[Index]);
196 }
John McCall109de5e2009-10-21 00:23:54 +0000197};
198
199}
200
201#endif