]> granicus.if.org Git - clang/commitdiff
Access control polish: drop the note on the original declaration and
authorJohn McCall <rjmccall@apple.com>
Wed, 20 Oct 2010 08:15:06 +0000 (08:15 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 20 Oct 2010 08:15:06 +0000 (08:15 +0000)
say 'implicitly' when it was implicit.  Resolves PR 7930 and my peace of mind.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116916 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaAccess.cpp
test/CXX/class.access/class.friend/p1.cpp
test/CXX/class.access/p4.cpp

index c3a1e7521050bb1d38cbf98c8aa7eac831705fac..2a150d7c03225118b2aec830de4f73497ec59078 100644 (file)
@@ -1008,9 +1008,51 @@ static void DiagnoseAccessPath(Sema &S,
           TryDiagnoseProtectedAccess(S, EC, Entity))
         return;
 
+      // Find an original declaration.
+      while (D->isOutOfLine()) {
+        NamedDecl *PrevDecl = 0;
+        if (isa<VarDecl>(D))
+          PrevDecl = cast<VarDecl>(D)->getPreviousDeclaration();
+        else if (isa<FunctionDecl>(D))
+          PrevDecl = cast<FunctionDecl>(D)->getPreviousDeclaration();
+        else if (isa<TypedefDecl>(D))
+          PrevDecl = cast<TypedefDecl>(D)->getPreviousDeclaration();
+        else if (isa<TagDecl>(D)) {
+          if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
+            break;
+          PrevDecl = cast<TagDecl>(D)->getPreviousDeclaration();
+        }
+        if (!PrevDecl) break;
+        D = PrevDecl;
+      }
+
+      CXXRecordDecl *DeclaringClass = FindDeclaringClass(D);
+      Decl *ImmediateChild;
+      if (D->getDeclContext() == DeclaringClass)
+        ImmediateChild = D;
+      else {
+        DeclContext *DC = D->getDeclContext();
+        while (DC->getParent() != DeclaringClass)
+          DC = DC->getParent();
+        ImmediateChild = cast<Decl>(DC);
+      }
+      
+      // Check whether there's an AccessSpecDecl preceding this in the
+      // chain of the DeclContext.
+      bool Implicit = true;
+      for (CXXRecordDecl::decl_iterator
+             I = DeclaringClass->decls_begin(), E = DeclaringClass->decls_end();
+           I != E; ++I) {
+        if (*I == ImmediateChild) break;
+        if (isa<AccessSpecDecl>(*I)) {
+          Implicit = false;
+          break;
+        }
+      }
+
       S.Diag(D->getLocation(), diag::note_access_natural)
         << (unsigned) (Access == AS_protected)
-        << /*FIXME: not implicitly*/ 0;
+        << Implicit;
       return;
     }
 
index 277b70bee6bdb423f3708b33a7de91457d310697..761643b7d7e83f406518ccd77bd45eef28c5888e 100644 (file)
@@ -258,13 +258,12 @@ namespace test7 {
 namespace test8 {
   class A {
     typedef int I; // expected-note 4 {{declared private here}}
-    static const I x = 0;
+    static const I x = 0; // expected-note {{implicitly declared private here}}
     friend I f(I i);
     template<typename T> friend I g(I i);
   };
 
-  // FIXME: This should be on line 264.
-  const A::I A::x; // expected-note {{declared private here}}
+  const A::I A::x;
   A::I f(A::I i = A::x) {}
   template<typename T> A::I g(A::I i) {
     T t;
index 92b41b030d1bc112a39e822427008c4c6693df05..565fcefe65a60bb9b34599d46905216213e640ea 100644 (file)
@@ -201,7 +201,7 @@ namespace test4 {
 // Implicit copy assignment operator uses.
 namespace test5 {
   class A {
-    void operator=(const A &); // expected-note 2 {{declared private here}}
+    void operator=(const A &); // expected-note 2 {{implicitly declared private here}}
   };
 
   class Test1 { A a; }; // expected-error {{private member}}
@@ -458,3 +458,33 @@ namespace test19 {
   // testing PR7281, earlier in this file.
   void b(A* x) { throw x; }
 }
+
+// PR7930
+namespace test20 {
+  class Foo {
+    Foo(); // expected-note {{implicitly declared private here}}
+  };
+  Foo::Foo() {}
+
+  void test() {
+    Foo a; // expected-error {{calling a private constructor}}
+  }
+}
+
+namespace test21 {
+  template <class T> class A {
+    void foo();
+    void bar();
+    class Inner; // expected-note {{implicitly declared private here}}
+  public:
+    void baz();
+  };
+  template <class T> class A<T>::Inner {};
+  class B {
+    template <class T> class A<T>::Inner;
+  };
+
+  void test() {
+    A<int>::Inner i; // expected-error {{'Inner' is a private member}}
+  }
+}