summaryrefslogtreecommitdiffstats
path: root/clang
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
commit1694e0d21df5fbab8576fe8c7bc4e7c25b838f5e (patch)
treebac19a0a5596bae65e7eac4faaee9006e93f752f /clang
parent2ce6b43f40a4c21683338f88d943aeac798f8404 (diff)
downloadbcm5719-llvm-1694e0d21df5fbab8576fe8c7bc4e7c25b838f5e.tar.gz
bcm5719-llvm-1694e0d21df5fbab8576fe8c7bc4e7c25b838f5e.zip
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. llvm-svn: 176163
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/CGClass.cpp17
-rw-r--r--clang/test/CodeGenCXX/pod-member-memcpys.cpp14
2 files changed, 24 insertions, 7 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index d5c5fd23222..05894465d2a 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/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/clang/test/CodeGenCXX/pod-member-memcpys.cpp b/clang/test/CodeGenCXX/pod-member-memcpys.cpp
index fc99137c391..1e76c08899a 100644
--- a/clang/test/CodeGenCXX/pod-member-memcpys.cpp
+++ b/clang/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
OpenPOWER on IntegriCloud