[PATCH] D77754: [MS] Fix packed struct layout for arrays of aligned non-record types
Reid Kleckner via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 8 14:09:10 PDT 2020
rnk created this revision.
rnk added a reviewer: rjmccall.
Herald added a subscriber: jfb.
Herald added a project: clang.
In particular, this affects Clang's vectors. Users encounter this issue
when a struct contains an __m128 type.
Fixes PR45420
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D77754
Files:
clang/lib/AST/ASTContext.cpp
clang/test/Layout/ms-aligned-array.c
Index: clang/test/Layout/ms-aligned-array.c
===================================================================
--- /dev/null
+++ clang/test/Layout/ms-aligned-array.c
@@ -0,0 +1,53 @@
+// RUN: %clang_cc1 -fno-rtti -emit-llvm-only -triple x86_64-pc-win32 -fms-extensions -fdump-record-layouts -fsyntax-only %s 2>/dev/null \
+// RUN: | FileCheck %s -check-prefix CHECK
+
+// Before PR45420, we would only find the alignment on this record. Afterwards,
+// we can see the alignment on the typedef through the array type.
+// FIXME: What about other type sugar, like _Atomic? This would only matter in a
+// packed struct context.
+struct __declspec(align(16)) AlignedStruct { int x; };
+typedef int __declspec(align(16)) AlignedInt;
+
+#define CHECK_SIZE(X, Align) \
+ _Static_assert(__alignof(struct X) == Align, "should be aligned");
+
+#pragma pack(push, 2)
+
+struct A {
+ struct AlignedStruct a[1];
+};
+CHECK_SIZE(A, 16);
+
+struct B {
+ char b;
+ AlignedInt a[1];
+};
+CHECK_SIZE(B, 16);
+
+struct C {
+ char b;
+ AlignedInt a[];
+};
+CHECK_SIZE(C, 16);
+
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct AlignedStruct
+// CHECK-NEXT: 0 | int x
+// CHECK-NEXT: | [sizeof=16, align=16]
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct A
+// CHECK-NEXT: 0 | struct AlignedStruct [1] a
+// CHECK-NEXT: | [sizeof=16, align=16]
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct B
+// CHECK-NEXT: 0 | char b
+// CHECK-NEXT: 16 | AlignedInt [1] a
+// CHECK-NEXT: | [sizeof=32, align=16]
+// CHECK: *** Dumping AST Record Layout
+// CHECK-NEXT: 0 | struct C
+// CHECK-NEXT: 0 | char b
+// CHECK-NEXT: 16 | AlignedInt [] a
+// CHECK-NEXT: | [sizeof=16, align=16]
+
+#pragma pack(pop)
+
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -1892,24 +1892,24 @@
case Type::IncompleteArray:
case Type::VariableArray:
- Width = 0;
- Align = getTypeAlign(cast<ArrayType>(T)->getElementType());
- break;
-
case Type::ConstantArray: {
- const auto *CAT = cast<ConstantArrayType>(T);
+ // Model non-constant sized arrays as size zero, but track the alignment.
+ uint64_t Size = 0;
+ if (const auto *CAT = dyn_cast<ConstantArrayType>(T))
+ Size = CAT->getSize().getZExtValue();
- TypeInfo EltInfo = getTypeInfo(CAT->getElementType());
- uint64_t Size = CAT->getSize().getZExtValue();
+ TypeInfo EltInfo = getTypeInfo(cast<ArrayType>(T)->getElementType());
assert((Size == 0 || EltInfo.Width <= (uint64_t)(-1) / Size) &&
"Overflow in array type bit size evaluation");
Width = EltInfo.Width * Size;
Align = EltInfo.Align;
+ AlignIsRequired = EltInfo.AlignIsRequired;
if (!getTargetInfo().getCXXABI().isMicrosoft() ||
getTargetInfo().getPointerWidth(0) == 64)
Width = llvm::alignTo(Width, Align);
break;
}
+
case Type::ExtVector:
case Type::Vector: {
const auto *VT = cast<VectorType>(T);
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D77754.256110.patch
Type: text/x-patch
Size: 3228 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200408/ba1d0f32/attachment-0001.bin>
More information about the cfe-commits
mailing list