]> granicus.if.org Git - clang/commitdiff
Use the correct alignment for POD-member memcpys where the first field is a
authorLang Hames <lhames@gmail.com>
Wed, 27 Feb 2013 04:14:49 +0000 (04:14 +0000)
committerLang Hames <lhames@gmail.com>
Wed, 27 Feb 2013 04:14:49 +0000 (04:14 +0000)
bitfield. CGBitField::StorageAlignment holds the alignment in chars, but
emitMemcpy had been treating it as if it were held in bits, leading to
underaligned memcpys.

Related to PR15348.

Thanks very much to Chandler for the diagnosis.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176163 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGClass.cpp
test/CodeGenCXX/pod-member-memcpys.cpp

index d5c5fd23222d2b4c2e7488d92e83056fbd32e0fa..05894465d2a07b25a46f3b45886781b03a1aaf3b 100644 (file)
@@ -788,19 +788,22 @@ namespace {
         return;
       }
 
-      unsigned FirstFieldAlign = ~0U; // Set to invalid.
+      CharUnits Alignment;
 
       if (FirstField->isBitField()) {
         const CGRecordLayout &RL =
           CGF.getTypes().getCGRecordLayout(FirstField->getParent());
         const CGBitFieldInfo &BFInfo = RL.getBitFieldInfo(FirstField);
-        FirstFieldAlign = BFInfo.StorageAlignment;
-      } else
-        FirstFieldAlign = CGF.getContext().getTypeAlign(FirstField->getType());
+        Alignment = CharUnits::fromQuantity(BFInfo.StorageAlignment);
+      } else {
+        unsigned AlignBits =
+          CGF.getContext().getTypeAlign(FirstField->getType());
+        Alignment = CGF.getContext().toCharUnitsFromBits(AlignBits);
+      }
+
+      assert((CGF.getContext().toCharUnitsFromBits(FirstFieldOffset) %
+              Alignment) == 0 && "Bad field alignment.");
 
-      assert(FirstFieldOffset % FirstFieldAlign == 0 && "Bad field alignment.");
-      CharUnits Alignment =
-        CGF.getContext().toCharUnitsFromBits(FirstFieldAlign);
       CharUnits MemcpySize = getMemcpySize();
       QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
       llvm::Value *ThisPtr = CGF.LoadCXXThis();
index fc99137c391598764ccc95e35df6c32f55be8d09..1e76c08899abdc473e85b35dc8d67bda0442e210 100644 (file)
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -std=c++03 -fexceptions -fcxx-exceptions -O1 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -std=c++03 -O0 -o - %s | FileCheck --check-prefix=CHECK-2 %s
 
 struct POD {
   int w, x, y, z;
@@ -60,6 +61,12 @@ struct BitfieldMember {
   int z : 6;
 };
 
+struct BitfieldMember2 {
+  unsigned a : 1;
+  unsigned b, c, d;
+  NonPOD np;
+};
+
 struct InnerClassMember {
   struct {
     int a, b, c, d;
@@ -152,6 +159,7 @@ CALL_AO(InnerClassMember)
 
 #define CALL_CC(T) T callCC##T(const T& b) { return b; }
 
+CALL_CC(BitfieldMember2)
 CALL_CC(ReferenceMember)
 CALL_CC(InnerClassMember)
 CALL_CC(BitfieldMember)
@@ -220,3 +228,9 @@ CALL_CC(Basic)
 // CHECK: tail call void @_ZN6NonPODC1ERKS_
 // CHECK: tail call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 8{{.*}})
 // CHECK: ret void
+
+// BitfieldMember2 copy-constructor:
+// CHECK-2: define linkonce_odr void @_ZN15BitfieldMember2C2ERKS_(%struct.BitfieldMember2* %this, %struct.BitfieldMember2*)
+// CHECK-2: call void @llvm.memcpy.p0i8.p0i8.i64({{.*}}i64 16, i32 4, i1 false)
+// CHECK-2: call void @_ZN6NonPODC1ERKS_
+// CHECK-2: ret void