[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