Home | History | Annotate | Download | only in Sema
      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 
     21 namespace clang {
     22 
     23 class 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 
    128 private:
    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