aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-10-21 00:23:54 +0000
committerJohn McCall <rjmccall@apple.com>2009-10-21 00:23:54 +0000
commit109de5ead1dfcb3bc985cddb8cb3ed5bcecad88d (patch)
tree3a723b640c5f395ce4cf80ece943b565fcab03b4
parentbb833dcc562f686a0652865d1945cfa3a421379c (diff)
Add TypeLocBuilder, an API for incrementally creating TypeLocs. Change
the API for creating DeclaratorInfos to allow callers to provide an exact size. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84715 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ASTContext.h5
-rw-r--r--include/clang/AST/TypeLocBuilder.h122
-rw-r--r--lib/AST/ASTContext.cpp10
3 files changed, 134 insertions, 3 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h
index df480e9a36..8507cd4175 100644
--- a/include/clang/AST/ASTContext.h
+++ b/include/clang/AST/ASTContext.h
@@ -1059,7 +1059,10 @@ public:
/// \param T the type that will be the basis for type source info. This type
/// should refer to how the declarator was written in source code, not to
/// what type semantic analysis resolved the declarator to.
- DeclaratorInfo *CreateDeclaratorInfo(QualType T);
+ ///
+ /// \param Size the size of the type info to create, or 0 if the size
+ /// should be calculated based on the type.
+ DeclaratorInfo *CreateDeclaratorInfo(QualType T, unsigned Size = 0);
private:
ASTContext(const ASTContext&); // DO NOT IMPLEMENT
diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h
new file mode 100644
index 0000000000..4e1fbaaf4c
--- /dev/null
+++ b/include/clang/AST/TypeLocBuilder.h
@@ -0,0 +1,122 @@
+//===--- 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_AST_TYPELOCBUILDER_H
+#define LLVM_CLANG_AST_TYPELOCBUILDER_H
+
+#include "clang/AST/TypeLoc.h"
+#include "llvm/ADT/SmallVector.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 space for a new TypeLoc onto the given type. Invalidates
+ /// any TypeLocs previously retrieved from this builder.
+ template <class TyLocType> TyLocType push(QualType T) {
+#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
+
+ size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize();
+
+ // 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 cast<TyLocType>(TypeLoc(T, &Buffer[Index]));
+ }
+
+ /// Creates a DeclaratorInfo for the given type.
+ DeclaratorInfo *getDeclaratorInfo(ASTContext& Context, QualType T) {
+#ifndef NDEBUG
+ assert(T == LastTy && "type doesn't match last type pushed!");
+#endif
+
+ size_t FullDataSize = Capacity - Index;
+ DeclaratorInfo *DI = Context.CreateDeclaratorInfo(T, FullDataSize);
+ memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize);
+ return DI;
+ }
+
+ private:
+ /// 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;
+ }
+};
+
+}
+
+#endif
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 98aef39022..8855cba159 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -943,8 +943,14 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,
/// \param T the type that will be the basis for type source info. This type
/// should refer to how the declarator was written in source code, not to
/// what type semantic analysis resolved the declarator to.
-DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T) {
- unsigned DataSize = TypeLoc::getFullDataSizeForType(T);
+DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T,
+ unsigned DataSize) {
+ if (!DataSize)
+ DataSize = TypeLoc::getFullDataSizeForType(T);
+ else
+ assert(DataSize == TypeLoc::getFullDataSizeForType(T) &&
+ "incorrect data size provided to CreateDeclaratorInfo!");
+
DeclaratorInfo *DInfo =
(DeclaratorInfo*)BumpAlloc.Allocate(sizeof(DeclaratorInfo) + DataSize, 8);
new (DInfo) DeclaratorInfo(T);