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 TypeLocBuilder(const TypeLocBuilder
&) = delete;
57 TypeLocBuilder
&operator=(const TypeLocBuilder
&) = delete;
59 /// Ensures that this buffer has at least as much capacity as described.
60 void reserve(size_t Requested
) {
61 if (Requested
> Capacity
)
62 // For now, match the request exactly.
66 /// Pushes a copy of the given TypeLoc onto this builder. The builder
67 /// must be empty for this to work.
68 void pushFullCopy(TypeLoc L
);
70 /// Pushes 'T' with all locations pointing to 'Loc'.
71 /// The builder must be empty for this to work.
72 void pushTrivial(ASTContext
&Context
, QualType T
, SourceLocation Loc
);
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 unsigned LocalAlign
= TypeSpecTypeLoc::LocalDataAlignment
;
79 return pushImpl(T
, LocalSize
, LocalAlign
).castAs
<TypeSpecTypeLoc
>();
82 /// Resets this builder to the newly-initialized state.
92 /// Tell the TypeLocBuilder that the type it is storing has been
93 /// modified in some safe way that doesn't affect type-location information.
94 void TypeWasModifiedSafely(QualType T
) {
100 /// Pushes space for a new TypeLoc of the given type. Invalidates
101 /// any TypeLocs previously retrieved from this builder.
102 template <class TyLocType
> TyLocType
push(QualType T
) {
103 TyLocType Loc
= TypeLoc(T
, nullptr).castAs
<TyLocType
>();
104 size_t LocalSize
= Loc
.getLocalDataSize();
105 unsigned LocalAlign
= Loc
.getLocalDataAlignment();
106 return pushImpl(T
, LocalSize
, LocalAlign
).castAs
<TyLocType
>();
109 /// Creates a TypeSourceInfo for the given type.
110 TypeSourceInfo
*getTypeSourceInfo(ASTContext
& Context
, QualType T
) {
112 assert(T
== LastTy
&& "type doesn't match last type pushed!");
115 size_t FullDataSize
= Capacity
- Index
;
116 TypeSourceInfo
*DI
= Context
.CreateTypeSourceInfo(T
, FullDataSize
);
117 memcpy(DI
->getTypeLoc().getOpaqueData(), &Buffer
[Index
], FullDataSize
);
121 /// Copies the type-location information to the given AST context and
122 /// returns a \c TypeLoc referring into the AST context.
123 TypeLoc
getTypeLocInContext(ASTContext
&Context
, QualType T
) {
125 assert(T
== LastTy
&& "type doesn't match last type pushed!");
128 size_t FullDataSize
= Capacity
- Index
;
129 void *Mem
= Context
.Allocate(FullDataSize
);
130 memcpy(Mem
, &Buffer
[Index
], FullDataSize
);
131 return TypeLoc(T
, Mem
);
136 TypeLoc
pushImpl(QualType T
, size_t LocalSize
, unsigned LocalAlignment
);
138 /// Grow to the given capacity.
139 void grow(size_t NewCapacity
);
141 /// Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
144 /// The resulting \c TypeLoc should only be used so long as the
145 /// \c TypeLocBuilder is active and has not had more type information
147 TypeLoc
getTemporaryTypeLoc(QualType T
) {
149 assert(LastTy
== T
&& "type doesn't match last type pushed!");
151 return TypeLoc(T
, &Buffer
[Index
]);