Hi all. Please find patch in attachment for review.

What patch does:
For all default object assignments (Foo a,b; a = b;) it forbids to use 
alignment in memcpy.

-Stepan.
Index: lib/CodeGen/CGExprAgg.cpp
===================================================================
--- lib/CodeGen/CGExprAgg.cpp	(revision 153430)
+++ lib/CodeGen/CGExprAgg.cpp	(working copy)
@@ -1192,7 +1192,9 @@
 
 void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr,
                                         llvm::Value *SrcPtr, QualType Ty,
-                                        bool isVolatile, unsigned Alignment) {
+                                        bool isVolatile, unsigned Alignment,
+                                        bool noAlignmentForStructAndClasses
+                                        ) {
   assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex");
 
   if (getContext().getLangOpts().CPlusPlus) {
@@ -1224,7 +1226,55 @@
   // Get size and alignment info for this aggregate.
   std::pair<CharUnits, CharUnits> TypeInfo = 
     getContext().getTypeInfoInChars(Ty);
+  
+  // PR12204 fix: static_cast to Base class overrides the Derived class field.
+  // Consider next example:
+  //  class Foo {
+  //  int i;
+  //  short j;
+  //  };
+  //
+  //  class Bar : public Foo {
+  //    short t;
+  //  public:
+  //    void set(int v) { t = v; }
+  //    int get() { return t; }
+  //  };
+  //  int main() {
+  //    Bar a,b;
+  //    b.set(8);
+  //    a.set(0);
+  //    static_cast<Foo&>(a) = static_cast<Foo&>(b);
+  //    printf("%i\n", a.get());
+  //    return 0;
+  //  }  
+  // In this case assignment will replaced memcpy.
+  // In usual way Foo size will rounded to 8,
+  // and memcpy(&a, &b, 8) will invoked.
+  // Due to avoid unwanted changes in Bar we should ignore alignment
+  // in this case.
+  const Type* T = Ty.getTypePtr();
+  Type::TypeClass TyClass = T->getTypeClass();
+  if (noAlignmentForStructAndClasses && TyClass == Type::Record) {
+    
+    const TagType *TT = cast<TagType>(T);
+    assert(!TT->getDecl()->isInvalidDecl() && "Invalid type declaration.");
+    const EnumType *ET = dyn_cast<EnumType>(TT);
+    assert(!ET &&
+      "noAlignmentForStructAndClasses works for structs and classes only.");
 
+    if (!ET && !TT->getDecl()->isInvalidDecl()) {
+      const RecordType *RT = cast<RecordType>(TT);
+      const ASTRecordLayout &Layout =
+          getContext().getASTRecordLayout(RT->getDecl());
+      CharUnits DataSize = Layout.getDataSize();
+      CharUnits Size = Layout.getSize();
+      
+      TypeInfo.first = DataSize;
+      TypeInfo.second = CharUnits::One();
+    }
+  }
+
   if (!Alignment)
     Alignment = TypeInfo.second.getQuantity();
 
Index: lib/CodeGen/CGExprCXX.cpp
===================================================================
--- lib/CodeGen/CGExprCXX.cpp	(revision 153430)
+++ lib/CodeGen/CGExprCXX.cpp	(working copy)
@@ -212,7 +212,7 @@
       // We don't like to generate the trivial copy/move assignment operator
       // when it isn't necessary; just produce the proper effect here.
       llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress();
-      EmitAggregateCopy(This, RHS, CE->getType());
+      EmitAggregateCopy(This, RHS, CE->getType(), false, 0, true);
       return RValue::get(This);
     }
     
@@ -339,7 +339,7 @@
       MD->isTrivial()) {
     llvm::Value *Src = EmitLValue(E->getArg(1)).getAddress();
     QualType Ty = E->getType();
-    EmitAggregateCopy(This, Src, Ty);
+    EmitAggregateCopy(This, Src, Ty, false, 0, true);
     return RValue::get(This);
   }
 
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h	(revision 153430)
+++ lib/CodeGen/CodeGenFunction.h	(working copy)
@@ -1643,7 +1643,8 @@
   /// volatile.
   void EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr,
                          QualType EltTy, bool isVolatile=false,
-                         unsigned Alignment = 0);
+                         unsigned Alignment = 0,
+                         bool noAlignmentForStructAndClasses = false);
 
   /// StartBlock - Start new block named N. If insert block is a dummy block
   /// then reuse it.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to