[CodeGen] Fix Bug 47499: __unaligned extension inconsistent behaviour with C and C++

For the language C++ the keyword __unaligned (a Microsoft extension) had no effect on pointers.

The reason, why there was a difference between C and C++ for the keyword __unaligned:
For C, the Method getAsCXXREcordDecl() returns nullptr. That guarantees that hasUnaligned() is called.
If the language is C++, it is not guaranteed, that hasUnaligend() is called and evaluated.

Here are some links:

The Bug: https://bugs.llvm.org/show_bug.cgi?id=47499
Thread on the cfe-dev mailing list: http://lists.llvm.org/pipermail/cfe-dev/2020-September/066783.html
Diff, that introduced the check hasUnaligned() in getNaturalTypeAlignment(): https://reviews.llvm.org/D30166

Reviewed By: rnk

Differential Revision: https://reviews.llvm.org/D90630
This commit is contained in:
Jan Ole Hüser 2020-11-05 11:01:51 -08:00 committed by Reid Kleckner
parent 1af037f643
commit d2e7dca5ca
2 changed files with 39 additions and 6 deletions

View File

@ -6197,16 +6197,17 @@ CharUnits CodeGenModule::getNaturalTypeAlignment(QualType T,
*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

View File

@ -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
}