1 //===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This files defines TypeLocBuilder, a class for building TypeLocs
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H
16 #define LLVM_CLANG_SEMA_TYPELOCBUILDER_H
18 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/TypeLoc.h"
23 class TypeLocBuilder {
24 enum { InlineCapacity = 8 * sizeof(SourceLocation) };
26 /// The underlying location-data buffer. Data grows from the end
27 /// of the buffer backwards.
30 /// The capacity of the current buffer.
33 /// The index of the first occupied byte in the buffer.
37 /// The last type pushed on this builder.
41 /// The inline buffer.
42 char InlineBuffer[InlineCapacity];
46 : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {}
49 if (Buffer != InlineBuffer)
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.
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);
68 /// Pushes uninitialized space for the given type. The builder must
70 TypeLoc pushFullUninitialized(QualType T) {
71 return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T));
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>();
81 /// Resets this builder to the newly-initialized state.
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) {
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>();
104 /// Creates a TypeSourceInfo for the given type.
105 TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
107 assert(T == LastTy && "type doesn't match last type pushed!");
110 size_t FullDataSize = Capacity - Index;
111 TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
112 memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
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) {
120 assert(T == LastTy && "type doesn't match last type pushed!");
123 size_t FullDataSize = Capacity - Index;
124 void *Mem = Context.Allocate(FullDataSize);
125 memcpy(Mem, &Buffer[Index], FullDataSize);
126 return TypeLoc(T, Mem);
130 TypeLoc pushImpl(QualType T, size_t LocalSize) {
132 QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
133 assert(TLast == LastTy &&
134 "mismatch between last type and new type's inner type");
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)
149 return getTemporaryTypeLoc(T);
152 /// Grow to the given capacity.
153 void grow(size_t NewCapacity) {
154 assert(NewCapacity > Capacity);
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],
163 if (Buffer != InlineBuffer)
167 Capacity = NewCapacity;
171 TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) {
173 assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder");
176 assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder");
181 return getTemporaryTypeLoc(T);
185 /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
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
191 TypeLoc getTemporaryTypeLoc(QualType T) {
193 assert(LastTy == T && "type doesn't match last type pushed!");
195 return TypeLoc(T, &Buffer[Index]);