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/lib/Sema/CMakeLists.txt b/lib/Sema/CMakeLists.txt
index e92f767..836d125 100644
--- a/lib/Sema/CMakeLists.txt
+++ b/lib/Sema/CMakeLists.txt
@@ -51,6 +51,7 @@
   SemaTemplateVariadic.cpp
   SemaType.cpp
   TargetAttributesSema.cpp
+  TypeLocBuilder.cpp
   )
 
 add_dependencies(clangSema
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index d647be3..3402f22 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -445,6 +445,7 @@
     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 @@
   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 @@
   //   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 3b82280..cb6f4c1 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 @@
                                        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,
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 39664d0..e27d627 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -3418,9 +3418,11 @@
         TemplateSpecializationTypeLoc NamedTL = ElabTL.getNamedTypeLoc()
             .castAs<TemplateSpecializationTypeLoc>();
         TL.copy(NamedTL);
-      }
-      else
+      } else {
         TL.copy(OldTL.castAs<TemplateSpecializationTypeLoc>());
+        assert(TL.getRAngleLoc() == OldTL.castAs<TemplateSpecializationTypeLoc>().getRAngleLoc());
+      }
+        
     }
     void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
       assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 3fcd037..fe49153 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -3427,7 +3427,7 @@
       } 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 f36ec9f..b1e9098 100644
--- a/lib/Sema/TypeLocBuilder.h
+++ b/lib/Sema/TypeLocBuilder.h
@@ -39,14 +39,19 @@
 #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 @@
 
   /// 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 @@
     LastTy = QualType();
 #endif
     Index = Capacity;
+    NumBytesAtAlign4 = NumBytesAtAlign8 = 0;
   }  
 
   /// \brief Tell the TypeLocBuilder that the type it is storing has been
@@ -97,8 +94,10 @@
   /// 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 @@
   }
 
 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);
+  void grow(size_t NewCapacity);
 
-    // Allocate the new buffer and copy the old data into it.
-    char *NewBuffer = new char[NewCapacity];
-    unsigned NewIndex = Index + NewCapacity - Capacity;
-    memcpy(&NewBuffer[NewIndex],
-           &Buffer[Index],
-           Capacity - Index);
-
-    if (Buffer != InlineBuffer)
-      delete[] Buffer;
-
-    Buffer = NewBuffer;
-    Capacity = NewCapacity;
-    Index = NewIndex;
-  }
-
-  TypeLoc pushFullUninitializedImpl(QualType T, size_t Size) {
-#ifndef NDEBUG
-    assert(LastTy.isNull() && "pushing full on non-empty TypeLocBuilder");
-    LastTy = T;
-#endif
-    assert(Index == Capacity && "pushing full on non-empty TypeLocBuilder");
-
-    reserve(Size);
-    Index -= Size;
-
-    return getTemporaryTypeLoc(T);
-  }
-
-public:
   /// \brief Retrieve a temporary TypeLoc that refers into this \c TypeLocBuilder
   /// object.
   ///