diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-12-02 00:05:49 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-12-02 00:05:49 +0000 |
commit | 7e44e3fcd75147f229f42e6912898ce62d6b4d08 (patch) | |
tree | e4568720f13a9d139dee876d598757158f8d2daf /lib/Sema | |
parent | 26ac3f30ecef21749c00a4b1a08dd15d772dd5aa (diff) |
Make TypeLocBuilder an implementation detail of Sema. Nobody else should be using it
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@120628 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/TreeTransform.h | 2 | ||||
-rw-r--r-- | lib/Sema/TypeLocBuilder.h | 180 |
2 files changed, 181 insertions, 1 deletions
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 807346c4c5..5aea3f029d 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -25,11 +25,11 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" -#include "clang/AST/TypeLocBuilder.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/Designator.h" #include "clang/Lex/Preprocessor.h" #include "llvm/Support/ErrorHandling.h" +#include "TypeLocBuilder.h" #include <algorithm> namespace clang { diff --git a/lib/Sema/TypeLocBuilder.h b/lib/Sema/TypeLocBuilder.h new file mode 100644 index 0000000000..3d20a5273d --- /dev/null +++ b/lib/Sema/TypeLocBuilder.h @@ -0,0 +1,180 @@ +//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files defines TypeLocBuilder, a class for building TypeLocs +// bottom-up. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_SEMA_TYPELOCBUILDER_H +#define LLVM_CLANG_SEMA_TYPELOCBUILDER_H + +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/SmallVector.h" +#include "clang/AST/ASTContext.h" + +namespace clang { + +class TypeLocBuilder { + enum { InlineCapacity = 8 * sizeof(SourceLocation) }; + + /// The underlying location-data buffer. Data grows from the end + /// of the buffer backwards. + char *Buffer; + + /// The capacity of the current buffer. + size_t Capacity; + + /// The index of the first occupied byte in the buffer. + size_t Index; + +#ifndef NDEBUG + /// The last type pushed on this builder. + QualType LastTy; +#endif + + /// The inline buffer. + char InlineBuffer[InlineCapacity]; + + public: + TypeLocBuilder() + : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) + {} + + ~TypeLocBuilder() { + if (Buffer != InlineBuffer) + delete[] Buffer; + } + + /// Ensures that this buffer has at least as much capacity as described. + void reserve(size_t Requested) { + if (Requested > Capacity) + // For now, match the request exactly. + grow(Requested); + } + + /// Pushes a copy of the given TypeLoc onto this builder. The builder + /// must be empty for this to work. + void pushFullCopy(TypeLoc L) { + size_t Size = L.getFullDataSize(); + TypeLoc Copy = pushFullUninitializedImpl(L.getType(), Size); + memcpy(Copy.getOpaqueData(), L.getOpaqueData(), Size); + } + + /// Pushes uninitialized space for the given type. The builder must + /// be empty. + TypeLoc pushFullUninitialized(QualType T) { + return pushFullUninitializedImpl(T, TypeLoc::getFullDataSizeForType(T)); + } + + /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs + /// previously retrieved from this builder. + TypeSpecTypeLoc pushTypeSpec(QualType T) { + size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; + return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize)); + } + + /// Resets this builder to the newly-initialized state. + void clear() { +#ifndef NDEBUG + LastTy = QualType(); +#endif + Index = Capacity; + } + + /// Pushes space for a new TypeLoc of the given type. Invalidates + /// any TypeLocs previously retrieved from this builder. + template <class TyLocType> TyLocType push(QualType T) { + size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); + return cast<TyLocType>(pushImpl(T, LocalSize)); + } + + /// Creates a TypeSourceInfo for the given type. + TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) { +#ifndef NDEBUG + assert(T == LastTy && "type doesn't match last type pushed!"); +#endif + + size_t FullDataSize = Capacity - Index; + TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize); + memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); + return DI; + } + +private: + TypeLoc pushImpl(QualType T, size_t LocalSize) { +#ifndef NDEBUG + QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); + assert(TLast == LastTy && + "mismatch between last type and new type's inner type"); + LastTy = T; +#endif + + // If we need to grow, grow by a factor of 2. + if (LocalSize > Index) { + size_t RequiredCapacity = Capacity + (LocalSize - Index); + size_t NewCapacity = Capacity * 2; + while (RequiredCapacity > NewCapacity) + NewCapacity *= 2; + grow(NewCapacity); + } + + Index -= LocalSize; + + return getTypeLoc(T); + } + + /// Grow to the given capacity. + void grow(size_t NewCapacity) { + assert(NewCapacity > Capacity); + + // Allocate the new buffer and copy the old data into it. + char *NewBuffer = new char[NewCapacity]; + unsigned NewIndex = Index + NewCapacity - Capacity; + memcpy(&NewBuffer[NewIndex], + &Buffer[Index], + Capacity - Index); + + if (Buffer != InlineBuffer) + delete[] Buffer; + + Buffer = NewBuffer; + Capacity = NewCapacity; + Index = NewIndex; + } + + TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) { +#ifndef NDEBUG + assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder"); + LastTy = T; +#endif + assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder"); + + reserve(Size); + Index -= Size; + + return getTypeLoc(T); + } + + + // This is private because, when we kill off TypeSourceInfo in favor + // of TypeLoc, we'll want an interface that creates a TypeLoc given + // an ASTContext, and we don't want people to think they can just + // use this as an equivalent. + TypeLoc getTypeLoc(QualType T) { +#ifndef NDEBUG + assert(LastTy == T && "type doesn't match last type pushed!"); +#endif + return TypeLoc(T, &Buffer[Index]); + } +}; + +} + +#endif |