aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2013-02-27 04:14:49 +0000
committerLang Hames <lhames@gmail.com>2013-02-27 04:14:49 +0000
commit5e8577ece79b5ed07b0ab4dcb284a26076efdf65 (patch)
tree74f02c2ba549e348075d047cf4c2b237f6179015
parentf127eb8aeb3ce861f3dbc1adbb3362bfd98461e1 (diff)
Use the correct alignment for POD-member memcpys where the first field is a
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
-rw-r--r--lib/CodeGen/CGClass.cpp17
-rw-r--r--test/CodeGenCXX/pod-member-memcpys.cpp14
2 files changed, 24 insertions, 7 deletions
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index d5c5fd2322..05894465d2 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -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();
diff --git a/test/CodeGenCXX/pod-member-memcpys.cpp b/test/CodeGenCXX/pod-member-memcpys.cpp
index fc99137c39..1e76c08899 100644
--- a/test/CodeGenCXX/pod-member-memcpys.cpp
+++ b/test/CodeGenCXX/pod-member-memcpys.cpp
@@ -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