From 2fe684bb1478ef89efd8122e442ec76efaf5f857 Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Tue, 28 Feb 2017 20:44:39 +0000 Subject: [PATCH] Allow attributes before union definition permits typedef union __attribute__((transparent_union)) {...} Differential Revision: https://reviews.llvm.org/D28266 llvm-svn: 296518 --- clang/include/clang/Sema/Sema.h | 2 ++ clang/lib/Parse/ParseDeclCXX.cpp | 4 ++++ clang/lib/Sema/SemaDecl.cpp | 6 +++--- clang/lib/Sema/SemaDeclAttr.cpp | 14 ++++++++++++-- clang/test/CodeGen/transparent-union.c | 11 +++++++++++ clang/test/Sema/transparent-union.c | 24 ++++++++++++++++++++++++ 6 files changed, 56 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 0ad45657691b..a23948181ac9 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3122,6 +3122,8 @@ public: 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 of attributes. + void ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList); void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL, bool IncludeCXX11Attributes = true); bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index c3ede1b7f527..241c959474ab 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1887,6 +1887,10 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get()); } + if (!TagOrTempResult.isInvalid()) + // Delayed proccessing of attributes. + Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList()); + const char *PrevSpec = nullptr; unsigned DiagID; bool Result; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 62bcabc2903e..40ab1d29ae89 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13637,9 +13637,6 @@ CreateNewDecl: 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); @@ -13658,6 +13655,9 @@ CreateNewDecl: 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; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 430d4e6ed981..fcfa708c785e 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3193,8 +3193,9 @@ static void handleTransparentUnionAttr(Sema &S, Decl *D, } 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; } @@ -6314,6 +6315,15 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } } +// Helper for delayed proccessing TransparentUnion attribute. +void Sema::ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList) { + for (const AttributeList *Attr = AttrList; Attr; Attr = Attr->getNext()) + if (Attr->getKind() == AttributeList::AT_TransparentUnion) { + handleTransparentUnionAttr(*this, D, *Attr); + break; + } +} + // Annotation attributes are the only attributes allowed after an access // specifier. bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, diff --git a/clang/test/CodeGen/transparent-union.c b/clang/test/CodeGen/transparent-union.c index 2f00c2d21a05..efaef1bae987 100644 --- a/clang/test/CodeGen/transparent-union.c +++ b/clang/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); diff --git a/clang/test/Sema/transparent-union.c b/clang/test/Sema/transparent-union.c index a1a67dfd26fc..dfbadcfe62c7 100644 --- a/clang/test/Sema/transparent-union.c +++ b/clang/test/Sema/transparent-union.c @@ -54,11 +54,21 @@ typedef union { 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 pr30520a { int b[]; } __attribute__((transparent_union)); // expected-erro 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); +}