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 llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;
43 unsigned NumBytesAtAlign4, NumBytesAtAlign8;
47 : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity),
48 Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0)
53 if (Buffer != InlineBuffer.buffer)
57 /// Ensures that this buffer has at least as much capacity as described.
58 void reserve(size_t Requested) {
59 if (Requested > Capacity)
60 // For now, match the request exactly.
64 /// Pushes a copy of the given TypeLoc onto this builder. The builder
65 /// must be empty for this to work.
66 void pushFullCopy(TypeLoc L);
68 /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
69 /// previously retrieved from this builder.
70 TypeSpecTypeLoc pushTypeSpec(QualType T) {
71 size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
72 unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment;
73 return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>();
76 /// Resets this builder to the newly-initialized state.
82 NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
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]);