Hi, Nikola.
Thanks you again for updating the patch. The only thing you missed to do is to pass additional parameter to CheckLookupAccess in SemaDeclCXX.cpp:
CheckLookupAccess(Previous, *true*);
"true" means - use current declaration context in delayed check. Since as I wrote before we're parsing class with "friend" declaration, but diagnostics is invoked for class with definition of friend member itself, and improper context is used by default.

Well, I attached two patches. The first is without any fixes in delayed diagnostics. I just implemented CheckLookupAccessNow, that doesn't use DD. Ss McCall said: "because we know exactly what we're checking access to, and we're getting nothing out of delaying the diagnostic."
The patch name is pr12328-checknow.patch

But IMHO, the DD works a little bit improperly. I think it is not proper to use decl context for class for which it was invoked. We should use decl context for class/method for which it was *requested*.
The patch name is ppr12328-fixedDD.patch

Also I patch with testcases is attached.

-Stepan.

Nikola Smiljanic wrote:
I was just looking for something to work on myself when I saw your
patch and gave it a try. I'm not in position to comment the
implementation but I guess that John McCall is the right person to CC
when (or if) you get back to this issue.


Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h	(revision 161486)
+++ include/clang/Sema/Sema.h	(working copy)
@@ -4444,6 +4444,7 @@
                                     bool ForceCheck = false,
                                     bool ForceUnprivileged = false);
   void CheckLookupAccess(const LookupResult &R);
+  void CheckLookupAccessNow(const LookupResult &R);
   bool IsSimplyAccessible(NamedDecl *decl, DeclContext *Ctx);
   bool isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
                                             AccessSpecifier access,
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp	(revision 161486)
+++ lib/Sema/SemaDeclCXX.cpp	(working copy)
@@ -10306,6 +10306,10 @@
     }
   }
 
+  if (Previous.getResultKind() == LookupResult::Found &&
+      Previous.getFoundDecl()->isCXXClassMember())
+    CheckLookupAccessNow(Previous);
+  
   // FIXME: This is an egregious hack to cope with cases where the scope stack
   // does not contain the declaration context, i.e., in an out-of-line 
   // definition of a class.
Index: lib/Sema/SemaAccess.cpp
===================================================================
--- lib/Sema/SemaAccess.cpp	(revision 161486)
+++ lib/Sema/SemaAccess.cpp	(working copy)
@@ -1418,6 +1418,24 @@
   llvm_unreachable("falling off end");
 }
 
+/// CheckAccessNow - does the same as CheckAccess, but doesn't perform
+/// delayed diagnostics. It is supposed that user knows that diagnostics
+/// shouldn't be delayed.
+static Sema::AccessResult CheckAccessNow(Sema &S, SourceLocation Loc,
+                                      AccessTarget &Entity) {
+  // If the access path is public, it's accessible everywhere.
+  if (Entity.getAccess() == AS_public)
+    return Sema::AR_accessible;
+
+  EffectiveContext EC(S.CurContext);
+  switch (CheckEffectiveAccess(S, EC, Loc, Entity)) {
+  case AR_accessible: return Sema::AR_accessible;
+  case AR_inaccessible: return Sema::AR_inaccessible;
+  case AR_dependent: return Sema::AR_dependent;
+  }
+  llvm_unreachable("falling off end");
+}
+
 void Sema::HandleDelayedAccessCheck(DelayedDiagnostic &DD, Decl *decl) {
   // Access control for names used in the declarations of functions
   // and function templates should normally be evaluated in the context
@@ -1768,6 +1786,23 @@
   }
 }
 
+/// Checks access to all the declarations in the given result set.
+void Sema::CheckLookupAccessNow(const LookupResult &R) {
+  assert(getLangOpts().AccessControl
+         && "performing access check without access control");
+  assert(R.getNamingClass() && "performing access check without naming class");
+
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    if (I.getAccess() != AS_public) {
+      AccessTarget Entity(Context, AccessedEntity::Member,
+                          R.getNamingClass(), I.getPair(),
+                          R.getBaseObjectType());
+      Entity.setDiag(diag::err_access);
+      CheckAccessNow(*this, R.getNameLoc(), Entity);
+    }
+  }
+}
+
 /// Checks access to Decl from the given class. The check will take access
 /// specifiers into account, but no member access expressions and such.
 ///
Index: include/clang/Sema/DelayedDiagnostic.h
===================================================================
--- include/clang/Sema/DelayedDiagnostic.h	(revision 161486)
+++ include/clang/Sema/DelayedDiagnostic.h	(working copy)
@@ -44,10 +44,13 @@
                  MemberNonce _,
                  CXXRecordDecl *NamingClass,
                  DeclAccessPair FoundDecl,
-                 QualType BaseObjectType)
+                 QualType BaseObjectType,
+                 DeclContext *FromContext = 0)
     : Access(FoundDecl.getAccess()), IsMember(true),
       Target(FoundDecl.getDecl()), NamingClass(NamingClass),
-      BaseObjectType(BaseObjectType), Diag(0, Allocator) {
+      BaseObjectType(BaseObjectType),
+      FromContext(FromContext),
+      Diag(0, Allocator) {
   }
 
   AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator,
@@ -58,6 +61,7 @@
     : Access(Access), IsMember(false),
       Target(BaseClass),
       NamingClass(DerivedClass),
+      FromContext(0),
       Diag(0, Allocator) {
   }
 
@@ -78,6 +82,10 @@
   /// Retrieves the base object type, important when accessing
   /// an instance member.
   QualType getBaseObjectType() const { return BaseObjectType; }
+  
+  /// Retrieves the specified DeclarationContext from which
+  /// we want to access the target.
+  DeclContext *getFromContext() const { return FromContext; }
 
   /// Sets a diagnostic to be performed.  The diagnostic is given
   /// four (additional) arguments:
@@ -105,6 +113,7 @@
   NamedDecl *Target;
   CXXRecordDecl *NamingClass;
   QualType BaseObjectType;
+  DeclContext *FromContext;
   PartialDiagnostic Diag;
 };
 
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h	(revision 161486)
+++ include/clang/Sema/Sema.h	(working copy)
@@ -4443,7 +4443,7 @@
                                     unsigned DiagID,
                                     bool ForceCheck = false,
                                     bool ForceUnprivileged = false);
-  void CheckLookupAccess(const LookupResult &R);
+  void CheckLookupAccess(const LookupResult &R, bool UseCurContext = false);
   bool IsSimplyAccessible(NamedDecl *decl, DeclContext *Ctx);
   bool isSpecialMemberAccessibleForDeletion(CXXMethodDecl *decl,
                                             AccessSpecifier access,
Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp	(revision 161486)
+++ lib/Sema/SemaDeclCXX.cpp	(working copy)
@@ -10306,6 +10306,10 @@
     }
   }
 
+  if (Previous.getResultKind() == LookupResult::Found &&
+      Previous.getFoundDecl()->isCXXClassMember())
+    CheckLookupAccess(Previous, true);
+  
   // FIXME: This is an egregious hack to cope with cases where the scope stack
   // does not contain the declaration context, i.e., in an out-of-line 
   // definition of a class.
Index: lib/Sema/SemaAccess.cpp
===================================================================
--- lib/Sema/SemaAccess.cpp	(revision 161486)
+++ lib/Sema/SemaAccess.cpp	(working copy)
@@ -151,9 +151,10 @@
                MemberNonce _,
                CXXRecordDecl *NamingClass,
                DeclAccessPair FoundDecl,
-               QualType BaseObjectType)
+               QualType BaseObjectType,
+               DeclContext *FromContext = 0)
     : AccessedEntity(Context.getDiagAllocator(), Member, NamingClass,
-                     FoundDecl, BaseObjectType) {
+                     FoundDecl, BaseObjectType, FromContext) {
     initialize();
   }
 
@@ -1424,12 +1425,15 @@
   // of the declaration, just in case it's a friend of something.
   // However, this does not apply to local extern declarations.
 
-  DeclContext *DC = decl->getDeclContext();
-  if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
-    if (!DC->isFunctionOrMethod()) DC = fn;
-  } else if (FunctionTemplateDecl *fnt = dyn_cast<FunctionTemplateDecl>(decl)) {
-    // Never a local declaration.
-    DC = fnt->getTemplatedDecl();
+  DeclContext *DC = DD.getAccessData().getFromContext();
+  if (!DC) {
+    DC = decl->getDeclContext();
+    if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) {
+      if (!DC->isFunctionOrMethod()) DC = fn;
+    } else if (FunctionTemplateDecl *fnt = dyn_cast<FunctionTemplateDecl>(decl)) {
+      // Never a local declaration.
+      DC = fnt->getTemplatedDecl();
+    }
   }
 
   EffectiveContext EC(DC);
@@ -1752,7 +1756,7 @@
 }
 
 /// Checks access to all the declarations in the given result set.
-void Sema::CheckLookupAccess(const LookupResult &R) {
+void Sema::CheckLookupAccess(const LookupResult &R, bool UseCurContext) {
   assert(getLangOpts().AccessControl
          && "performing access check without access control");
   assert(R.getNamingClass() && "performing access check without naming class");
@@ -1761,7 +1765,8 @@
     if (I.getAccess() != AS_public) {
       AccessTarget Entity(Context, AccessedEntity::Member,
                           R.getNamingClass(), I.getPair(),
-                          R.getBaseObjectType());
+                          R.getBaseObjectType(),
+                          UseCurContext ? CurContext : 0);
       Entity.setDiag(diag::err_access);
       CheckAccess(*this, R.getNameLoc(), Entity);
     }
Index: test/CXX/class.access/class.friend/p1.cpp
===================================================================
--- test/CXX/class.access/class.friend/p1.cpp	(revision 155311)
+++ test/CXX/class.access/class.friend/p1.cpp	(working copy)
@@ -64,6 +64,7 @@
   };
 
   class MemberFriend {
+  public:
     void test();
   };
 
@@ -309,6 +310,7 @@
 // PR8705
 namespace test11 {
   class A {
+  public:
     void test0(int);
     void test1(int);
     void test2(int);
Index: test/SemaCXX/friend.cpp
===================================================================
--- test/SemaCXX/friend.cpp	(revision 155311)
+++ test/SemaCXX/friend.cpp	(working copy)
@@ -138,3 +138,13 @@
     };
   }
 }
+
+// PR12328
+namespace test8 {
+  class X {
+    void f(); // expected-note {{implicitly declared private here}}
+  };
+  class Y {
+    friend void X::f(); // expected-error {{'f' is a private member of 'test8::X'}}
+  };
+}
\ No newline at end of file

_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to