Add TypeLocBuilder, an API for incrementally creating TypeLocs. Change

the API for creating DeclaratorInfos to allow callers to provide an exact
size.

llvm-svn: 84715
This commit is contained in:
John McCall 2009-10-21 00:23:54 +00:00
parent e4bdb93570
commit 26fe7e0b8a
3 changed files with 134 additions and 3 deletions

View File

@ -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

View File

@ -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

View File

@ -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);