TypeLocBuilder.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. alignas(BufferMaxAlignment) char InlineBuffer[InlineCapacity];
  34. unsigned NumBytesAtAlign4, NumBytesAtAlign8;
  35. public:
  36. TypeLocBuilder()
  37. : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity),
  38. NumBytesAtAlign4(0), NumBytesAtAlign8(0) {}
  39. ~TypeLocBuilder() {
  40. if (Buffer != InlineBuffer)
  41. delete[] Buffer;
  42. }
  43. /// Ensures that this buffer has at least as much capacity as described.
  44. void reserve(size_t Requested) {
  45. if (Requested > Capacity)
  46. // For now, match the request exactly.
  47. grow(Requested);
  48. }
  49. /// Pushes a copy of the given TypeLoc onto this builder. The builder
  50. /// must be empty for this to work.
  51. void pushFullCopy(TypeLoc L);
  52. /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
  53. /// previously retrieved from this builder.
  54. TypeSpecTypeLoc pushTypeSpec(QualType T) {
  55. size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
  56. unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment;
  57. return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>();
  58. }
  59. /// Resets this builder to the newly-initialized state.
  60. void clear() {
  61. #ifndef NDEBUG
  62. LastTy = QualType();
  63. #endif
  64. Index = Capacity;
  65. NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
  66. }
  67. /// Tell the TypeLocBuilder that the type it is storing has been
  68. /// modified in some safe way that doesn't affect type-location information.
  69. void TypeWasModifiedSafely(QualType T) {
  70. #ifndef NDEBUG
  71. LastTy = T;
  72. #endif
  73. }
  74. /// Pushes space for a new TypeLoc of the given type. Invalidates
  75. /// any TypeLocs previously retrieved from this builder.
  76. template <class TyLocType> TyLocType push(QualType T) {
  77. TyLocType Loc = TypeLoc(T, nullptr).castAs<TyLocType>();
  78. size_t LocalSize = Loc.getLocalDataSize();
  79. unsigned LocalAlign = Loc.getLocalDataAlignment();
  80. return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();
  81. }
  82. /// Creates a TypeSourceInfo for the given type.
  83. TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
  84. #ifndef NDEBUG
  85. assert(T == LastTy && "type doesn't match last type pushed!");
  86. #endif
  87. size_t FullDataSize = Capacity - Index;
  88. TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
  89. memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
  90. return DI;
  91. }
  92. /// Copies the type-location information to the given AST context and
  93. /// returns a \c TypeLoc referring into the AST context.
  94. TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
  95. #ifndef NDEBUG
  96. assert(T == LastTy && "type doesn't match last type pushed!");
  97. #endif
  98. size_t FullDataSize = Capacity - Index;
  99. void *Mem = Context.Allocate(FullDataSize);
  100. memcpy(Mem, &Buffer[Index], FullDataSize);
  101. return TypeLoc(T, Mem);
  102. }
  103. private:
  104. TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment);
  105. /// Grow to the given capacity.
  106. void grow(size_t NewCapacity);
  107. /// Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
  108. /// object.
  109. ///
  110. /// The resulting \c TypeLoc should only be used so long as the
  111. /// \c TypeLocBuilder is active and has not had more type information
  112. /// pushed into it.
  113. TypeLoc getTemporaryTypeLoc(QualType T) {
  114. #ifndef NDEBUG
  115. assert(LastTy == T && "type doesn't match last type pushed!");
  116. #endif
  117. return TypeLoc(T, &Buffer[Index]);
  118. }
  119. };
  120. }
  121. #endif