aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Sema/SemaDecl.cpp54
-rw-r--r--test/SemaCXX/anonymous-struct.cpp5
2 files changed, 33 insertions, 26 deletions
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<TranslationUnitDecl>(Owner) ||
- (isa<NamespaceDecl>(Owner) &&
- cast<NamespaceDecl>(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<RecordDecl>(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<TranslationUnitDecl>(Owner) ||
+ (isa<NamespaceDecl>(Owner) &&
+ cast<NamespaceDecl>(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<RecordDecl>(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 {
+ };
};