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