[cfe-commits] r104376 - in /cfe/trunk: include/clang/Parse/Action.h lib/Frontend/PrintParserCallbacks.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Parse/ParseTemplate.cpp lib/Parse/Parser.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp test/SemaCXX/anonymous-union.cpp

John McCall rjmccall at apple.com
Fri May 21 13:45:30 PDT 2010


Author: rjmccall
Date: Fri May 21 15:45:30 2010
New Revision: 104376

URL: http://llvm.org/viewvc/llvm-project?rev=104376&view=rev
Log:
Propagate access specifiers to anonymous union members nested within classes.
Fixes <rdar://problem/7987650>.


Modified:
    cfe/trunk/include/clang/Parse/Action.h
    cfe/trunk/lib/Frontend/PrintParserCallbacks.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseTemplate.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaCXX/anonymous-union.cpp

Modified: cfe/trunk/include/clang/Parse/Action.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Action.h?rev=104376&r1=104375&r2=104376&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Action.h (original)
+++ cfe/trunk/include/clang/Parse/Action.h Fri May 21 15:45:30 2010
@@ -573,7 +573,9 @@
 
   /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
   /// no declarator (e.g. "struct foo;") is parsed.
-  virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
+  virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S,
+                                               AccessSpecifier Access,
+                                               DeclSpec &DS) {
     return DeclPtrTy();
   }
 

Modified: cfe/trunk/lib/Frontend/PrintParserCallbacks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PrintParserCallbacks.cpp?rev=104376&r1=104375&r2=104376&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PrintParserCallbacks.cpp (original)
+++ cfe/trunk/lib/Frontend/PrintParserCallbacks.cpp Fri May 21 15:45:30 2010
@@ -161,7 +161,8 @@
 
     /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
     /// no declarator (e.g. "struct foo;") is parsed.
-    virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
+    virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+                                                 DeclSpec &DS) {
       Out << __FUNCTION__ << "\n";
       return DeclPtrTy();
     }

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=104376&r1=104375&r2=104376&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri May 21 15:45:30 2010
@@ -364,7 +364,8 @@
   // declaration-specifiers init-declarator-list[opt] ';'
   if (Tok.is(tok::semi)) {
     if (RequireSemi) ConsumeToken();
-    DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, AS_none,
+                                                           DS);
     DS.complete(TheDecl);
     return Actions.ConvertDeclToDeclGroup(TheDecl);
   }
@@ -1676,7 +1677,7 @@
   // If there are no declarators, this is a free-standing declaration
   // specifier. Let the actions module cope with it.
   if (Tok.is(tok::semi)) {
-    Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    Actions.ParsedFreeStandingDeclSpec(CurScope, AS_none, DS);
     return;
   }
 

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=104376&r1=104375&r2=104376&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Fri May 21 15:45:30 2010
@@ -1307,7 +1307,7 @@
 
   if (Tok.is(tok::semi)) {
     ConsumeToken();
-    Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    Actions.ParsedFreeStandingDeclSpec(CurScope, AS, DS);
     return;
   }
 

Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=104376&r1=104375&r2=104376&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Fri May 21 15:45:30 2010
@@ -201,7 +201,7 @@
 
   if (Tok.is(tok::semi)) {
     DeclEnd = ConsumeToken();
-    DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DeclPtrTy Decl = Actions.ParsedFreeStandingDeclSpec(CurScope, AS, DS);
     DS.complete(Decl);
     return Decl;
   }

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=104376&r1=104375&r2=104376&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Fri May 21 15:45:30 2010
@@ -538,7 +538,7 @@
   // declaration-specifiers init-declarator-list[opt] ';'
   if (Tok.is(tok::semi)) {
     ConsumeToken();
-    DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
+    DeclPtrTy TheDecl = Actions.ParsedFreeStandingDeclSpec(CurScope, AS, DS);
     DS.complete(TheDecl);
     return Actions.ConvertDeclToDeclGroup(TheDecl);
   }

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=104376&r1=104375&r2=104376&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri May 21 15:45:30 2010
@@ -907,11 +907,11 @@
 
   /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
   /// no declarator (e.g. "struct foo;") is parsed.
-  virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS);
+  virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+                                               DeclSpec &DS);
 
-  bool InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
-                                           RecordDecl *AnonRecord);
   virtual DeclPtrTy BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
+                                                AccessSpecifier AS,
                                                 RecordDecl *Record);
 
   bool isAcceptableTagRedeclaration(const TagDecl *Previous,

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=104376&r1=104375&r2=104376&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri May 21 15:45:30 2010
@@ -1455,7 +1455,8 @@
 
 /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with
 /// no declarator (e.g. "struct foo;") is parsed.
-Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
+Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS,
+                                                 DeclSpec &DS) {
   // FIXME: Error on auto/register at file scope
   // FIXME: Error on inline/virtual/explicit
   // FIXME: Warn on useless __thread
@@ -1505,7 +1506,7 @@
         DS.getStorageClassSpec() != DeclSpec::SCS_typedef) {
       if (getLangOptions().CPlusPlus ||
           Record->getDeclContext()->isRecord())
-        return BuildAnonymousStructOrUnion(S, DS, Record);
+        return BuildAnonymousStructOrUnion(S, DS, AS, Record);
 
       Diag(DS.getSourceRange().getBegin(), diag::ext_no_declarators)
         << DS.getSourceRange();
@@ -1583,8 +1584,10 @@
 ///
 /// This routine is recursive, injecting the names of nested anonymous
 /// structs/unions into the owning context and scope as well.
-bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
-                                               RecordDecl *AnonRecord) {
+static bool InjectAnonymousStructOrUnionMembers(Sema &SemaRef, Scope *S,
+                                                DeclContext *Owner,
+                                                RecordDecl *AnonRecord,
+                                                AccessSpecifier AS) {
   unsigned diagKind
     = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
                             : diag::err_anonymous_struct_member_redecl;
@@ -1594,7 +1597,7 @@
                                FEnd = AnonRecord->field_end();
        F != FEnd; ++F) {
     if ((*F)->getDeclName()) {
-      if (CheckAnonMemberRedeclaration(*this, S, Owner, (*F)->getDeclName(),
+      if (CheckAnonMemberRedeclaration(SemaRef, S, Owner, (*F)->getDeclName(),
                                        (*F)->getLocation(), diagKind)) {
         // C++ [class.union]p2:
         //   The names of the members of an anonymous union shall be
@@ -1608,15 +1611,19 @@
         //   considered to have been defined in the scope in which the
         //   anonymous union is declared.
         Owner->makeDeclVisibleInContext(*F);
-        S->AddDecl(DeclPtrTy::make(*F));
-        IdResolver.AddDecl(*F);
+        S->AddDecl(Sema::DeclPtrTy::make(*F));
+        SemaRef.IdResolver.AddDecl(*F);
+
+        // That includes picking up the appropriate access specifier.
+        if (AS != AS_none) (*F)->setAccess(AS);
       }
     } else if (const RecordType *InnerRecordType
                  = (*F)->getType()->getAs<RecordType>()) {
       RecordDecl *InnerRecord = InnerRecordType->getDecl();
       if (InnerRecord->isAnonymousStructOrUnion())
         Invalid = Invalid ||
-          InjectAnonymousStructOrUnionMembers(S, Owner, InnerRecord);
+          InjectAnonymousStructOrUnionMembers(SemaRef, S, Owner,
+                                              InnerRecord, AS);
     }
   }
 
@@ -1686,6 +1693,7 @@
 /// (C++ [class.union]) and a GNU C extension; anonymous structures
 /// are a GNU C and GNU C++ extension.
 Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,
+                                                  AccessSpecifier AS,
                                                   RecordDecl *Record) {
   DeclContext *Owner = Record->getDeclContext();
 
@@ -1740,7 +1748,8 @@
         // C++ [class.union]p3:
         //   An anonymous union shall not have private or protected
         //   members (clause 11).
-        if (FD->getAccess() == AS_protected || FD->getAccess() == AS_private) {
+        assert(FD->getAccess() != AS_none);
+        if (FD->getAccess() != AS_public) {
           Diag(FD->getLocation(), diag::err_anonymous_record_nonpublic_member)
             << (int)Record->isUnion() << (int)(FD->getAccess() == AS_protected);
           Invalid = true;
@@ -1797,7 +1806,7 @@
                              Context.getTypeDeclType(Record),
                              TInfo,
                              /*BitWidth=*/0, /*Mutable=*/false);
-    Anon->setAccess(AS_public);
+    Anon->setAccess(AS);
     if (getLangOptions().CPlusPlus) {
       FieldCollector->Add(cast<FieldDecl>(Anon));
       if (!cast<CXXRecordDecl>(Record)->isEmpty())
@@ -1834,7 +1843,7 @@
   // Inject the members of the anonymous struct/union into the owning
   // context and into the identifier resolver chain for name lookup
   // purposes.
-  if (InjectAnonymousStructOrUnionMembers(S, Owner, Record))
+  if (InjectAnonymousStructOrUnionMembers(*this, S, Owner, Record, AS))
     Invalid = true;
 
   // Mark this as an anonymous struct/union type. Note that we do not

Modified: cfe/trunk/test/SemaCXX/anonymous-union.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/anonymous-union.cpp?rev=104376&r1=104375&r2=104376&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/anonymous-union.cpp (original)
+++ cfe/trunk/test/SemaCXX/anonymous-union.cpp Fri May 21 15:45:30 2010
@@ -121,3 +121,37 @@
         int Foo;
     };
 } s, *ps;
+
+// <rdar://problem/7987650>
+namespace test4 {
+  class A {
+    struct {
+      int s0; // expected-note {{declared private here}}
+      double s1; // expected-note {{declared private here}}
+      union {
+        int su0; // expected-note {{declared private here}}
+        double su1; // expected-note {{declared private here}}
+      };
+    };
+    union {
+      int u0; // expected-note {{declared private here}}
+      double u1; // expected-note {{declared private here}}
+      struct {
+        int us0; // expected-note {{declared private here}}
+        double us1; // expected-note {{declared private here}}
+      };
+    };
+  };
+
+  void test() {
+    A a;
+    (void) a.s0;  // expected-error {{private member}}
+    (void) a.s1;  // expected-error {{private member}}
+    (void) a.su0; // expected-error {{private member}}
+    (void) a.su1; // expected-error {{private member}}
+    (void) a.u0;  // expected-error {{private member}}
+    (void) a.u1;  // expected-error {{private member}}
+    (void) a.us0; // expected-error {{private member}}
+    (void) a.us1; // expected-error {{private member}}
+  }
+}





More information about the cfe-commits mailing list