r183466 - Perform dynamic alignment computations so that the data in TypeLocs is
Manuel Klimek
klimek at google.com
Fri Jun 7 04:29:26 PDT 2013
Rollback in r183513.
Regression test in r183514.
On Fri, Jun 7, 2013 at 1:27 PM, Manuel Klimek <klimek at google.com> wrote:
> 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/d7ee5945/attachment.html>
More information about the cfe-commits
mailing list