summaryrefslogtreecommitdiff
path: root/clang/test/CXX/class.access/p4.cpp
blob: 5ad738bebf9cc384ed45a84566e1c1deed2bb630 (about) (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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -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 3 {{declared private here}}

    static A foo;
  };

  A a; // expected-error {{calling a private constructor}}
  A A::foo; // okay
  
  class B : A { }; // expected-error {{base class 'test2::A' has private default constructor}}
  B b; // expected-note{{implicit default constructor}}
  
  class C : virtual A { 
  public:
    C();
  };

  class D : C { }; // expected-error {{inherited virtual base class 'test2::A' has private default constructor}}
  D d; // expected-note{{implicit default constructor}}
}

// Implicit destructor calls.
namespace test3 {
  class A {
  private:
    ~A(); // expected-note 2 {{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) { // okay
    A local; // expected-error {{variable of type 'test3::A' has private destructor}}
  }

  template <unsigned N> class Base { ~Base(); }; // expected-note 14 {{declared private here}}
  class Base2 : virtual Base<2> { ~Base2(); }; // expected-note 3 {{declared private here}} \
                                               // expected-error {{base class 'Base<2>' has private destructor}}
  class Base3 : virtual Base<3> { public: ~Base3(); }; // expected-error {{base class 'Base<3>' has private destructor}}

  // 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 2 {{inherited virtual base class 'Base<2>' has private destructor}} \
                   // expected-error 2 {{inherited virtual base class 'Base<3>' has private destructor}} \
    // expected-note 2{{implicit default constructor}}
    Base<0>,  // expected-error 2 {{base class 'Base<0>' has private destructor}}
    virtual Base<1>, // expected-error 2 {{base class 'Base<1>' has private destructor}}
    Base2, // expected-error 2 {{base class 'test3::Base2' has private destructor}}
    virtual Base3
  {}; 
  Derived3 d3; // expected-note {{implicit default constructor}}\
               // expected-note{{implicit default destructor}}}
}

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

  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 {{implicitly declared private here}}
  };

  class Test1 { A a; }; // expected-error {{private member}}
  void test1() {
    Test1 a; 
    a = Test1(); // expected-note{{implicit default copy}}
  }

  class Test2 : A {}; // expected-error {{private member}}
  void test2() {
    Test2 a;
    a = Test2(); // expected-note{{implicit default copy}}
  }
}

// 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; // expected-note{{implicit default copy}}
  }

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

// Redeclaration lookups are not accesses.
namespace test7 {
  class A {
    int private_member;
  };
  class B : A {
    int foo(int private_member) {
      return 0;
    }
  };
}

// Ignored operator new and delete overloads are not 
namespace test8 {
  typedef __typeof__(sizeof(int)) size_t;

  class A {
    void *operator new(size_t s);
    void operator delete(void *p);
  public:
    void *operator new(size_t s, int n);
    void operator delete(void *p, int n);
  };

  void test() {
    new (2) A();
  }
}

// Don't silently upgrade forbidden-access paths to private.
namespace test9 {
  class A {
  public: static int x; // expected-note {{member is declared here}}
  };
  class B : private A { // expected-note {{constrained by private inheritance here}}
  };
  class C : public B {
    static int getX() { return x; } // expected-error {{'x' is a private member of 'test9::A'}}
  };
}

namespace test10 {
  class A {
    enum {
      value = 10 // expected-note {{declared private here}}
    };
    friend class C;
  };

  class B {
    enum {
      value = A::value // expected-error {{'value' is a private member of 'test10::A'}}
    };
  };

  class C {
    enum {
      value = A::value
    };
  };
}

namespace test11 {
  class A {
    protected: virtual ~A();
  };

  class B : public A {
    ~B();
  };

  B::~B() {};
}

namespace test12 {
  class A {
    int x;

    void foo() {
      class Local {
        int foo(A *a) {
          return a->x;
        }
      };
    }
  };
}

namespace test13 {
  struct A {
    int x;
    unsigned foo() const;
  };

  struct B : protected A {
    using A::foo;
    using A::x;
  };

  void test() {
    A *d;
    d->foo();
    (void) d->x;
  }
}

// Destructors for temporaries.
namespace test14 {
  class A {
  private: ~A(); // expected-note {{declared private here}}
  };
  A foo();

  void test() {
    foo(); // expected-error {{temporary of type 'test14::A' has private destructor}}
  }

  class X {
    ~X(); // expected-note {{declared private here}}
  };
  
  struct Y1 {
    operator X();
  };
  
  void g() {
    const X &xr = Y1(); // expected-error{{temporary of type 'test14::X' has private destructor}}
  }
}

// PR 7024
namespace test15 {
  template <class T> class A {
  private:
    int private_foo; // expected-note {{declared private here}}
    static int private_sfoo; // expected-note {{declared private here}}
  protected:
    int protected_foo; // expected-note 3 {{declared protected here}} // expected-note {{can only access this member on an object of type 'test15::B<int>'}}
    static int protected_sfoo; // expected-note 3 {{declared protected here}}

    int test1(A<int> &a) {
      return a.private_foo; // expected-error {{private member}}
    }

    int test2(A<int> &a) {
      return a.private_sfoo; // expected-error {{private member}}
    }

    int test3(A<int> &a) {
      return a.protected_foo; // expected-error {{protected member}}
    }

    int test4(A<int> &a) {
      return a.protected_sfoo; // expected-error {{protected member}}
    }
  };

  template class A<int>;
  template class A<long>; // expected-note 4 {{in instantiation}} 

  template <class T> class B : public A<T> {
    // TODO: These first two accesses can be detected as ill-formed at
    // definition time because they're member accesses and A<int> can't
    // be a subclass of B<T> for any T.

    int test1(A<int> &a) {
      return a.protected_foo; // expected-error 2 {{protected member}}
    }

    int test2(A<int> &a) {
      return a.protected_sfoo; // expected-error {{protected member}}
    }

    int test3(B<int> &b) {
      return b.protected_foo; // expected-error {{protected member}}
    }

    int test4(B<int> &b) {
      return b.protected_sfoo; // expected-error {{protected member}}
    }
  };

  template class B<int>;  // expected-note {{in instantiation}}
  template class B<long>; // expected-note 4 {{in instantiation}}
}

// PR7281
namespace test16 {
  class A { ~A(); }; // expected-note 2{{declared private here}}
  void b() { throw A(); } // expected-error{{temporary of type 'test16::A' has private destructor}} \
  // expected-error{{exception object of type 'test16::A' has private destructor}}
}

// rdar://problem/8146294
namespace test17 {
  class A {
    template <typename T> class Inner { }; // expected-note {{declared private here}}
  };

  A::Inner<int> s; // expected-error {{'Inner' is a private member of 'test17::A'}}
}

namespace test18 {
  template <class T> class A {};
  class B : A<int> {
    A<int> member;
  };

  // FIXME: this access to A should be forbidden (because C++ is dumb),
  // but LookupResult can't express the necessary information to do
  // the check, so we aggressively suppress access control.
  class C : B {
    A<int> member;
  };
}

// PR8325
namespace test19 {
  class A { ~A(); };
  // The destructor is not implicitly referenced here.  Contrast to test16, 
  // 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; // expected-error{{non-friend class member 'Inner' cannot have a qualified name}}
  };

  void test() {
    A<int>::Inner i; // expected-error {{'Inner' is a private member}}
  }
}

namespace rdar8876150 {
  struct A { operator bool(); };
  struct B : private A { using A::operator bool; };

  bool f() {
    B b;
    return !b;
  }
}

namespace test23 {
  template <typename T> class A {
    A();
    static A instance;
  };

  template <typename T> A<T> A<T>::instance;
  template class A<int>;
}