1 //===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines TypeLocBuilder, a class for building TypeLocs
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H
15 #define LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H
17 #include "clang/AST/ASTContext.h"
18 #include "clang/AST/TypeLoc.h"
22 class TypeLocBuilder
{
23 enum { InlineCapacity
= 8 * sizeof(SourceLocation
) };
25 /// The underlying location-data buffer. Data grows from the end
26 /// of the buffer backwards.
29 /// The capacity of the current buffer.
32 /// The index of the first occupied byte in the buffer.
36 /// The last type pushed on this builder.
40 /// The inline buffer.
41 enum { BufferMaxAlignment
= alignof(void *) };
42 alignas(BufferMaxAlignment
) char InlineBuffer
[InlineCapacity
];
43 unsigned NumBytesAtAlign4
;
48 : Buffer(InlineBuffer
), Capacity(InlineCapacity
), Index(InlineCapacity
),
49 NumBytesAtAlign4(0), AtAlign8(false) {}
52 if (Buffer
!= InlineBuffer
)
56 /// Ensures that this buffer has at least as much capacity as described.
57 void reserve(size_t Requested
) {
58 if (Requested
> Capacity
)
59 // For now, match the request exactly.
63 /// Pushes a copy of the given TypeLoc onto this builder. The builder
64 /// must be empty for this to work.
65 void pushFullCopy(TypeLoc L
);
67 /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
68 /// previously retrieved from this builder.
69 TypeSpecTypeLoc
pushTypeSpec(QualType T
) {
70 size_t LocalSize
= TypeSpecTypeLoc::LocalDataSize
;
71 unsigned LocalAlign
= TypeSpecTypeLoc::LocalDataAlignment
;
72 return pushImpl(T
, LocalSize
, LocalAlign
).castAs
<TypeSpecTypeLoc
>();
75 /// Resets this builder to the newly-initialized state.
85 /// Tell the TypeLocBuilder that the type it is storing has been
86 /// modified in some safe way that doesn't affect type-location information.
87 void TypeWasModifiedSafely(QualType T
) {
93 /// Pushes space for a new TypeLoc of the given type. Invalidates
94 /// any TypeLocs previously retrieved from this builder.
95 template <class TyLocType
> TyLocType
push(QualType T
) {
96 TyLocType Loc
= TypeLoc(T
, nullptr).castAs
<TyLocType
>();
97 size_t LocalSize
= Loc
.getLocalDataSize();
98 unsigned LocalAlign
= Loc
.getLocalDataAlignment();
99 return pushImpl(T
, LocalSize
, LocalAlign
).castAs
<TyLocType
>();
102 /// Creates a TypeSourceInfo for the given type.
103 TypeSourceInfo
*getTypeSourceInfo(ASTContext
& Context
, QualType T
) {
105 assert(T
== LastTy
&& "type doesn't match last type pushed!");
108 size_t FullDataSize
= Capacity
- Index
;
109 TypeSourceInfo
*DI
= Context
.CreateTypeSourceInfo(T
, FullDataSize
);
110 memcpy(DI
->getTypeLoc().getOpaqueData(), &Buffer
[Index
], FullDataSize
);
114 /// Copies the type-location information to the given AST context and
115 /// returns a \c TypeLoc referring into the AST context.
116 TypeLoc
getTypeLocInContext(ASTContext
&Context
, QualType T
) {
118 assert(T
== LastTy
&& "type doesn't match last type pushed!");
121 size_t FullDataSize
= Capacity
- Index
;
122 void *Mem
= Context
.Allocate(FullDataSize
);
123 memcpy(Mem
, &Buffer
[Index
], FullDataSize
);
124 return TypeLoc(T
, Mem
);
129 TypeLoc
pushImpl(QualType T
, size_t LocalSize
, unsigned LocalAlignment
);
131 /// Grow to the given capacity.
132 void grow(size_t NewCapacity
);
134 /// Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
137 /// The resulting \c TypeLoc should only be used so long as the
138 /// \c TypeLocBuilder is active and has not had more type information
140 TypeLoc
getTemporaryTypeLoc(QualType T
) {
142 assert(LastTy
== T
&& "type doesn't match last type pushed!");
144 return TypeLoc(T
, &Buffer
[Index
]);