diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 1c893d008cb49..a7cee3b7ba2b0 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1680,14 +1680,16 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr())); if (BaseT.getQualifiers().hasUnaligned()) Align = Target->getCharWidth(); - if (const auto *VD = dyn_cast(D)) { - if (VD->hasGlobalStorage() && !ForAlignof) { - uint64_t TypeSize = getTypeSize(T.getTypePtr()); - Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize)); - } - } } + // Ensure miminum alignment for global variables. + if (const auto *VD = dyn_cast(D)) + if (VD->hasGlobalStorage() && !ForAlignof) { + uint64_t TypeSize = + !BaseT->isIncompleteType() ? getTypeSize(T.getTypePtr()) : 0; + Align = std::max(Align, getTargetInfo().getMinGlobalAlign(TypeSize)); + } + // Fields can be subject to extra alignment constraints, like if // the field is packed, the struct is packed, or the struct has a // a max-field-alignment constraint (#pragma pack). So calculate diff --git a/clang/test/Driver/systemz-alignment.c b/clang/test/Driver/systemz-alignment.c new file mode 100644 index 0000000000000..6f3b2bc38be36 --- /dev/null +++ b/clang/test/Driver/systemz-alignment.c @@ -0,0 +1,32 @@ +// RUN: %clang --target=s390x-linux -S -emit-llvm -o - %s | FileCheck %s +// +// Test that a global variable with an incomplete type gets the minimum +// alignment of 2 per the ABI if no alignment was specified by user. +// +// CHECK: @VarNoAl {{.*}} align 2 +// CHECK-NEXT: @VarExplAl1 {{.*}} align 1 +// CHECK-NEXT: @VarExplAl4 {{.*}} align 4 + +// No alignemnt specified by user. +struct incomplete_ty_noal; +extern struct incomplete_ty_noal VarNoAl; +struct incomplete_ty_noal *fun0 (void) +{ + return &VarNoAl; +} + +// User-specified alignment of 1. +struct incomplete_ty_al1; +extern struct incomplete_ty_al1 __attribute__((aligned(1))) VarExplAl1; +struct incomplete_ty_al1 *fun1 (void) +{ + return &VarExplAl1; +} + +// User-specified alignment of 4. +struct incomplete_ty_al4; +extern struct incomplete_ty_al4 __attribute__((aligned(4))) VarExplAl4; +struct incomplete_ty_al4 *fun2 (void) +{ + return &VarExplAl4; +}