From: David Blaikie Date: Wed, 19 Oct 2011 22:43:29 +0000 (+0000) Subject: Don't provide errors for anonymous unions when they're actually anonymous classes. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2b79c320b0801e0094df6c70ad8062da6c58bd1c;p=clang Don't provide errors for anonymous unions when they're actually anonymous classes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142551 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7dafc50b3d..46774b18f6 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2642,32 +2642,34 @@ Decl *Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, if (getLangOptions().CPlusPlus) { const char* PrevSpec = 0; unsigned DiagID; - // C++ [class.union]p3: - // Anonymous unions declared in a named namespace or in the - // global namespace shall be declared static. - if (DS.getStorageClassSpec() != DeclSpec::SCS_static && - (isa(Owner) || - (isa(Owner) && - cast(Owner)->getDeclName()))) { - Diag(Record->getLocation(), diag::err_anonymous_union_not_static); - Invalid = true; - - // Recover by adding 'static'. - DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(), - PrevSpec, DiagID); - } - // C++ [class.union]p3: - // A storage class is not allowed in a declaration of an - // anonymous union in a class scope. - else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified && - isa(Owner)) { - Diag(DS.getStorageClassSpecLoc(), - diag::err_anonymous_union_with_storage_spec); - Invalid = true; - - // Recover by removing the storage specifier. - DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified, SourceLocation(), - PrevSpec, DiagID); + if (Record->isUnion()) { + // C++ [class.union]p6: + // Anonymous unions declared in a named namespace or in the + // global namespace shall be declared static. + if (DS.getStorageClassSpec() != DeclSpec::SCS_static && + (isa(Owner) || + (isa(Owner) && + cast(Owner)->getDeclName()))) { + Diag(Record->getLocation(), diag::err_anonymous_union_not_static); + Invalid = true; + + // Recover by adding 'static'. + DS.SetStorageClassSpec(*this, DeclSpec::SCS_static, SourceLocation(), + PrevSpec, DiagID); + } + // C++ [class.union]p6: + // A storage class is not allowed in a declaration of an + // anonymous union in a class scope. + else if (DS.getStorageClassSpec() != DeclSpec::SCS_unspecified && + isa(Owner)) { + Diag(DS.getStorageClassSpecLoc(), + diag::err_anonymous_union_with_storage_spec); + Invalid = true; + + // Recover by removing the storage specifier. + DS.SetStorageClassSpec(*this, DeclSpec::SCS_unspecified, SourceLocation(), + PrevSpec, DiagID); + } } // Ignore const/volatile/restrict qualifiers. diff --git a/test/SemaCXX/anonymous-struct.cpp b/test/SemaCXX/anonymous-struct.cpp index dfa284ae8b..19a88d739a 100644 --- a/test/SemaCXX/anonymous-struct.cpp +++ b/test/SemaCXX/anonymous-struct.cpp @@ -4,8 +4,13 @@ struct S { S(); // expected-note {{because type 'S' has a user-declared constructor}} }; +struct { // expected-error {{anonymous structs and classes must be class members}} +}; + struct E { struct { S x; // expected-error {{anonymous struct member 'x' has a non-trivial constructor}} }; + static struct { + }; };