forked from OSchip/llvm-project
[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:
parent
1af037f643
commit
d2e7dca5ca
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue