r183466 - Perform dynamic alignment computations so that the data in TypeLocs is

Eli Friedman eli.friedman at gmail.com
Thu Jun 6 17:04:31 PDT 2013


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.
   ///





More information about the cfe-commits mailing list