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
187745cab137b9d91205f13a7adaebe6ed801595f7Douglas Gregor#include "clang/AST/ASTContext.h"
1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/TypeLoc.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.
4244ee0a710c59d8e6793189f903bae21c16814324Eli Friedman  enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment };
4344ee0a710c59d8e6793189f903bae21c16814324Eli Friedman  llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;
4444ee0a710c59d8e6793189f903bae21c16814324Eli Friedman  unsigned NumBytesAtAlign4, NumBytesAtAlign8;
45109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
46109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall public:
47109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  TypeLocBuilder()
4844ee0a710c59d8e6793189f903bae21c16814324Eli Friedman    : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity),
4944ee0a710c59d8e6793189f903bae21c16814324Eli Friedman      Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0)
5044ee0a710c59d8e6793189f903bae21c16814324Eli Friedman  {
5144ee0a710c59d8e6793189f903bae21c16814324Eli Friedman  }
52109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
53109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  ~TypeLocBuilder() {
5444ee0a710c59d8e6793189f903bae21c16814324Eli Friedman    if (Buffer != InlineBuffer.buffer)
55109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall      delete[] Buffer;
56109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  }
57109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
58109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// Ensures that this buffer has at least as much capacity as described.
59109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  void reserve(size_t Requested) {
60109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall    if (Requested > Capacity)
61109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall      // For now, match the request exactly.
62109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall      grow(Requested);
63109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  }
64109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
65c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall  /// Pushes a copy of the given TypeLoc onto this builder.  The builder
66c12c5bba6ceb6acd4e51e7a0fc03257da9cfd44eJohn McCall  /// must be empty for this to work.
6744ee0a710c59d8e6793189f903bae21c16814324Eli Friedman  void pushFullCopy(TypeLoc L);
6841bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall
69ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  /// Pushes space for a typespec TypeLoc.  Invalidates any TypeLocs
70ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  /// previously retrieved from this builder.
71ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  TypeSpecTypeLoc pushTypeSpec(QualType T) {
72ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
7344ee0a710c59d8e6793189f903bae21c16814324Eli Friedman    unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment;
7444ee0a710c59d8e6793189f903bae21c16814324Eli Friedman    return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>();
75ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  }
76480076c3defdcaf07e8a87c81930da467a702425John McCall
77480076c3defdcaf07e8a87c81930da467a702425John McCall  /// Resets this builder to the newly-initialized state.
78480076c3defdcaf07e8a87c81930da467a702425John McCall  void clear() {
79480076c3defdcaf07e8a87c81930da467a702425John McCall#ifndef NDEBUG
80480076c3defdcaf07e8a87c81930da467a702425John McCall    LastTy = QualType();
81480076c3defdcaf07e8a87c81930da467a702425John McCall#endif
82480076c3defdcaf07e8a87c81930da467a702425John McCall    Index = Capacity;
8344ee0a710c59d8e6793189f903bae21c16814324Eli Friedman    NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
84480076c3defdcaf07e8a87c81930da467a702425John McCall  }
85ed97649e9574b9d854fa4d6109c9333ae0993554John McCall
86f85e193739c953358c865005855253af4f68a497John McCall  /// \brief Tell the TypeLocBuilder that the type it is storing has been
87f85e193739c953358c865005855253af4f68a497John McCall  /// modified in some safe way that doesn't affect type-location information.
88f85e193739c953358c865005855253af4f68a497John McCall  void TypeWasModifiedSafely(QualType T) {
89f85e193739c953358c865005855253af4f68a497John McCall#ifndef NDEBUG
90f85e193739c953358c865005855253af4f68a497John McCall    LastTy = T;
91f85e193739c953358c865005855253af4f68a497John McCall#endif
92f85e193739c953358c865005855253af4f68a497John McCall  }
93f85e193739c953358c865005855253af4f68a497John McCall
94ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  /// Pushes space for a new TypeLoc of the given type.  Invalidates
95109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// any TypeLocs previously retrieved from this builder.
96109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  template <class TyLocType> TyLocType push(QualType T) {
976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines    TyLocType Loc = TypeLoc(T, nullptr).castAs<TyLocType>();
9844ee0a710c59d8e6793189f903bae21c16814324Eli Friedman    size_t LocalSize = Loc.getLocalDataSize();
9944ee0a710c59d8e6793189f903bae21c16814324Eli Friedman    unsigned LocalAlign = Loc.getLocalDataAlignment();
10044ee0a710c59d8e6793189f903bae21c16814324Eli Friedman    return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();
101ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  }
102ed97649e9574b9d854fa4d6109c9333ae0993554John McCall
103a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall  /// Creates a TypeSourceInfo for the given type.
104a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall  TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
105ed97649e9574b9d854fa4d6109c9333ae0993554John McCall#ifndef NDEBUG
106ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    assert(T == LastTy && "type doesn't match last type pushed!");
107ed97649e9574b9d854fa4d6109c9333ae0993554John McCall#endif
108ed97649e9574b9d854fa4d6109c9333ae0993554John McCall
109ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    size_t FullDataSize = Capacity - Index;
110a93c934af4fbf97cbe8e649d82e68ccacfe57c95John McCall    TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
111ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
112ed97649e9574b9d854fa4d6109c9333ae0993554John McCall    return DI;
113ed97649e9574b9d854fa4d6109c9333ae0993554John McCall  }
114ed97649e9574b9d854fa4d6109c9333ae0993554John McCall
1152e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor  /// \brief Copies the type-location information to the given AST context and
1162e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor  /// returns a \c TypeLoc referring into the AST context.
1172e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor  TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
1182e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor#ifndef NDEBUG
1192e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor    assert(T == LastTy && "type doesn't match last type pushed!");
1202e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor#endif
1212e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor
1222e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor    size_t FullDataSize = Capacity - Index;
1232e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor    void *Mem = Context.Allocate(FullDataSize);
1242e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor    memcpy(Mem, &Buffer[Index], FullDataSize);
1252e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor    return TypeLoc(T, Mem);
1262e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor  }
1272e4c34ac53d08633b9473df921db4c7e4c9cd577Douglas Gregor
128ed97649e9574b9d854fa4d6109c9333ae0993554John McCallprivate:
129109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
13044ee0a710c59d8e6793189f903bae21c16814324Eli Friedman  TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment);
131109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
132109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall  /// Grow to the given capacity.
13344ee0a710c59d8e6793189f903bae21c16814324Eli Friedman  void grow(size_t NewCapacity);
13441bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall
1354020caec546d221170072d2388b57d151cb26111Douglas Gregor  /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
1364020caec546d221170072d2388b57d151cb26111Douglas Gregor  /// object.
1374020caec546d221170072d2388b57d151cb26111Douglas Gregor  ///
1384020caec546d221170072d2388b57d151cb26111Douglas Gregor  /// The resulting \c TypeLoc should only be used so long as the
1394020caec546d221170072d2388b57d151cb26111Douglas Gregor  /// \c TypeLocBuilder is active and has not had more type information
1404020caec546d221170072d2388b57d151cb26111Douglas Gregor  /// pushed into it.
1414020caec546d221170072d2388b57d151cb26111Douglas Gregor  TypeLoc getTemporaryTypeLoc(QualType T) {
14241bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall#ifndef NDEBUG
14341bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    assert(LastTy == T && "type doesn't match last type pushed!");
14441bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall#endif
14541bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall    return TypeLoc(T, &Buffer[Index]);
14641bafb1b62dfb2577c5aa7ba7fbd6ba5bebdbfeeJohn McCall  }
147109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall};
148109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
149109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall}
150109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall
151109de5ead1dfcb3bc985cddb8cb3ed5bcecad88dJohn McCall#endif
152