TypeLocBuilder.h revision 263508
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
21namespace clang {
22
23class 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
128private:
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
152