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