158 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file defines TypeLocBuilder, a class for building TypeLocs10// bottom-up.11//12//===----------------------------------------------------------------------===//13 14#ifndef LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H15#define LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H16 17#include "clang/AST/ASTContext.h"18#include "clang/AST/TypeLoc.h"19 20namespace clang {21 22class TypeLocBuilder {23 static constexpr int InlineCapacity = 8 * sizeof(SourceLocation);24 25 /// The underlying location-data buffer. Data grows from the end26 /// 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 NDEBUG36 /// The last type pushed on this builder.37 QualType LastTy;38#endif39 40 /// The inline buffer.41 static constexpr int BufferMaxAlignment = alignof(void *);42 alignas(BufferMaxAlignment) char InlineBuffer[InlineCapacity];43 unsigned NumBytesAtAlign4;44 bool AtAlign8;45 46public:47 TypeLocBuilder()48 : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity),49 NumBytesAtAlign4(0), AtAlign8(false) {}50 51 ~TypeLocBuilder() {52 if (Buffer != InlineBuffer)53 delete[] Buffer;54 }55 56 TypeLocBuilder(const TypeLocBuilder &) = delete;57 TypeLocBuilder &operator=(const TypeLocBuilder &) = delete;58 59 /// Ensures that this buffer has at least as much capacity as described.60 void reserve(size_t Requested) {61 if (Requested > Capacity)62 // For now, match the request exactly.63 grow(Requested);64 }65 66 /// Pushes a copy of the given TypeLoc onto this builder. The builder67 /// must be empty for this to work.68 void pushFullCopy(TypeLoc L);69 70 /// Pushes 'T' with all locations pointing to 'Loc'.71 /// The builder must be empty for this to work.72 void pushTrivial(ASTContext &Context, QualType T, SourceLocation Loc);73 74 /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs75 /// previously retrieved from this builder.76 TypeSpecTypeLoc pushTypeSpec(QualType T) {77 size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;78 unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment;79 return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>();80 }81 82 /// Resets this builder to the newly-initialized state.83 void clear() {84#ifndef NDEBUG85 LastTy = QualType();86#endif87 Index = Capacity;88 NumBytesAtAlign4 = 0;89 AtAlign8 = false;90 }91 92 /// Tell the TypeLocBuilder that the type it is storing has been93 /// modified in some safe way that doesn't affect type-location information.94 void TypeWasModifiedSafely(QualType T) {95#ifndef NDEBUG96 LastTy = T;97#endif98 }99 100 /// Pushes space for a new TypeLoc of the given type. Invalidates101 /// any TypeLocs previously retrieved from this builder.102 template <class TyLocType> TyLocType push(QualType T) {103 TyLocType Loc = TypeLoc(T, nullptr).castAs<TyLocType>();104 size_t LocalSize = Loc.getLocalDataSize();105 unsigned LocalAlign = Loc.getLocalDataAlignment();106 return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();107 }108 109 /// Creates a TypeSourceInfo for the given type.110 TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {111#ifndef NDEBUG112 assert(T == LastTy && "type doesn't match last type pushed!");113#endif114 115 size_t FullDataSize = Capacity - Index;116 TypeSourceInfo *TSI = Context.CreateTypeSourceInfo(T, FullDataSize);117 memcpy(TSI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);118 return TSI;119 }120 121 /// Copies the type-location information to the given AST context and122 /// returns a \c TypeLoc referring into the AST context.123 TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {124#ifndef NDEBUG125 assert(T == LastTy && "type doesn't match last type pushed!");126#endif127 128 size_t FullDataSize = Capacity - Index;129 void *Mem = Context.Allocate(FullDataSize);130 memcpy(Mem, &Buffer[Index], FullDataSize);131 return TypeLoc(T, Mem);132 }133 134private:135 136 TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment);137 138 /// Grow to the given capacity.139 void grow(size_t NewCapacity);140 141 /// Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder142 /// object.143 ///144 /// The resulting \c TypeLoc should only be used so long as the145 /// \c TypeLocBuilder is active and has not had more type information146 /// pushed into it.147 TypeLoc getTemporaryTypeLoc(QualType T) {148#ifndef NDEBUG149 assert(LastTy == T && "type doesn't match last type pushed!");150#endif151 return TypeLoc(T, &Buffer[Index]);152 }153};154 155}156 157#endif158