1218887Sdim//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// This files defines TypeLocBuilder, a class for building TypeLocs 11218887Sdim// bottom-up. 12218887Sdim// 13218887Sdim//===----------------------------------------------------------------------===// 14218887Sdim 15218887Sdim#ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H 16218887Sdim#define LLVM_CLANG_SEMA_TYPELOCBUILDER_H 17218887Sdim 18249423Sdim#include "clang/AST/ASTContext.h" 19218887Sdim#include "clang/AST/TypeLoc.h" 20218887Sdim 21218887Sdimnamespace clang { 22218887Sdim 23218887Sdimclass TypeLocBuilder { 24218887Sdim enum { InlineCapacity = 8 * sizeof(SourceLocation) }; 25218887Sdim 26218887Sdim /// The underlying location-data buffer. Data grows from the end 27218887Sdim /// of the buffer backwards. 28218887Sdim char *Buffer; 29218887Sdim 30218887Sdim /// The capacity of the current buffer. 31218887Sdim size_t Capacity; 32218887Sdim 33218887Sdim /// The index of the first occupied byte in the buffer. 34218887Sdim size_t Index; 35218887Sdim 36218887Sdim#ifndef NDEBUG 37218887Sdim /// The last type pushed on this builder. 38218887Sdim QualType LastTy; 39218887Sdim#endif 40218887Sdim 41218887Sdim /// The inline buffer. 42263508Sdim enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment }; 43263508Sdim llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer; 44263508Sdim unsigned NumBytesAtAlign4, NumBytesAtAlign8; 45218887Sdim 46218887Sdim public: 47218887Sdim TypeLocBuilder() 48263508Sdim : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity), 49263508Sdim Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0) 50263508Sdim { 51263508Sdim } 52218887Sdim 53218887Sdim ~TypeLocBuilder() { 54263508Sdim if (Buffer != InlineBuffer.buffer) 55218887Sdim delete[] Buffer; 56218887Sdim } 57218887Sdim 58218887Sdim /// Ensures that this buffer has at least as much capacity as described. 59218887Sdim void reserve(size_t Requested) { 60218887Sdim if (Requested > Capacity) 61218887Sdim // For now, match the request exactly. 62218887Sdim grow(Requested); 63218887Sdim } 64218887Sdim 65218887Sdim /// Pushes a copy of the given TypeLoc onto this builder. The builder 66218887Sdim /// must be empty for this to work. 67263508Sdim void pushFullCopy(TypeLoc L); 68218887Sdim 69218887Sdim /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs 70218887Sdim /// previously retrieved from this builder. 71218887Sdim TypeSpecTypeLoc pushTypeSpec(QualType T) { 72218887Sdim size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; 73263508Sdim unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment; 74263508Sdim return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>(); 75218887Sdim } 76218887Sdim 77218887Sdim /// Resets this builder to the newly-initialized state. 78218887Sdim void clear() { 79218887Sdim#ifndef NDEBUG 80218887Sdim LastTy = QualType(); 81218887Sdim#endif 82218887Sdim Index = Capacity; 83263508Sdim NumBytesAtAlign4 = NumBytesAtAlign8 = 0; 84218887Sdim } 85218887Sdim 86224145Sdim /// \brief Tell the TypeLocBuilder that the type it is storing has been 87224145Sdim /// modified in some safe way that doesn't affect type-location information. 88224145Sdim void TypeWasModifiedSafely(QualType T) { 89224145Sdim#ifndef NDEBUG 90224145Sdim LastTy = T; 91224145Sdim#endif 92224145Sdim } 93224145Sdim 94218887Sdim /// Pushes space for a new TypeLoc of the given type. Invalidates 95218887Sdim /// any TypeLocs previously retrieved from this builder. 96218887Sdim template <class TyLocType> TyLocType push(QualType T) { 97263508Sdim TyLocType Loc = TypeLoc(T, 0).castAs<TyLocType>(); 98263508Sdim size_t LocalSize = Loc.getLocalDataSize(); 99263508Sdim unsigned LocalAlign = Loc.getLocalDataAlignment(); 100263508Sdim return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>(); 101218887Sdim } 102218887Sdim 103218887Sdim /// Creates a TypeSourceInfo for the given type. 104218887Sdim TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) { 105218887Sdim#ifndef NDEBUG 106218887Sdim assert(T == LastTy && "type doesn't match last type pushed!"); 107218887Sdim#endif 108218887Sdim 109218887Sdim size_t FullDataSize = Capacity - Index; 110218887Sdim TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize); 111218887Sdim memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); 112218887Sdim return DI; 113218887Sdim } 114218887Sdim 115219077Sdim /// \brief Copies the type-location information to the given AST context and 116219077Sdim /// returns a \c TypeLoc referring into the AST context. 117219077Sdim TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) { 118219077Sdim#ifndef NDEBUG 119219077Sdim assert(T == LastTy && "type doesn't match last type pushed!"); 120219077Sdim#endif 121219077Sdim 122219077Sdim size_t FullDataSize = Capacity - Index; 123219077Sdim void *Mem = Context.Allocate(FullDataSize); 124219077Sdim memcpy(Mem, &Buffer[Index], FullDataSize); 125219077Sdim return TypeLoc(T, Mem); 126219077Sdim } 127219077Sdim 128218887Sdimprivate: 129218887Sdim 130263508Sdim TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment); 131218887Sdim 132218887Sdim /// Grow to the given capacity. 133263508Sdim void grow(size_t NewCapacity); 134218887Sdim 135224145Sdim /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder 136224145Sdim /// object. 137224145Sdim /// 138224145Sdim /// The resulting \c TypeLoc should only be used so long as the 139224145Sdim /// \c TypeLocBuilder is active and has not had more type information 140224145Sdim /// pushed into it. 141224145Sdim TypeLoc getTemporaryTypeLoc(QualType T) { 142218887Sdim#ifndef NDEBUG 143218887Sdim assert(LastTy == T && "type doesn't match last type pushed!"); 144218887Sdim#endif 145218887Sdim return TypeLoc(T, &Buffer[Index]); 146218887Sdim } 147218887Sdim}; 148218887Sdim 149218887Sdim} 150218887Sdim 151218887Sdim#endif 152