125 lines
3.2 KiB
C++
125 lines
3.2 KiB
C++
|
// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify -std=c++98 %s
|
||
|
// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify -std=c++98 %s
|
||
|
// RUN: %clang_cc1 -fsyntax-only -triple %itanium_abi_triple -verify -std=c++11 %s
|
||
|
// RUN: %clang_cc1 -fsyntax-only -triple %ms_abi_triple -DMSABI -verify -std=c++11 %s
|
||
|
|
||
|
typedef __typeof(sizeof(int)) size_t;
|
||
|
|
||
|
// PR7803
|
||
|
namespace test0 {
|
||
|
class A {
|
||
|
public:
|
||
|
static void operator delete(void *p) {};
|
||
|
virtual ~A();
|
||
|
};
|
||
|
|
||
|
class B : protected A {
|
||
|
public:
|
||
|
~B();
|
||
|
};
|
||
|
|
||
|
class C : protected B {
|
||
|
public:
|
||
|
using B::operator delete;
|
||
|
~C();
|
||
|
};
|
||
|
|
||
|
// Shouldn't have an error.
|
||
|
C::~C() {}
|
||
|
}
|
||
|
|
||
|
namespace test1 {
|
||
|
class A {
|
||
|
public:
|
||
|
static void operator delete(void *p) {};
|
||
|
virtual ~A();
|
||
|
};
|
||
|
|
||
|
class B : protected A {
|
||
|
public:
|
||
|
static void operator delete(void *, size_t) {};
|
||
|
~B();
|
||
|
};
|
||
|
|
||
|
class C : protected B {
|
||
|
public:
|
||
|
using A::operator delete;
|
||
|
using B::operator delete;
|
||
|
|
||
|
~C();
|
||
|
};
|
||
|
|
||
|
// We assume that the intent is to treat C::operator delete(void*, size_t) as
|
||
|
// /not/ being a usual deallocation function, as it would be if it were
|
||
|
// declared with in C directly.
|
||
|
C::~C() {}
|
||
|
|
||
|
struct D {
|
||
|
void operator delete(void*); // expected-note {{member 'operator delete' declared here}}
|
||
|
void operator delete(void*, ...); // expected-note {{member 'operator delete' declared here}}
|
||
|
virtual ~D();
|
||
|
};
|
||
|
// FIXME: The standard doesn't say this is ill-formed, but presumably either
|
||
|
// it should be or the variadic operator delete should not be a usual
|
||
|
// deallocation function.
|
||
|
D::~D() {} // expected-error {{multiple suitable 'operator delete' functions in 'D'}}
|
||
|
}
|
||
|
|
||
|
// ...at the point of definition of a virtual destructor...
|
||
|
namespace test2 {
|
||
|
struct A {
|
||
|
virtual ~A();
|
||
|
static void operator delete(void*, const int &);
|
||
|
};
|
||
|
|
||
|
struct B {
|
||
|
virtual ~B();
|
||
|
static void operator delete(void*, const int &); // expected-note {{declared here}}
|
||
|
};
|
||
|
B::~B() {} // expected-error {{no suitable member 'operator delete' in 'B'}}
|
||
|
|
||
|
#if __cplusplus < 201103L
|
||
|
struct CBase { virtual ~CBase(); };
|
||
|
struct C : CBase { // expected-error {{no suitable member 'operator delete' in 'C'}}
|
||
|
static void operator delete(void*, const int &); // expected-note {{declared here}}
|
||
|
};
|
||
|
void test() {
|
||
|
C c; // expected-note {{first required here}}
|
||
|
}
|
||
|
#else
|
||
|
struct CBase { virtual ~CBase(); }; // expected-note {{overridden virtual function is here}}
|
||
|
struct C : CBase { // expected-error {{deleted function '~C' cannot override a non-deleted function}} expected-note 2{{requires an unambiguous, accessible 'operator delete'}}
|
||
|
static void operator delete(void*, const int &);
|
||
|
};
|
||
|
void test() {
|
||
|
C c; // expected-error {{attempt to use a deleted function}}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// PR7346
|
||
|
namespace test3 {
|
||
|
struct A {
|
||
|
#ifdef MSABI
|
||
|
// expected-error@+2 {{no suitable member 'operator delete' in 'A'}}
|
||
|
#endif
|
||
|
virtual ~A();
|
||
|
#ifdef MSABI
|
||
|
// expected-note@+2 {{declared here}}
|
||
|
#endif
|
||
|
static void operator delete(void*, const int &);
|
||
|
};
|
||
|
|
||
|
struct B : A {
|
||
|
virtual ~B() {}
|
||
|
static void operator delete(void*);
|
||
|
};
|
||
|
|
||
|
void f() {
|
||
|
#ifdef MSABI
|
||
|
// expected-note@+2 {{implicit default constructor for 'test3::B' first required here}}
|
||
|
#endif
|
||
|
B use_vtable;
|
||
|
}
|
||
|
}
|