summaryrefslogtreecommitdiff
path: root/clang/test/CXX/special/class.dtor
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/special/class.dtor')
-rw-r--r--clang/test/CXX/special/class.dtor/p10-0x.cpp39
-rw-r--r--clang/test/CXX/special/class.dtor/p2-0x.cpp10
-rw-r--r--clang/test/CXX/special/class.dtor/p2.cpp7
-rw-r--r--clang/test/CXX/special/class.dtor/p3-0x.cpp177
-rw-r--r--clang/test/CXX/special/class.dtor/p5-0x.cpp104
-rw-r--r--clang/test/CXX/special/class.dtor/p9.cpp85
6 files changed, 422 insertions, 0 deletions
diff --git a/clang/test/CXX/special/class.dtor/p10-0x.cpp b/clang/test/CXX/special/class.dtor/p10-0x.cpp
new file mode 100644
index 0000000..e10afb5
--- /dev/null
+++ b/clang/test/CXX/special/class.dtor/p10-0x.cpp
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+// PR10127/N3031
+struct A { ~A(); };
+struct B {};
+template<typename T>
+void b(const T *x, const A *y) {
+ x->~decltype(T())();
+ x->~decltype(*x)(); // expected-error{{the type of object expression ('const int') does not match the type being destroyed ('decltype(*x)' (aka 'const int &')) in pseudo-destructor expression}} \
+ expected-error{{no member named '~const struct A &' in 'A'}}
+ x->~decltype(int())(); // expected-error{{no member named '~int' in 'A'}}
+
+ y->~decltype(*y)(); // expected-error{{destructor type 'decltype(*y)' (aka 'const A &') in object destruction expression does not match the type 'const A' of the object being destroyed}}
+ y->~decltype(T())(); // expected-error{{destructor type 'decltype(T())' in object destruction expression does not match the type 'const A' of the object being destroyed}}
+ y->~decltype(A())();
+}
+template void b(const int*, const A*); // expected-note{{in instantiation of function template specialization 'b<int>' requested here}}
+template void b(const A*,const A*); // expected-note{{in instantiation of function template specialization 'b<A>' requested here}}
+void a(const A *x, int i, int *pi) {
+ x->~decltype(A())();
+ x->~decltype(*x)(); // expected-error{{destructor type 'decltype(*x)' (aka 'const A &') in object destruction expression does not match the type 'const A' of the object being destroyed}}
+ x->~decltype()(); // expected-error{{expected expression}}
+ x->~decltype(B())(); // expected-error{{destructor type 'decltype(B())' (aka 'B') in object destruction expression does not match the type 'const A' of the object being destroyed}}
+ x->~decltype(x)(); // expected-error{{destructor type 'decltype(x)' (aka 'const A *') in object destruction expression does not match the type 'const A' of the object being destroyed}}
+ // this last one could be better, mentioning that the nested-name-specifier could be removed or a type name after the ~
+ x->::A::~decltype(*x)(); // expected-error{{expected a class name after '~' to name a destructor}}
+ y->~decltype(A())(); // expected-error{{use of undeclared identifier 'y'}}
+
+ typedef int *intp;
+ i->~decltype(int())(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}}
+ i.~decltype(int())();
+ i->~decltype(intp())(); // expected-error{{member reference type 'int' is not a pointer; maybe you meant to use '.'?}} \
+ expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}}
+ i.~decltype(intp())(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}}
+ pi->~decltype(int())();
+ pi.~decltype(int())(); // expected-error{{the type of object expression ('int *') does not match the type being destroyed ('decltype(int())' (aka 'int')) in pseudo-destructor expression}}
+ pi.~decltype(intp())();
+ pi->~decltype(intp())(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('decltype(intp())' (aka 'int *')) in pseudo-destructor expression}}
+}
diff --git a/clang/test/CXX/special/class.dtor/p2-0x.cpp b/clang/test/CXX/special/class.dtor/p2-0x.cpp
new file mode 100644
index 0000000..c7b1b58
--- /dev/null
+++ b/clang/test/CXX/special/class.dtor/p2-0x.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+// A destructor shall not be declared with a ref-qualifier.
+struct X {
+ ~X() &; // expected-error{{ref-qualifier '&' is not allowed on a destructor}}
+};
+
+struct Y {
+ ~Y() &&; // expected-error{{ref-qualifier '&&' is not allowed on a destructor}}
+};
diff --git a/clang/test/CXX/special/class.dtor/p2.cpp b/clang/test/CXX/special/class.dtor/p2.cpp
new file mode 100644
index 0000000..b05c992
--- /dev/null
+++ b/clang/test/CXX/special/class.dtor/p2.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// PR5548
+struct A {~A();};
+void a(const A* x) {
+ x->~A();
+}
diff --git a/clang/test/CXX/special/class.dtor/p3-0x.cpp b/clang/test/CXX/special/class.dtor/p3-0x.cpp
new file mode 100644
index 0000000..44bf5aa
--- /dev/null
+++ b/clang/test/CXX/special/class.dtor/p3-0x.cpp
@@ -0,0 +1,177 @@
+// RUN: %clang_cc1 -std=c++11 -fexceptions -fcxx-exceptions -emit-llvm -o - %s | FileCheck %s
+
+struct A {
+ ~A();
+};
+
+struct B {
+ ~B() throw(int);
+};
+
+struct C {
+ B b;
+ ~C() {}
+};
+
+struct D {
+ ~D() noexcept(false);
+};
+
+struct E {
+ D d;
+ ~E() {}
+};
+
+void foo() {
+ A a;
+ C c;
+ E e;
+ // CHECK: invoke {{.*}} @_ZN1ED1Ev
+ // CHECK: invoke {{.*}} @_ZN1CD1Ev
+ // CHECK: call {{.*}} @_ZN1AD1Ev
+}
+
+struct F {
+ D d;
+ ~F();
+};
+F::~F() noexcept(false) {}
+
+struct G {
+ D d;
+ ~G();
+};
+G::~G() {}
+
+struct H {
+ B b;
+ ~H();
+};
+H::~H() throw(int) {}
+
+struct I {
+ B b;
+ ~I();
+};
+I::~I() {}
+
+// Template variants.
+
+template <typename T>
+struct TA {
+ ~TA();
+};
+
+template <typename T>
+struct TB {
+ ~TB() throw(int);
+};
+
+template <typename T>
+struct TC {
+ TB<T> b;
+ ~TC() {}
+};
+
+template <typename T>
+struct TD {
+ ~TD() noexcept(false);
+};
+
+template <typename T>
+struct TE {
+ TD<T> d;
+ ~TE() {}
+};
+
+void tfoo() {
+ TA<int> a;
+ TC<int> c;
+ TE<int> e;
+ // CHECK: invoke {{.*}} @_ZN2TEIiED1Ev
+ // CHECK: invoke {{.*}} @_ZN2TCIiED1Ev
+ // CHECK: call {{.*}} @_ZN2TAIiED1Ev
+}
+
+template <typename T>
+struct TF {
+ TD<T> d;
+ ~TF();
+};
+template <typename T>
+TF<T>::~TF() noexcept(false) {}
+
+template <typename T>
+struct TG {
+ TD<T> d;
+ ~TG();
+};
+template <typename T>
+TG<T>::~TG() {}
+
+template <typename T>
+struct TH {
+ TB<T> b;
+ ~TH();
+};
+template <typename T>
+TH<T>::~TH() {}
+
+void tinst() {
+ TF<int> f;
+ TG<int> g;
+ TH<int> h;
+}
+// CHECK: define linkonce_odr {{.*}} @_ZN2THIiED1Ev
+// CHECK: _ZTIi
+// CHECK: __cxa_call_unexpected
+
+struct VX
+{ virtual ~VX() {} };
+
+struct VY : VX
+{ virtual ~VY() {} };
+
+template<typename T>
+struct TVY : VX
+{ virtual ~TVY() {} };
+
+
+struct VA {
+ B b;
+ virtual ~VA() {}
+};
+
+struct VB : VA
+{ virtual ~VB() {} };
+
+template<typename T>
+struct TVB : VA
+{ virtual ~TVB() {} };
+
+void tinst2() {
+ TVY<int> tvy;
+ TVB<int> tvb;
+}
+
+template <typename T>
+struct Sw {
+ T t;
+ ~Sw() {}
+};
+
+void tsw() {
+ Sw<int> swi;
+ Sw<B> swb;
+}
+// CHECK-NOT: define linkonce_odr {{.*}} @_ZN2SwI1BED1Ev({{.*}} nounwind
+// CHECK: define linkonce_odr {{.*}} @_ZN2SwI1BED1Ev({{.*}}
+// CHECK: _ZTIi
+// CHECK: __cxa_call_unexpected
+// CHECK: define linkonce_odr {{.*}} @_ZN2SwIiED1Ev({{.*}} nounwind
+
+template <typename T>
+struct TVC : VX
+{ virtual ~TVC(); };
+template <typename T>
+TVC<T>::~TVC() {}
diff --git a/clang/test/CXX/special/class.dtor/p5-0x.cpp b/clang/test/CXX/special/class.dtor/p5-0x.cpp
new file mode 100644
index 0000000..dbfa004
--- /dev/null
+++ b/clang/test/CXX/special/class.dtor/p5-0x.cpp
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 -verify -std=c++11 %s
+
+struct NonTrivDtor {
+ ~NonTrivDtor();
+};
+struct DeletedDtor {
+ ~DeletedDtor() = delete; // expected-note 5 {{deleted here}}
+};
+class InaccessibleDtor {
+ ~InaccessibleDtor() = default;
+};
+
+// A defaulted destructor for a class X is defined as deleted if:
+
+// -- X is a union-like class that has a variant member with a non-trivial
+// destructor.
+union A1 {
+ A1();
+ NonTrivDtor n; // expected-note {{destructor of union 'A1' is implicitly deleted because field 'n' has a non-trivial destructor}}
+};
+A1 a1; // expected-error {{deleted function}}
+struct A2 {
+ A2();
+ union {
+ NonTrivDtor n; // expected-note {{because field 'n' has a non-trivial destructor}}
+ };
+};
+A2 a2; // expected-error {{deleted function}}
+union A3 {
+ A3();
+ NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}}
+};
+A3 a3; // expected-error {{deleted function}}
+struct A4 {
+ A4();
+ union {
+ NonTrivDtor n[3]; // expected-note {{because field 'n' has a non-trivial destructor}}
+ };
+};
+A4 a4; // expected-error {{deleted function}}
+
+// -- any of the non-static data members has class type M (or array thereof) and
+// M has a deleted or inaccessible destructor.
+struct B1 {
+ B1();
+ DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}}
+};
+B1 b1; // expected-error {{deleted function}}
+struct B2 {
+ B2();
+ InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}}
+};
+B2 b2; // expected-error {{deleted function}}
+struct B3 {
+ B3();
+ DeletedDtor a[4]; // expected-note {{because field 'a' has a deleted destructor}}
+};
+B3 b3; // expected-error {{deleted function}}
+struct B4 {
+ B4();
+ InaccessibleDtor a[4]; // expected-note {{because field 'a' has an inaccessible destructor}}
+};
+B4 b4; // expected-error {{deleted function}}
+union B5 {
+ B5();
+ // FIXME: Describe the anonymous union member better than ''.
+ union { // expected-note {{because field '' has a deleted destructor}}
+ DeletedDtor a; // expected-note {{because field 'a' has a deleted destructor}}
+ };
+};
+B5 b5; // expected-error {{deleted function}}
+union B6 {
+ B6();
+ union { // expected-note {{because field '' has a deleted destructor}}
+ InaccessibleDtor a; // expected-note {{because field 'a' has an inaccessible destructor}}
+ };
+};
+B6 b6; // expected-error {{deleted function}}
+
+// -- any direct or virtual base class has a deleted or inaccessible destructor.
+struct C1 : DeletedDtor { C1(); } c1; // expected-error {{deleted function}} expected-note {{base class 'DeletedDtor' has a deleted destructor}}
+struct C2 : InaccessibleDtor { C2(); } c2; // expected-error {{deleted function}} expected-note {{base class 'InaccessibleDtor' has an inaccessible destructor}}
+struct C3 : virtual DeletedDtor { C3(); } c3; // expected-error {{deleted function}} expected-note {{base class 'DeletedDtor' has a deleted destructor}}
+struct C4 : virtual InaccessibleDtor { C4(); } c4; // expected-error {{deleted function}} expected-note {{base class 'InaccessibleDtor' has an inaccessible destructor}}
+
+// -- for a virtual destructor, lookup of the non-array deallocation function
+// results in an ambiguity or a function that is deleted or inaccessible.
+class D1 {
+ void operator delete(void*);
+public:
+ virtual ~D1() = default;
+} d1; // ok
+struct D2 : D1 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}}
+ // implicitly-virtual destructor
+} d2; // expected-error {{deleted function}}
+struct D3 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}}
+ virtual ~D3() = default; // expected-note {{explicitly defaulted function was implicitly deleted here}}
+ void operator delete(void*, double = 0.0);
+ void operator delete(void*, char = 0);
+} d3; // expected-error {{deleted function}}
+struct D4 { // expected-note {{virtual destructor requires an unambiguous, accessible 'operator delete'}}
+ virtual ~D4() = default; // expected-note {{implicitly deleted here}}
+ void operator delete(void*) = delete;
+} d4; // expected-error {{deleted function}}
diff --git a/clang/test/CXX/special/class.dtor/p9.cpp b/clang/test/CXX/special/class.dtor/p9.cpp
new file mode 100644
index 0000000..8b76a15
--- /dev/null
+++ b/clang/test/CXX/special/class.dtor/p9.cpp
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %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) {}; // expected-note {{member 'operator delete' declared here}}
+ virtual ~A();
+ };
+
+ class B : protected A {
+ public:
+ static void operator delete(void *, size_t) {}; // expected-note {{member 'operator delete' declared here}}
+ ~B();
+ };
+
+ class C : protected B {
+ public:
+ using A::operator delete;
+ using B::operator delete;
+
+ ~C();
+ };
+
+ C::~C() {} // expected-error {{multiple suitable 'operator delete' functions in 'C'}}
+}
+
+// ...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'}}
+
+ 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}}
+ }
+}
+
+// PR7346
+namespace test3 {
+ struct A {
+ virtual ~A();
+ static void operator delete(void*, const int &);
+ };
+
+ struct B : A {
+ virtual ~B() {}
+ static void operator delete(void*);
+ };
+}