Index: test/CodeGenObjCXX/implicit-copy-assign-operator.mm
===================================================================
--- test/CodeGenObjCXX/implicit-copy-assign-operator.mm	(revision 160268)
+++ test/CodeGenObjCXX/implicit-copy-assign-operator.mm	(working copy)
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -fobjc-gc -emit-llvm -triple x86_64-apple-darwin10.0.0 -fobjc-runtime=macosx-fragile-10.5 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -fobjc-gc -emit-llvm -triple x86_64-apple-darwin10.0.0 -fobjc-runtime=macosx-fragile-10.5 -o - %s | FileCheck %s -check-prefix=OBJ
+// RUN: %clang_cc1 -x c++    -emit-llvm -triple x86_64-apple-darwin10.0.0                                    -o - %s | FileCheck %s -check-prefix=CPP
+#ifdef __OBJC__
 struct A { 
   A &operator=(const A&);
   A &operator=(A&);
@@ -41,17 +43,83 @@
   d1 = d2;
 }
 
-// CHECK: define linkonce_odr %struct.D* @_ZN1DaSERS_
-// CHECK: {{call.*_ZN1AaSERS_}}
-// CHECK: {{call.*_ZN1BaSERS_}}
-// CHECK: {{call.*_ZN1CaSERKS_}}
-// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 24}}
-// CHECK: {{call.*_ZN1BaSERS_}}
-// CHECK: br
-// CHECK: {{call.*_ZN1CaSERKS_}}
-// CHECK: {{call.*@objc_memmove_collectable}}
-// CHECK: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 12}}
-// CHECK: call void @_ZN11CopyByValueC1ERKS_
-// CHECK: {{call.*_ZN11CopyByValueaSES_}}
-// CHECK: ret
+// CHECK OBJ: define linkonce_odr %struct.D* @_ZN1DaSERS_
+// CHECK OBJ: {{call.*_ZN1AaSERS_}}
+// CHECK OBJ: {{call.*_ZN1BaSERS_}}
+// CHECK OBJ: {{call.*_ZN1CaSERKS_}}
+// CHECK OBJ: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 24}}
+// CHECK OBJ: {{call.*_ZN1BaSERS_}}
+// CHECK OBJ: br
+// CHECK OBJ: {{call.*_ZN1CaSERKS_}}
+// CHECK OBJ: {{call.*@objc_memmove_collectable}}
+// CHECK OBJ: {{call void @llvm.memcpy.p0i8.p0i8.i64.*i64 12}}
+// CHECK OBJ: call void @_ZN11CopyByValueC1ERKS_
+// CHECK OBJ: {{call.*_ZN11CopyByValueaSES_}}
+// CHECK OBJ: ret
+#endif
 
+namespace PR13329 {
+#ifndef __OBJC__
+  typedef void* id;
+#endif
+  struct POD {
+    id    i;
+    short s;
+  };
+  
+  struct NonPOD {
+    id    i;
+    short s;
+    
+    NonPOD();
+  };
+  
+  struct DerivedNonPOD: NonPOD {
+    char  c;
+  };
+  
+  struct DerivedPOD: POD {
+    char  c;
+  };
+  
+  void testPOD() {
+    POD a;
+    POD b;
+    // CHECK OBJ: @objc_memmove_collectable{{.*}}i64 16
+    // CHECK CPP: @llvm.memcpy{{.*}}i64 16
+    b = a;
+  }
+  
+  void testNonPOD() {
+    NonPOD a;
+    NonPOD b;
+    // CHECK OBJ: @objc_memmove_collectable{{.*}}i64 10
+    // CHECK CPP: @llvm.memcpy{{.*}}i64 10
+    b = a;
+  }
+  
+  void testDerivedNonPOD() {
+    DerivedNonPOD a;
+    NonPOD        b;
+    DerivedNonPOD c;
+    // CHECK OBJ: @objc_memmove_collectable{{.*}}i64 10
+    // CHECK CPP: @llvm.memcpy{{.*}}i64 10
+    (NonPOD&) a = b;
+    // CHECK OBJ: @objc_memmove_collectable{{.*}}i64 11
+    // CHECK CPP: @llvm.memcpy{{.*}}i64 11
+    a = c;
+  };
+  
+  void testDerivedPOD() {
+    DerivedPOD a;
+    POD        b;
+    DerivedPOD c;
+    // CHECK OBJ: @objc_memmove_collectable{{.*}}i64 16
+    // CHECK CPP: @llvm.memcpy{{.*}}i64 16
+    (POD&) a = b;
+    // FIXME: Why is DerivedPOD not a POD?
+    // CHECK OBJ: @objc_memmove_collectable{{.*}}i64 17
+    // CHECK CPP: @llvm.memcpy{{.*}}i64 17
+    a = c;
+  };
+}
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h	(revision 160268)
+++ include/clang/AST/Type.h	(working copy)
@@ -630,18 +630,18 @@
   }
 
   /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10).
-  bool isPODType(ASTContext &Context) const;
+  bool isPODType(const ASTContext &Context) const;
 
   /// isCXX98PODType() - Return true if this is a POD type according to the
   /// rules of the C++98 standard, regardless of the current compilation's
   /// language.
-  bool isCXX98PODType(ASTContext &Context) const;
+  bool isCXX98PODType(const ASTContext &Context) const;
 
   /// isCXX11PODType() - Return true if this is a POD type according to the
   /// more relaxed rules of the C++11 standard, regardless of the current
   /// compilation's language.
   /// (C++0x [basic.types]p9)
-  bool isCXX11PODType(ASTContext &Context) const;
+  bool isCXX11PODType(const ASTContext &Context) const;
 
   /// isTrivialType - Return true if this is a trivial type
   /// (C++0x [basic.types]p9)
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h	(revision 160268)
+++ include/clang/AST/ASTContext.h	(working copy)
@@ -1363,7 +1363,12 @@
   /// characters. This method does not work on incomplete types.
   CharUnits getTypeAlignInChars(QualType T) const;
   CharUnits getTypeAlignInChars(const Type *T) const;
-
+  
+  // getTypeInfoForCopyInChars - Return the size of a type, in chars, when
+  // values of that type are copied. In the case of a POD type this means that
+  // possible tail padding is not counted.
+  std::pair<CharUnits, CharUnits> getTypeInfoForCopyInChars(QualType T) const;
+  
   std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const;
   std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const;
 
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp	(revision 160268)
+++ lib/AST/Type.cpp	(working copy)
@@ -916,7 +916,7 @@
   }
 }
 
-bool QualType::isPODType(ASTContext &Context) const {
+bool QualType::isPODType(const ASTContext &Context) const {
   // C++11 has a more relaxed definition of POD.
   if (Context.getLangOpts().CPlusPlus0x)
     return isCXX11PODType(Context);
@@ -924,7 +924,7 @@
   return isCXX98PODType(Context);
 }
 
-bool QualType::isCXX98PODType(ASTContext &Context) const {
+bool QualType::isCXX98PODType(const ASTContext &Context) const {
   // The compiler shouldn't query this for incomplete types, but the user might.
   // We return false for that case. Except for incomplete arrays of PODs, which
   // are PODs according to the standard.
@@ -1189,7 +1189,7 @@
 // This is effectively the intersection of isTrivialType and
 // isStandardLayoutType. We implement it directly to avoid redundant
 // conversions from a type to a CXXRecordDecl.
-bool QualType::isCXX11PODType(ASTContext &Context) const {
+bool QualType::isCXX11PODType(const ASTContext &Context) const {
   const Type *ty = getTypePtr();
   if (ty->isDependentType())
     return false;
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp	(revision 160268)
+++ lib/AST/ASTContext.cpp	(working copy)
@@ -970,7 +970,29 @@
   return toCharUnitsFromBits(Align);
 }
 
+
+// getTypeInfoForCopyInChars - Return the size of a type, in chars, when
+// values of that type are copied. In the case of a POD type this means that
+// possible tail padding is not counted.
 std::pair<CharUnits, CharUnits>
+ASTContext::getTypeInfoForCopyInChars(QualType T) const {
+  std::pair<CharUnits, CharUnits> Info = getTypeInfoInChars(T);
+  if (getLangOpts().CPlusPlus) {
+    if (const RecordType *RecordTy = T->getAs<RecordType>()) {
+      // This check is more expensive than the others, so put it last:
+      if (!T.isPODType(*this)) {
+        // Do not copy the tail padding of non-POD types, as the compiler will
+        // reuse it for fields of derived classes
+        const ASTRecordLayout &Layout =
+          getASTRecordLayout(RecordTy->getDecl());
+        Info.first = Layout.getDataSize();
+      }
+    }
+  }
+  return Info;
+}
+
+std::pair<CharUnits, CharUnits>
 ASTContext::getTypeInfoInChars(const Type *T) const {
   std::pair<uint64_t, unsigned> Info = getTypeInfo(T);
   return std::make_pair(toCharUnitsFromBits(Info.first),
Index: lib/CodeGen/CGExprAgg.cpp
===================================================================
--- lib/CodeGen/CGExprAgg.cpp	(revision 160268)
+++ lib/CodeGen/CGExprAgg.cpp	(working copy)
@@ -1302,7 +1302,7 @@
 
   // Get size and alignment info for this aggregate.
   std::pair<CharUnits, CharUnits> TypeInfo = 
-    getContext().getTypeInfoInChars(Ty);
+    getContext().getTypeInfoForCopyInChars(Ty);
 
   if (alignment.isZero())
     alignment = TypeInfo.second;
