]> granicus.if.org Git - clang/commitdiff
Relaxing the alignment requirements for fields in a transparent_union. Emits the...
authorAaron Ballman <aaron@aaronballman.com>
Tue, 28 Jan 2014 01:47:34 +0000 (01:47 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Tue, 28 Jan 2014 01:47:34 +0000 (01:47 +0000)
Fixes PR15134

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@200277 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclAttr.cpp
test/Sema/transparent-union.c

index c6e8f3490a6b4caf5971371bb8946e099120a0fd..dd7aa477b17a5743de4eab1d0d21a570147cd7e7 100644 (file)
@@ -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)
index bbe0a32d4830a9238f43cc42b781407261760e6f..eff7df67b9ad1ba4bc06fad0eaa8a3438c0678dd 100644 (file)
@@ -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));