[cfe-commits] protected anonymous union member not visible in derived class
Nikola Smiljanic
popizdeh at gmail.com
Sun Aug 26 14:20:09 PDT 2012
I think this mail got lost while the mailing list was down so I'm
sending it again.
On Fri, Aug 17, 2012 at 10:11 PM, John McCall <rjmccall at apple.com> wrote:
> This is from building value.x, right? That's not the implicit member access case.
> It is definitely possible for an actual base expression to be non-null.
This should be it (test included).
However I do have some questions:
I'm using the real decl only for building the fist member access. The
rest of them are still built with FieldDecls that are obtained from
indirectField. There's even a FIXIT that says "these are somewhat
meaningless", but I don't know what it refers to. Should this stay the
same or should I use the real decl here too?
The 'if (!baseVariable)' block ends with 'baseObjectIsPointer = false'
but this variable is never used after this. I'm guessing that you
wanted the variable to remain valid throughout the function, but maybe
the assignment should be removed?
-------------- next part --------------
include/clang/Sema/Sema.h | 1 +
lib/Sema/SemaExprMember.cpp | 11 +++++++----
test/CXX/class.access/class.access.base/p1.cpp | 14 ++++++++++++++
3 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 4e2a971..76fccde 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2838,6 +2838,7 @@ public:
BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
SourceLocation nameLoc,
IndirectFieldDecl *indirectField,
+ LookupResult *R = 0,
Expr *baseObjectExpr = 0,
SourceLocation opLoc = SourceLocation());
ExprResult BuildPossibleImplicitMemberExpr(const CXXScopeSpec &SS,
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index 8f445e2..d7d13b1 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -677,6 +677,7 @@ ExprResult
Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
SourceLocation loc,
IndirectFieldDecl *indirectField,
+ LookupResult *R,
Expr *baseObjectExpr,
SourceLocation opLoc) {
// First, build the expression that refers to the base object.
@@ -742,6 +743,7 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
= new (Context) CXXThisExpr(loc, ThisTy, /*isImplicit=*/ true);
baseObjectIsPointer = true;
baseQuals = ThisTy->castAs<PointerType>()->getPointeeType().getQualifiers();
+ R->setBaseObjectType(ThisTy->castAs<PointerType>()->getPointeeType());
}
// Build the implicit member references to the field of the
@@ -754,8 +756,9 @@ Sema::BuildAnonymousStructUnionMemberReference(const CXXScopeSpec &SS,
if (!baseVariable) {
FieldDecl *field = cast<FieldDecl>(*FI);
- // FIXME: use the real found-decl info!
- DeclAccessPair foundDecl = DeclAccessPair::make(field, field->getAccess());
+ assert(R->getResultKind() == LookupResult::Found);
+ NamedDecl *ND = *R->begin();
+ DeclAccessPair foundDecl = DeclAccessPair::make(ND, ND->getAccess());
// Make a nameInfo that properly uses the anonymous name.
DeclarationNameInfo memberNameInfo(field->getDeclName(), loc);
@@ -946,7 +949,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType,
if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl))
// We may have found a field within an anonymous union or struct
// (C++ [class.union]).
- return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD,
+ return BuildAnonymousStructUnionMemberReference(SS, MemberLoc, FD, &R,
BaseExpr, OpLoc);
if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
@@ -1643,7 +1646,7 @@ Sema::BuildImplicitMemberExpr(const CXXScopeSpec &SS,
// (C++ [class.union]).
// FIXME: template-ids inside anonymous structs?
if (IndirectFieldDecl *FD = R.getAsSingle<IndirectFieldDecl>())
- return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD);
+ return BuildAnonymousStructUnionMemberReference(SS, R.getNameLoc(), FD, &R);
// If this is known to be an instance access, go ahead and build an
// implicit 'this' expression now.
diff --git a/test/CXX/class.access/class.access.base/p1.cpp b/test/CXX/class.access/class.access.base/p1.cpp
index 43cc99e..d88e8ea 100644
--- a/test/CXX/class.access/class.access.base/p1.cpp
+++ b/test/CXX/class.access/class.access.base/p1.cpp
@@ -153,3 +153,17 @@ namespace test2 {
t->Base::spriv++; // expected-error 2 {{private member}}
}
}
+
+namespace PR12788 {
+ class Base {
+ protected:
+ struct { int x; };
+ };
+
+ class Test : public Base {
+ void mem() {
+ x++;
+ Base::x++;
+ }
+ };
+}
More information about the cfe-commits
mailing list