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:
parent
e4bdb93570
commit
26fe7e0b8a
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue