]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/clang/lib/Sema/TypeLocBuilder.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / clang / lib / Sema / TypeLocBuilder.h
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
20 namespace clang {
21
22 class 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
127 private:
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