]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/AST/TypeLocBuilder.h
Merge OpenSSL 0.9.8p into head.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / AST / 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_AST_TYPELOCBUILDER_H
16 #define LLVM_CLANG_AST_TYPELOCBUILDER_H
17
18 #include "clang/AST/TypeLoc.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "clang/AST/ASTContext.h"
21
22 namespace clang {
23
24 class TypeLocBuilder {
25   enum { InlineCapacity = 8 * sizeof(SourceLocation) };
26
27   /// The underlying location-data buffer.  Data grows from the end
28   /// of the buffer backwards.
29   char *Buffer;
30
31   /// The capacity of the current buffer.
32   size_t Capacity;
33
34   /// The index of the first occupied byte in the buffer.
35   size_t Index;
36
37 #ifndef NDEBUG
38   /// The last type pushed on this builder.
39   QualType LastTy;
40 #endif
41     
42   /// The inline buffer.
43   char InlineBuffer[InlineCapacity];
44
45  public:
46   TypeLocBuilder()
47     : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity)
48   {}
49
50   ~TypeLocBuilder() {
51     if (Buffer != InlineBuffer)
52       delete[] Buffer;
53   }
54
55   /// Ensures that this buffer has at least as much capacity as described.
56   void reserve(size_t Requested) {
57     if (Requested > Capacity)
58       // For now, match the request exactly.
59       grow(Requested);
60   }
61
62   /// Pushes a copy of the given TypeLoc onto this builder.  The builder
63   /// must be empty for this to work.
64   void pushFullCopy(TypeLoc L) {
65 #ifndef NDEBUG
66     assert(LastTy.isNull() && "pushing copy on non-empty TypeLocBuilder");
67     LastTy = L.getNextTypeLoc().getType();
68 #endif
69     assert(Index == Capacity && "pushing copy on non-empty TypeLocBuilder");
70
71     unsigned Size = L.getFullDataSize();
72     TypeLoc Copy = pushImpl(L.getType(), Size);
73     memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
74   }
75
76   /// Pushes space for a typespec TypeLoc.  Invalidates any TypeLocs
77   /// previously retrieved from this builder.
78   TypeSpecTypeLoc pushTypeSpec(QualType T) {
79     size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
80     return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize));
81   }
82
83   /// Resets this builder to the newly-initialized state.
84   void clear() {
85 #ifndef NDEBUG
86     LastTy = QualType();
87 #endif
88     Index = Capacity;
89   }  
90
91   /// Pushes space for a new TypeLoc of the given type.  Invalidates
92   /// any TypeLocs previously retrieved from this builder.
93   template <class TyLocType> TyLocType push(QualType T) {
94     size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
95     return cast<TyLocType>(pushImpl(T, LocalSize));
96   }
97
98   /// Creates a TypeSourceInfo for the given type.
99   TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
100 #ifndef NDEBUG
101     assert(T == LastTy && "type doesn't match last type pushed!");
102 #endif
103
104     size_t FullDataSize = Capacity - Index;
105     TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
106     memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
107     return DI;
108   }
109
110 private:
111   TypeLoc pushImpl(QualType T, size_t LocalSize) {
112 #ifndef NDEBUG
113     QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
114     assert(TLast == LastTy &&
115            "mismatch between last type and new type's inner type");
116     LastTy = T;
117 #endif
118
119     // If we need to grow, grow by a factor of 2.
120     if (LocalSize > Index) {
121       size_t RequiredCapacity = Capacity + (LocalSize - Index);
122       size_t NewCapacity = Capacity * 2;
123       while (RequiredCapacity > NewCapacity)
124         NewCapacity *= 2;
125       grow(NewCapacity);
126     }
127
128     Index -= LocalSize;
129
130     return TypeLoc(T, &Buffer[Index]);
131   }
132
133   /// Grow to the given capacity.
134   void grow(size_t NewCapacity) {
135     assert(NewCapacity > Capacity);
136
137     // Allocate the new buffer and copy the old data into it.
138     char *NewBuffer = new char[NewCapacity];
139     unsigned NewIndex = Index + NewCapacity - Capacity;
140     memcpy(&NewBuffer[NewIndex],
141            &Buffer[Index],
142            Capacity - Index);
143
144     if (Buffer != InlineBuffer)
145       delete[] Buffer;
146
147     Buffer = NewBuffer;
148     Capacity = NewCapacity;
149     Index = NewIndex;
150   }
151 };
152
153 }
154
155 #endif