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 file defines TypeLocBuilder, a class for building TypeLocs
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H
16 #define LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H
18 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/TypeLoc.h"
23 class TypeLocBuilder {
24 enum { InlineCapacity = 8 * sizeof(SourceLocation) };
26 /// The underlying location-data buffer. Data grows from the end
27 /// of the buffer backwards.
30 /// The capacity of the current buffer.
33 /// The index of the first occupied byte in the buffer.
37 /// The last type pushed on this builder.
41 /// The inline buffer.
42 enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment };
43 llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;
44 unsigned NumBytesAtAlign4, NumBytesAtAlign8;
48 : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity),
49 Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0)
54 if (Buffer != InlineBuffer.buffer)
58 /// Ensures that this buffer has at least as much capacity as described.
59 void reserve(size_t Requested) {
60 if (Requested > Capacity)
61 // For now, match the request exactly.
65 /// Pushes a copy of the given TypeLoc onto this builder. The builder
66 /// must be empty for this to work.
67 void pushFullCopy(TypeLoc L);
69 /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
70 /// previously retrieved from this builder.
71 TypeSpecTypeLoc pushTypeSpec(QualType T) {
72 size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
73 unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment;
74 return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>();
77 /// Resets this builder to the newly-initialized state.
83 NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
86 /// \brief Tell the TypeLocBuilder that the type it is storing has been
87 /// modified in some safe way that doesn't affect type-location information.
88 void TypeWasModifiedSafely(QualType T) {
94 /// Pushes space for a new TypeLoc of the given type. Invalidates
95 /// any TypeLocs previously retrieved from this builder.
96 template <class TyLocType> TyLocType push(QualType T) {
97 TyLocType Loc = TypeLoc(T, nullptr).castAs<TyLocType>();
98 size_t LocalSize = Loc.getLocalDataSize();
99 unsigned LocalAlign = Loc.getLocalDataAlignment();
100 return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();
103 /// Creates a TypeSourceInfo for the given type.
104 TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
106 assert(T == LastTy && "type doesn't match last type pushed!");
109 size_t FullDataSize = Capacity - Index;
110 TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
111 memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
115 /// \brief Copies the type-location information to the given AST context and
116 /// returns a \c TypeLoc referring into the AST context.
117 TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
119 assert(T == LastTy && "type doesn't match last type pushed!");
122 size_t FullDataSize = Capacity - Index;
123 void *Mem = Context.Allocate(FullDataSize);
124 memcpy(Mem, &Buffer[Index], FullDataSize);
125 return TypeLoc(T, Mem);
130 TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment);
132 /// Grow to the given capacity.
133 void grow(size_t NewCapacity);
135 /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
138 /// The resulting \c TypeLoc should only be used so long as the
139 /// \c TypeLocBuilder is active and has not had more type information
141 TypeLoc getTemporaryTypeLoc(QualType T) {
143 assert(LastTy == T && "type doesn't match last type pushed!");
145 return TypeLoc(T, &Buffer[Index]);