summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/Sema.h2
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp4
-rw-r--r--clang/lib/Sema/SemaDecl.cpp6
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp14
-rw-r--r--clang/test/CodeGen/transparent-union.c11
-rw-r--r--clang/test/Sema/transparent-union.c24
6 files changed, 56 insertions, 5 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 0ad45657691..a23948181ac 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 c3ede1b7f52..241c959474a 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 62bcabc2903..40ab1d29ae8 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 430d4e6ed98..fcfa708c785 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 2f00c2d21a0..efaef1bae98 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 a1a67dfd26f..dfbadcfe62c 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);
+}
OpenPOWER on IntegriCloud