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_AST_TYPELOCBUILDER_H
16 #define LLVM_CLANG_AST_TYPELOCBUILDER_H
18 #include "clang/AST/TypeLoc.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "clang/AST/ASTContext.h"
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.
31 /// The capacity of the current buffer.
34 /// The index of the first occupied byte in the buffer.
38 /// The last type pushed on this builder.
42 /// The inline buffer.
43 char InlineBuffer[InlineCapacity];
47 : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity)
51 if (Buffer != InlineBuffer)
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.
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) {
66 assert(LastTy.isNull() && "pushing copy on non-empty TypeLocBuilder");
67 LastTy = L.getNextTypeLoc().getType();
69 assert(Index == Capacity && "pushing copy on non-empty TypeLocBuilder");
71 unsigned Size = L.getFullDataSize();
72 TypeLoc Copy = pushImpl(L.getType(), Size);
73 memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
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.
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) {
101 assert(T == LastTy && "type doesn't match last type pushed!");
104 size_t FullDataSize = Capacity - Index;
105 TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
106 memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
111 TypeLoc pushImpl(QualType T, size_t LocalSize) {
113 QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
114 assert(TLast == LastTy &&
115 "mismatch between last type and new type's inner type");
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)
130 return TypeLoc(T, &Buffer[Index]);
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],
144 if (Buffer != InlineBuffer)
148 Capacity = NewCapacity;