1 // RUN: %clang_cc1 -std=c++1z -verify %s 2 3 struct A { 4 A() {} 5 A(int) : A() {} // ok 6 7 virtual void f() = 0; // expected-note 1+{{unimplemented}} 8 }; 9 10 template<typename> struct SecretlyAbstract { 11 SecretlyAbstract(); 12 SecretlyAbstract(int); 13 virtual void f() = 0; // expected-note 1+{{unimplemented}} 14 }; 15 using B = SecretlyAbstract<int>; 16 using C = SecretlyAbstract<float>; 17 using D = SecretlyAbstract<char>[1]; 18 19 B b; // expected-error {{abstract class}} 20 D d; // expected-error {{abstract class}} 21 22 template<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 37 void f(A&); 38 void f(A); // expected-error {{abstract class}} 39 void f(A[1]); // expected-error {{abstract class}} 40 void f(B); // expected-error {{abstract class}} 41 void f(B[1]); // expected-error {{abstract class}} 42 void f(C); 43 void f(C[1]); 44 void f(D); // expected-error {{abstract class}} 45 void f(D[1]); // expected-error {{abstract class}} 46 47 // - as a function return type 48 A &f(N<0>); 49 A *f(N<1>); 50 A f(N<2>); // expected-error {{abstract class}} 51 A (&f(N<3>))[2]; // expected-error {{abstract class}} 52 B f(N<4>); // expected-error {{abstract class}} 53 B (&f(N<5>))[2]; // expected-error {{abstract class}} 54 C f(N<6>); 55 C (&f(N<7>))[2]; 56 57 // - as the type of an explicit conversion 58 void g(A&&); 59 void 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 75 template<typename T> void t(T); // expected-note 2{{abstract class}} 76 void 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 86 struct E : A { 87 E() : A() {} // ok 88 E(int n) : A( A(n) ) {} // expected-error {{abstract class}} 89 }; 90 91 namespace std { 92 template<typename T> struct initializer_list { 93 const T *begin, *end; 94 initializer_list(); 95 }; 96 } 97 std::initializer_list<A> ila = {1, 2, 3, 4}; // expected-error {{abstract class}} 98