1 //===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines TypeLocBuilder, a class for building TypeLocs 11 // bottom-up. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H 16 #define LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H 17 18 #include "clang/AST/ASTContext.h" 19 #include "clang/AST/TypeLoc.h" 20 21 namespace clang { 22 23 class TypeLocBuilder { 24 enum { InlineCapacity = 8 * sizeof(SourceLocation) }; 25 26 /// The underlying location-data buffer. Data grows from the end 27 /// of the buffer backwards. 28 char *Buffer; 29 30 /// The capacity of the current buffer. 31 size_t Capacity; 32 33 /// The index of the first occupied byte in the buffer. 34 size_t Index; 35 36 #ifndef NDEBUG 37 /// The last type pushed on this builder. 38 QualType LastTy; 39 #endif 40 41 /// The inline buffer. 42 enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment }; 43 llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer; 44 unsigned NumBytesAtAlign4, NumBytesAtAlign8; 45 46 public: TypeLocBuilder()47 TypeLocBuilder() 48 : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity), 49 Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0) 50 { 51 } 52 ~TypeLocBuilder()53 ~TypeLocBuilder() { 54 if (Buffer != InlineBuffer.buffer) 55 delete[] Buffer; 56 } 57 58 /// Ensures that this buffer has at least as much capacity as described. reserve(size_t Requested)59 void reserve(size_t Requested) { 60 if (Requested > Capacity) 61 // For now, match the request exactly. 62 grow(Requested); 63 } 64 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); 68 69 /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs 70 /// previously retrieved from this builder. pushTypeSpec(QualType T)71 TypeSpecTypeLoc pushTypeSpec(QualType T) { 72 size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; 73 unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment; 74 return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>(); 75 } 76 77 /// Resets this builder to the newly-initialized state. clear()78 void clear() { 79 #ifndef NDEBUG 80 LastTy = QualType(); 81 #endif 82 Index = Capacity; 83 NumBytesAtAlign4 = NumBytesAtAlign8 = 0; 84 } 85 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. TypeWasModifiedSafely(QualType T)88 void TypeWasModifiedSafely(QualType T) { 89 #ifndef NDEBUG 90 LastTy = T; 91 #endif 92 } 93 94 /// Pushes space for a new TypeLoc of the given type. Invalidates 95 /// any TypeLocs previously retrieved from this builder. push(QualType T)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>(); 101 } 102 103 /// Creates a TypeSourceInfo for the given type. getTypeSourceInfo(ASTContext & Context,QualType T)104 TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) { 105 #ifndef NDEBUG 106 assert(T == LastTy && "type doesn't match last type pushed!"); 107 #endif 108 109 size_t FullDataSize = Capacity - Index; 110 TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize); 111 memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); 112 return DI; 113 } 114 115 /// \brief Copies the type-location information to the given AST context and 116 /// returns a \c TypeLoc referring into the AST context. getTypeLocInContext(ASTContext & Context,QualType T)117 TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) { 118 #ifndef NDEBUG 119 assert(T == LastTy && "type doesn't match last type pushed!"); 120 #endif 121 122 size_t FullDataSize = Capacity - Index; 123 void *Mem = Context.Allocate(FullDataSize); 124 memcpy(Mem, &Buffer[Index], FullDataSize); 125 return TypeLoc(T, Mem); 126 } 127 128 private: 129 130 TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment); 131 132 /// Grow to the given capacity. 133 void grow(size_t NewCapacity); 134 135 /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder 136 /// object. 137 /// 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 140 /// pushed into it. getTemporaryTypeLoc(QualType T)141 TypeLoc getTemporaryTypeLoc(QualType T) { 142 #ifndef NDEBUG 143 assert(LastTy == T && "type doesn't match last type pushed!"); 144 #endif 145 return TypeLoc(T, &Buffer[Index]); 146 } 147 }; 148 149 } 150 151 #endif 152