1109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===//
2109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//
3109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//                     The LLVM Compiler Infrastructure
4109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//
5109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// This file is distributed under the University of Illinois Open Source
6109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall// License. See LICENSE.TXT for details.
7109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//
8109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//===----------------------------------------------------------------------===//
9109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//
10109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//  This files defines TypeLocBuilder, a class for building TypeLocs
11109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//  bottom-up.
12109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//
13109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall//===----------------------------------------------------------------------===//
14109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
157e44e3fcd75147f229f42e6912898ce62d6b4d08Douglas Gregor#ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H
167e44e3fcd75147f229f42e6912898ce62d6b4d08Douglas Gregor#define LLVM_CLANG_SEMA_TYPELOCBUILDER_H
17109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
18109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#include "clang/AST/TypeLoc.h"
197745cab137b9d91205f13a7adaebe6ed801595f7Douglas Gregor#include "clang/AST/ASTContext.h"
20109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
21109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCallnamespace clang {
22109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
23109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCallclass TypeLocBuilder {
24109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  enum { InlineCapacity = 8 * sizeof(SourceLocation) };
25109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
26109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// The underlying location-data buffer.  Data grows from the end
27109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// of the buffer backwards.
28109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  char *Buffer;
29109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
30109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// The capacity of the current buffer.
31109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  size_t Capacity;
32109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
33109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// The index of the first occupied byte in the buffer.
34109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  size_t Index;
35109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
36109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#ifndef NDEBUG
37109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// The last type pushed on this builder.
38109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  QualType LastTy;
39109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#endif
40109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
41109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// The inline buffer.
42109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  char InlineBuffer[InlineCapacity];
43109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
44109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall public:
45109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  TypeLocBuilder()
46b995e04b90f07c75178dbcbf71c9735876787185Ted Kremenek    : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {}
47109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
48109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  ~TypeLocBuilder() {
49109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    if (Buffer != InlineBuffer)
50109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall      delete[] Buffer;
51109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  }
52109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
53109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// Ensures that this buffer has at least as much capacity as described.
54109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  void reserve(size_t Requested) {
55109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    if (Requested > Capacity)
56109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall      // For now, match the request exactly.
57109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall      grow(Requested);
58109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  }
59109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
60c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall  /// Pushes a copy of the given TypeLoc onto this builder.  The builder
61c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall  /// must be empty for this to work.
62c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall  void pushFullCopy(TypeLoc L) {
6341bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    size_t Size = L.getFullDataSize();
6441bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size);
65c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall    memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size);
66c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall  }
67c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall
6841bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall  /// Pushes uninitialized space for the given type.  The builder must
6941bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall  /// be empty.
7041bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall  TypeLoc pushFullUninitialized(QualType T) {
7141bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T));
7241bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall  }
7341bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall
74ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  /// Pushes space for a typespec TypeLoc.  Invalidates any TypeLocs
75ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  /// previously retrieved from this builder.
76ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  TypeSpecTypeLoc pushTypeSpec(QualType T) {
77ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
78ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize));
79ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  }
80480076c3defdcaf07e8a87c81930da467a702425John McCall
81480076c3defdcaf07e8a87c81930da467a702425John McCall  /// Resets this builder to the newly-initialized state.
82480076c3defdcaf07e8a87c81930da467a702425John McCall  void clear() {
83480076c3defdcaf07e8a87c81930da467a702425John McCall#ifndef NDEBUG
84480076c3defdcaf07e8a87c81930da467a702425John McCall    LastTy = QualType();
85480076c3defdcaf07e8a87c81930da467a702425John McCall#endif
86480076c3defdcaf07e8a87c81930da467a702425John McCall    Index = Capacity;
87480076c3defdcaf07e8a87c81930da467a702425John McCall  }
88ed97649e9574b9d854fa4d6109c9333ae0993554John McCall
89f85e193739c953358c865005855253af4f68a497John McCall  /// \brief Tell the TypeLocBuilder that the type it is storing has been
90f85e193739c953358c865005855253af4f68a497John McCall  /// modified in some safe way that doesn't affect type-location information.
91f85e193739c953358c865005855253af4f68a497John McCall  void TypeWasModifiedSafely(QualType T) {
92f85e193739c953358c865005855253af4f68a497John McCall#ifndef NDEBUG
93f85e193739c953358c865005855253af4f68a497John McCall    LastTy = T;
94f85e193739c953358c865005855253af4f68a497John McCall#endif
95f85e193739c953358c865005855253af4f68a497John McCall  }
96f85e193739c953358c865005855253af4f68a497John McCall
97ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  /// Pushes space for a new TypeLoc of the given type.  Invalidates
98109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// any TypeLocs previously retrieved from this builder.
99109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  template <class TyLocType> TyLocType push(QualType T) {
100ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
101ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    return cast<TyLocType>(pushImpl(T, LocalSize));
102ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  }
103ed97649e9574b9d854fa4d6109c9333ae0993554John McCall
104a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall  /// Creates a TypeSourceInfo for the given type.
105a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall  TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
106ed97649e9574b9d854fa4d6109c9333ae0993554John McCall#ifndef NDEBUG
107ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    assert(T == LastTy && "type doesn't match last type pushed!");
108ed97649e9574b9d854fa4d6109c9333ae0993554John McCall#endif
109ed97649e9574b9d854fa4d6109c9333ae0993554John McCall
110ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    size_t FullDataSize = Capacity - Index;
111a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall    TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
112ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
113ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    return DI;
114ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  }
115ed97649e9574b9d854fa4d6109c9333ae0993554John McCall
1162e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor  /// \brief Copies the type-location information to the given AST context and
1172e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor  /// returns a \c TypeLoc referring into the AST context.
1182e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor  TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
1192e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor#ifndef NDEBUG
1202e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor    assert(T == LastTy && "type doesn't match last type pushed!");
1212e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor#endif
1222e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor
1232e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor    size_t FullDataSize = Capacity - Index;
1242e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor    void *Mem = Context.Allocate(FullDataSize);
1252e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor    memcpy(Mem, &Buffer[Index], FullDataSize);
1262e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor    return TypeLoc(T, Mem);
1272e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor  }
1282e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor
129ed97649e9574b9d854fa4d6109c9333ae0993554John McCallprivate:
130ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  TypeLoc pushImpl(QualType T, size_t LocalSize) {
131109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#ifndef NDEBUG
132109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType();
133109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    assert(TLast == LastTy &&
134109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall           "mismatch between last type and new type's inner type");
135109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    LastTy = T;
136109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#endif
137109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
138109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    // If we need to grow, grow by a factor of 2.
139109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    if (LocalSize > Index) {
140109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall      size_t RequiredCapacity = Capacity + (LocalSize - Index);
141109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall      size_t NewCapacity = Capacity * 2;
142109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall      while (RequiredCapacity > NewCapacity)
143109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall        NewCapacity *= 2;
144109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall      grow(NewCapacity);
145109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    }
146109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
147109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    Index -= LocalSize;
148109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
1494020caec546d221170072d2388b57d151cb26111Douglas Gregor    return getTemporaryTypeLoc(T);
150109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  }
151109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
152109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// Grow to the given capacity.
153109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  void grow(size_t NewCapacity) {
154109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    assert(NewCapacity > Capacity);
155109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
156109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    // Allocate the new buffer and copy the old data into it.
157109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    char *NewBuffer = new char[NewCapacity];
158109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    unsigned NewIndex = Index + NewCapacity - Capacity;
159109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    memcpy(&NewBuffer[NewIndex],
160109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall           &Buffer[Index],
161109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall           Capacity - Index);
162109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
163109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    if (Buffer != InlineBuffer)
164109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall      delete[] Buffer;
165109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
166109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    Buffer = NewBuffer;
167109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    Capacity = NewCapacity;
168109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    Index = NewIndex;
169109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  }
17041bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall
17141bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall  TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) {
17241bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall#ifndef NDEBUG
17341bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder");
17441bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    LastTy = T;
17541bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall#endif
17641bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder");
17741bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall
17841bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    reserve(Size);
17941bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    Index -= Size;
18041bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall
1814020caec546d221170072d2388b57d151cb26111Douglas Gregor    return getTemporaryTypeLoc(T);
18241bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall  }
18341bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall
1844020caec546d221170072d2388b57d151cb26111Douglas Gregorpublic:
1854020caec546d221170072d2388b57d151cb26111Douglas Gregor  /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
1864020caec546d221170072d2388b57d151cb26111Douglas Gregor  /// object.
1874020caec546d221170072d2388b57d151cb26111Douglas Gregor  ///
1884020caec546d221170072d2388b57d151cb26111Douglas Gregor  /// The resulting \c TypeLoc should only be used so long as the
1894020caec546d221170072d2388b57d151cb26111Douglas Gregor  /// \c TypeLocBuilder is active and has not had more type information
1904020caec546d221170072d2388b57d151cb26111Douglas Gregor  /// pushed into it.
1914020caec546d221170072d2388b57d151cb26111Douglas Gregor  TypeLoc getTemporaryTypeLoc(QualType T) {
19241bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall#ifndef NDEBUG
19341bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    assert(LastTy == T && "type doesn't match last type pushed!");
19441bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall#endif
19541bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    return TypeLoc(T, &Buffer[Index]);
19641bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall  }
197109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall};
198109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
199109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall}
200109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
201109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#endif
202