197 lines · cpp
1// RUN: %clang_cc1 -emit-llvm-only -verify -std=c++11 %s2struct A {};3 4enum Foo { F };5typedef Foo Bar; // expected-note{{type 'Bar' (aka 'Foo') found by destructor name lookup}}6 7typedef int Integer;8typedef double Double;9 10void g();11 12namespace N {13 typedef Foo Wibble;14 typedef int OtherInteger;15}16 17template <typename T>18void cv_test(const volatile T* cvt) {19 cvt->T::~T(); // no-warning20}21 22void f(A* a, Foo *f, int *i, double *d, int ii) {23 a->~A();24 a->A::~A();25 26 a->~foo(); // expected-error{{undeclared identifier 'foo' in destructor name}}27 28 a->~Bar(); // expected-error{{destructor type 'Bar' (aka 'Foo') in object destruction expression does not match the type 'A' of the object being destroyed}}29 30 f->~Bar();31 f->~Foo();32 i->~Bar(); // expected-error{{does not match}}33 34 g().~Bar(); // expected-error{{non-scalar}}35 36 f->::~Bar(); // expected-error {{not a structure or union}}37 f->::Bar::~Bar();38 f->N::~Wibble(); // expected-error{{'N' does not refer to a type}} expected-error{{'Wibble' does not refer to a type}}39 40 f->Bar::~Bar(17, 42); // expected-error{{cannot have any arguments}}41 42 i->~Integer();43 i->Integer::~Integer();44 i->N::~OtherInteger(); // expected-error{{'N' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}}45 // expected-error@-1{{'OtherInteger' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}}46 i->N::OtherInteger::~OtherInteger();47 i->N::OtherInteger::~OtherInteger();48 i->N::OtherInteger::~Integer(); // expected-error{{'Integer' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}}49 i->N::~Integer(); // expected-error{{'N' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}}50 i->N::OtherInteger::~Integer(); // expected-error{{'Integer' does not refer to a type name in pseudo-destructor expression; expected the name of type 'int'}}51 i->Integer::~Double(); // expected-error{{the type of object expression ('int') does not match the type being destroyed ('Double' (aka 'double')) in pseudo-destructor expression}}52 53 ii->~Integer(); // expected-error{{member reference type 'int' is not a pointer; did you mean to use '.'?}}54 ii.~Integer();55 56 cv_test(a);57 cv_test(f);58 cv_test(i);59 cv_test(d);60}61 62 63typedef int Integer;64 65void destroy_without_call(int *ip) {66 ip->~Integer; // expected-error{{reference to pseudo-destructor must be called}}67}68 69void paren_destroy_with_call(int *ip) {70 (ip->~Integer)();71}72 73// PR553074namespace N1 {75 class X0 { };76}77 78void test_X0(N1::X0 &x0) {79 x0.~X0();80}81 82namespace PR11339 {83 template<class T>84 void destroy(T* p) {85 p->~T(); // ok86 p->~oops(); // expected-error{{undeclared identifier 'oops' in destructor name}}87 }88 89 template void destroy(int*); // expected-note{{in instantiation of function template specialization}}90}91 92template<typename T> using Id = T;93void AliasTemplate(int *p) {94 p->~Id<int>();95 p->template ~Id<int>(); // expected-error {{'template' keyword not permitted in destructor name}}96 (0).~Id<int>();97 (0).template ~Id<int>(); // expected-error {{'template' keyword not permitted in destructor name}}98}99 100namespace dotPointerAccess {101struct Base {102 virtual ~Base() {}103};104 105struct Derived : Base {106 ~Derived() {}107};108 109void test() {110 Derived d;111 static_cast<Base *>(&d).~Base(); // expected-error {{member reference type 'Base *' is a pointer; did you mean to use '->'}}112 d->~Derived(); // expected-error {{member reference type 'Derived' is not a pointer; did you mean to use '.'}}113}114 115typedef Derived *Foo;116 117void test2(Foo d) {118 d.~Foo(); // This is ok119 d.~Derived(); // expected-error {{member reference type 'Foo' (aka 'Derived *') is a pointer; did you mean to use '->'}}120}121}122 123int pr45294 = 1 .~undeclared_tempate_name<>(); // expected-error {{use of undeclared 'undeclared_tempate_name'}}124 125namespace TwoPhaseLookup {126 namespace NonTemplate {127 struct Y {};128 using G = Y;129 template<typename T> void f(T *p) { p->~G(); } // expected-error {{no member named '~Y'}}130 void h1(Y *p) { p->~G(); }131 void h2(Y *p) { f(p); }132 namespace N { struct G{}; }133 void h3(N::G *p) { p->~G(); }134 void h4(N::G *p) { f(p); } // expected-note {{instantiation of}}135 }136 137 namespace NonTemplateUndeclared {138 struct Y {};139 template<typename T> void f(T *p) { p->~G(); } // expected-error {{undeclared identifier 'G' in destructor name}}140 using G = Y;141 void h1(Y *p) { p->~G(); }142 void h2(Y *p) { f(p); } // expected-note {{instantiation of}}143 namespace N { struct G{}; }144 void h3(N::G *p) { p->~G(); }145 void h4(N::G *p) { f(p); }146 }147 148 namespace Template {149 template<typename T> struct Y {};150 template<class U> using G = Y<U>;151 template<typename T> void f(T *p) { p->~G<int>(); } // expected-error {{no member named '~Y'}}152 void h1(Y<int> *p) { p->~G<int>(); }153 void h2(Y<int> *p) { f(p); }154 namespace N { template<typename T> struct G {}; }155 void h3(N::G<int> *p) { p->~G<int>(); }156 void h4(N::G<int> *p) { f(p); } // expected-note {{instantiation of}}157 }158 159 namespace TemplateUndeclared {160 template<typename T> struct Y {};161 // FIXME: Formally, this is ill-formed before we hit any instantiation,162 // because we aren't supposed to treat the '<' as introducing a template163 // name.164 template<typename T> void f(T *p) { p->~G<int>(); } // expected-error {{no member named 'G'}}165 template<class U> using G = Y<U>;166 void h1(Y<int> *p) { p->~G<int>(); }167 void h2(Y<int> *p) { f(p); } // expected-note {{instantiation of}}168 namespace N { template<typename T> struct G {}; }169 void h3(N::G<int> *p) { p->~G<int>(); }170 void h4(N::G<int> *p) { f(p); }171 }172 173 namespace TemplateNamesNonTemplate {174 int A; // expected-note 2{{non-template here}}175 template<typename> int B; // expected-note 2{{variable template 'B' declared here}} expected-warning {{extension}}176 using C = int; // expected-note 2{{non-template here}}177 178 template<typename T> void f1(int *p) { p->~A<int>(); } // expected-error {{'A' does not refer to a template}}179 template<typename T> void f2(int *p) { p->~B<int>(); } // expected-error {{template name refers to non-type template 'B'}}180 template<typename T> void f3(int *p) { p->~C<int>(); } // expected-error {{'C' does not refer to a template}}181 template<typename T> void f4(int *p) { p->TemplateNamesNonTemplate::C::~A<int>(); } // expected-error {{'A' does not refer to a template}}182 template<typename T> void f5(int *p) { p->TemplateNamesNonTemplate::C::~B<int>(); } // expected-error {{template name refers to non-type template 'TemplateNamesNonTemplate::B'}}183 template<typename T> void f6(int *p) { p->TemplateNamesNonTemplate::C::~C<int>(); } // expected-error {{'C' does not refer to a template}}184 }185}186 187void destroy_array_element() {188 int arr[5];189 using T = int;190 arr->~T(); // ok, destroy arr[0].191}192 193void destroy_function() {194 using T = void();195 destroy_function->~T(); // expected-error {{object expression of non-scalar type 'void ()' cannot be used in a pseudo-destructor expression}}196}197