TypeLocBuilder.h revision 218887
11541Srgrimes//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===// 21541Srgrimes// 31541Srgrimes// The LLVM Compiler Infrastructure 41541Srgrimes// 51541Srgrimes// This file is distributed under the University of Illinois Open Source 61541Srgrimes// License. See LICENSE.TXT for details. 71541Srgrimes// 81541Srgrimes//===----------------------------------------------------------------------===// 91541Srgrimes// 101541Srgrimes// This files defines TypeLocBuilder, a class for building TypeLocs 111541Srgrimes// bottom-up. 121541Srgrimes// 131541Srgrimes//===----------------------------------------------------------------------===// 141541Srgrimes 151541Srgrimes#ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H 161541Srgrimes#define LLVM_CLANG_SEMA_TYPELOCBUILDER_H 171541Srgrimes 181541Srgrimes#include "clang/AST/TypeLoc.h" 191541Srgrimes#include "llvm/ADT/SmallVector.h" 201541Srgrimes#include "clang/AST/ASTContext.h" 211541Srgrimes 221541Srgrimesnamespace clang { 231541Srgrimes 241541Srgrimesclass TypeLocBuilder { 251541Srgrimes enum { InlineCapacity = 8 * sizeof(SourceLocation) }; 261541Srgrimes 271541Srgrimes /// The underlying location-data buffer. Data grows from the end 281541Srgrimes /// of the buffer backwards. 291541Srgrimes char *Buffer; 301541Srgrimes 311541Srgrimes /// The capacity of the current buffer. 321541Srgrimes size_t Capacity; 331541Srgrimes 341541Srgrimes /// The index of the first occupied byte in the buffer. 351541Srgrimes size_t Index; 361541Srgrimes 371541Srgrimes#ifndef NDEBUG 381541Srgrimes /// The last type pushed on this builder. 3950477Speter QualType LastTy; 401541Srgrimes#endif 411541Srgrimes 4213203Swollman /// The inline buffer. 43101127Srwatson char InlineBuffer[InlineCapacity]; 4413203Swollman 451541Srgrimes public: 462112Swollman TypeLocBuilder() 4769664Speter : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) 4876166Smarkm {} 49101127Srwatson 5089316Salfred ~TypeLocBuilder() { 511541Srgrimes if (Buffer != InlineBuffer) 521541Srgrimes delete[] Buffer; 531541Srgrimes } 541541Srgrimes 551541Srgrimes /// Ensures that this buffer has at least as much capacity as described. 561541Srgrimes void reserve(size_t Requested) { 571541Srgrimes if (Requested > Capacity) 581541Srgrimes // For now, match the request exactly. 591541Srgrimes grow(Requested); 6092751Sjeff } 6132011Sbde 621541Srgrimes /// Pushes a copy of the given TypeLoc onto this builder. The builder 6369664Speter /// must be empty for this to work. 6469664Speter void pushFullCopy(TypeLoc L) { 6592751Sjeff size_t Size = L.getFullDataSize(); 6669664Speter TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size); 6769664Speter memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size); 6869664Speter } 6969664Speter 7092654Sjeff /// Pushes uninitialized space for the given type. The builder must 7192654Sjeff /// be empty. 7269664Speter TypeLoc pushFullUninitialized(QualType T) { 7369664Speter return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T)); 7469664Speter } 7569664Speter 7669664Speter /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs 771541Srgrimes /// previously retrieved from this builder. 781541Srgrimes TypeSpecTypeLoc pushTypeSpec(QualType T) { 791541Srgrimes size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; 801541Srgrimes return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize)); 811541Srgrimes } 821541Srgrimes 831541Srgrimes /// Resets this builder to the newly-initialized state. 841541Srgrimes void clear() { 851541Srgrimes#ifndef NDEBUG 861541Srgrimes LastTy = QualType(); 871541Srgrimes#endif 881541Srgrimes Index = Capacity; 891541Srgrimes } 901541Srgrimes 911541Srgrimes /// Pushes space for a new TypeLoc of the given type. Invalidates 921541Srgrimes /// any TypeLocs previously retrieved from this builder. 931541Srgrimes template <class TyLocType> TyLocType push(QualType T) { 941541Srgrimes size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); 951541Srgrimes return cast<TyLocType>(pushImpl(T, LocalSize)); 961541Srgrimes } 971541Srgrimes 981541Srgrimes /// Creates a TypeSourceInfo for the given type. 991541Srgrimes TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) { 1001541Srgrimes#ifndef NDEBUG 1011541Srgrimes assert(T == LastTy && "type doesn't match last type pushed!"); 1021541Srgrimes#endif 1031541Srgrimes 1041541Srgrimes size_t FullDataSize = Capacity - Index; 1051541Srgrimes TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize); 1061541Srgrimes memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); 10783366Sjulian return DI; 10883366Sjulian } 1091541Srgrimes 11091419Sjhbprivate: 11183366Sjulian TypeLoc pushImpl(QualType T, size_t LocalSize) { 11242408Seivind#ifndef NDEBUG 11342453Seivind QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); 11442408Seivind assert(TLast == LastTy && 11542453Seivind "mismatch between last type and new type's inner type"); 11683366Sjulian LastTy = T; 1171541Srgrimes#endif 1181541Srgrimes 1191541Srgrimes // If we need to grow, grow by a factor of 2. 1201541Srgrimes if (LocalSize > Index) { 1211541Srgrimes size_t RequiredCapacity = Capacity + (LocalSize - Index); 1221541Srgrimes size_t NewCapacity = Capacity * 2; 12392751Sjeff while (RequiredCapacity > NewCapacity) 1241541Srgrimes NewCapacity *= 2; 1251541Srgrimes grow(NewCapacity); 12636735Sdfr } 1271541Srgrimes 1281541Srgrimes Index -= LocalSize; 12936735Sdfr 13020069Sbde return getTypeLoc(T); 13120069Sbde } 13220069Sbde 13320069Sbde /// Grow to the given capacity. 13420069Sbde void grow(size_t NewCapacity) { 13520069Sbde assert(NewCapacity > Capacity); 13620069Sbde 1371541Srgrimes // Allocate the new buffer and copy the old data into it. 13892751Sjeff char *NewBuffer = new char[NewCapacity]; 139100613Srwatson unsigned NewIndex = Index + NewCapacity - Capacity; 140100613Srwatson memcpy(&NewBuffer[NewIndex], 141100613Srwatson &Buffer[Index], 142100613Srwatson Capacity - Index); 1431541Srgrimes 1441541Srgrimes if (Buffer != InlineBuffer) 1451541Srgrimes delete[] Buffer; 1461541Srgrimes 1471541Srgrimes Buffer = NewBuffer; 14897994Sjhb Capacity = NewCapacity; 14997994Sjhb Index = NewIndex; 15097994Sjhb } 15197994Sjhb 15297994Sjhb TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) { 1531541Srgrimes#ifndef NDEBUG 1541541Srgrimes assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder"); 1551541Srgrimes LastTy = T; 1561541Srgrimes#endif 1571541Srgrimes assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder"); 15889306Salfred 15933360Sdyson reserve(Size); 16051649Sphk Index -= Size; 16133360Sdyson 1621541Srgrimes return getTypeLoc(T); 1631541Srgrimes } 16489306Salfred 1651541Srgrimes 1661541Srgrimes // This is private because, when we kill off TypeSourceInfo in favor 1671541Srgrimes // of TypeLoc, we'll want an interface that creates a TypeLoc given 1681541Srgrimes // an ASTContext, and we don't want people to think they can just 1691541Srgrimes // use this as an equivalent. 1701541Srgrimes TypeLoc getTypeLoc(QualType T) { 1711541Srgrimes#ifndef NDEBUG 1721541Srgrimes assert(LastTy == T && "type doesn't match last type pushed!"); 1731541Srgrimes#endif 1741541Srgrimes return TypeLoc(T, &Buffer[Index]); 1751541Srgrimes } 1761541Srgrimes}; 1771541Srgrimes 1781541Srgrimes} 1791541Srgrimes 1801541Srgrimes#endif 1813148Sphk