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