Author: Jan Ole Hüser Date: 2020-11-05T12:57:17-08:00 New Revision: d2e7dca5ca92c655e451d6fcb806df38d7f2d56b
URL: https://github.com/llvm/llvm-project/commit/d2e7dca5ca92c655e451d6fcb806df38d7f2d56b DIFF: https://github.com/llvm/llvm-project/commit/d2e7dca5ca92c655e451d6fcb806df38d7f2d56b.diff LOG: [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 Added: clang/test/CodeGen/unaligned-struct-copy.c Modified: clang/lib/CodeGen/CodeGenModule.cpp Removed: ################################################################################ diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 24c067539f83..ccf5d24bb9eb 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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 diff --git a/clang/test/CodeGen/unaligned-struct-copy.c b/clang/test/CodeGen/unaligned-struct-copy.c new file mode 100644 index 000000000000..45a9670bc234 --- /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 +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits