diff options
author | John McCall <rjmccall@apple.com> | 2010-10-20 08:15:06 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-10-20 08:15:06 +0000 |
commit | aa56a66abb61e9f42b48ae88e43328aba10c9148 (patch) | |
tree | c1f6c01f26ef2a78c70244b260bb5bdc28e401de | |
parent | 6b40195e035e4b76705126ef53bad446153dd3f8 (diff) |
Access control polish: drop the note on the original declaration and
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
-rw-r--r-- | lib/Sema/SemaAccess.cpp | 44 | ||||
-rw-r--r-- | test/CXX/class.access/class.friend/p1.cpp | 5 | ||||
-rw-r--r-- | test/CXX/class.access/p4.cpp | 32 |
3 files changed, 76 insertions, 5 deletions
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index c3a1e75210..2a150d7c03 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -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; } diff --git a/test/CXX/class.access/class.friend/p1.cpp b/test/CXX/class.access/class.friend/p1.cpp index 277b70bee6..761643b7d7 100644 --- a/test/CXX/class.access/class.friend/p1.cpp +++ b/test/CXX/class.access/class.friend/p1.cpp @@ -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; diff --git a/test/CXX/class.access/p4.cpp b/test/CXX/class.access/p4.cpp index 92b41b030d..565fcefe65 100644 --- a/test/CXX/class.access/p4.cpp +++ b/test/CXX/class.access/p4.cpp @@ -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}} + } +} |