Reverts r183466: "Perform dynamic alignment computations..."

This introduces bugs in TemplateSpecializationTypeLoc's angle bracket
locations.

Regression test follows in a subsequent commit.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183513 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Manuel Klimek 2013-06-07 11:27:53 +00:00
Родитель 0d33f456ff
Коммит 20387efff0
8 изменённых файлов: 103 добавлений и 266 удалений

Просмотреть файл

@ -95,10 +95,6 @@ public:
/// \brief Returns the size of type source info data block for the given type.
static unsigned getFullDataSizeForType(QualType Ty);
/// \brief Returns the alignment of type source info data block for
/// the given type.
static unsigned getLocalAlignmentForType(QualType Ty);
/// \brief Get the type for which this source info wrapper provides
/// information.
QualType getType() const {
@ -233,11 +229,7 @@ public:
}
UnqualTypeLoc getUnqualifiedLoc() const {
unsigned align =
TypeLoc::getLocalAlignmentForType(QualType(getTypePtr(), 0));
uintptr_t dataInt = reinterpret_cast<uintptr_t>(Data);
dataInt = llvm::RoundUpToAlignment(dataInt, align);
return UnqualTypeLoc(getTypePtr(), reinterpret_cast<void*>(dataInt));
return UnqualTypeLoc(getTypePtr(), Data);
}
/// Initializes the local data of this type source info block to
@ -258,11 +250,10 @@ public:
return 0;
}
/// \brief Returns the alignment of the type source info data block that is
/// specific to this type.
unsigned getLocalDataAlignment() const {
// We don't preserve any location information.
return 1;
/// \brief Returns the size of the type source info data block.
unsigned getFullDataSize() const {
return getLocalDataSize() +
getFullDataSizeForType(getType().getLocalUnqualifiedType());
}
private:
@ -289,6 +280,9 @@ inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const {
/// \tparam LocalData the structure type of local location data for
/// this type
///
/// sizeof(LocalData) needs to be a multiple of sizeof(void*) or
/// else the world will end.
///
/// TypeLocs with non-constant amounts of local data should override
/// getExtraLocalDataSize(); getExtraLocalData() will then point to
/// this extra memory.
@ -323,16 +317,12 @@ class ConcreteTypeLoc : public Base {
}
public:
unsigned getLocalDataAlignment() const {
return std::max(llvm::alignOf<LocalData>(),
asDerived()->getExtraLocalDataAlignment());
}
unsigned getLocalDataSize() const {
unsigned size = sizeof(LocalData);
unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
size = llvm::RoundUpToAlignment(size, extraAlign);
size += asDerived()->getExtraLocalDataSize();
return size;
return sizeof(LocalData) + asDerived()->getExtraLocalDataSize();
}
// Give a default implementation that's useful for leaf types.
unsigned getFullDataSize() const {
return asDerived()->getLocalDataSize() + getInnerTypeSize();
}
TypeLoc getNextTypeLoc() const {
@ -348,10 +338,6 @@ protected:
return 0;
}
unsigned getExtraLocalDataAlignment() const {
return 1;
}
LocalData *getLocalData() const {
return static_cast<LocalData*>(Base::Data);
}
@ -360,17 +346,11 @@ protected:
/// local data that can't be captured in the Info (e.g. because it's
/// of variable size).
void *getExtraLocalData() const {
unsigned size = sizeof(LocalData);
unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
size = llvm::RoundUpToAlignment(size, extraAlign);
return reinterpret_cast<char*>(Base::Data) + size;
return getLocalData() + 1;
}
void *getNonLocalData() const {
uintptr_t data = reinterpret_cast<uintptr_t>(Base::Data);
data += asDerived()->getLocalDataSize();
data = llvm::RoundUpToAlignment(data, getNextTypeAlign());
return reinterpret_cast<void*>(data);
return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize();
}
struct HasNoInnerType {};
@ -393,18 +373,6 @@ private:
return getInnerTypeLoc().getFullDataSize();
}
unsigned getNextTypeAlign() const {
return getNextTypeAlign(asDerived()->getInnerType());
}
unsigned getNextTypeAlign(HasNoInnerType _) const {
return 1;
}
unsigned getNextTypeAlign(QualType T) const {
return TypeLoc::getLocalAlignmentForType(T);
}
TypeLoc getNextTypeLoc(HasNoInnerType _) const {
return TypeLoc();
}
@ -449,8 +417,7 @@ class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
Type,
TypeSpecLocInfo> {
public:
enum { LocalDataSize = sizeof(TypeSpecLocInfo),
LocalDataAlignment = llvm::AlignOf<TypeSpecLocInfo>::Alignment };
enum { LocalDataSize = sizeof(TypeSpecLocInfo) };
SourceLocation getNameLoc() const {
return this->getLocalData()->NameLoc;
@ -481,6 +448,8 @@ class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc,
BuiltinType,
BuiltinLocInfo> {
public:
enum { LocalDataSize = sizeof(BuiltinLocInfo) };
SourceLocation getBuiltinLoc() const {
return getLocalData()->BuiltinLoc;
}
@ -509,10 +478,6 @@ public:
return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0;
}
unsigned getExtraLocalDataAlignment() const {
return needsExtraLocalData() ? llvm::alignOf<WrittenBuiltinSpecs>() : 1;
}
SourceRange getLocalSourceRange() const {
return SourceRange(getBuiltinLoc(), getBuiltinLoc());
}
@ -875,10 +840,6 @@ public:
return this->getNumProtocols() * sizeof(SourceLocation);
}
unsigned getExtraLocalDataAlignment() const {
return llvm::alignOf<SourceLocation>();
}
QualType getInnerType() const {
return getTypePtr()->getBaseType();
}
@ -1205,10 +1166,6 @@ public:
return getNumArgs() * sizeof(ParmVarDecl*);
}
unsigned getExtraLocalDataAlignment() const {
return llvm::alignOf<ParmVarDecl*>();
}
QualType getInnerType() const { return getTypePtr()->getResultType(); }
};
@ -1400,10 +1357,6 @@ public:
return getNumArgs() * sizeof(TemplateArgumentLocInfo);
}
unsigned getExtraLocalDataAlignment() const {
return llvm::alignOf<TemplateArgumentLocInfo>();
}
private:
TemplateArgumentLocInfo *getArgInfos() const {
return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
@ -1808,10 +1761,6 @@ public:
return getNumArgs() * sizeof(TemplateArgumentLocInfo);
}
unsigned getExtraLocalDataAlignment() const {
return llvm::alignOf<TemplateArgumentLocInfo>();
}
private:
TemplateArgumentLocInfo *getArgInfos() const {
return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());

Просмотреть файл

@ -40,31 +40,13 @@ SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) {
return TypeLocRanger().Visit(TL);
}
namespace {
class TypeAligner : public TypeLocVisitor<TypeAligner, unsigned> {
public:
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
return TyLoc.getLocalDataAlignment(); \
}
#include "clang/AST/TypeLocNodes.def"
};
}
/// \brief Returns the alignment of the type source info data block.
unsigned TypeLoc::getLocalAlignmentForType(QualType Ty) {
if (Ty.isNull()) return 1;
return TypeAligner().Visit(TypeLoc(Ty, 0));
}
namespace {
class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> {
public:
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \
return TyLoc.getLocalDataSize(); \
return TyLoc.getFullDataSize(); \
}
#include "clang/AST/TypeLocNodes.def"
};
@ -72,18 +54,8 @@ namespace {
/// \brief Returns the size of the type source info data block.
unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
unsigned Total = 0;
TypeLoc TyLoc(Ty, 0);
unsigned MaxAlign = 1;
while (!TyLoc.isNull()) {
unsigned Align = getLocalAlignmentForType(TyLoc.getType());
MaxAlign = std::max(Align, MaxAlign);
Total = llvm::RoundUpToAlignment(Total, Align);
Total += TypeSizer().Visit(TyLoc);
TyLoc = TyLoc.getNextTypeLoc();
}
Total = llvm::RoundUpToAlignment(Total, MaxAlign);
return Total;
if (Ty.isNull()) return 0;
return TypeSizer().Visit(TypeLoc(Ty, 0));
}
namespace {

Просмотреть файл

@ -51,7 +51,6 @@ add_clang_library(clangSema
SemaTemplateVariadic.cpp
SemaType.cpp
TargetAttributesSema.cpp
TypeLocBuilder.cpp
)
add_dependencies(clangSema

Просмотреть файл

@ -445,7 +445,6 @@ FieldDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef,
assert(!DeductType.isNull() && "can't build reference to auto");
TLB.push<ReferenceTypeLoc>(DeductType).setSigilLoc(Loc);
}
TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType);
InitializationKind InitKind = InitializationKind::CreateDefault(Loc);
Expr *Init = InitExpr;
@ -477,7 +476,8 @@ FieldDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef,
else
InitKind = InitializationKind::CreateCopy(Loc, Loc);
QualType DeducedType;
if (DeduceAutoType(TSI, Init, DeducedType) == DAR_Failed) {
if (DeduceAutoType(TLB.getTemporaryTypeLoc(DeductType),
Init, DeducedType) == DAR_Failed) {
if (isa<InitListExpr>(Init))
Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list)
<< Id << Init->getSourceRange();
@ -492,7 +492,7 @@ FieldDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef,
// the closure type. This member is not a bit-field and not mutable.
// Core issue: the member is (probably...) public.
FieldDecl *NewFD = CheckFieldDecl(
Id, DeducedType, TSI, LSI->Lambda,
Id, DeducedType, TLB.getTypeSourceInfo(Context, DeductType), LSI->Lambda,
Loc, /*Mutable*/ false, /*BitWidth*/ 0, ICIS_NoInit,
Loc, AS_public, /*PrevDecl*/ 0, /*Declarator*/ 0);
LSI->Lambda->addDecl(NewFD);

Просмотреть файл

@ -18,7 +18,6 @@
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "TypeLocBuilder.h"
using namespace clang;
@ -464,13 +463,17 @@ Sema::CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc,
EllipsisLoc, NumExpansions);
if (Result.isNull())
return 0;
TypeLocBuilder TLB;
TLB.pushFullCopy(Pattern->getTypeLoc());
PackExpansionTypeLoc TL = TLB.push<PackExpansionTypeLoc>(Result);
TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
PackExpansionTypeLoc TL =
TSResult->getTypeLoc().castAs<PackExpansionTypeLoc>();
TL.setEllipsisLoc(EllipsisLoc);
return TLB.getTypeSourceInfo(Context, Result);
// Copy over the source-location information from the type.
memcpy(TL.getNextTypeLoc().getOpaqueData(),
Pattern->getTypeLoc().getOpaqueData(),
Pattern->getTypeLoc().getFullDataSize());
return TSResult;
}
QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange PatternRange,

Просмотреть файл

@ -3427,7 +3427,7 @@ TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB,
} else {
// Otherwise, complain about the addition of a qualifier to an
// already-qualified type.
SourceRange R = T.getUnqualifiedLoc().getSourceRange();
SourceRange R = TLB.getTemporaryTypeLoc(Result).getSourceRange();
SemaRef.Diag(R.getBegin(), diag::err_attr_objc_ownership_redundant)
<< Result << R;

Просмотреть файл

@ -1,136 +0,0 @@
//===--- TypeLocBuilder.cpp - Type Source Info collector ------------------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
#include "TypeLocBuilder.h"
using namespace clang;
void TypeLocBuilder::pushFullCopy(TypeLoc L) {
size_t Size = L.getFullDataSize();
reserve(Size);
SmallVector<TypeLoc, 4> TypeLocs;
TypeLoc CurTL = L;
while (CurTL) {
TypeLocs.push_back(CurTL);
CurTL = CurTL.getNextTypeLoc();
}
for (unsigned i = 0, e = TypeLocs.size(); i < e; ++i) {
TypeLoc CurTL = TypeLocs[e-i-1];
switch (CurTL.getTypeLocClass()) {
#define ABSTRACT_TYPELOC(CLASS, PARENT)
#define TYPELOC(CLASS, PARENT) \
case TypeLoc::CLASS: { \
CLASS##TypeLoc NewTL = push<class CLASS##TypeLoc>(CurTL.getType()); \
memcpy(NewTL.getOpaqueData(), CurTL.getOpaqueData(), NewTL.getLocalDataSize()); \
break; \
}
#include "clang/AST/TypeLocNodes.def"
}
}
}
void TypeLocBuilder::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.buffer)
delete[] Buffer;
Buffer = NewBuffer;
Capacity = NewCapacity;
Index = NewIndex;
}
TypeLoc TypeLocBuilder::pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment) {
#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
assert(LocalAlignment <= BufferMaxAlignment && "Unexpected alignment");
// 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);
}
// Because we're adding elements to the TypeLoc backwards, we have to
// do some extra work to keep everything aligned appropriately.
// FIXME: This algorithm is a absolute mess because every TypeLoc returned
// needs to be valid. Partial TypeLocs are a terrible idea.
// FIXME: 4 and 8 are sufficient at the moment, but it's pretty ugly to
// hardcode them.
if (LocalAlignment == 4) {
if (NumBytesAtAlign8 == 0) {
NumBytesAtAlign4 += LocalSize;
} else {
unsigned Padding = NumBytesAtAlign4 % 8;
if (Padding == 0) {
if (LocalSize % 8 == 0) {
// Everything is set: there's no padding and we don't need to add
// any.
} else {
assert(LocalSize % 8 == 4);
// No existing padding; add in 4 bytes padding
memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
Index -= 4;
}
} else {
assert(Padding == 4);
if (LocalSize % 8 == 0) {
// Everything is set: there's 4 bytes padding and we don't need
// to add any.
} else {
assert(LocalSize % 8 == 4);
// There are 4 bytes padding, but we don't need any; remove it.
memmove(&Buffer[Index + 4], &Buffer[Index], NumBytesAtAlign4);
Index += 4;
}
}
NumBytesAtAlign4 += LocalSize;
}
} else if (LocalAlignment == 8) {
if (!NumBytesAtAlign8 && NumBytesAtAlign4 % 8 != 0) {
// No existing padding and misaligned members; add in 4 bytes padding
memmove(&Buffer[Index - 4], &Buffer[Index], NumBytesAtAlign4);
Index -= 4;
}
// Forget about any padding.
NumBytesAtAlign4 = 0;
NumBytesAtAlign8 += LocalSize;
} else {
assert(LocalSize == 0);
}
Index -= LocalSize;
assert(Capacity - Index == TypeLoc::getFullDataSizeForType(T) &&
"incorrect data size provided to CreateTypeSourceInfo!");
return getTemporaryTypeLoc(T);
}

Просмотреть файл

@ -39,19 +39,14 @@ class TypeLocBuilder {
#endif
/// The inline buffer.
enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment };
llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity> InlineBuffer;
unsigned NumBytesAtAlign4, NumBytesAtAlign8;
char InlineBuffer[InlineCapacity];
public:
TypeLocBuilder()
: Buffer(InlineBuffer.buffer), Capacity(InlineCapacity),
Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0)
{
}
: Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) {}
~TypeLocBuilder() {
if (Buffer != InlineBuffer.buffer)
if (Buffer != InlineBuffer)
delete[] Buffer;
}
@ -64,14 +59,23 @@ class TypeLocBuilder {
/// Pushes a copy of the given TypeLoc onto this builder. The builder
/// must be empty for this to work.
void pushFullCopy(TypeLoc L);
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;
unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment;
return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>();
return pushImpl(T, LocalSize).castAs<TypeSpecTypeLoc>();
}
/// Resets this builder to the newly-initialized state.
@ -80,7 +84,6 @@ class TypeLocBuilder {
LastTy = QualType();
#endif
Index = Capacity;
NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
}
/// \brief Tell the TypeLocBuilder that the type it is storing has been
@ -94,10 +97,8 @@ class TypeLocBuilder {
/// 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) {
TyLocType Loc = TypeLoc(T, 0).castAs<TyLocType>();
size_t LocalSize = Loc.getLocalDataSize();
unsigned LocalAlign = Loc.getLocalDataAlignment();
return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();
size_t LocalSize = TypeLoc(T, 0).castAs<TyLocType>().getLocalDataSize();
return pushImpl(T, LocalSize).castAs<TyLocType>();
}
/// Creates a TypeSourceInfo for the given type.
@ -126,12 +127,61 @@ class TypeLocBuilder {
}
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
TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned LocalAlignment);
// 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 getTemporaryTypeLoc(T);
}
/// Grow to the given capacity.
void grow(size_t NewCapacity);
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 getTemporaryTypeLoc(T);
}
public:
/// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
/// object.
///