Index: llvm/tools/clang/include/clang/AST/DeclBase.h =================================================================== --- llvm/tools/clang/include/clang/AST/DeclBase.h +++ llvm/tools/clang/include/clang/AST/DeclBase.h @@ -281,6 +281,9 @@ /// are regarded as "referenced" but not "used". unsigned Referenced : 1; + /// \brief Whether this declaration is parsing. + unsigned IsParsing : 1; + /// \brief Whether statistic collection is enabled. static bool StatisticsEnabled; @@ -332,25 +335,22 @@ bool AccessDeclContextSanity() const; protected: - Decl(Kind DK, DeclContext *DC, SourceLocation L) - : NextInContextAndBits(), DeclCtx(DC), - Loc(L), DeclKind(DK), InvalidDecl(0), - HasAttrs(false), Implicit(false), Used(false), Referenced(false), - Access(AS_none), FromASTFile(0), Hidden(DC && cast(DC)->Hidden), - IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - CacheValidAndLinkage(0) - { + : NextInContextAndBits(), DeclCtx(DC), Loc(L), DeclKind(DK), + InvalidDecl(0), HasAttrs(false), Implicit(false), Used(false), + Referenced(false), IsParsing(false), Access(AS_none), FromASTFile(0), + Hidden(DC && cast(DC)->Hidden), + IdentifierNamespace(getIdentifierNamespaceForKind(DK)), + CacheValidAndLinkage(0) { if (StatisticsEnabled) add(DK); } Decl(Kind DK, EmptyShell Empty) - : NextInContextAndBits(), DeclKind(DK), InvalidDecl(0), - HasAttrs(false), Implicit(false), Used(false), Referenced(false), - Access(AS_none), FromASTFile(0), Hidden(0), - IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - CacheValidAndLinkage(0) - { + : NextInContextAndBits(), DeclKind(DK), InvalidDecl(0), HasAttrs(false), + Implicit(false), Used(false), Referenced(false), IsParsing(false), + Access(AS_none), FromASTFile(0), Hidden(0), + IdentifierNamespace(getIdentifierNamespaceForKind(DK)), + CacheValidAndLinkage(0) { if (StatisticsEnabled) add(DK); } @@ -546,6 +546,11 @@ void setReferenced(bool R = true) { Referenced = R; } + /// \brief Whether any declaration of this is parsing. + bool isParsing() const { return IsParsing; } + + void setIsParsing(bool I) { IsParsing = I; } + /// \brief Whether this declaration is a top-level declaration (function, /// global variable, etc.) that is lexically inside an objc container /// definition. 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 @@ -3069,6 +3069,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: llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp =================================================================== --- llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -1822,6 +1822,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: llvm/tools/clang/lib/Sema/SemaDecl.cpp =================================================================== --- llvm/tools/clang/lib/Sema/SemaDecl.cpp +++ llvm/tools/clang/lib/Sema/SemaDecl.cpp @@ -13292,8 +13292,10 @@ if (Invalid) New->setInvalidDecl(); + New->setIsParsing(true); + if (Attr) - ProcessDeclAttributeList(S, New, Attr); + ProcessDeclAttributeList(S, New, Attr, true); // 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 @@ -3023,8 +3023,9 @@ } if (!RD->isCompleteDefinition()) { - S.Diag(Attr.getLoc(), - diag::warn_transparent_union_attribute_not_definition); + if (!D->isParsing()) + S.Diag(Attr.getLoc(), + diag::warn_transparent_union_attribute_not_definition); return; } @@ -6100,6 +6101,18 @@ } } +// Helper for delayed proccessing TransparentUnion attribute. +void Sema::ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList) { + + if (D) D->setIsParsing(false); + + 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: 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); +}