Index: llvm/tools/clang/include/clang/Sema/Sema.h =================================================================== --- llvm/tools/clang/include/clang/Sema/Sema.h +++ llvm/tools/clang/include/clang/Sema/Sema.h @@ -2025,7 +2025,8 @@ bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, - bool IsTypeSpecifier, SkipBodyInfo *SkipBody = nullptr); + bool IsTypeSpecifier, SkipBodyInfo *SkipBody = nullptr, + bool DeclIsParsed = true); Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, @@ -3069,8 +3070,11 @@ 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 IncludeCXX11Attributes = true, + bool DeclIsParsed = true); bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, const AttributeList *AttrList); Index: llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp =================================================================== --- llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -1796,7 +1796,8 @@ SourceLocation(), false, clang::TypeResult(), DSC == DSC_type_specifier, - &SkipBody); + &SkipBody, + false); // If ActOnTag said the type was dependent, try again with the // less common call. @@ -1821,6 +1822,8 @@ else ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get()); } + // Delayed proccessing TransparentUnion attribute. + Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList()); const char *PrevSpec = nullptr; unsigned DiagID; Index: llvm/tools/clang/lib/Sema/SemaDecl.cpp =================================================================== --- llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -12503,7 +12503,8 @@ SourceLocation ScopedEnumKWLoc, bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, - bool IsTypeSpecifier, SkipBodyInfo *SkipBody) { + bool IsTypeSpecifier, SkipBodyInfo *SkipBody, + bool DeclIsParsed) { // If this is not a definition, it must have a name. IdentifierInfo *OrigName = Name; assert((Name != nullptr || TUK == TUK_Definition) && @@ -13293,7 +13294,7 @@ New->setInvalidDecl(); if (Attr) - ProcessDeclAttributeList(S, New, Attr); + ProcessDeclAttributeList(S, New, Attr, true, DeclIsParsed); // Set the lexical context. If the tag has a C++ scope specifier, the // lexical context will be different from the semantic context. Index: llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp +++ llvm/tools/clang/lib/Sema/SemaDeclAttr.cpp @@ -3007,7 +3007,8 @@ } static void handleTransparentUnionAttr(Sema &S, Decl *D, - const AttributeList &Attr) { + const AttributeList &Attr, + bool DeclIsParsed) { // Try to find the underlying union declaration. RecordDecl *RD = nullptr; TypedefNameDecl *TD = dyn_cast(D); @@ -3023,8 +3024,9 @@ } if (!RD->isCompleteDefinition()) { - S.Diag(Attr.getLoc(), - diag::warn_transparent_union_attribute_not_definition); + if (DeclIsParsed) + S.Diag(Attr.getLoc(), + diag::warn_transparent_union_attribute_not_definition); return; } @@ -5468,7 +5470,8 @@ /// silently ignore it if a GNU attribute. static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const AttributeList &Attr, - bool IncludeCXX11Attributes) { + bool IncludeCXX11Attributes, + bool DeclIsParsed = true) { if (Attr.isInvalid() || Attr.getKind() == AttributeList::IgnoredAttribute) return; @@ -5818,7 +5821,7 @@ handleWeakImportAttr(S, D, Attr); break; case AttributeList::AT_TransparentUnion: - handleTransparentUnionAttr(S, D, Attr); + handleTransparentUnionAttr(S, D, Attr, DeclIsParsed); break; case AttributeList::AT_ObjCException: handleSimpleAttribute(S, D, Attr); @@ -6048,9 +6051,11 @@ /// attribute list to the specified decl, ignoring any type attributes. void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AttrList, - bool IncludeCXX11Attributes) { + bool IncludeCXX11Attributes, + bool DeclIsParsed) { for (const AttributeList* l = AttrList; l; l = l->getNext()) - ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes); + ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes, + DeclIsParsed); // FIXME: We should be able to handle these cases in TableGen. // GCC accepts @@ -6100,6 +6105,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, true); + break; + } +} + // Annotation attributes are the only attributes allowed after an access // specifier. bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, Index: llvm/tools/clang/test/CodeGen/transparent-union.c =================================================================== --- llvm/tools/clang/test/CodeGen/transparent-union.c +++ llvm/tools/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); Index: llvm/tools/clang/test/Sema/transparent-union.c =================================================================== --- llvm/tools/clang/test/Sema/transparent-union.c +++ llvm/tools/clang/test/Sema/transparent-union.c @@ -98,3 +98,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); +}