When we can't prove that the target of an aggregate copy is
a complete object, the memcpy needs to use the data size of
the structure instead of its sizeof() value.  Fixes PR12204.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153613 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGValue.h b/lib/CodeGen/CGValue.h
index ac704e7..731b6ab 100644
--- a/lib/CodeGen/CGValue.h
+++ b/lib/CodeGen/CGValue.h
@@ -318,22 +318,22 @@
   // Qualifiers
   Qualifiers Quals;
 
-  unsigned short Alignment;
+  unsigned Alignment : 16;
 
   /// DestructedFlag - This is set to true if some external code is
   /// responsible for setting up a destructor for the slot.  Otherwise
   /// the code which constructs it should push the appropriate cleanup.
-  bool DestructedFlag : 1;
+  unsigned DestructedFlag : 1;
 
   /// ObjCGCFlag - This is set to true if writing to the memory in the
   /// slot might require calling an appropriate Objective-C GC
   /// barrier.  The exact interaction here is unnecessarily mysterious.
-  bool ObjCGCFlag : 1;
+  unsigned ObjCGCFlag : 1;
   
   /// ZeroedFlag - This is set to true if the memory in the slot is
   /// known to be zero before the assignment into it.  This means that
   /// zero fields don't need to be set.
-  bool ZeroedFlag : 1;
+  unsigned ZeroedFlag : 1;
 
   /// AliasedFlag - This is set to true if the slot might be aliased
   /// and it's not undefined behavior to access it through such an
@@ -347,19 +347,32 @@
   /// over.  Since it's invalid in general to memcpy a non-POD C++
   /// object, it's important that this flag never be set when
   /// evaluating an expression which constructs such an object.
-  bool AliasedFlag : 1;
+  unsigned AliasedFlag : 1;
+
+  /// CompleteObjectFlag - This is set to true if the slot is known to
+  /// be a complete object.  When emitting an aggregate copy of a
+  /// non-POD C++ struct to a location which may not be a complete
+  /// object, only the data size of the type can be copied in order to
+  /// prevent unrelated fields from being overwritten.
+  unsigned CompleteObjectFlag : 1;
 
 public:
   enum IsAliased_t { IsNotAliased, IsAliased };
   enum IsDestructed_t { IsNotDestructed, IsDestructed };
   enum IsZeroed_t { IsNotZeroed, IsZeroed };
+  enum IsCompleteObject_t {
+    IsNotCompleteObject,
+    MayNotBeCompleteObject = IsNotCompleteObject,
+    IsCompleteObject
+  };
   enum NeedsGCBarriers_t { DoesNotNeedGCBarriers, NeedsGCBarriers };
 
   /// ignored - Returns an aggregate value slot indicating that the
   /// aggregate value is being ignored.
   static AggValueSlot ignored() {
     return forAddr(0, CharUnits(), Qualifiers(), IsNotDestructed,
-                   DoesNotNeedGCBarriers, IsNotAliased);
+                   DoesNotNeedGCBarriers, IsNotAliased,
+                   IsCompleteObject);
   }
 
   /// forAddr - Make a slot for an aggregate value.
@@ -377,6 +390,7 @@
                               IsDestructed_t isDestructed,
                               NeedsGCBarriers_t needsGC,
                               IsAliased_t isAliased,
+                              IsCompleteObject_t isCompleteObject,
                               IsZeroed_t isZeroed = IsNotZeroed) {
     AggValueSlot AV;
     AV.Addr = addr;
@@ -386,15 +400,18 @@
     AV.ObjCGCFlag = needsGC;
     AV.ZeroedFlag = isZeroed;
     AV.AliasedFlag = isAliased;
+    AV.CompleteObjectFlag = isCompleteObject;
     return AV;
   }
 
   static AggValueSlot forLValue(LValue LV, IsDestructed_t isDestructed,
                                 NeedsGCBarriers_t needsGC,
                                 IsAliased_t isAliased,
+                                IsCompleteObject_t isCompleteObject,
                                 IsZeroed_t isZeroed = IsNotZeroed) {
     return forAddr(LV.getAddress(), LV.getAlignment(),
-                   LV.getQuals(), isDestructed, needsGC, isAliased, isZeroed);
+                   LV.getQuals(), isDestructed, needsGC, isAliased,
+                   isCompleteObject, isZeroed);
   }
 
   IsDestructed_t isExternallyDestructed() const {
@@ -434,6 +451,10 @@
     return IsAliased_t(AliasedFlag);
   }
 
+  IsCompleteObject_t isCompleteObject() const {
+    return IsCompleteObject_t(CompleteObjectFlag);
+  }
+
   // FIXME: Alignment?
   RValue asRValue() const {
     return RValue::getAggregate(getAddr(), isVolatile());