TypeLocBuilder.h 4.5 KB

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