1109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===// 2109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// 3109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// The LLVM Compiler Infrastructure 4109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// 5109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// This file is distributed under the University of Illinois Open Source 6109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// License. See LICENSE.TXT for details. 7109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// 8109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//===----------------------------------------------------------------------===// 9109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// 10109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// This files defines TypeLocBuilder, a class for building TypeLocs 11109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// bottom-up. 12109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// 13109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//===----------------------------------------------------------------------===// 14109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 157e44e3fcd75147f229f42e6912898ce62d6b4d08Douglas Gregor#ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H 167e44e3fcd75147f229f42e6912898ce62d6b4d08Douglas Gregor#define LLVM_CLANG_SEMA_TYPELOCBUILDER_H 17109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 18109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#include "clang/AST/TypeLoc.h" 197745cab137b9d91205f13a7adaebe6ed801595f7Douglas Gregor#include "clang/AST/ASTContext.h" 20109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 21109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCallnamespace clang { 22109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 23109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCallclass TypeLocBuilder { 24109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall enum { InlineCapacity = 8 * sizeof(SourceLocation) }; 25109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 26109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall /// The underlying location-data buffer. Data grows from the end 27109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall /// of the buffer backwards. 28109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall char *Buffer; 29109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 30109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall /// The capacity of the current buffer. 31109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall size_t Capacity; 32109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 33109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall /// The index of the first occupied byte in the buffer. 34109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall size_t Index; 35109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 36109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#ifndef NDEBUG 37109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall /// The last type pushed on this builder. 38109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall QualType LastTy; 39109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#endif 40109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 41109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall /// The inline buffer. 42109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall char InlineBuffer[InlineCapacity]; 43109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 44109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall public: 45109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall TypeLocBuilder() 46b995e04b90f07c75178dbcbf71c9735876787185Ted Kremenek : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {} 47109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 48109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall ~TypeLocBuilder() { 49109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall if (Buffer != InlineBuffer) 50109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall delete[] Buffer; 51109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall } 52109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 53109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall /// Ensures that this buffer has at least as much capacity as described. 54109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall void reserve(size_t Requested) { 55109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall if (Requested > Capacity) 56109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall // For now, match the request exactly. 57109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall grow(Requested); 58109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall } 59109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 60c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall /// Pushes a copy of the given TypeLoc onto this builder. The builder 61c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall /// must be empty for this to work. 62c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall void pushFullCopy(TypeLoc L) { 6341bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall size_t Size = L.getFullDataSize(); 6441bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size); 65c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size); 66c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall } 67c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall 6841bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall /// Pushes uninitialized space for the given type. The builder must 6941bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall /// be empty. 7041bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall TypeLoc pushFullUninitialized(QualType T) { 7141bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T)); 7241bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall } 7341bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall 74ed97649e9574b9d854fa4d6109c9333ae0993554John McCall /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs 75ed97649e9574b9d854fa4d6109c9333ae0993554John McCall /// previously retrieved from this builder. 76ed97649e9574b9d854fa4d6109c9333ae0993554John McCall TypeSpecTypeLoc pushTypeSpec(QualType T) { 77ed97649e9574b9d854fa4d6109c9333ae0993554John McCall size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; 78ed97649e9574b9d854fa4d6109c9333ae0993554John McCall return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize)); 79ed97649e9574b9d854fa4d6109c9333ae0993554John McCall } 80480076c3defdcaf07e8a87c81930da467a702425John McCall 81480076c3defdcaf07e8a87c81930da467a702425John McCall /// Resets this builder to the newly-initialized state. 82480076c3defdcaf07e8a87c81930da467a702425John McCall void clear() { 83480076c3defdcaf07e8a87c81930da467a702425John McCall#ifndef NDEBUG 84480076c3defdcaf07e8a87c81930da467a702425John McCall LastTy = QualType(); 85480076c3defdcaf07e8a87c81930da467a702425John McCall#endif 86480076c3defdcaf07e8a87c81930da467a702425John McCall Index = Capacity; 87480076c3defdcaf07e8a87c81930da467a702425John McCall } 88ed97649e9574b9d854fa4d6109c9333ae0993554John McCall 89f85e193739c953358c865005855253af4f68a497John McCall /// \brief Tell the TypeLocBuilder that the type it is storing has been 90f85e193739c953358c865005855253af4f68a497John McCall /// modified in some safe way that doesn't affect type-location information. 91f85e193739c953358c865005855253af4f68a497John McCall void TypeWasModifiedSafely(QualType T) { 92f85e193739c953358c865005855253af4f68a497John McCall#ifndef NDEBUG 93f85e193739c953358c865005855253af4f68a497John McCall LastTy = T; 94f85e193739c953358c865005855253af4f68a497John McCall#endif 95f85e193739c953358c865005855253af4f68a497John McCall } 96f85e193739c953358c865005855253af4f68a497John McCall 97ed97649e9574b9d854fa4d6109c9333ae0993554John McCall /// Pushes space for a new TypeLoc of the given type. Invalidates 98109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall /// any TypeLocs previously retrieved from this builder. 99109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall template <class TyLocType> TyLocType push(QualType T) { 100ed97649e9574b9d854fa4d6109c9333ae0993554John McCall size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); 101ed97649e9574b9d854fa4d6109c9333ae0993554John McCall return cast<TyLocType>(pushImpl(T, LocalSize)); 102ed97649e9574b9d854fa4d6109c9333ae0993554John McCall } 103ed97649e9574b9d854fa4d6109c9333ae0993554John McCall 104a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall /// Creates a TypeSourceInfo for the given type. 105a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) { 106ed97649e9574b9d854fa4d6109c9333ae0993554John McCall#ifndef NDEBUG 107ed97649e9574b9d854fa4d6109c9333ae0993554John McCall assert(T == LastTy && "type doesn't match last type pushed!"); 108ed97649e9574b9d854fa4d6109c9333ae0993554John McCall#endif 109ed97649e9574b9d854fa4d6109c9333ae0993554John McCall 110ed97649e9574b9d854fa4d6109c9333ae0993554John McCall size_t FullDataSize = Capacity - Index; 111a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize); 112ed97649e9574b9d854fa4d6109c9333ae0993554John McCall memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); 113ed97649e9574b9d854fa4d6109c9333ae0993554John McCall return DI; 114ed97649e9574b9d854fa4d6109c9333ae0993554John McCall } 115ed97649e9574b9d854fa4d6109c9333ae0993554John McCall 1162e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor /// \brief Copies the type-location information to the given AST context and 1172e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor /// returns a \c TypeLoc referring into the AST context. 1182e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) { 1192e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor#ifndef NDEBUG 1202e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor assert(T == LastTy && "type doesn't match last type pushed!"); 1212e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor#endif 1222e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor 1232e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor size_t FullDataSize = Capacity - Index; 1242e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor void *Mem = Context.Allocate(FullDataSize); 1252e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor memcpy(Mem, &Buffer[Index], FullDataSize); 1262e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor return TypeLoc(T, Mem); 1272e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor } 1282e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor 129ed97649e9574b9d854fa4d6109c9333ae0993554John McCallprivate: 130ed97649e9574b9d854fa4d6109c9333ae0993554John McCall TypeLoc pushImpl(QualType T, size_t LocalSize) { 131109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#ifndef NDEBUG 132109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); 133109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall assert(TLast == LastTy && 134109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall "mismatch between last type and new type's inner type"); 135109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall LastTy = T; 136109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#endif 137109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 138109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall // If we need to grow, grow by a factor of 2. 139109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall if (LocalSize > Index) { 140109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall size_t RequiredCapacity = Capacity + (LocalSize - Index); 141109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall size_t NewCapacity = Capacity * 2; 142109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall while (RequiredCapacity > NewCapacity) 143109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall NewCapacity *= 2; 144109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall grow(NewCapacity); 145109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall } 146109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 147109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall Index -= LocalSize; 148109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 1494020caec546d221170072d2388b57d151cb26111Douglas Gregor return getTemporaryTypeLoc(T); 150109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall } 151109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 152109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall /// Grow to the given capacity. 153109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall void grow(size_t NewCapacity) { 154109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall assert(NewCapacity > Capacity); 155109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 156109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall // Allocate the new buffer and copy the old data into it. 157109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall char *NewBuffer = new char[NewCapacity]; 158109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall unsigned NewIndex = Index + NewCapacity - Capacity; 159109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall memcpy(&NewBuffer[NewIndex], 160109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall &Buffer[Index], 161109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall Capacity - Index); 162109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 163109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall if (Buffer != InlineBuffer) 164109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall delete[] Buffer; 165109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 166109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall Buffer = NewBuffer; 167109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall Capacity = NewCapacity; 168109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall Index = NewIndex; 169109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall } 17041bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall 17141bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) { 17241bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall#ifndef NDEBUG 17341bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder"); 17441bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall LastTy = T; 17541bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall#endif 17641bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder"); 17741bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall 17841bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall reserve(Size); 17941bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall Index -= Size; 18041bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall 1814020caec546d221170072d2388b57d151cb26111Douglas Gregor return getTemporaryTypeLoc(T); 18241bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall } 18341bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall 1844020caec546d221170072d2388b57d151cb26111Douglas Gregorpublic: 1854020caec546d221170072d2388b57d151cb26111Douglas Gregor /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder 1864020caec546d221170072d2388b57d151cb26111Douglas Gregor /// object. 1874020caec546d221170072d2388b57d151cb26111Douglas Gregor /// 1884020caec546d221170072d2388b57d151cb26111Douglas Gregor /// The resulting \c TypeLoc should only be used so long as the 1894020caec546d221170072d2388b57d151cb26111Douglas Gregor /// \c TypeLocBuilder is active and has not had more type information 1904020caec546d221170072d2388b57d151cb26111Douglas Gregor /// pushed into it. 1914020caec546d221170072d2388b57d151cb26111Douglas Gregor TypeLoc getTemporaryTypeLoc(QualType T) { 19241bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall#ifndef NDEBUG 19341bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall assert(LastTy == T && "type doesn't match last type pushed!"); 19441bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall#endif 19541bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall return TypeLoc(T, &Buffer[Index]); 19641bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall } 197109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall}; 198109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 199109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall} 200109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall 201109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#endif 202