[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