diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -6197,16 +6197,17 @@ *BaseInfo = LValueBaseInfo(AlignmentSource::Type); CharUnits Alignment; - // For C++ class pointees, we don't know whether we're pointing at a - // base or a complete object, so we generally need to use the - // non-virtual alignment. const CXXRecordDecl *RD; - if (forPointeeType && !AlignForArray && (RD = T->getAsCXXRecordDecl())) { + if (T.getQualifiers().hasUnaligned()) { + Alignment = CharUnits::One(); + } else if (forPointeeType && !AlignForArray && + (RD = T->getAsCXXRecordDecl())) { + // For C++ class pointees, we don't know whether we're pointing at a + // base or a complete object, so we generally need to use the + // non-virtual alignment. Alignment = getClassPointerAlignment(RD); } else { Alignment = getContext().getTypeAlignInChars(T); - if (T.getQualifiers().hasUnaligned()) - Alignment = CharUnits::One(); } // Cap to the global maximum type alignment unless the alignment diff --git a/clang/test/CodeGen/unaligned-struct-copy.c b/clang/test/CodeGen/unaligned-struct-copy.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/unaligned-struct-copy.c @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -xc -O2 -triple thumbv7a-unknown-windows-eabi -fms-extensions -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -xc++ -O2 -triple thumbv7a-unknown-windows-eabi -fms-extensions -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -xc -O2 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s +// RUN: %clang_cc1 -xc++ -O2 -triple x86_64-unknown-linux-gnu -fms-extensions -emit-llvm < %s | FileCheck %s + +struct S1 { + unsigned long x; +}; + +// CHECK: define +// CHECK-SAME: void +// CHECK-SAME: test1 + +void test1(__unaligned struct S1 *out) { + // CHECK: store + // CHECK-SAME: align 1 + out->x = 5; + // CHECK: ret void +} + +// CHECK: define +// CHECK-SAME: void +// CHECK-SAME: test2 + +void test2(__unaligned struct S1 *out, __unaligned struct S1 *in) { + // CHECK: load + // CHECK-SAME: align 1 + // CHECK: store + // CHECK-SAME: align 1 + *out = *in; + // CHECK: ret void +}