r183466 - Perform dynamic alignment computations so that the data in TypeLocs is
Manuel Klimek
klimek at google.com
Fri Jun 7 04:27:11 PDT 2013
I have no idea what's wrong... With lg from chandlerc on irc I'm rolling
back and adding a regression test case.
/Manuel
On Fri, Jun 7, 2013 at 11:09 AM, Manuel Klimek <klimek at google.com> wrote:
> More specifically, we get a TemplateSpecializationTypeLoc for which:
> getLAngleLoc().isValid() is false, while
> getRAngleLoc().isValid() && getLocStart().isValid() &&
> getLocEnd().isValid() is true.
>
>
> On Fri, Jun 7, 2013 at 10:46 AM, Manuel Klimek <klimek at google.com> wrote:
>
>> FYI: this test leads to invalid type source locations in some cases. I
>> don't have a good enough repro yet (internal refactoring tests found this),
>> but the general idea is this:
>> Given a TypeLoc for a templated type A<B> of a function parameter (like
>> void f(const A<B>&), trying to getAs<clang::TemplateSpecializationTypeLoc>
>> would previously return a valid type loc, and now returns an invalid type
>> loc... Is that intentional?
>>
>> Thanks,
>> /Manuel
>>
>>
>>
>> On Fri, Jun 7, 2013 at 2:04 AM, Eli Friedman <eli.friedman at gmail.com>wrote:
>>
>>> Author: efriedma
>>> Date: Thu Jun 6 19:04:31 2013
>>> New Revision: 183466
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=183466&view=rev
>>> Log:
>>> Perform dynamic alignment computations so that the data in TypeLocs is
>>> correctly aligned. Not performing such computations led to misaligned
>>> loads,
>>> which crash on some platforms and are generally bad on other platforms.
>>>
>>> The implementation of TypeLocBuilder::pushImpl is rather messy; code
>>> using
>>> TypeLocBuilder accidentally assumes that partial TypeLocs are
>>> laid out like a complete TypeLoc. As a followup, I intend to work on
>>> fixing the TypeLocBuilder API to avoid exposing partial TypeLocs; this
>>> should
>>> substantially simplify the implemementation.
>>>
>>> Fixes PR16144.
>>>
>>>
>>> Added:
>>> cfe/trunk/lib/Sema/TypeLocBuilder.cpp
>>> Modified:
>>> cfe/trunk/include/clang/AST/TypeLoc.h
>>> cfe/trunk/lib/AST/TypeLoc.cpp
>>> cfe/trunk/lib/Sema/CMakeLists.txt
>>> cfe/trunk/lib/Sema/SemaLambda.cpp
>>> cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
>>> cfe/trunk/lib/Sema/TreeTransform.h
>>> cfe/trunk/lib/Sema/TypeLocBuilder.h
>>>
>>> Modified: cfe/trunk/include/clang/AST/TypeLoc.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/TypeLoc.h?rev=183466&r1=183465&r2=183466&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/AST/TypeLoc.h (original)
>>> +++ cfe/trunk/include/clang/AST/TypeLoc.h Thu Jun 6 19:04:31 2013
>>> @@ -95,6 +95,10 @@ 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 {
>>> @@ -229,7 +233,11 @@ public:
>>> }
>>>
>>> UnqualTypeLoc getUnqualifiedLoc() const {
>>> - return UnqualTypeLoc(getTypePtr(), Data);
>>> + 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));
>>> }
>>>
>>> /// Initializes the local data of this type source info block to
>>> @@ -250,10 +258,11 @@ public:
>>> return 0;
>>> }
>>>
>>> - /// \brief Returns the size of the type source info data block.
>>> - unsigned getFullDataSize() const {
>>> - return getLocalDataSize() +
>>> - getFullDataSizeForType(getType().getLocalUnqualifiedType());
>>> + /// \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;
>>> }
>>>
>>> private:
>>> @@ -280,9 +289,6 @@ inline UnqualTypeLoc TypeLoc::getUnquali
>>> /// \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.
>>> @@ -317,12 +323,16 @@ class ConcreteTypeLoc : public Base {
>>> }
>>>
>>> public:
>>> - unsigned getLocalDataSize() const {
>>> - return sizeof(LocalData) + asDerived()->getExtraLocalDataSize();
>>> + unsigned getLocalDataAlignment() const {
>>> + return std::max(llvm::alignOf<LocalData>(),
>>> + asDerived()->getExtraLocalDataAlignment());
>>> }
>>> - // Give a default implementation that's useful for leaf types.
>>> - unsigned getFullDataSize() const {
>>> - return asDerived()->getLocalDataSize() + getInnerTypeSize();
>>> + unsigned getLocalDataSize() const {
>>> + unsigned size = sizeof(LocalData);
>>> + unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
>>> + size = llvm::RoundUpToAlignment(size, extraAlign);
>>> + size += asDerived()->getExtraLocalDataSize();
>>> + return size;
>>> }
>>>
>>> TypeLoc getNextTypeLoc() const {
>>> @@ -338,6 +348,10 @@ protected:
>>> return 0;
>>> }
>>>
>>> + unsigned getExtraLocalDataAlignment() const {
>>> + return 1;
>>> + }
>>> +
>>> LocalData *getLocalData() const {
>>> return static_cast<LocalData*>(Base::Data);
>>> }
>>> @@ -346,11 +360,17 @@ protected:
>>> /// local data that can't be captured in the Info (e.g. because it's
>>> /// of variable size).
>>> void *getExtraLocalData() const {
>>> - return getLocalData() + 1;
>>> + unsigned size = sizeof(LocalData);
>>> + unsigned extraAlign = asDerived()->getExtraLocalDataAlignment();
>>> + size = llvm::RoundUpToAlignment(size, extraAlign);
>>> + return reinterpret_cast<char*>(Base::Data) + size;
>>> }
>>>
>>> void *getNonLocalData() const {
>>> - return static_cast<char*>(Base::Data) +
>>> asDerived()->getLocalDataSize();
>>> + uintptr_t data = reinterpret_cast<uintptr_t>(Base::Data);
>>> + data += asDerived()->getLocalDataSize();
>>> + data = llvm::RoundUpToAlignment(data, getNextTypeAlign());
>>> + return reinterpret_cast<void*>(data);
>>> }
>>>
>>> struct HasNoInnerType {};
>>> @@ -373,6 +393,18 @@ 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();
>>> }
>>> @@ -417,7 +449,8 @@ class TypeSpecTypeLoc : public ConcreteT
>>> Type,
>>> TypeSpecLocInfo> {
>>> public:
>>> - enum { LocalDataSize = sizeof(TypeSpecLocInfo) };
>>> + enum { LocalDataSize = sizeof(TypeSpecLocInfo),
>>> + LocalDataAlignment = llvm::AlignOf<TypeSpecLocInfo>::Alignment
>>> };
>>>
>>> SourceLocation getNameLoc() const {
>>> return this->getLocalData()->NameLoc;
>>> @@ -448,8 +481,6 @@ class BuiltinTypeLoc : public ConcreteTy
>>> BuiltinType,
>>> BuiltinLocInfo> {
>>> public:
>>> - enum { LocalDataSize = sizeof(BuiltinLocInfo) };
>>> -
>>> SourceLocation getBuiltinLoc() const {
>>> return getLocalData()->BuiltinLoc;
>>> }
>>> @@ -478,6 +509,10 @@ public:
>>> return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0;
>>> }
>>>
>>> + unsigned getExtraLocalDataAlignment() const {
>>> + return needsExtraLocalData() ? llvm::alignOf<WrittenBuiltinSpecs>()
>>> : 1;
>>> + }
>>> +
>>> SourceRange getLocalSourceRange() const {
>>> return SourceRange(getBuiltinLoc(), getBuiltinLoc());
>>> }
>>> @@ -840,6 +875,10 @@ public:
>>> return this->getNumProtocols() * sizeof(SourceLocation);
>>> }
>>>
>>> + unsigned getExtraLocalDataAlignment() const {
>>> + return llvm::alignOf<SourceLocation>();
>>> + }
>>> +
>>> QualType getInnerType() const {
>>> return getTypePtr()->getBaseType();
>>> }
>>> @@ -1166,6 +1205,10 @@ public:
>>> return getNumArgs() * sizeof(ParmVarDecl*);
>>> }
>>>
>>> + unsigned getExtraLocalDataAlignment() const {
>>> + return llvm::alignOf<ParmVarDecl*>();
>>> + }
>>> +
>>> QualType getInnerType() const { return getTypePtr()->getResultType();
>>> }
>>> };
>>>
>>> @@ -1357,6 +1400,10 @@ public:
>>> return getNumArgs() * sizeof(TemplateArgumentLocInfo);
>>> }
>>>
>>> + unsigned getExtraLocalDataAlignment() const {
>>> + return llvm::alignOf<TemplateArgumentLocInfo>();
>>> + }
>>> +
>>> private:
>>> TemplateArgumentLocInfo *getArgInfos() const {
>>> return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
>>> @@ -1761,6 +1808,10 @@ public:
>>> return getNumArgs() * sizeof(TemplateArgumentLocInfo);
>>> }
>>>
>>> + unsigned getExtraLocalDataAlignment() const {
>>> + return llvm::alignOf<TemplateArgumentLocInfo>();
>>> + }
>>> +
>>> private:
>>> TemplateArgumentLocInfo *getArgInfos() const {
>>> return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData());
>>>
>>> Modified: cfe/trunk/lib/AST/TypeLoc.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/TypeLoc.cpp?rev=183466&r1=183465&r2=183466&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/AST/TypeLoc.cpp (original)
>>> +++ cfe/trunk/lib/AST/TypeLoc.cpp Thu Jun 6 19:04:31 2013
>>> @@ -41,12 +41,30 @@ SourceRange TypeLoc::getLocalSourceRange
>>> }
>>>
>>> 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.getFullDataSize(); \
>>> + return TyLoc.getLocalDataSize(); \
>>> }
>>> #include "clang/AST/TypeLocNodes.def"
>>> };
>>> @@ -54,8 +72,18 @@ namespace {
>>>
>>> /// \brief Returns the size of the type source info data block.
>>> unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {
>>> - if (Ty.isNull()) return 0;
>>> - return TypeSizer().Visit(TypeLoc(Ty, 0));
>>> + 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;
>>> }
>>>
>>> namespace {
>>>
>>> Modified: cfe/trunk/lib/Sema/CMakeLists.txt
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/CMakeLists.txt?rev=183466&r1=183465&r2=183466&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/CMakeLists.txt (original)
>>> +++ cfe/trunk/lib/Sema/CMakeLists.txt Thu Jun 6 19:04:31 2013
>>> @@ -51,6 +51,7 @@ add_clang_library(clangSema
>>> SemaTemplateVariadic.cpp
>>> SemaType.cpp
>>> TargetAttributesSema.cpp
>>> + TypeLocBuilder.cpp
>>> )
>>>
>>> add_dependencies(clangSema
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=183466&r1=183465&r2=183466&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaLambda.cpp Thu Jun 6 19:04:31 2013
>>> @@ -445,6 +445,7 @@ FieldDecl *Sema::checkInitCapture(Source
>>> 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;
>>> @@ -476,8 +477,7 @@ FieldDecl *Sema::checkInitCapture(Source
>>> else
>>> InitKind = InitializationKind::CreateCopy(Loc, Loc);
>>> QualType DeducedType;
>>> - if (DeduceAutoType(TLB.getTemporaryTypeLoc(DeductType),
>>> - Init, DeducedType) == DAR_Failed) {
>>> + if (DeduceAutoType(TSI, 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(Source
>>> // 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, TLB.getTypeSourceInfo(Context, DeductType),
>>> LSI->Lambda,
>>> + Id, DeducedType, TSI, LSI->Lambda,
>>> Loc, /*Mutable*/ false, /*BitWidth*/ 0, ICIS_NoInit,
>>> Loc, AS_public, /*PrevDecl*/ 0, /*Declarator*/ 0);
>>> LSI->Lambda->addDecl(NewFD);
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=183466&r1=183465&r2=183466&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Thu Jun 6 19:04:31 2013
>>> @@ -18,6 +18,7 @@
>>> #include "clang/Sema/ScopeInfo.h"
>>> #include "clang/Sema/SemaInternal.h"
>>> #include "clang/Sema/Template.h"
>>> +#include "TypeLocBuilder.h"
>>>
>>> using namespace clang;
>>>
>>> @@ -463,17 +464,13 @@ Sema::CheckPackExpansion(TypeSourceInfo
>>> EllipsisLoc, NumExpansions);
>>> if (Result.isNull())
>>> return 0;
>>> -
>>> - TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result);
>>> - PackExpansionTypeLoc TL =
>>> - TSResult->getTypeLoc().castAs<PackExpansionTypeLoc>();
>>> +
>>> + TypeLocBuilder TLB;
>>> + TLB.pushFullCopy(Pattern->getTypeLoc());
>>> + PackExpansionTypeLoc TL = TLB.push<PackExpansionTypeLoc>(Result);
>>> TL.setEllipsisLoc(EllipsisLoc);
>>> -
>>> - // Copy over the source-location information from the type.
>>> - memcpy(TL.getNextTypeLoc().getOpaqueData(),
>>> - Pattern->getTypeLoc().getOpaqueData(),
>>> - Pattern->getTypeLoc().getFullDataSize());
>>> - return TSResult;
>>> +
>>> + return TLB.getTypeSourceInfo(Context, Result);
>>> }
>>>
>>> QualType Sema::CheckPackExpansion(QualType Pattern, SourceRange
>>> PatternRange,
>>>
>>> Modified: cfe/trunk/lib/Sema/TreeTransform.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=183466&r1=183465&r2=183466&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/TreeTransform.h (original)
>>> +++ cfe/trunk/lib/Sema/TreeTransform.h Thu Jun 6 19:04:31 2013
>>> @@ -3427,7 +3427,7 @@ TreeTransform<Derived>::TransformQualifi
>>> } else {
>>> // Otherwise, complain about the addition of a qualifier to an
>>> // already-qualified type.
>>> - SourceRange R =
>>> TLB.getTemporaryTypeLoc(Result).getSourceRange();
>>> + SourceRange R = T.getUnqualifiedLoc().getSourceRange();
>>> SemaRef.Diag(R.getBegin(),
>>> diag::err_attr_objc_ownership_redundant)
>>> << Result << R;
>>>
>>>
>>> Added: cfe/trunk/lib/Sema/TypeLocBuilder.cpp
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TypeLocBuilder.cpp?rev=183466&view=auto
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/TypeLocBuilder.cpp (added)
>>> +++ cfe/trunk/lib/Sema/TypeLocBuilder.cpp Thu Jun 6 19:04:31 2013
>>> @@ -0,0 +1,136 @@
>>> +//===--- 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);
>>> +}
>>>
>>> Modified: cfe/trunk/lib/Sema/TypeLocBuilder.h
>>> URL:
>>> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TypeLocBuilder.h?rev=183466&r1=183465&r2=183466&view=diff
>>>
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/TypeLocBuilder.h (original)
>>> +++ cfe/trunk/lib/Sema/TypeLocBuilder.h Thu Jun 6 19:04:31 2013
>>> @@ -39,14 +39,19 @@ class TypeLocBuilder {
>>> #endif
>>>
>>> /// The inline buffer.
>>> - char InlineBuffer[InlineCapacity];
>>> + enum { BufferMaxAlignment = llvm::AlignOf<void*>::Alignment };
>>> + llvm::AlignedCharArray<BufferMaxAlignment, InlineCapacity>
>>> InlineBuffer;
>>> + unsigned NumBytesAtAlign4, NumBytesAtAlign8;
>>>
>>> public:
>>> TypeLocBuilder()
>>> - : Buffer(InlineBuffer), Capacity(InlineCapacity),
>>> Index(InlineCapacity) {}
>>> + : Buffer(InlineBuffer.buffer), Capacity(InlineCapacity),
>>> + Index(InlineCapacity), NumBytesAtAlign4(0), NumBytesAtAlign8(0)
>>> + {
>>> + }
>>>
>>> ~TypeLocBuilder() {
>>> - if (Buffer != InlineBuffer)
>>> + if (Buffer != InlineBuffer.buffer)
>>> delete[] Buffer;
>>> }
>>>
>>> @@ -59,23 +64,14 @@ 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) {
>>> - 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));
>>> - }
>>> + void pushFullCopy(TypeLoc L);
>>>
>>> /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs
>>> /// previously retrieved from this builder.
>>> TypeSpecTypeLoc pushTypeSpec(QualType T) {
>>> size_t LocalSize = TypeSpecTypeLoc::LocalDataSize;
>>> - return pushImpl(T, LocalSize).castAs<TypeSpecTypeLoc>();
>>> + unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment;
>>> + return pushImpl(T, LocalSize, LocalAlign).castAs<TypeSpecTypeLoc>();
>>> }
>>>
>>> /// Resets this builder to the newly-initialized state.
>>> @@ -84,6 +80,7 @@ class TypeLocBuilder {
>>> LastTy = QualType();
>>> #endif
>>> Index = Capacity;
>>> + NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
>>> }
>>>
>>> /// \brief Tell the TypeLocBuilder that the type it is storing has
>>> been
>>> @@ -97,8 +94,10 @@ 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) {
>>> - size_t LocalSize = TypeLoc(T,
>>> 0).castAs<TyLocType>().getLocalDataSize();
>>> - return pushImpl(T, LocalSize).castAs<TyLocType>();
>>> + TyLocType Loc = TypeLoc(T, 0).castAs<TyLocType>();
>>> + size_t LocalSize = Loc.getLocalDataSize();
>>> + unsigned LocalAlign = Loc.getLocalDataAlignment();
>>> + return pushImpl(T, LocalSize, LocalAlign).castAs<TyLocType>();
>>> }
>>>
>>> /// Creates a TypeSourceInfo for the given type.
>>> @@ -127,61 +126,12 @@ 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
>>> -
>>> - // 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);
>>> - }
>>> + TypeLoc pushImpl(QualType T, size_t LocalSize, unsigned
>>> LocalAlignment);
>>>
>>> /// 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 getTemporaryTypeLoc(T);
>>> - }
>>> + void grow(size_t NewCapacity);
>>>
>>> -public:
>>> /// \brief Retrieve a temporary TypeLoc that refers into this \c
>>> TypeLocBuilder
>>> /// object.
>>> ///
>>>
>>>
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130607/e95dcf11/attachment.html>
More information about the cfe-commits
mailing list