From 54fe5eb8cb4938ba4edb12c6f400b0aba9039fd7 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Tue, 28 Jan 2014 01:47:34 +0000 Subject: [PATCH] Relaxing the alignment requirements for fields in a transparent_union. Emits the diagnostic only when subsequent alignments are more strict than the alignment required by the first field. Fixes PR15134 llvm-svn: 200277 --- clang/lib/Sema/SemaDeclAttr.cpp | 7 ++++++- clang/test/Sema/transparent-union.c | 20 +++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c6e8f3490a6b..dd7aa477b17a 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2664,8 +2664,13 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, uint64_t FirstAlign = S.Context.getTypeAlign(FirstType); for (; Field != FieldEnd; ++Field) { QualType FieldType = Field->getType(); + // FIXME: this isn't fully correct; we also need to test whether the + // members of the union would all have the same calling convention as the + // first member of the union. Checking just the size and alignment isn't + // sufficient (consider structs passed on the stack instead of in registers + // as an example). if (S.Context.getTypeSize(FieldType) != FirstSize || - S.Context.getTypeAlign(FieldType) != FirstAlign) { + S.Context.getTypeAlign(FieldType) > FirstAlign) { // Warn if we drop the attribute. bool isSize = S.Context.getTypeSize(FieldType) != FirstSize; unsigned FieldBits = isSize? S.Context.getTypeSize(FieldType) diff --git a/clang/test/Sema/transparent-union.c b/clang/test/Sema/transparent-union.c index bbe0a32d4830..eff7df67b9ad 100644 --- a/clang/test/Sema/transparent-union.c +++ b/clang/test/Sema/transparent-union.c @@ -70,4 +70,22 @@ typedef union { int4 vec; // expected-warning{{first field of a transparent union cannot have vector type 'int4'; transparent_union attribute ignored}} } TU5 __attribute__((transparent_union)); - +union pr15134 { + unsigned int u; + struct { + unsigned int expo:2; + unsigned int mant:30; + } __attribute__((packed)); + // The packed attribute is acceptable because it defines a less strict + // alignment than required by the first field of the transparent union. +} __attribute__((transparent_union)); + +union pr15134v2 { + struct { // expected-note {{alignment of first field is 32 bits}} + unsigned int u1; + unsigned int u2; + }; + struct { // expected-warning {{alignment of field '' (64 bits) does not match the alignment of the first field in transparent union; transparent_union attribute ignored}} + unsigned int u3; + } __attribute__((aligned(8))); +} __attribute__((transparent_union));