]> granicus.if.org Git - clang/commitdiff
Don't provide errors for anonymous unions when they're actually anonymous classes.
authorDavid Blaikie <dblaikie@gmail.com>
Wed, 19 Oct 2011 22:43:29 +0000 (22:43 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Wed, 19 Oct 2011 22:43:29 +0000 (22:43 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142551 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/SemaCXX/anonymous-struct.cpp

index 7dafc50b3dc5b2d7400f2daaad91bc2a2cd99afe..46774b18f65fdf5092219f050119cbe0ac8a1221 100644 (file)
@@ -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.
index dfa284ae8b52b1e1607c476fc5cf3c5f6abdacb4..19a88d739acdf2e5e2413ed146a8d61c341d1312 100644 (file)
@@ -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 {
+  };
 };