1218887Sdim//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===// 2218887Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6218887Sdim// 7218887Sdim//===----------------------------------------------------------------------===// 8218887Sdim// 9309124Sdim// This file defines TypeLocBuilder, a class for building TypeLocs 10218887Sdim// bottom-up. 11218887Sdim// 12218887Sdim//===----------------------------------------------------------------------===// 13218887Sdim 14280031Sdim#ifndef LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H 15280031Sdim#define LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H 16218887Sdim 17249423Sdim#include "clang/AST/ASTContext.h" 18218887Sdim#include "clang/AST/TypeLoc.h" 19218887Sdim 20218887Sdimnamespace clang { 21218887Sdim 22218887Sdimclass TypeLocBuilder { 23218887Sdim enum { InlineCapacity = 8 * sizeof(SourceLocation) }; 24218887Sdim 25218887Sdim /// The underlying location-data buffer. Data grows from the end 26218887Sdim /// of the buffer backwards. 27218887Sdim char *Buffer; 28218887Sdim 29218887Sdim /// The capacity of the current buffer. 30218887Sdim size_t Capacity; 31218887Sdim 32218887Sdim /// The index of the first occupied byte in the buffer. 33218887Sdim size_t Index; 34218887Sdim 35218887Sdim#ifndef NDEBUG 36218887Sdim /// The last type pushed on this builder. 37218887Sdim QualType LastTy; 38218887Sdim#endif 39341825Sdim 40218887Sdim /// The inline buffer. 41314564Sdim enum { BufferMaxAlignment = alignof(void *) }; 42360784Sdim alignas(BufferMaxAlignment) char InlineBuffer[InlineCapacity]; 43261991Sdim unsigned NumBytesAtAlign4, NumBytesAtAlign8; 44218887Sdim 45360784Sdimpublic: 46218887Sdim TypeLocBuilder() 47360784Sdim : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity), 48360784Sdim NumBytesAtAlign4(0), NumBytesAtAlign8(0) {} 49218887Sdim 50218887Sdim ~TypeLocBuilder() { 51360784Sdim if (Buffer != InlineBuffer) 52218887Sdim delete[] Buffer; 53218887Sdim } 54218887Sdim 55218887Sdim /// Ensures that this buffer has at least as much capacity as described. 56218887Sdim void reserve(size_t Requested) { 57218887Sdim if (Requested > Capacity) 58218887Sdim // For now, match the request exactly. 59218887Sdim grow(Requested); 60218887Sdim } 61218887Sdim 62218887Sdim /// Pushes a copy of the given TypeLoc onto this builder. The builder 63218887Sdim /// must be empty for this to work. 64261991Sdim void pushFullCopy(TypeLoc L); 65218887Sdim 66218887Sdim /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs 67218887Sdim /// previously retrieved from this builder. 68218887Sdim TypeSpecTypeLoc pushTypeSpec(QualType T) { 69218887Sdim size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; 70261991Sdim unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment; 71261991Sdim return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>(); 72218887Sdim } 73218887Sdim 74218887Sdim /// Resets this builder to the newly-initialized state. 75218887Sdim void clear() { 76218887Sdim#ifndef NDEBUG 77218887Sdim LastTy = QualType(); 78218887Sdim#endif 79218887Sdim Index = Capacity; 80261991Sdim NumBytesAtAlign4 = NumBytesAtAlign8 = 0; 81341825Sdim } 82218887Sdim 83341825Sdim /// Tell the TypeLocBuilder that the type it is storing has been 84224145Sdim /// modified in some safe way that doesn't affect type-location information. 85224145Sdim void TypeWasModifiedSafely(QualType T) { 86224145Sdim#ifndef NDEBUG 87224145Sdim LastTy = T; 88224145Sdim#endif 89224145Sdim } 90341825Sdim 91218887Sdim /// Pushes space for a new TypeLoc of the given type. Invalidates 92218887Sdim /// any TypeLocs previously retrieved from this builder. 93218887Sdim template <class TyLocType> TyLocType push(QualType T) { 94276479Sdim TyLocType Loc = TypeLoc(T, nullptr).castAs<TyLocType>(); 95261991Sdim size_t LocalSize = Loc.getLocalDataSize(); 96261991Sdim unsigned LocalAlign = Loc.getLocalDataAlignment(); 97261991Sdim return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>(); 98218887Sdim } 99218887Sdim 100218887Sdim /// Creates a TypeSourceInfo for the given type. 101218887Sdim TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) { 102218887Sdim#ifndef NDEBUG 103218887Sdim assert(T == LastTy && "type doesn't match last type pushed!"); 104218887Sdim#endif 105218887Sdim 106218887Sdim size_t FullDataSize = Capacity - Index; 107218887Sdim TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize); 108218887Sdim memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); 109218887Sdim return DI; 110218887Sdim } 111218887Sdim 112341825Sdim /// Copies the type-location information to the given AST context and 113219077Sdim /// returns a \c TypeLoc referring into the AST context. 114219077Sdim TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) { 115219077Sdim#ifndef NDEBUG 116219077Sdim assert(T == LastTy && "type doesn't match last type pushed!"); 117219077Sdim#endif 118341825Sdim 119219077Sdim size_t FullDataSize = Capacity - Index; 120219077Sdim void *Mem = Context.Allocate(FullDataSize); 121219077Sdim memcpy(Mem, &Buffer[Index], FullDataSize); 122219077Sdim return TypeLoc(T, Mem); 123219077Sdim } 124219077Sdim 125218887Sdimprivate: 126218887Sdim 127261991Sdim TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment); 128218887Sdim 129218887Sdim /// Grow to the given capacity. 130261991Sdim void grow(size_t NewCapacity); 131218887Sdim 132341825Sdim /// Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder 133224145Sdim /// object. 134224145Sdim /// 135341825Sdim /// The resulting \c TypeLoc should only be used so long as the 136224145Sdim /// \c TypeLocBuilder is active and has not had more type information 137224145Sdim /// pushed into it. 138224145Sdim TypeLoc getTemporaryTypeLoc(QualType T) { 139218887Sdim#ifndef NDEBUG 140218887Sdim assert(LastTy == T && "type doesn't match last type pushed!"); 141218887Sdim#endif 142218887Sdim return TypeLoc(T, &Buffer[Index]); 143218887Sdim } 144218887Sdim}; 145218887Sdim 146218887Sdim} 147218887Sdim 148218887Sdim#endif 149