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