| // RUN: %clang_cc1 -fsyntax-only -verify %s |
| |
| // C++0x [class.access]p6: |
| // All access controls in [class.access] affect the ability to |
| // access a class member name from a particular scope. For purposes |
| // of access control, the base-specifiers of a class and the |
| // definitions of class members that appear outside of the class |
| // definition are considered to be within the scope of that |
| // class. In particular, access controls apply as usual to member |
| // names accessed as part of a function return type, even though it |
| // is not possible to determine the access privileges of that use |
| // without first parsing the rest of the function |
| // declarator. Similarly, access control for implicit calls to the |
| // constructors, the conversion functions, or the destructor called |
| // to create and destroy a static data member is performed as if |
| // these calls appeared in the scope of the member's class. |
| |
| struct Public {}; struct Protected {}; struct Private {}; |
| |
| namespace test0 { |
| class A { |
| typedef int type; // expected-note {{declared private here}} |
| type foo(); |
| }; |
| |
| A::type foo() { } // expected-error {{'type' is a private member}} |
| A::type A::foo() { } |
| } |
| |
| // conversion decls |
| namespace test1 { |
| class A { |
| public: |
| A(); |
| operator Public (); |
| A(Public); |
| protected: |
| operator Protected (); // expected-note {{declared protected here}} |
| A(Protected); // expected-note {{declared protected here}} |
| private: |
| operator Private (); // expected-note {{declared private here}} |
| A(Private); // expected-note {{declared private here}} |
| }; |
| |
| void test() { |
| A a; |
| Public pub = a; |
| Protected prot = a; // expected-error {{'operator Protected' is a protected member}} |
| Private priv = a; // expected-error {{'operator Private' is a private member}} |
| A apub = pub; |
| A aprot = prot; // expected-error {{protected constructor}} |
| A apriv = priv; // expected-error {{private constructor}} |
| } |
| } |
| |
| // PR6967 |
| namespace test2 { |
| class A { |
| public: |
| template <class T> static void set(T &t, typename T::type v) { |
| t.value = v; |
| } |
| template <class T> static typename T::type get(const T &t) { |
| return t.value; |
| } |
| }; |
| |
| class B { |
| friend class A; |
| |
| private: |
| typedef int type; |
| type value; |
| }; |
| |
| int test() { |
| B b; |
| A::set(b, 0); |
| return A::get(b); |
| } |
| } |
| |
| namespace test3 { |
| class Green {}; class Blue {}; |
| |
| // We have to wrap this in a class because a partial specialization |
| // isn't actually in the context of the template. |
| struct Outer { |
| template <class T, class Nat> class A { |
| }; |
| }; |
| |
| template <class T> class Outer::A<T, typename T::nature> { |
| public: |
| static void foo(); |
| }; |
| |
| class B { |
| private: typedef Green nature; |
| friend class Outer; |
| }; |
| |
| void test() { |
| Outer::A<B, Green>::foo(); |
| Outer::A<B, Blue>::foo(); // expected-error {{no member named 'foo'}} |
| } |
| } |
| |
| namespace test4 { |
| template <class T> class A { |
| private: typedef int type; |
| template <class U> friend void foo(U &, typename U::type); |
| }; |
| |
| template <class U> void foo(U &, typename U::type) {} |
| |
| void test() { |
| A<int> a; |
| foo(a, 0); |
| } |
| } |
| |
| // PR7644 |
| namespace test5 { |
| class A { |
| enum Enum { E0, E1, E2 }; // expected-note 4 {{declared private here}} |
| template <Enum> void foo(); |
| template <Enum> class bar; |
| }; |
| |
| template <A::Enum en> void A::foo() {} |
| template <A::Enum en> class A::bar {}; |
| |
| template <A::Enum en> void foo() {} // expected-error {{'Enum' is a private member of 'test5::A'}} |
| template <A::Enum en> class bar {}; // expected-error {{'Enum' is a private member of 'test5::A'}} |
| |
| class B { |
| template <A::Enum en> void foo() {} // expected-error {{'Enum' is a private member of 'test5::A'}} |
| template <A::Enum en> class bar {}; // expected-error {{'Enum' is a private member of 'test5::A'}} |
| }; |
| } |
| |
| namespace test6 { |
| class A { |
| public: class public_inner {}; |
| protected: class protected_inner {}; |
| private: class private_inner {}; // expected-note {{declared private here}} |
| }; |
| |
| class B : A { |
| public_inner a; |
| protected_inner b; |
| private_inner c; // expected-error {{'private_inner' is a private member of 'test6::A'}} |
| }; |
| } |
| |
| // PR9229 |
| namespace test7 { |
| void foo(int arg[1]); |
| class A { |
| void check(); |
| }; |
| class B { |
| friend class A; |
| A ins; |
| }; |
| void A::check() { |
| void foo(int arg[__builtin_offsetof(B, ins)]); |
| } |
| } |
| |
| // rdar://problem/10155256 |
| namespace test8 { |
| class A { |
| typedef void* (A::*UnspecifiedBoolType)() const; |
| operator UnspecifiedBoolType() const; // expected-note {{implicitly declared private here}} |
| }; |
| |
| void test(A &a) { |
| if (a) return; // expected-error {{'operator void *(class test8::A::*)(void) const' is a private member of 'test8::A'}} |
| } |
| } |
| |
| namespace test9 { |
| class A { |
| operator char*() const; // expected-note {{implicitly declared private here}} |
| }; |
| |
| void test(A &a) { |
| delete a; // expected-error {{'operator char *' is a private member of 'test9::A'}} |
| } |
| } |