p6.cpp revision b5c7768a74936d4e2c7a484570a638cb74702d8b
1// RUN: %clang_cc1 -fsyntax-only -verify %s
2
3// C++0x [class.access]p6:
4//   All access controls in [class.access] affect the ability to
5//   access a class member name from a particular scope. For purposes
6//   of access control, the base-specifiers of a class and the
7//   definitions of class members that appear outside of the class
8//   definition are considered to be within the scope of that
9//   class. In particular, access controls apply as usual to member
10//   names accessed as part of a function return type, even though it
11//   is not possible to determine the access privileges of that use
12//   without first parsing the rest of the function
13//   declarator. Similarly, access control for implicit calls to the
14//   constructors, the conversion functions, or the destructor called
15//   to create and destroy a static data member is performed as if
16//   these calls appeared in the scope of the member's class.
17
18struct Public {}; struct Protected {}; struct Private {};
19
20namespace test0 {
21  class A {
22    typedef int type; // expected-note {{declared private here}}
23    type foo();
24  };
25
26  A::type foo() { } // expected-error {{'type' is a private member}}
27  A::type A::foo() { }
28}
29
30// conversion decls
31namespace test1 {
32  class A {
33  public:
34    A();
35    operator Public ();
36    A(Public);
37  protected:
38    operator Protected (); // expected-note {{declared protected here}}
39    A(Protected); // expected-note {{declared protected here}}
40  private:
41    operator Private (); // expected-note {{declared private here}}
42    A(Private); // expected-note {{declared private here}}
43  };
44
45  void test() {
46    A a;
47    Public pub = a;
48    Protected prot = a; // expected-error {{'operator Protected' is a protected member}}
49    Private priv = a; // expected-error {{'operator Private' is a private member}}
50    A apub = pub;
51    A aprot = prot; // expected-error {{protected constructor}}
52    A apriv = priv; // expected-error {{private constructor}}
53  }
54}
55
56// PR6967
57namespace test2 {
58  class A {
59  public:
60    template <class T> static void set(T &t, typename T::type v) {
61      t.value = v;
62    }
63    template <class T> static typename T::type get(const T &t) {
64      return t.value;
65    }
66  };
67
68  class B {
69    friend class A;
70
71  private:
72    typedef int type;
73    type value;
74  };
75
76  int test() {
77    B b;
78    A::set(b, 0);
79    return A::get(b);
80  }
81}
82
83namespace test3 {
84  class Green {}; class Blue {};
85
86  // We have to wrap this in a class because a partial specialization
87  // isn't actually in the context of the template.
88  struct Outer {
89    template <class T, class Nat> class A {
90    };
91  };
92
93  template <class T> class Outer::A<T, typename T::nature> {
94  public:
95    static void foo(); // expected-note {{'Outer::A<B, Green>::foo' declared here}}
96  };
97
98  class B {
99  private: typedef Green nature;
100    friend class Outer;
101  };
102
103  void test() {
104    Outer::A<B, Green>::foo();
105    Outer::A<B, Blue>::foo(); // expected-error {{no member named 'foo' in 'test3::Outer::A<test3::B, test3::Blue>'; did you mean 'Outer::A<B, Green>::foo'?}}
106  }
107}
108
109namespace test4 {
110  template <class T> class A {
111  private: typedef int type;
112    template <class U> friend void foo(U &, typename U::type);
113  };
114
115  template <class U> void foo(U &, typename U::type) {}
116
117  void test() {
118    A<int> a;
119    foo(a, 0);
120  }
121}
122
123// PR7644
124namespace test5 {
125  class A {
126    enum Enum { E0, E1, E2 }; // expected-note 4 {{declared private here}}
127    template <Enum> void foo();
128    template <Enum> class bar;
129  };
130
131  template <A::Enum en> void A::foo() {}
132  template <A::Enum en> class A::bar {};
133
134  template <A::Enum en> void foo() {} // expected-error {{'Enum' is a private member of 'test5::A'}}
135  template <A::Enum en> class bar {}; // expected-error {{'Enum' is a private member of 'test5::A'}}
136
137  class B {
138    template <A::Enum en> void foo() {} // expected-error {{'Enum' is a private member of 'test5::A'}}
139    template <A::Enum en> class bar {}; // expected-error {{'Enum' is a private member of 'test5::A'}}
140  };
141}
142
143namespace test6 {
144  class A {
145  public: class public_inner {};
146  protected: class protected_inner {};
147  private: class private_inner {}; // expected-note {{declared private here}}
148  };
149
150  class B : A {
151    public_inner a;
152    protected_inner b;
153    private_inner c; // expected-error {{'private_inner' is a private member of 'test6::A'}}
154  };
155}
156
157// PR9229
158namespace test7 {
159  void foo(int arg[1]);
160  class A {
161    void check();
162  };
163  class B {
164    friend class A;
165    A ins;
166  };
167  void A::check() {
168    void foo(int arg[__builtin_offsetof(B, ins)]);
169  }
170}
171
172// rdar://problem/10155256
173namespace test8 {
174  class A {
175    typedef void* (A::*UnspecifiedBoolType)() const;
176    operator UnspecifiedBoolType() const; // expected-note {{implicitly declared private here}}
177  };
178
179  void test(A &a) {
180    if (a) return; // expected-error {{'operator void *(class test8::A::*)(void) const' is a private member of 'test8::A'}}
181  }
182}
183
184namespace test9 {
185  class A {
186    operator char*() const; // expected-note {{implicitly declared private here}}
187  };
188
189  void test(A &a) {
190    delete a; // expected-error {{'operator char *' is a private member of 'test9::A'}}
191  }
192}
193