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/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
) {
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
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.
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 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
],
144 if (Buffer
!= InlineBuffer
)
148 Capacity
= NewCapacity
;
152 TypeLoc
pushFullUninitializedImpl(QualType T
, size_t Size
) {
154 assert(LastTy
.isNull() && "pushing full on non-empty TypeLocBuilder");
157 assert(Index
== Capacity
&& "pushing full on non-empty TypeLocBuilder");
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
) {
172 assert(LastTy
== T
&& "type doesn't match last type pushed!");
174 return TypeLoc(T
, &Buffer
[Index
]);