Clang Project

clang_source_code/test/CXX/class.derived/class.abstract/p3.cpp
1// RUN: %clang_cc1 -std=c++1z -verify %s
2
3struct A {
4  A() {}
5  A(int) : A() {} // ok
6
7  virtual void f() = 0; // expected-note 1+{{unimplemented}}
8};
9
10template<typename> struct SecretlyAbstract {
11  SecretlyAbstract();
12  SecretlyAbstract(int);
13  virtual void f() = 0; // expected-note 1+{{unimplemented}}
14};
15using B = SecretlyAbstract<int>;
16using C = SecretlyAbstract<float>;
17using D = SecretlyAbstract<char>[1];
18
19B b; // expected-error {{abstract class}}
20D d; // expected-error {{abstract class}}
21
22template<int> struct N;
23
24// Note: C is not instantiated anywhere in this file, so we never discover that
25// it is in fact abstract. The C++ standard suggests that we need to
26// instantiate in all cases where abstractness could affect the validity of a
27// program, but that breaks a *lot* of code, so we don't do that.
28//
29// FIXME: Once DR1640 is resolved, remove the check on forming an abstract
30// array type entirely. The only restriction we need is that you can't create
31// an object of abstract (most-derived) type.
32
33
34// An abstract class shall not be used
35
36//  - as a parameter type
37void f(A&);
38void f(A); // expected-error {{abstract class}}
39void f(A[1]); // expected-error {{abstract class}}
40void f(B); // expected-error {{abstract class}}
41void f(B[1]); // expected-error {{abstract class}}
42void f(C);
43void f(C[1]);
44void f(D); // expected-error {{abstract class}}
45void f(D[1]); // expected-error {{abstract class}}
46
47//  - as a function return type
48A &f(N<0>);
49A *f(N<1>);
50A f(N<2>); // expected-error {{abstract class}}
51A (&f(N<3>))[2]; // expected-error {{abstract class}}
52B f(N<4>); // expected-error {{abstract class}}
53B (&f(N<5>))[2]; // expected-error {{abstract class}}
54C f(N<6>);
55C (&f(N<7>))[2];
56
57//  - as the type of an explicit conversion
58void g(A&&);
59void h() {
60  A(); // expected-error {{abstract class}}
61  A(0); // expected-error {{abstract class}}
62  A{}; // expected-error {{abstract class}}
63  A{0}; // expected-error {{abstract class}}
64  (A)(0); // expected-error {{abstract class}}
65  (A){}; // expected-error {{abstract class}}
66  (A){0}; // expected-error {{abstract class}}
67
68  D(); // expected-error {{array type}}
69  D{}; // expected-error {{abstract class}}
70  D{0}; // expected-error {{abstract class}}
71  (D){}; // expected-error {{abstract class}}
72  (D){0}; // expected-error {{abstract class}}
73}
74
75template<typename T> void t(T); // expected-note 2{{abstract class}}
76void i(A &a, B &b, C &c, D &d) {
77  // FIXME: These should be handled consistently. We currently reject the first
78  // two early because we (probably incorrectly, depending on dr1640) take
79  // abstractness into account in forming implicit conversion sequences.
80  t(a); // expected-error {{no matching function}}
81  t(b); // expected-error {{no matching function}}
82  t(c); // expected-error {{allocating an object of abstract class type}}
83  t(d); // ok, decays to pointer
84}
85
86struct E : A {
87  E() : A() {} // ok
88  E(int n) : A( A(n) ) {} // expected-error {{abstract class}}
89};
90
91namespace std {
92  template<typename T> struct initializer_list {
93    const T *begin, *end;
94    initializer_list();
95  };
96}
97std::initializer_list<A> ila = {1, 2, 3, 4}; // expected-error {{abstract class}}
98