summaryrefslogtreecommitdiffstats
path: root/test/CXX/class.access/p4.cpp
blob: 15b336a4d8e6a031edded2ffa813b131f39e1b27 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// RUN: %clang_cc1 -fsyntax-only -faccess-control -verify %s

// C++0x [class.access]p4:

//   Access control is applied uniformly to all names, whether the
//   names are referred to from declarations or expressions.  In the
//   case of overloaded function names, access control is applied to
//   the function selected by overload resolution.

class Public {} PublicInst;
class Protected {} ProtectedInst;
class Private {} PrivateInst;

namespace test0 {
  class A {
  public:
    void foo(Public&);
  protected:
    void foo(Protected&); // expected-note 2 {{declared protected here}}
  private:
    void foo(Private&); // expected-note 2 {{declared private here}}
  };

  void test(A *op) {
    op->foo(PublicInst);
    op->foo(ProtectedInst); // expected-error {{'foo' is a protected member}}
    op->foo(PrivateInst); // expected-error {{'foo' is a private member}}

    void (A::*a)(Public&) = &A::foo;
    void (A::*b)(Protected&) = &A::foo; // expected-error {{'foo' is a protected member}}
    void (A::*c)(Private&) = &A::foo; // expected-error {{'foo' is a private member}}
  }
}

// Member operators.
namespace test1 {
  class A {
  public:
    void operator+(Public&);
    void operator[](Public&);
    void operator()(Public&);
    typedef void (*PublicSurrogate)(Public&);
    operator PublicSurrogate() const;
  protected:
    void operator+(Protected&); // expected-note {{declared protected here}}
    void operator[](Protected&); // expected-note {{declared protected here}}
    void operator()(Protected&); // expected-note {{declared protected here}}
    typedef void (*ProtectedSurrogate)(Protected&);
    operator ProtectedSurrogate() const; // expected-note {{declared protected here}}
  private:
    void operator+(Private&); // expected-note {{declared private here}}
    void operator[](Private&); // expected-note {{declared private here}}
    void operator()(Private&); // expected-note {{declared private here}}
    void operator-(); // expected-note {{declared private here}}
    typedef void (*PrivateSurrogate)(Private&);
    operator PrivateSurrogate() const; // expected-note {{declared private here}}
  };
  void operator+(const A &, Public&);
  void operator+(const A &, Protected&);
  void operator+(const A &, Private&);
  void operator-(const A &);

  void test(A &a, Public &pub, Protected &prot, Private &priv) {
    a + pub;
    a + prot; // expected-error {{'operator+' is a protected member}}
    a + priv; // expected-error {{'operator+' is a private member}}
    a[pub];
    a[prot]; // expected-error {{'operator[]' is a protected member}}
    a[priv]; // expected-error {{'operator[]' is a private member}}
    a(pub);
    a(prot); // expected-error {{'operator()' is a protected member}}
    a(priv); // expected-error {{'operator()' is a private member}}
    -a;       // expected-error {{'operator-' is a private member}}

    const A &ca = a;
    ca + pub;
    ca + prot;
    ca + priv;
    -ca;
    // These are all surrogate calls
    ca(pub);
    ca(prot); // expected-error {{'operator void (*)(class Protected &)' is a protected member}}
    ca(priv); // expected-error {{'operator void (*)(class Private &)' is a private member}}
  }
}

// Implicit constructor calls.
namespace test2 {
  class A {
  private:
    A(); // expected-note {{declared private here}}

    static A foo;
  };

  A a; // expected-error {{calling a private constructor}}
  A A::foo; // okay
}

// Implicit destructor calls.
namespace test3 {
  class A {
  private:
    ~A(); // expected-note 3 {{declared private here}}
    static A foo;
  };

  A a; // expected-error {{variable of type 'test3::A' has private destructor}}
  A A::foo;

  void foo(A param) { // expected-error {{variable of type 'test3::A' has private destructor}}
    A local; // expected-error {{variable of type 'test3::A' has private destructor}}
  }

  template <unsigned N> class Base { ~Base(); }; // expected-note 8 {{declared private here}}
  class Base2 : virtual Base<2> { ~Base2(); }; // expected-note 2 {{declared private here}}
  class Base3 : virtual Base<3> { public: ~Base3(); };

  // These don't cause diagnostics because we don't need the destructor.
  class Derived0 : Base<0> { ~Derived0(); };
  class Derived1 : Base<1> { };

  class Derived2 : // expected-error {{inherited virtual base class 'Base<2>' has private destructor}} \
                   // expected-error {{inherited virtual base class 'Base<3>' has private destructor}}
    Base<0>,  // expected-error {{base class 'Base<0>' has private destructor}}
    virtual Base<1>, // expected-error {{base class 'Base<1>' has private destructor}}
    Base2, // expected-error {{base class 'test3::Base2' has private destructor}}
    virtual Base3
  {
    ~Derived2() {}
  };

  class Derived3 : // expected-error {{inherited virtual base class 'Base<2>' has private destructor}} \
                   // expected-error {{inherited virtual base class 'Base<3>' has private destructor}}
    Base<0>,  // expected-error {{base class 'Base<0>' has private destructor}}
    virtual Base<1>, // expected-error {{base class 'Base<1>' has private destructor}}
    Base2, // expected-error {{base class 'test3::Base2' has private destructor}}
    virtual Base3
  {};
  Derived3 d3;
}

// Conversion functions.
namespace test4 {
  class Base {
  private:
    operator Private(); // expected-note 4 {{declared private here}}
  public:
    operator Public();
  };

  class Derived1 : private Base { // expected-note 2 {{declared private here}} \
                                  // expected-note {{constrained by private inheritance}}
    Private test1() { return *this; } // expected-error {{'operator Private' is a private member}}
    Public test2() { return *this; }
  };
  Private test1(Derived1 &d) { return d; } // expected-error {{'operator Private' is a private member}} \
                                           // expected-error {{cannot cast 'test4::Derived1' to its private base class}}
  Public test2(Derived1 &d) { return d; } // expected-error {{cannot cast 'test4::Derived1' to its private base class}} \
                                          // expected-error {{'operator Public' is a private member}}


  class Derived2 : public Base {
    Private test1() { return *this; } // expected-error {{'operator Private' is a private member}}
    Public test2() { return *this; }
  };
  Private test1(Derived2 &d) { return d; } // expected-error {{'operator Private' is a private member}}
  Public test2(Derived2 &d) { return d; }

  class Derived3 : private Base { // expected-note {{constrained by private inheritance here}} \
                                  // expected-note {{declared private here}}
  public:
    operator Private();
  };
  Private test1(Derived3 &d) { return d; }
  Public test2(Derived3 &d) { return d; } // expected-error {{'operator Public' is a private member of 'test4::Base'}} \
                                          // expected-error {{cannot cast 'test4::Derived3' to its private base class}}

  class Derived4 : public Base {
  public:
    operator Private();
  };
  Private test1(Derived4 &d) { return d; }
  Public test2(Derived4 &d) { return d; }
}

// Implicit copy assignment operator uses.
namespace test5 {
  class A {
    void operator=(const A &); // expected-note 2 {{declared private here}}
  };

  class Test1 { A a; }; // expected-error {{field of type 'test5::A' has private copy assignment operator}}
  void test1() {
    Test1 a;
    a = Test1();
  }

  class Test2 : A {}; // expected-error {{base class 'test5::A' has private copy assignment operator}}
  void test2() {
    Test2 a;
    a = Test2();
  }
}

// Implicit copy constructor uses.
namespace test6 {
  class A {
    public: A();
    private: A(const A &); // expected-note 2 {{declared private here}}
  };

  class Test1 { A a; }; // expected-error {{field of type 'test6::A' has private copy constructor}}
  void test1(const Test1 &t) {
    Test1 a = t;
  }

  class Test2 : A {}; // expected-error {{base class 'test6::A' has private copy constructor}}
  void test2(const Test2 &t) {
    Test2 a = t;
  }
}
OpenPOWER on IntegriCloud