erichkeane created this revision.
erichkeane added reviewers: cfe-commits, bruno, aaron.ballman, rsmith.

This is an update of this patch: https://reviews.llvm.org/D25824

I cannot seem to get that review to update with my diff.  This first patch 
removes the dependency on isParsing and switches to isBeingDefined.  In order 
to get that to work, changing where attributes where changed was necessary.

Original description below:

Clang compiles with error following test case

typedef union attribute((transparent_union)) {

int *i;
struct st *s;

} TU;

void bar(TU);

void foo(int *i) {

bar(i);

}

clang -c tu.c
tu.c:1:30: warning: transparent_union attribute can only be applied to a union 
definition; attribute ignored [-Wignored-attributes]
typedef union attribute((transparent_union)) {

^

tu.c:8:24: error: passing 'int *' to parameter of incompatible type 'TU'
void foo(int *i) { bar(i); }

^

tu.c:6:12: note: passing argument to parameter here
void bar(TU);

^

GCC compiles this test successfully.

The compilation is failed because the routine handleTransparentUnionAttr 
requires for the record decl to be completed. This fix provides handling of the 
attribute ‘transparent_union’ after parsing of union.


https://reviews.llvm.org/D28266

Files:
  include/clang/Sema/Sema.h
  lib/Parse/ParseDeclCXX.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  test/CodeGen/transparent-union.c
  test/Sema/transparent-union.c

Index: lib/Parse/ParseDeclCXX.cpp
===================================================================
--- lib/Parse/ParseDeclCXX.cpp
+++ lib/Parse/ParseDeclCXX.cpp
@@ -1885,6 +1885,10 @@
       ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
   }
 
+  if (!TagOrTempResult.isInvalid())
+    // Delayed proccessing TransparentUnion attribute.
+    Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList());
+
   const char *PrevSpec = nullptr;
   unsigned DiagID;
   bool Result;
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -13477,9 +13477,6 @@
   if (Invalid)
     New->setInvalidDecl();
 
-  if (Attr)
-    ProcessDeclAttributeList(S, New, Attr);
-
   // Set the lexical context. If the tag has a C++ scope specifier, the
   // lexical context will be different from the semantic context.
   New->setLexicalDeclContext(CurContext);
@@ -13498,6 +13495,9 @@
   if (TUK == TUK_Definition)
     New->startDefinition();
 
+  if (Attr)
+    ProcessDeclAttributeList(S, New, Attr);
+
   // If this has an identifier, add it to the scope stack.
   if (TUK == TUK_Friend) {
     // We might be replacing an existing declaration in the lookup tables;
Index: lib/Sema/SemaDeclAttr.cpp
===================================================================
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -3109,8 +3109,9 @@
   }
 
   if (!RD->isCompleteDefinition()) {
-    S.Diag(Attr.getLoc(),
-        diag::warn_transparent_union_attribute_not_definition);
+    if (!RD->isBeingDefined())
+      S.Diag(Attr.getLoc(),
+             diag::warn_transparent_union_attribute_not_definition);
     return;
   }
 
@@ -6195,6 +6196,15 @@
   }
 }
 
+// Helper for delayed proccessing TransparentUnion attribute.
+void Sema::ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList) {
+  for (const AttributeList* l = AttrList; l; l = l->getNext())
+    if (l->getKind() == AttributeList::AT_TransparentUnion) {
+      handleTransparentUnionAttr(*this, D, *l);
+      break;
+    }
+}
+
 // Annotation attributes are the only attributes allowed after an access
 // specifier.
 bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -3056,6 +3056,8 @@
   void ProcessPragmaWeak(Scope *S, Decl *D);
   // Decl attributes - this routine is the top level dispatcher.
   void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD);
+  // Helper for delayed proccessing TransparentUnion attribute.
+  void ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList);
   void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL,
                                 bool IncludeCXX11Attributes = true);
   bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl,
Index: test/CodeGen/transparent-union.c
===================================================================
--- test/CodeGen/transparent-union.c
+++ test/CodeGen/transparent-union.c
@@ -3,10 +3,21 @@
 // RUN: %clang_cc1 -Werror -triple armv7-linux -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM
 // RUN: %clang_cc1 -Werror -triple powerpc64le-linux -emit-llvm -o - %s | FileCheck %s
 // RUN: %clang_cc1 -Werror -triple aarch64-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DINFRONT -Werror -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DINFRONT -Werror -triple i386-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DINFRONT -Werror -triple armv7-linux -emit-llvm -o - %s | FileCheck %s --check-prefix=ARM
+// RUN: %clang_cc1 -DINFRONT -Werror -triple powerpc64le-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -DINFRONT -Werror -triple aarch64-linux -emit-llvm -o - %s | FileCheck %s
 
+#ifdef INFRONT
+typedef union __attribute__((transparent_union)) {
+  void *f0;
+} transp_t0;
+#else
 typedef union {
   void *f0;
 } transp_t0 __attribute__((transparent_union));
+#endif
 
 void f0(transp_t0 obj);
 
Index: test/Sema/transparent-union.c
===================================================================
--- test/Sema/transparent-union.c
+++ test/Sema/transparent-union.c
@@ -54,11 +54,21 @@
   aligned_struct8 s8; // expected-warning{{alignment of field}}
 } TU1 __attribute__((transparent_union));
 
+typedef union __attribute__((transparent_union)) {
+  aligned_struct4 s4; // expected-note{{alignment of first field}}
+  aligned_struct8 s8; // expected-warning{{alignment of field}}
+} TU1b ;
+
 typedef union {
   char c; // expected-note{{size of first field is 8 bits}}
   int i; // expected-warning{{size of field}}
 } TU2 __attribute__((transparent_union));
 
+typedef union __attribute__((transparent_union)){
+  char c; // expected-note{{size of first field is 8 bits}}
+  int i; // expected-warning{{size of field}}
+} TU2b;
+
 typedef union {
   float f; // expected-warning{{floating}}
 } TU3 __attribute__((transparent_union));
@@ -98,3 +108,17 @@
 union pr30520s { struct stb b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'struct stb'}}
 
 union pr30520s2 { int *v; struct stb b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'struct stb'}}
+
+typedef union __attribute__((__transparent_union__)) {
+  int *i;
+  struct st *s;
+} TU6;
+
+void bar(TU6);
+
+void foo11(int *i) {
+  bar(i);
+}
+void foo2(struct st *s) {
+  bar(s);
+}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D28266: Transparent_un... Erich Keane via Phabricator via cfe-commits

Reply via email to