2013-07-22 10:56:56 +08:00
|
|
|
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wabstract-vbase-init
|
2009-03-22 09:52:17 +08:00
|
|
|
|
|
|
|
#ifndef __GXX_EXPERIMENTAL_CXX0X__
|
|
|
|
#define __CONCAT(__X, __Y) __CONCAT1(__X, __Y)
|
|
|
|
#define __CONCAT1(__X, __Y) __X ## __Y
|
|
|
|
|
|
|
|
#define static_assert(__b, __m) \
|
|
|
|
typedef int __CONCAT(__sa, __LINE__)[__b ? 1 : -1]
|
|
|
|
#endif
|
|
|
|
|
2015-11-16 14:58:51 +08:00
|
|
|
union IncompleteUnion;
|
|
|
|
|
|
|
|
static_assert(!__is_abstract(IncompleteUnion), "unions are never abstract");
|
|
|
|
|
2009-03-22 09:52:17 +08:00
|
|
|
class C {
|
2011-02-19 07:59:51 +08:00
|
|
|
virtual void f() = 0; // expected-note {{unimplemented pure virtual method 'f'}}
|
2009-03-22 09:52:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static_assert(__is_abstract(C), "C has a pure virtual function");
|
|
|
|
|
|
|
|
class D : C {
|
|
|
|
};
|
|
|
|
|
|
|
|
static_assert(__is_abstract(D), "D inherits from an abstract class");
|
|
|
|
|
|
|
|
class E : D {
|
2009-09-09 23:08:12 +08:00
|
|
|
virtual void f();
|
2009-03-22 09:52:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static_assert(!__is_abstract(E), "E inherits from an abstract class but implements f");
|
2009-03-23 04:18:17 +08:00
|
|
|
|
2011-02-19 08:12:23 +08:00
|
|
|
C *d = new C; // expected-error {{allocating an object of abstract class type 'C'}}
|
2009-03-24 01:49:10 +08:00
|
|
|
|
2009-03-23 04:18:17 +08:00
|
|
|
C c; // expected-error {{variable type 'C' is an abstract class}}
|
|
|
|
void t1(C c); // expected-error {{parameter type 'C' is an abstract class}}
|
|
|
|
void t2(C); // expected-error {{parameter type 'C' is an abstract class}}
|
|
|
|
|
|
|
|
struct S {
|
|
|
|
C c; // expected-error {{field type 'C' is an abstract class}}
|
|
|
|
};
|
2009-03-24 01:49:10 +08:00
|
|
|
|
2009-03-24 03:10:31 +08:00
|
|
|
void t3(const C&);
|
|
|
|
|
|
|
|
void f() {
|
2011-02-19 08:12:23 +08:00
|
|
|
C(); // expected-error {{allocating an object of abstract class type 'C'}}
|
|
|
|
t3(C()); // expected-error {{allocating an object of abstract class type 'C'}}
|
2009-03-24 03:10:31 +08:00
|
|
|
}
|
|
|
|
|
2010-04-28 03:38:14 +08:00
|
|
|
C e1[2]; // expected-error {{array of abstract class type 'C'}}
|
|
|
|
C (*e2)[2]; // expected-error {{array of abstract class type 'C'}}
|
|
|
|
C (**e3)[2]; // expected-error {{array of abstract class type 'C'}}
|
2009-03-24 03:10:31 +08:00
|
|
|
|
2010-04-28 03:38:14 +08:00
|
|
|
void t4(C c[2]); // expected-error {{array of abstract class type 'C'}}
|
2009-03-24 03:10:31 +08:00
|
|
|
|
|
|
|
void t5(void (*)(C)); // expected-error {{parameter type 'C' is an abstract class}}
|
|
|
|
|
|
|
|
typedef void (*Func)(C); // expected-error {{parameter type 'C' is an abstract class}}
|
|
|
|
void t6(Func);
|
|
|
|
|
2009-03-24 09:19:16 +08:00
|
|
|
class F {
|
2009-09-09 23:08:12 +08:00
|
|
|
F a() { while (1) {} } // expected-error {{return type 'F' is an abstract class}}
|
2009-03-24 09:19:16 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
class D {
|
|
|
|
void f(F c); // expected-error {{parameter type 'F' is an abstract class}}
|
|
|
|
};
|
2009-03-24 09:19:16 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
union U {
|
|
|
|
void u(F c); // expected-error {{parameter type 'F' is an abstract class}}
|
|
|
|
};
|
2009-03-24 09:19:16 +08:00
|
|
|
|
2011-02-19 07:59:51 +08:00
|
|
|
virtual void f() = 0; // expected-note {{unimplemented pure virtual method 'f'}}
|
2009-03-24 09:19:16 +08:00
|
|
|
};
|
2009-03-25 01:23:42 +08:00
|
|
|
|
2010-08-18 17:41:07 +08:00
|
|
|
// Diagnosing in these cases is prohibitively expensive. We still
|
|
|
|
// diagnose at the function definition, of course.
|
|
|
|
|
2009-03-25 01:23:42 +08:00
|
|
|
class Abstract;
|
|
|
|
|
2010-08-18 17:41:07 +08:00
|
|
|
void t7(Abstract a);
|
2009-03-25 01:23:42 +08:00
|
|
|
|
|
|
|
void t8() {
|
2010-08-18 17:41:07 +08:00
|
|
|
void h(Abstract a);
|
2009-03-25 01:23:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace N {
|
2010-08-18 17:41:07 +08:00
|
|
|
void h(Abstract a);
|
2009-03-25 01:23:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
class Abstract {
|
2010-08-18 17:41:07 +08:00
|
|
|
virtual void f() = 0;
|
2009-03-25 01:23:42 +08:00
|
|
|
};
|
2009-05-17 08:00:05 +08:00
|
|
|
|
|
|
|
// <rdar://problem/6854087>
|
|
|
|
class foo {
|
|
|
|
public:
|
2009-09-09 23:08:12 +08:00
|
|
|
virtual foo *getFoo() = 0;
|
2009-05-17 08:00:05 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class bar : public foo {
|
|
|
|
public:
|
2009-09-09 23:08:12 +08:00
|
|
|
virtual bar *getFoo();
|
2009-05-17 08:00:05 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
bar x;
|
2009-05-30 08:52:53 +08:00
|
|
|
|
|
|
|
// <rdar://problem/6902298>
|
2009-09-09 23:08:12 +08:00
|
|
|
class A {
|
2009-05-30 08:52:53 +08:00
|
|
|
public:
|
2009-09-09 23:08:12 +08:00
|
|
|
virtual void release() = 0;
|
|
|
|
virtual void release(int count) = 0;
|
|
|
|
virtual void retain() = 0;
|
2009-05-30 08:52:53 +08:00
|
|
|
};
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
class B : public A {
|
2009-05-30 08:52:53 +08:00
|
|
|
public:
|
2009-09-09 23:08:12 +08:00
|
|
|
virtual void release();
|
|
|
|
virtual void release(int count);
|
|
|
|
virtual void retain();
|
2009-05-30 08:52:53 +08:00
|
|
|
};
|
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
void foo(void) {
|
|
|
|
B b;
|
2009-05-30 08:52:53 +08:00
|
|
|
}
|
|
|
|
|
2009-05-31 01:26:39 +08:00
|
|
|
struct K {
|
|
|
|
int f;
|
|
|
|
virtual ~K();
|
|
|
|
};
|
|
|
|
|
|
|
|
struct L : public K {
|
|
|
|
void f();
|
|
|
|
};
|
2009-10-19 03:34:08 +08:00
|
|
|
|
|
|
|
// PR5222
|
|
|
|
namespace PR5222 {
|
|
|
|
struct A {
|
|
|
|
virtual A *clone() = 0;
|
|
|
|
};
|
|
|
|
struct B : public A {
|
|
|
|
virtual B *clone() = 0;
|
|
|
|
};
|
|
|
|
struct C : public B {
|
|
|
|
virtual C *clone();
|
|
|
|
};
|
|
|
|
|
|
|
|
C c;
|
|
|
|
}
|
2009-11-19 05:51:29 +08:00
|
|
|
|
|
|
|
// PR5550 - instantiating template didn't track overridden methods
|
|
|
|
namespace PR5550 {
|
|
|
|
struct A {
|
|
|
|
virtual void a() = 0;
|
|
|
|
virtual void b() = 0;
|
|
|
|
};
|
|
|
|
template<typename T> struct B : public A {
|
|
|
|
virtual void b();
|
|
|
|
virtual void c() = 0;
|
|
|
|
};
|
|
|
|
struct C : public B<int> {
|
|
|
|
virtual void a();
|
|
|
|
virtual void c();
|
|
|
|
};
|
|
|
|
C x;
|
|
|
|
}
|
2009-12-17 04:00:27 +08:00
|
|
|
|
|
|
|
namespace PureImplicit {
|
|
|
|
// A pure virtual destructor should be implicitly overridden.
|
|
|
|
struct A { virtual ~A() = 0; };
|
|
|
|
struct B : A {};
|
|
|
|
B x;
|
|
|
|
|
|
|
|
// A pure virtual assignment operator should be implicitly overridden.
|
|
|
|
struct D;
|
|
|
|
struct C { virtual D& operator=(const D&) = 0; };
|
|
|
|
struct D : C {};
|
|
|
|
D y;
|
|
|
|
}
|
2010-06-16 17:33:39 +08:00
|
|
|
|
|
|
|
namespace test1 {
|
|
|
|
struct A {
|
|
|
|
virtual void foo() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct B : A {
|
|
|
|
using A::foo;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct C : B {
|
|
|
|
void foo();
|
|
|
|
};
|
|
|
|
|
|
|
|
void test() {
|
|
|
|
C c;
|
|
|
|
}
|
|
|
|
}
|
2010-08-18 17:41:07 +08:00
|
|
|
|
|
|
|
// rdar://problem/8302168
|
|
|
|
namespace test2 {
|
|
|
|
struct X1 {
|
2011-02-19 07:59:51 +08:00
|
|
|
virtual void xfunc(void) = 0; // expected-note {{unimplemented pure virtual method}}
|
2010-08-18 17:41:07 +08:00
|
|
|
void g(X1 parm7); // expected-error {{parameter type 'test2::X1' is an abstract class}}
|
|
|
|
void g(X1 parm8[2]); // expected-error {{array of abstract class type 'test2::X1'}}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <int N>
|
|
|
|
struct X2 {
|
2011-02-19 07:59:51 +08:00
|
|
|
virtual void xfunc(void) = 0; // expected-note {{unimplemented pure virtual method}}
|
2010-08-18 17:41:07 +08:00
|
|
|
void g(X2 parm10); // expected-error {{parameter type 'X2<N>' is an abstract class}}
|
|
|
|
void g(X2 parm11[2]); // expected-error {{array of abstract class type 'X2<N>'}}
|
|
|
|
};
|
|
|
|
}
|
2010-08-18 17:58:15 +08:00
|
|
|
|
|
|
|
namespace test3 {
|
|
|
|
struct A { // expected-note {{not complete until}}
|
|
|
|
A x; // expected-error {{field has incomplete type}}
|
|
|
|
virtual void abstract() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct B { // expected-note {{not complete until}}
|
|
|
|
virtual void abstract() = 0;
|
|
|
|
B x; // expected-error {{field has incomplete type}}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct C {
|
|
|
|
static C x; // expected-error {{abstract class}}
|
2011-02-19 07:59:51 +08:00
|
|
|
virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}}
|
2010-08-18 17:58:15 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct D {
|
2011-02-19 07:59:51 +08:00
|
|
|
virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}}
|
2010-08-18 17:58:15 +08:00
|
|
|
static D x; // expected-error {{abstract class}}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace test4 {
|
|
|
|
template <class T> struct A {
|
|
|
|
A x; // expected-error {{abstract class}}
|
2011-02-19 07:59:51 +08:00
|
|
|
virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}}
|
2010-08-18 17:58:15 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class T> struct B {
|
2011-02-19 07:59:51 +08:00
|
|
|
virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}}
|
2010-08-18 17:58:15 +08:00
|
|
|
B x; // expected-error {{abstract class}}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T> struct C {
|
|
|
|
static C x; // expected-error {{abstract class}}
|
2011-02-19 07:59:51 +08:00
|
|
|
virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}}
|
2010-08-18 17:58:15 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
template <class T> struct D {
|
2011-02-19 07:59:51 +08:00
|
|
|
virtual void abstract() = 0; // expected-note {{unimplemented pure virtual method}}
|
2010-08-18 17:58:15 +08:00
|
|
|
static D x; // expected-error {{abstract class}}
|
|
|
|
};
|
|
|
|
}
|
2011-02-23 07:21:06 +08:00
|
|
|
|
2013-07-21 03:41:36 +08:00
|
|
|
namespace test5 {
|
|
|
|
struct A { A(int); virtual ~A() = 0; }; // expected-note {{pure virtual method}}
|
|
|
|
const A &a = 0; // expected-error {{abstract class}}
|
|
|
|
void f(const A &a = 0); // expected-error {{abstract class}}
|
2020-06-03 01:42:36 +08:00
|
|
|
void g(const A &a);
|
|
|
|
void h() { g(0); } // expected-error {{abstract class}}
|
2013-07-21 03:41:36 +08:00
|
|
|
}
|
|
|
|
|
2011-02-23 07:21:06 +08:00
|
|
|
// PR9247: Crash on invalid in clang::Sema::ActOnFinishCXXMemberSpecification
|
|
|
|
namespace pr9247 {
|
|
|
|
struct A {
|
|
|
|
virtual void g(const A& input) = 0;
|
|
|
|
struct B {
|
|
|
|
C* f(int foo);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
2012-05-07 08:02:00 +08:00
|
|
|
|
|
|
|
namespace pr12658 {
|
2014-03-03 02:46:05 +08:00
|
|
|
class C {
|
|
|
|
public:
|
|
|
|
C(int v){}
|
|
|
|
virtual void f() = 0; // expected-note {{unimplemented pure virtual method 'f' in 'C'}}
|
|
|
|
};
|
|
|
|
|
2020-08-24 20:20:36 +08:00
|
|
|
void foo(const C& c ) {}
|
2014-03-03 02:46:05 +08:00
|
|
|
|
|
|
|
void bar( void ) {
|
|
|
|
foo(C(99)); // expected-error {{allocating an object of abstract class type 'pr12658::C'}}
|
2012-05-07 08:02:00 +08:00
|
|
|
}
|
|
|
|
}
|
2013-07-22 10:56:56 +08:00
|
|
|
|
|
|
|
namespace pr16659 {
|
|
|
|
struct A {
|
|
|
|
A(int);
|
|
|
|
virtual void x() = 0; // expected-note {{unimplemented pure virtual method 'x' in 'RedundantInit'}}
|
|
|
|
};
|
|
|
|
struct B : virtual A {};
|
|
|
|
struct C : B {
|
|
|
|
C() : A(37) {}
|
|
|
|
void x() override {}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct X {
|
|
|
|
friend class Z;
|
|
|
|
private:
|
|
|
|
X &operator=(const X&);
|
|
|
|
};
|
|
|
|
struct Y : virtual X { // expected-note {{::X' has an inaccessible copy assignment}}
|
|
|
|
virtual ~Y() = 0;
|
|
|
|
};
|
|
|
|
struct Z : Y {}; // expected-note {{::Y' has a deleted copy assignment}}
|
|
|
|
void f(Z &a, const Z &b) { a = b; } // expected-error {{copy assignment operator is implicitly deleted}}
|
|
|
|
|
|
|
|
struct RedundantInit : virtual A {
|
|
|
|
RedundantInit() : A(0) {} // expected-warning {{initializer for virtual base class 'pr16659::A' of abstract class 'RedundantInit' will never be used}}
|
|
|
|
};
|
|
|
|
}
|
2021-10-12 07:16:32 +08:00
|
|
|
|
|
|
|
struct inline_var { // expected-note {{until the closing '}'}}
|
|
|
|
static inline inline_var v = 0; // expected-error {{incomplete type}} expected-warning {{extension}}
|
|
|
|
virtual void f() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct var_template {
|
|
|
|
template<typename T>
|
|
|
|
static var_template v; // expected-error {{abstract class}} expected-warning {{extension}}
|
|
|
|
virtual void f() = 0; // expected-note {{unimplemented}}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct var_template_def { // expected-note {{until the closing '}'}}
|
|
|
|
template<typename T>
|
|
|
|
static inline var_template_def v = {}; // expected-error {{incomplete type}} expected-warning 2{{extension}}
|
|
|
|
virtual void f() = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct friend_fn {
|
|
|
|
friend void g(friend_fn); // expected-error {{abstract class}}
|
|
|
|
virtual void f() = 0; // expected-note {{unimplemented}}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct friend_fn_def {
|
|
|
|
friend void g(friend_fn_def) {} // expected-error {{abstract class}}
|
|
|
|
virtual void f() = 0; // expected-note {{unimplemented}}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct friend_template {
|
|
|
|
template<typename T>
|
|
|
|
friend void g(friend_template); // expected-error {{abstract class}}
|
|
|
|
virtual void f() = 0; // expected-note {{unimplemented}}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct friend_template_def {
|
|
|
|
template<typename T>
|
|
|
|
friend void g(friend_template_def) {} // expected-error {{abstract class}}
|
|
|
|
virtual void f() = 0; // expected-note {{unimplemented}}
|
|
|
|
};
|