From: Eli Friedman Date: Fri, 7 Jun 2013 20:31:48 +0000 (+0000) Subject: Re-commit r183466 with a fix to make the TypeLoc casting machinery work X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=44ee0a710c59d8e6793189f903bae21c16814324;p=clang Re-commit r183466 with a fix to make the TypeLoc casting machinery work correctly in the presence of qualified types. (I had to change the unittest because it was trying to cast a QualifiedTypeLoc to TemplateSpecializationTypeLoc.) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@183563 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 9e2d3bffb9..1eb8835f4d 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -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(Data); + dataInt = llvm::RoundUpToAlignment(dataInt, align); + return UnqualTypeLoc(getTypePtr(), reinterpret_cast(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::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. @@ -309,7 +315,8 @@ class ConcreteTypeLoc : public Base { friend class TypeLoc; static bool isKind(const TypeLoc &TL) { - return Derived::classofType(TL.getTypePtr()); + return !TL.getType().hasLocalQualifiers() && + Derived::classofType(TL.getTypePtr()); } static bool classofType(const Type *Ty) { @@ -317,12 +324,16 @@ class ConcreteTypeLoc : public Base { } public: - unsigned getLocalDataSize() const { - return sizeof(LocalData) + asDerived()->getExtraLocalDataSize(); + unsigned getLocalDataAlignment() const { + return std::max(llvm::alignOf(), + 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 +349,10 @@ protected: return 0; } + unsigned getExtraLocalDataAlignment() const { + return 1; + } + LocalData *getLocalData() const { return static_cast(Base::Data); } @@ -346,11 +361,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(Base::Data) + size; } void *getNonLocalData() const { - return static_cast(Base::Data) + asDerived()->getLocalDataSize(); + uintptr_t data = reinterpret_cast(Base::Data); + data += asDerived()->getLocalDataSize(); + data = llvm::RoundUpToAlignment(data, getNextTypeAlign()); + return reinterpret_cast(data); } struct HasNoInnerType {}; @@ -373,6 +394,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(); } @@ -393,7 +426,8 @@ class InheritingConcreteTypeLoc : public Base { } static bool isKind(const TypeLoc &TL) { - return Derived::classofType(TL.getTypePtr()); + return !TL.getType().hasLocalQualifiers() && + Derived::classofType(TL.getTypePtr()); } static bool isKind(const UnqualTypeLoc &TL) { return Derived::classofType(TL.getTypePtr()); @@ -417,7 +451,8 @@ class TypeSpecTypeLoc : public ConcreteTypeLoc { public: - enum { LocalDataSize = sizeof(TypeSpecLocInfo) }; + enum { LocalDataSize = sizeof(TypeSpecLocInfo), + LocalDataAlignment = llvm::AlignOf::Alignment }; SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; @@ -448,8 +483,6 @@ class BuiltinTypeLoc : public ConcreteTypeLoc { public: - enum { LocalDataSize = sizeof(BuiltinLocInfo) }; - SourceLocation getBuiltinLoc() const { return getLocalData()->BuiltinLoc; } @@ -478,6 +511,10 @@ public: return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0; } + unsigned getExtraLocalDataAlignment() const { + return needsExtraLocalData() ? llvm::alignOf() : 1; + } + SourceRange getLocalSourceRange() const { return SourceRange(getBuiltinLoc(), getBuiltinLoc()); } @@ -840,6 +877,10 @@ public: return this->getNumProtocols() * sizeof(SourceLocation); } + unsigned getExtraLocalDataAlignment() const { + return llvm::alignOf(); + } + QualType getInnerType() const { return getTypePtr()->getBaseType(); } @@ -1166,6 +1207,10 @@ public: return getNumArgs() * sizeof(ParmVarDecl*); } + unsigned getExtraLocalDataAlignment() const { + return llvm::alignOf(); + } + QualType getInnerType() const { return getTypePtr()->getResultType(); } }; @@ -1357,6 +1402,10 @@ public: return getNumArgs() * sizeof(TemplateArgumentLocInfo); } + unsigned getExtraLocalDataAlignment() const { + return llvm::alignOf(); + } + private: TemplateArgumentLocInfo *getArgInfos() const { return static_cast(getExtraLocalData()); @@ -1761,6 +1810,10 @@ public: return getNumArgs() * sizeof(TemplateArgumentLocInfo); } + unsigned getExtraLocalDataAlignment() const { + return llvm::alignOf(); + } + private: TemplateArgumentLocInfo *getArgInfos() const { return static_cast(getExtraLocalData()); diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index 03d40309f5..c47bde8dde 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -40,13 +40,31 @@ SourceRange TypeLoc::getLocalSourceRangeImpl(TypeLoc TL) { return TypeLocRanger().Visit(TL); } +namespace { + class TypeAligner : public TypeLocVisitor { + 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 { 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 { diff --git a/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt index e92f767134..836d125978 100644 --- a/lib/Sema/CMakeLists.txt +++ b/lib/Sema/CMakeLists.txt @@ -51,6 +51,7 @@ add_clang_library(clangSema SemaTemplateVariadic.cpp SemaType.cpp TargetAttributesSema.cpp + TypeLocBuilder.cpp ) add_dependencies(clangSema diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index d647be3761..3402f22062 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -445,6 +445,7 @@ FieldDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef, assert(!DeductType.isNull() && "can't build reference to auto"); TLB.push(DeductType).setSigilLoc(Loc); } + TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType); InitializationKind InitKind = InitializationKind::CreateDefault(Loc); Expr *Init = InitExpr; @@ -476,8 +477,7 @@ FieldDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef, 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(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, 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); diff --git a/lib/Sema/SemaTemplateVariadic.cpp b/lib/Sema/SemaTemplateVariadic.cpp index 3b8228016c..cb6f4c19de 100644 --- a/lib/Sema/SemaTemplateVariadic.cpp +++ b/lib/Sema/SemaTemplateVariadic.cpp @@ -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 *Pattern, SourceLocation EllipsisLoc, EllipsisLoc, NumExpansions); if (Result.isNull()) return 0; - - TypeSourceInfo *TSResult = Context.CreateTypeSourceInfo(Result); - PackExpansionTypeLoc TL = - TSResult->getTypeLoc().castAs(); + + TypeLocBuilder TLB; + TLB.pushFullCopy(Pattern->getTypeLoc()); + PackExpansionTypeLoc TL = TLB.push(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, diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 39664d0491..e27d627d3f 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -3418,9 +3418,11 @@ namespace { TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc() .castAs(); TL.copy(NamedTL); - } - else + } else { TL.copy(OldTL.castAs()); + assert(TL.getRAngleLoc() == OldTL.castAs().getRAngleLoc()); + } + } void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 3fcd0375d0..fe49153d99 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -3427,7 +3427,7 @@ TreeTransform::TransformQualifiedType(TypeLocBuilder &TLB, } 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; diff --git a/lib/Sema/TypeLocBuilder.h b/lib/Sema/TypeLocBuilder.h index f36ec9f3e2..b1e909859b 100644 --- a/lib/Sema/TypeLocBuilder.h +++ b/lib/Sema/TypeLocBuilder.h @@ -39,14 +39,19 @@ class TypeLocBuilder { #endif /// The inline buffer. - char InlineBuffer[InlineCapacity]; + enum { BufferMaxAlignment = llvm::AlignOf::Alignment }; + llvm::AlignedCharArray 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(); + unsigned LocalAlign = TypeSpecTypeLoc::LocalDataAlignment; + return pushImpl(T, LocalSize, LocalAlign).castAs(); } /// 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 TyLocType push(QualType T) { - size_t LocalSize = TypeLoc(T, 0).castAs().getLocalDataSize(); - return pushImpl(T, LocalSize).castAs(); + TyLocType Loc = TypeLoc(T, 0).castAs(); + size_t LocalSize = Loc.getLocalDataSize(); + unsigned LocalAlign = Loc.getLocalDataAlignment(); + return pushImpl(T, LocalSize, LocalAlign).castAs(); } /// 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. /// diff --git a/unittests/AST/SourceLocationTest.cpp b/unittests/AST/SourceLocationTest.cpp index 55356f11da..990e6dfc85 100644 --- a/unittests/AST/SourceLocationTest.cpp +++ b/unittests/AST/SourceLocationTest.cpp @@ -159,7 +159,7 @@ class TemplateAngleBracketLocRangeVerifier : public RangeVerifier { protected: virtual SourceRange getRange(const TypeLoc &Node) { TemplateSpecializationTypeLoc T = - Node.castAs(); + Node.getUnqualifiedLoc().castAs(); assert(!T.isNull()); return SourceRange(T.getLAngleLoc(), T.getRAngleLoc()); }