Skip to content

Commit 2e09ea6

Browse files
authored
[clang] Ensure minimal alignment of global vars of incomplete type. (#72886)
The SystemZ ABI requires any global variable to be aligned to at least 2 bytes, and therefore an external global Value with an opaque type should get this alignment as well.
1 parent 510fb87 commit 2e09ea6

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

clang/lib/AST/ASTContext.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1680,14 +1680,16 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const {
16801680
Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr()));
16811681
if (BaseT.getQualifiers().hasUnaligned())
16821682
Align = Target->getCharWidth();
1683-
if (const auto *VD = dyn_cast<VarDecl>(D)) {
1684-
if (VD->hasGlobalStorage() && !ForAlignof) {
1685-
uint64_t TypeSize = getTypeSize(T.getTypePtr());
1686-
Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize));
1687-
}
1688-
}
16891683
}
16901684

1685+
// Ensure miminum alignment for global variables.
1686+
if (const auto *VD = dyn_cast<VarDecl>(D))
1687+
if (VD->hasGlobalStorage() && !ForAlignof) {
1688+
uint64_t TypeSize =
1689+
!BaseT->isIncompleteType() ? getTypeSize(T.getTypePtr()) : 0;
1690+
Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize));
1691+
}
1692+
16911693
// Fields can be subject to extra alignment constraints, like if
16921694
// the field is packed, the struct is packed, or the struct has a
16931695
// a max-field-alignment constraint (#pragma pack). So calculate

clang/test/Driver/systemz-alignment.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %clang --target=s390x-linux -S -emit-llvm -o - %s | FileCheck %s
2+
//
3+
// Test that a global variable with an incomplete type gets the minimum
4+
// alignment of 2 per the ABI if no alignment was specified by user.
5+
//
6+
// CHECK: @VarNoAl {{.*}} align 2
7+
// CHECK-NEXT: @VarExplAl1 {{.*}} align 1
8+
// CHECK-NEXT: @VarExplAl4 {{.*}} align 4
9+
10+
// No alignemnt specified by user.
11+
struct incomplete_ty_noal;
12+
extern struct incomplete_ty_noal VarNoAl;
13+
struct incomplete_ty_noal *fun0 (void)
14+
{
15+
return &VarNoAl;
16+
}
17+
18+
// User-specified alignment of 1.
19+
struct incomplete_ty_al1;
20+
extern struct incomplete_ty_al1 __attribute__((aligned(1))) VarExplAl1;
21+
struct incomplete_ty_al1 *fun1 (void)
22+
{
23+
return &VarExplAl1;
24+
}
25+
26+
// User-specified alignment of 4.
27+
struct incomplete_ty_al4;
28+
extern struct incomplete_ty_al4 __attribute__((aligned(4))) VarExplAl4;
29+
struct incomplete_ty_al4 *fun2 (void)
30+
{
31+
return &VarExplAl4;
32+
}

0 commit comments

Comments
 (0)