clang API Documentation

TypeLocBuilder.h
Go to the documentation of this file.
00001 //===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 //  This files defines TypeLocBuilder, a class for building TypeLocs
00011 //  bottom-up.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H
00016 #define LLVM_CLANG_LIB_SEMA_TYPELOCBUILDER_H
00017 
00018 #include "clang/AST/ASTContext.h"
00019 #include "clang/AST/TypeLoc.h"
00020 
00021 namespace clang {
00022 
00023 class TypeLocBuilder {
00024   enum { InlineCapacity = 8 * sizeof(SourceLocation) };
00025 
00026   /// The underlying location-data buffer.  Data grows from the end
00027   /// of the buffer backwards.
00028   char *Buffer;
00029 
00030   /// The capacity of the current buffer.
00031   size_t Capacity;
00032 
00033   /// The index of the first occupied byte in the buffer.
00034   size_t Index;
00035 
00036 #ifndef NDEBUG
00037   /// The last type pushed on this builder.
00038   QualType LastTy;
00039 #endif
00040     
00041   /// The inline buffer.
00042   enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment };
00043   llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;
00044   unsigned NumBytesAtAlign4, NumBytesAtAlign8;
00045 
00046  public:
00047   TypeLocBuilder()
00048     : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity),
00049       Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0)
00050   {
00051   }
00052 
00053   ~TypeLocBuilder() {
00054     if (Buffer != InlineBuffer.buffer)
00055       delete[] Buffer;
00056   }
00057 
00058   /// Ensures that this buffer has at least as much capacity as described.
00059   void reserve(size_t Requested) {
00060     if (Requested > Capacity)
00061       // For now, match the request exactly.
00062       grow(Requested);
00063   }
00064 
00065   /// Pushes a copy of the given TypeLoc onto this builder.  The builder
00066   /// must be empty for this to work.
00067   void pushFullCopy(TypeLoc L);
00068 
00069   /// Pushes space for a typespec TypeLoc.  Invalidates any TypeLocs
00070   /// previously retrieved from this builder.
00071   TypeSpecTypeLoc pushTypeSpec(QualType T) {
00072     size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
00073     unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment;
00074     return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>();
00075   }
00076 
00077   /// Resets this builder to the newly-initialized state.
00078   void clear() {
00079 #ifndef NDEBUG
00080     LastTy = QualType();
00081 #endif
00082     Index = Capacity;
00083     NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
00084   }  
00085 
00086   /// \brief Tell the TypeLocBuilder that the type it is storing has been
00087   /// modified in some safe way that doesn't affect type-location information.
00088   void TypeWasModifiedSafely(QualType T) {
00089 #ifndef NDEBUG
00090     LastTy = T;
00091 #endif
00092   }
00093   
00094   /// Pushes space for a new TypeLoc of the given type.  Invalidates
00095   /// any TypeLocs previously retrieved from this builder.
00096   template <class TyLocType> TyLocType push(QualType T) {
00097     TyLocType Loc = TypeLoc(T, nullptr).castAs<TyLocType>();
00098     size_t LocalSize = Loc.getLocalDataSize();
00099     unsigned LocalAlign = Loc.getLocalDataAlignment();
00100     return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();
00101   }
00102 
00103   /// Creates a TypeSourceInfo for the given type.
00104   TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) {
00105 #ifndef NDEBUG
00106     assert(T == LastTy && "type doesn't match last type pushed!");
00107 #endif
00108 
00109     size_t FullDataSize = Capacity - Index;
00110     TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize);
00111     memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
00112     return DI;
00113   }
00114 
00115   /// \brief Copies the type-location information to the given AST context and 
00116   /// returns a \c TypeLoc referring into the AST context.
00117   TypeLoc getTypeLocInContext(ASTContext &Context, QualType T) {
00118 #ifndef NDEBUG
00119     assert(T == LastTy && "type doesn't match last type pushed!");
00120 #endif
00121     
00122     size_t FullDataSize = Capacity - Index;
00123     void *Mem = Context.Allocate(FullDataSize);
00124     memcpy(Mem, &Buffer[Index], FullDataSize);
00125     return TypeLoc(T, Mem);
00126   }
00127 
00128 private:
00129 
00130   TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment);
00131 
00132   /// Grow to the given capacity.
00133   void grow(size_t NewCapacity);
00134 
00135   /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
00136   /// object.
00137   ///
00138   /// The resulting \c TypeLoc should only be used so long as the 
00139   /// \c TypeLocBuilder is active and has not had more type information
00140   /// pushed into it.
00141   TypeLoc getTemporaryTypeLoc(QualType T) {
00142 #ifndef NDEBUG
00143     assert(LastTy == T && "type doesn't match last type pushed!");
00144 #endif
00145     return TypeLoc(T, &Buffer[Index]);
00146   }
00147 };
00148 
00149 }
00150 
00151 #endif