head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-9-5-RELEASE:1.1.1.8
	netbsd-11-0-RELEASE:1.1.1.9
	netbsd-11-0-RC7:1.1.1.9
	netbsd-11-0-RC6:1.1.1.9
	netbsd-11-0-RC5:1.1.1.9
	netbsd-11-0-RC4:1.1.1.9
	netbsd-11-0-RC3:1.1.1.9
	netbsd-11-0-RC2:1.1.1.9
	netbsd-11-0-RC1:1.1.1.9
	perseant-exfatfs-base-20250801:1.1.1.9
	netbsd-11:1.1.1.9.0.10
	netbsd-11-base:1.1.1.9
	netbsd-10-1-RELEASE:1.1.1.9
	perseant-exfatfs-base-20240630:1.1.1.9
	perseant-exfatfs:1.1.1.9.0.8
	perseant-exfatfs-base:1.1.1.9
	netbsd-8-3-RELEASE:1.1.1.7
	netbsd-9-4-RELEASE:1.1.1.8
	netbsd-10-0-RELEASE:1.1.1.9
	netbsd-10-0-RC6:1.1.1.9
	netbsd-10-0-RC5:1.1.1.9
	netbsd-10-0-RC4:1.1.1.9
	netbsd-10-0-RC3:1.1.1.9
	netbsd-10-0-RC2:1.1.1.9
	netbsd-10-0-RC1:1.1.1.9
	netbsd-10:1.1.1.9.0.6
	netbsd-10-base:1.1.1.9
	netbsd-9-3-RELEASE:1.1.1.8
	cjep_sun2x:1.1.1.9.0.4
	cjep_sun2x-base:1.1.1.9
	cjep_staticlib_x-base1:1.1.1.9
	netbsd-9-2-RELEASE:1.1.1.8
	cjep_staticlib_x:1.1.1.9.0.2
	cjep_staticlib_x-base:1.1.1.9
	netbsd-9-1-RELEASE:1.1.1.8
	phil-wifi-20200421:1.1.1.9
	phil-wifi-20200411:1.1.1.9
	phil-wifi-20200406:1.1.1.9
	netbsd-8-2-RELEASE:1.1.1.7
	netbsd-9-0-RELEASE:1.1.1.8
	netbsd-9-0-RC2:1.1.1.8
	netbsd-9-0-RC1:1.1.1.8
	netbsd-9:1.1.1.8.0.2
	netbsd-9-base:1.1.1.8
	phil-wifi-20190609:1.1.1.8
	netbsd-8-1-RELEASE:1.1.1.7
	netbsd-8-1-RC1:1.1.1.7
	pgoyette-compat-merge-20190127:1.1.1.7.10.1
	pgoyette-compat-20190127:1.1.1.8
	pgoyette-compat-20190118:1.1.1.8
	pgoyette-compat-1226:1.1.1.8
	pgoyette-compat-1126:1.1.1.8
	pgoyette-compat-1020:1.1.1.8
	pgoyette-compat-0930:1.1.1.8
	pgoyette-compat-0906:1.1.1.8
	netbsd-7-2-RELEASE:1.1.1.4
	pgoyette-compat-0728:1.1.1.8
	clang-337282:1.1.1.8
	netbsd-8-0-RELEASE:1.1.1.7
	phil-wifi:1.1.1.7.0.12
	phil-wifi-base:1.1.1.7
	pgoyette-compat-0625:1.1.1.7
	netbsd-8-0-RC2:1.1.1.7
	pgoyette-compat-0521:1.1.1.7
	pgoyette-compat-0502:1.1.1.7
	pgoyette-compat-0422:1.1.1.7
	netbsd-8-0-RC1:1.1.1.7
	pgoyette-compat-0415:1.1.1.7
	pgoyette-compat-0407:1.1.1.7
	pgoyette-compat-0330:1.1.1.7
	pgoyette-compat-0322:1.1.1.7
	pgoyette-compat-0315:1.1.1.7
	netbsd-7-1-2-RELEASE:1.1.1.4
	pgoyette-compat:1.1.1.7.0.10
	pgoyette-compat-base:1.1.1.7
	netbsd-7-1-1-RELEASE:1.1.1.4
	clang-319952:1.1.1.7
	matt-nb8-mediatek:1.1.1.7.0.8
	matt-nb8-mediatek-base:1.1.1.7
	clang-309604:1.1.1.7
	perseant-stdc-iso10646:1.1.1.7.0.6
	perseant-stdc-iso10646-base:1.1.1.7
	netbsd-8:1.1.1.7.0.4
	netbsd-8-base:1.1.1.7
	prg-localcount2-base3:1.1.1.7
	prg-localcount2-base2:1.1.1.7
	prg-localcount2-base1:1.1.1.7
	prg-localcount2:1.1.1.7.0.2
	prg-localcount2-base:1.1.1.7
	pgoyette-localcount-20170426:1.1.1.7
	bouyer-socketcan-base1:1.1.1.7
	pgoyette-localcount-20170320:1.1.1.7
	netbsd-7-1:1.1.1.4.0.10
	netbsd-7-1-RELEASE:1.1.1.4
	netbsd-7-1-RC2:1.1.1.4
	clang-294123:1.1.1.7
	netbsd-7-nhusb-base-20170116:1.1.1.4
	bouyer-socketcan:1.1.1.6.0.2
	bouyer-socketcan-base:1.1.1.6
	clang-291444:1.1.1.6
	pgoyette-localcount-20170107:1.1.1.5
	netbsd-7-1-RC1:1.1.1.4
	pgoyette-localcount-20161104:1.1.1.5
	netbsd-7-0-2-RELEASE:1.1.1.4
	localcount-20160914:1.1.1.5
	netbsd-7-nhusb:1.1.1.4.0.8
	netbsd-7-nhusb-base:1.1.1.4
	clang-280599:1.1.1.5
	pgoyette-localcount-20160806:1.1.1.5
	pgoyette-localcount-20160726:1.1.1.5
	pgoyette-localcount:1.1.1.5.0.2
	pgoyette-localcount-base:1.1.1.5
	netbsd-7-0-1-RELEASE:1.1.1.4
	clang-261930:1.1.1.5
	netbsd-7-0:1.1.1.4.0.6
	netbsd-7-0-RELEASE:1.1.1.4
	netbsd-7-0-RC3:1.1.1.4
	netbsd-7-0-RC2:1.1.1.4
	netbsd-7-0-RC1:1.1.1.4
	clang-237755:1.1.1.4
	clang-232565:1.1.1.4
	clang-227398:1.1.1.4
	tls-maxphys-base:1.1.1.4
	tls-maxphys:1.1.1.4.0.4
	netbsd-7:1.1.1.4.0.2
	netbsd-7-base:1.1.1.4
	clang-215315:1.1.1.4
	clang-209886:1.1.1.3
	yamt-pagecache:1.1.1.2.0.4
	yamt-pagecache-base9:1.1.1.2
	tls-earlyentropy:1.1.1.2.0.2
	tls-earlyentropy-base:1.1.1.3
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.2
	riastradh-drm2-base3:1.1.1.2
	clang-202566:1.1.1.2
	clang-201163:1.1.1.2
	clang-199312:1.1.1.2
	clang-198450:1.1.1.1
	clang-196603:1.1.1.1
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.56;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.56;	author joerg;	state Exp;
branches;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2014.01.15.21.26.05;	author joerg;	state Exp;
branches
	1.1.1.2.2.1
	1.1.1.2.4.1;
next	1.1.1.3;
commitid	NQXlzzA0SPkc5glx;

1.1.1.3
date	2014.05.30.18.14.49;	author joerg;	state Exp;
branches;
next	1.1.1.4;
commitid	8q0kdlBlCn09GACx;

1.1.1.4
date	2014.08.10.17.08.43;	author joerg;	state Exp;
branches
	1.1.1.4.4.1;
next	1.1.1.5;
commitid	N85tXAN6Ex9VZPLx;

1.1.1.5
date	2016.02.27.22.10.17;	author joerg;	state Exp;
branches
	1.1.1.5.2.1;
next	1.1.1.6;
commitid	tIimz3oDlh1NpBWy;

1.1.1.6
date	2017.01.11.10.37.43;	author joerg;	state Exp;
branches
	1.1.1.6.2.1;
next	1.1.1.7;
commitid	CNnUNfII1jgNmxBz;

1.1.1.7
date	2017.02.09.17.39.01;	author joerg;	state Exp;
branches
	1.1.1.7.10.1
	1.1.1.7.12.1;
next	1.1.1.8;
commitid	UxB8JMFWM7xyMiFz;

1.1.1.8
date	2018.07.17.18.31.33;	author joerg;	state Exp;
branches;
next	1.1.1.9;
commitid	wDzL46ALjrCZgwKA;

1.1.1.9
date	2019.11.13.22.22.55;	author joerg;	state dead;
branches;
next	;
commitid	QD8YATxuNG34YJKB;

1.1.1.2.2.1
date	2014.08.10.07.08.23;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.2.4.1
date	2014.01.15.21.26.05;	author yamt;	state dead;
branches;
next	1.1.1.2.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.2.4.2
date	2014.05.22.16.19.40;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.4.4.1
date	2014.08.10.17.08.43;	author tls;	state dead;
branches;
next	1.1.1.4.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.4.4.2
date	2014.08.19.23.49.18;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.5.2.1
date	2017.03.20.06.53.33;	author pgoyette;	state Exp;
branches;
next	;
commitid	jjw7cAwgyKq7RfKz;

1.1.1.6.2.1
date	2017.04.21.16.51.43;	author bouyer;	state Exp;
branches;
next	;
commitid	dUG7nkTKALCadqOz;

1.1.1.7.10.1
date	2018.07.28.04.34.11;	author pgoyette;	state Exp;
branches;
next	;
commitid	1UP1xAIUxv1ZgRLA;

1.1.1.7.12.1
date	2019.06.10.21.46.35;	author christos;	state Exp;
branches;
next	1.1.1.7.12.2;
commitid	jtc8rnCzWiEEHGqB;

1.1.1.7.12.2
date	2020.04.13.07.50.22;	author martin;	state dead;
branches;
next	;
commitid	X01YhRUPVUDaec4C;


desc
@@


1.1
log
@Initial revision
@
text
@// RUN: %clang_cc1 -std=c++11 -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
class A {
public:
  ~A();
};

class B {
public:
  ~B() { }
};

class C {
public:
  (~C)() { }
};

struct D {
  static void ~D(int, ...) const { } //                          \
    // expected-error{{static member function cannot have 'const' qualifier}} \
    // expected-error{{destructor cannot be declared 'static'}}  \
    // expected-error{{destructor cannot have any parameters}}   \
    // expected-error{{destructor cannot be variadic}} \
    // expected-error{{destructor cannot have a return type}} \
    // expected-error{{'const' qualifier is not allowed on a destructor}}
};

struct D2 {
  void ~D2() { } //                          \
  // expected-error{{destructor cannot have a return type}}  
};


struct E;

typedef E E_typedef;
struct E {
  ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}}
};

struct F {
  (~F)(); // expected-note {{previous declaration is here}}
  ~F(); // expected-error {{destructor cannot be redeclared}}
};

~; // expected-error {{expected a class name after '~' to name a destructor}}
~undef(); // expected-error {{expected the class name after '~' to name a destructor}}
~operator+(int, int);  // expected-error {{expected a class name after '~' to name a destructor}}
~F(){} // expected-error {{destructor must be a non-static member function}}

struct G {
  ~G();
};

G::~G() { }

// <rdar://problem/6841210>
struct H {
  ~H(void) { } 
};

struct X {};

struct Y {
  ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}}
};

namespace PR6421 {
  class T; // expected-note{{forward declaration}}

  class QGenericArgument // expected-note{{declared here}}
  {
    template<typename U>
    void foo(T t) // expected-error{{variable has incomplete type}}
    { }
    
    void disconnect()
    {
      T* t;
      bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}} \
      // expected-error{{does not refer to a value}}
    }
  };
}

namespace PR6709 {
  template<class T> class X { T v; ~X() { ++*v; } };
  void a(X<int> x) {}
}

struct X0 { virtual ~X0() throw(); };
struct X1 : public X0 { };

// Make sure we instantiate operator deletes when building a virtual
// destructor.
namespace test6 {
  template <class T> class A {
  public:
    void *operator new(__SIZE_TYPE__);
    void operator delete(void *p) {
      T::deleteIt(p); // expected-error {{type 'int' cannot be used prior to '::'}}
    }

    virtual ~A() {}
  };

  class B : A<int> { B(); }; // expected-note {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
  B::B() {}
}

// Make sure classes are marked invalid when they have invalid
// members.  This avoids a crash-on-invalid.
namespace test7 {
  struct A {
    ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}}
  };
  struct B : A {};

  void test() {
    B *b;
    b->~B();
  }
}

namespace nonvirtualdtor {
struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct S2 {
  ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct S3 : public S1 {  // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct S4 : public S2 {  // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct B {
  virtual ~B();
  virtual void m();
};

struct S5 : public B {
  virtual void m();
};

struct S6 {
  virtual void m();
private:
  ~S6();
};

struct S7 {
  virtual void m();
protected:
  ~S7();
};

template<class T> class TS : public B {
  virtual void m();
};

TS<int> baz;

template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
  virtual void m();
};

TS2<int> foo; // expected-note {{instantiation}}
}

namespace dnvd { // delete-non-virtual-dtor warning
struct NP {};

struct B { // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void foo();
};

struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}

struct F final: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}

struct VB {
  virtual void foo();
  virtual ~VB();
};

struct VD: VB {};

struct VF final: VB {};

template <typename T>
class simple_ptr {
public:
  simple_ptr(T* t): _ptr(t) {}
  ~simple_ptr() { delete _ptr; } // \
    // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} \
    // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}}
  T& operator*() const { return *_ptr; }
private:
  T* _ptr;
};

template <typename T>
class simple_ptr2 {
public:
  simple_ptr2(T* t): _ptr(t) {}
  ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
  T& operator*() const { return *_ptr; }
private:
  T* _ptr;
};

void use(B&);
void use(VB&);

void nowarnstack() {
  B b; use(b);
  D d; use(d);
  F f; use(f);
  VB vb; use(vb);
  VD vd; use(vd);
  VF vf; use(vf);
}

void nowarnnonpoly() {
  {
    NP* np = new NP();
    delete np;
  }
  {
    NP* np = new NP[4];
    delete[] np;
  }
}

void nowarnarray() {
  {
    B* b = new B[4];
    delete[] b;
  }
  {
    D* d = new D[4];
    delete[] d;
  }
  {
    VB* vb = new VB[4];
    delete[] vb;
  }
  {
    VD* vd = new VD[4];
    delete[] vd;
  }
}

template <typename T>
void nowarntemplate() {
  {
    T* t = new T();
    delete t;
  }
  {
    T* t = new T[4];
    delete[] t;
  }
}

void nowarn0() {
  {
    F* f = new F();
    delete f;
  }
  {
    VB* vb = new VB();
    delete vb;
  }
  {
    VB* vb = new VD();
    delete vb;
  }
  {
    VD* vd = new VD();
    delete vd;
  }
  {
    VF* vf = new VF();
    delete vf;
  }
}

void warn0() {
  {
    B* b = new B();
    delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
  }
  {
    B* b = new D();
    delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
  }
  {
    D* d = new D();
    delete d; // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}}
  }
}

void nowarn1() {
  {
    simple_ptr<F> f(new F());
    use(*f);
  }
  {
    simple_ptr<VB> vb(new VB());
    use(*vb);
  }
  {
    simple_ptr<VB> vb(new VD());
    use(*vb);
  }
  {
    simple_ptr<VD> vd(new VD());
    use(*vd);
  }
  {
    simple_ptr<VF> vf(new VF());
    use(*vf);
  }
}

void warn1() {
  {
    simple_ptr<B> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}}
    use(*b);
  }
  {
    simple_ptr2<B> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}}
    use(*b);
  }
  {
    simple_ptr<D> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}}
    use(*d);
  }
}
}

namespace PR9238 {
  class B { public: ~B(); };
  class C : virtual B { public: ~C() { } };
}

namespace PR7900 {
  struct A { // expected-note 2{{type 'PR7900::A' is declared here}}
  };
  struct B : public A {
  };
  void foo() {
    B b;
    b.~B();
    b.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
    (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
  }
}

namespace PR16892 {
  auto p = &A::~A; // expected-error{{taking the address of a destructor}}
}
@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.2
log
@Import Clang 3.5svn r199312
@
text
@d1 1
a1 2
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
// RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
a85 6
#ifdef MSABI
  // This bug, "Clang instantiates destructor for function argument" is intended
  // behaviour in the Microsoft ABI because the callee needs to destruct the arguments.
  // expected-error@@+3 {{indirection requires pointer operand ('int' invalid)}}
  // expected-note@@+3 {{in instantiation of member function 'PR6709::X<int>::~X' requested here}}
#endif
a102 3
#ifdef MSABI
    // expected-note@@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
#endif
d106 1
a106 4
#ifndef MSABI
    // expected-note@@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
#endif
  class B : A<int> { B(); };
@


1.1.1.2.2.1
log
@Rebase.
@
text
@d198 1
a198 1
struct F final : B {};
@


1.1.1.3
log
@Import Clang 3.5svn r209886.
@
text
@d198 1
a198 1
struct F final : B {};
@


1.1.1.4
log
@Import clang 3.6svn r215315.
@
text
@a382 6

namespace PR20238 {
struct S {
  volatile ~S() { } // expected-error{{destructor cannot have a return type}}
};
}
@


1.1.1.5
log
@Import Clang 3.8.0rc3 r261930.
@
text
@a175 6
struct S8 {} s8;

UnknownType S8::~S8() { // expected-error {{unknown type name 'UnknownType'}}
  s8.~S8();
}

d214 2
a215 2
    // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} \
    // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}}
d225 1
a225 1
  ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
d311 1
a311 1
    delete b; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
d315 1
a315 1
    delete b; // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}}
d319 1
a319 1
    delete d; // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}}
a388 11

namespace PR22668 {
struct S {
};
void f(S s) {
  (s.~S)();
}
void g(S s) {
  (s.~S); // expected-error{{reference to destructor must be called}}
}
}
@


1.1.1.5.2.1
log
@Sync with HEAD
@
text
@d1 1
a1 1
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -verify %s
a259 1
// FIXME: Why are these supposed to not warn?
a313 8
void nowarn0_explicit_dtor(F* f, VB* vb, VD* vd, VF* vf) {
  f->~F();
  f->~F();
  vb->~VB();
  vd->~VD();
  vf->~VF();
}

a328 11
void warn0_explicit_dtor(B* b, B& br, D* d) {
  b->~B(); // expected-warning {{destructor called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} expected-note{{qualify call to silence this warning}}
  b->B::~B(); // No warning when the call isn't virtual.

  br.~B(); // expected-warning {{destructor called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} expected-note{{qualify call to silence this warning}}
  br.B::~B();

  d->~D(); // expected-warning {{destructor called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}} expected-note{{qualify call to silence this warning}}
  d->D::~D();
}

a405 28

class Invalid {
    ~Invalid();
    UnknownType xx; // expected-error{{unknown type name}}
};

// The constructor definition should not have errors
Invalid::~Invalid() {}

namespace PR30361 {
template <typename T>
struct C1 {
  ~C1() {}
  operator C1<T>* () { return nullptr; }
  void foo1();
};

template<typename T>
void C1<T>::foo1() {
  C1::operator C1<T>*();
  C1::~C1();
}

void foo1() {
  C1<int> x;
  x.foo1();
}
}
@


1.1.1.6
log
@Import Clang pre-4.0.0 r291444.
@
text
@d1 1
a1 1
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -fcxx-exceptions -verify %s
a259 1
// FIXME: Why are these supposed to not warn?
a313 8
void nowarn0_explicit_dtor(F* f, VB* vb, VD* vd, VF* vf) {
  f->~F();
  f->~F();
  vb->~VB();
  vd->~VD();
  vf->~VF();
}

a328 11
void warn0_explicit_dtor(B* b, B& br, D* d) {
  b->~B(); // expected-warning {{destructor called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} expected-note{{qualify call to silence this warning}}
  b->B::~B(); // No warning when the call isn't virtual.

  br.~B(); // expected-warning {{destructor called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} expected-note{{qualify call to silence this warning}}
  br.B::~B();

  d->~D(); // expected-warning {{destructor called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}} expected-note{{qualify call to silence this warning}}
  d->D::~D();
}

a405 8

class Invalid {
    ~Invalid();
    UnknownType xx; // expected-error{{unknown type name}}
};

// The constructor definition should not have errors
Invalid::~Invalid() {}
@


1.1.1.6.2.1
log
@Sync with HEAD
@
text
@a433 20

namespace PR30361 {
template <typename T>
struct C1 {
  ~C1() {}
  operator C1<T>* () { return nullptr; }
  void foo1();
};

template<typename T>
void C1<T>::foo1() {
  C1::operator C1<T>*();
  C1::~C1();
}

void foo1() {
  C1<int> x;
  x.foo1();
}
}
@


1.1.1.7
log
@Import Clang 4.0RC1 r294123.
@
text
@a433 20

namespace PR30361 {
template <typename T>
struct C1 {
  ~C1() {}
  operator C1<T>* () { return nullptr; }
  void foo1();
};

template<typename T>
void C1<T>::foo1() {
  C1::operator C1<T>*();
  C1::~C1();
}

void foo1() {
  C1<int> x;
  x.foo1();
}
}
@


1.1.1.7.12.1
log
@Sync with HEAD
@
text
@a2 31

#if defined(BE_THE_HEADER)

// Wdelete-non-virtual-dtor should warn about the delete from smart pointer
// classes in system headers (std::unique_ptr...) too.

#pragma clang system_header
namespace dnvd {

struct SystemB {
  virtual void foo();
};

template <typename T>
class simple_ptr {
public:
  simple_ptr(T* t): _ptr(t) {}
  ~simple_ptr() { delete _ptr; } // \
    // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} \
    // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}}
  T& operator*() const { return *_ptr; }
private:
  T* _ptr;
};
}

#else

#define BE_THE_HEADER
#include __FILE__

d216 12
a237 1
void use(SystemB&);
a337 15
// Taken from libc++, slightly simplified.
template <class>
struct __is_destructible_apply { typedef int type; };
struct __two {char __lx[2];};
template <typename _Tp>
struct __is_destructor_wellformed {
  template <typename _Tp1>
  static char __test(typename __is_destructible_apply<
                       decltype(_Tp1().~_Tp1())>::type);
  template <typename _Tp1>
  static __two __test (...);
              
  static const bool value = sizeof(__test<_Tp>(12)) == sizeof(char);
};

a341 3
  // No warning in unevaluated contexts.
  (void)__is_destructor_wellformed<B>::value;

a369 4
  {
    simple_ptr<SystemB> sb(new SystemB());
    use(*sb);
  }
a453 1
#endif // BE_THE_HEADER
@


1.1.1.7.12.2
log
@Mostly merge changes from HEAD upto 20200411
@
text
@@


1.1.1.7.10.1
log
@Sync with HEAD
@
text
@a2 31

#if defined(BE_THE_HEADER)

// Wdelete-non-virtual-dtor should warn about the delete from smart pointer
// classes in system headers (std::unique_ptr...) too.

#pragma clang system_header
namespace dnvd {

struct SystemB {
  virtual void foo();
};

template <typename T>
class simple_ptr {
public:
  simple_ptr(T* t): _ptr(t) {}
  ~simple_ptr() { delete _ptr; } // \
    // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} \
    // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}}
  T& operator*() const { return *_ptr; }
private:
  T* _ptr;
};
}

#else

#define BE_THE_HEADER
#include __FILE__

d216 12
a237 1
void use(SystemB&);
a337 15
// Taken from libc++, slightly simplified.
template <class>
struct __is_destructible_apply { typedef int type; };
struct __two {char __lx[2];};
template <typename _Tp>
struct __is_destructor_wellformed {
  template <typename _Tp1>
  static char __test(typename __is_destructible_apply<
                       decltype(_Tp1().~_Tp1())>::type);
  template <typename _Tp1>
  static __two __test (...);
              
  static const bool value = sizeof(__test<_Tp>(12)) == sizeof(char);
};

a341 3
  // No warning in unevaluated contexts.
  (void)__is_destructor_wellformed<B>::value;

a369 4
  {
    simple_ptr<SystemB> sb(new SystemB());
    use(*sb);
  }
a453 1
#endif // BE_THE_HEADER
@


1.1.1.8
log
@Import clang r337282 from trunk
@
text
@a2 31

#if defined(BE_THE_HEADER)

// Wdelete-non-virtual-dtor should warn about the delete from smart pointer
// classes in system headers (std::unique_ptr...) too.

#pragma clang system_header
namespace dnvd {

struct SystemB {
  virtual void foo();
};

template <typename T>
class simple_ptr {
public:
  simple_ptr(T* t): _ptr(t) {}
  ~simple_ptr() { delete _ptr; } // \
    // expected-warning {{delete called on non-final 'dnvd::B' that has virtual functions but non-virtual destructor}} \
    // expected-warning {{delete called on non-final 'dnvd::D' that has virtual functions but non-virtual destructor}}
  T& operator*() const { return *_ptr; }
private:
  T* _ptr;
};
}

#else

#define BE_THE_HEADER
#include __FILE__

d216 12
a237 1
void use(SystemB&);
a337 15
// Taken from libc++, slightly simplified.
template <class>
struct __is_destructible_apply { typedef int type; };
struct __two {char __lx[2];};
template <typename _Tp>
struct __is_destructor_wellformed {
  template <typename _Tp1>
  static char __test(typename __is_destructible_apply<
                       decltype(_Tp1().~_Tp1())>::type);
  template <typename _Tp1>
  static __two __test (...);
              
  static const bool value = sizeof(__test<_Tp>(12)) == sizeof(char);
};

a341 3
  // No warning in unevaluated contexts.
  (void)__is_destructor_wellformed<B>::value;

a369 4
  {
    simple_ptr<SystemB> sb(new SystemB());
    use(*sb);
  }
a453 1
#endif // BE_THE_HEADER
@


1.1.1.9
log
@Mark old LLVM instance as dead.
@
text
@@


1.1.1.4.4.1
log
@file destructor.cpp was added on branch tls-maxphys on 2014-08-19 23:49:18 +0000
@
text
@d1 388
@


1.1.1.4.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 388
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
// RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
class A {
public:
  ~A();
};

class B {
public:
  ~B() { }
};

class C {
public:
  (~C)() { }
};

struct D {
  static void ~D(int, ...) const { } //                          \
    // expected-error{{static member function cannot have 'const' qualifier}} \
    // expected-error{{destructor cannot be declared 'static'}}  \
    // expected-error{{destructor cannot have any parameters}}   \
    // expected-error{{destructor cannot be variadic}} \
    // expected-error{{destructor cannot have a return type}} \
    // expected-error{{'const' qualifier is not allowed on a destructor}}
};

struct D2 {
  void ~D2() { } //                          \
  // expected-error{{destructor cannot have a return type}}  
};


struct E;

typedef E E_typedef;
struct E {
  ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}}
};

struct F {
  (~F)(); // expected-note {{previous declaration is here}}
  ~F(); // expected-error {{destructor cannot be redeclared}}
};

~; // expected-error {{expected a class name after '~' to name a destructor}}
~undef(); // expected-error {{expected the class name after '~' to name a destructor}}
~operator+(int, int);  // expected-error {{expected a class name after '~' to name a destructor}}
~F(){} // expected-error {{destructor must be a non-static member function}}

struct G {
  ~G();
};

G::~G() { }

// <rdar://problem/6841210>
struct H {
  ~H(void) { } 
};

struct X {};

struct Y {
  ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}}
};

namespace PR6421 {
  class T; // expected-note{{forward declaration}}

  class QGenericArgument // expected-note{{declared here}}
  {
    template<typename U>
    void foo(T t) // expected-error{{variable has incomplete type}}
    { }
    
    void disconnect()
    {
      T* t;
      bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}} \
      // expected-error{{does not refer to a value}}
    }
  };
}

namespace PR6709 {
#ifdef MSABI
  // This bug, "Clang instantiates destructor for function argument" is intended
  // behaviour in the Microsoft ABI because the callee needs to destruct the arguments.
  // expected-error@@+3 {{indirection requires pointer operand ('int' invalid)}}
  // expected-note@@+3 {{in instantiation of member function 'PR6709::X<int>::~X' requested here}}
#endif
  template<class T> class X { T v; ~X() { ++*v; } };
  void a(X<int> x) {}
}

struct X0 { virtual ~X0() throw(); };
struct X1 : public X0 { };

// Make sure we instantiate operator deletes when building a virtual
// destructor.
namespace test6 {
  template <class T> class A {
  public:
    void *operator new(__SIZE_TYPE__);
    void operator delete(void *p) {
      T::deleteIt(p); // expected-error {{type 'int' cannot be used prior to '::'}}
    }

#ifdef MSABI
    // expected-note@@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
#endif
    virtual ~A() {}
  };

#ifndef MSABI
    // expected-note@@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
#endif
  class B : A<int> { B(); };
  B::B() {}
}

// Make sure classes are marked invalid when they have invalid
// members.  This avoids a crash-on-invalid.
namespace test7 {
  struct A {
    ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}}
  };
  struct B : A {};

  void test() {
    B *b;
    b->~B();
  }
}

namespace nonvirtualdtor {
struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct S2 {
  ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct S3 : public S1 {  // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct S4 : public S2 {  // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct B {
  virtual ~B();
  virtual void m();
};

struct S5 : public B {
  virtual void m();
};

struct S6 {
  virtual void m();
private:
  ~S6();
};

struct S7 {
  virtual void m();
protected:
  ~S7();
};

template<class T> class TS : public B {
  virtual void m();
};

TS<int> baz;

template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
  virtual void m();
};

TS2<int> foo; // expected-note {{instantiation}}
}

namespace dnvd { // delete-non-virtual-dtor warning
struct NP {};

struct B { // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void foo();
};

struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}

struct F final : B {};

struct VB {
  virtual void foo();
  virtual ~VB();
};

struct VD: VB {};

struct VF final: VB {};

template <typename T>
class simple_ptr {
public:
  simple_ptr(T* t): _ptr(t) {}
  ~simple_ptr() { delete _ptr; } // \
    // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} \
    // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}}
  T& operator*() const { return *_ptr; }
private:
  T* _ptr;
};

template <typename T>
class simple_ptr2 {
public:
  simple_ptr2(T* t): _ptr(t) {}
  ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
  T& operator*() const { return *_ptr; }
private:
  T* _ptr;
};

void use(B&);
void use(VB&);

void nowarnstack() {
  B b; use(b);
  D d; use(d);
  F f; use(f);
  VB vb; use(vb);
  VD vd; use(vd);
  VF vf; use(vf);
}

void nowarnnonpoly() {
  {
    NP* np = new NP();
    delete np;
  }
  {
    NP* np = new NP[4];
    delete[] np;
  }
}

void nowarnarray() {
  {
    B* b = new B[4];
    delete[] b;
  }
  {
    D* d = new D[4];
    delete[] d;
  }
  {
    VB* vb = new VB[4];
    delete[] vb;
  }
  {
    VD* vd = new VD[4];
    delete[] vd;
  }
}

template <typename T>
void nowarntemplate() {
  {
    T* t = new T();
    delete t;
  }
  {
    T* t = new T[4];
    delete[] t;
  }
}

void nowarn0() {
  {
    F* f = new F();
    delete f;
  }
  {
    VB* vb = new VB();
    delete vb;
  }
  {
    VB* vb = new VD();
    delete vb;
  }
  {
    VD* vd = new VD();
    delete vd;
  }
  {
    VF* vf = new VF();
    delete vf;
  }
}

void warn0() {
  {
    B* b = new B();
    delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
  }
  {
    B* b = new D();
    delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
  }
  {
    D* d = new D();
    delete d; // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}}
  }
}

void nowarn1() {
  {
    simple_ptr<F> f(new F());
    use(*f);
  }
  {
    simple_ptr<VB> vb(new VB());
    use(*vb);
  }
  {
    simple_ptr<VB> vb(new VD());
    use(*vb);
  }
  {
    simple_ptr<VD> vd(new VD());
    use(*vd);
  }
  {
    simple_ptr<VF> vf(new VF());
    use(*vf);
  }
}

void warn1() {
  {
    simple_ptr<B> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}}
    use(*b);
  }
  {
    simple_ptr2<B> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}}
    use(*b);
  }
  {
    simple_ptr<D> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}}
    use(*d);
  }
}
}

namespace PR9238 {
  class B { public: ~B(); };
  class C : virtual B { public: ~C() { } };
}

namespace PR7900 {
  struct A { // expected-note 2{{type 'PR7900::A' is declared here}}
  };
  struct B : public A {
  };
  void foo() {
    B b;
    b.~B();
    b.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
    (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
  }
}

namespace PR16892 {
  auto p = &A::~A; // expected-error{{taking the address of a destructor}}
}

namespace PR20238 {
struct S {
  volatile ~S() { } // expected-error{{destructor cannot have a return type}}
};
}
@


1.1.1.2.4.1
log
@file destructor.cpp was added on branch yamt-pagecache on 2014-05-22 16:19:40 +0000
@
text
@d1 382
@


1.1.1.2.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 382
// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
// RUN: %clang_cc1 -std=c++11 -triple %ms_abi_triple -DMSABI -fsyntax-only -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -verify %s
class A {
public:
  ~A();
};

class B {
public:
  ~B() { }
};

class C {
public:
  (~C)() { }
};

struct D {
  static void ~D(int, ...) const { } //                          \
    // expected-error{{static member function cannot have 'const' qualifier}} \
    // expected-error{{destructor cannot be declared 'static'}}  \
    // expected-error{{destructor cannot have any parameters}}   \
    // expected-error{{destructor cannot be variadic}} \
    // expected-error{{destructor cannot have a return type}} \
    // expected-error{{'const' qualifier is not allowed on a destructor}}
};

struct D2 {
  void ~D2() { } //                          \
  // expected-error{{destructor cannot have a return type}}  
};


struct E;

typedef E E_typedef;
struct E {
  ~E_typedef(); // expected-error{{destructor cannot be declared using a typedef 'E_typedef' (aka 'E') of the class name}}
};

struct F {
  (~F)(); // expected-note {{previous declaration is here}}
  ~F(); // expected-error {{destructor cannot be redeclared}}
};

~; // expected-error {{expected a class name after '~' to name a destructor}}
~undef(); // expected-error {{expected the class name after '~' to name a destructor}}
~operator+(int, int);  // expected-error {{expected a class name after '~' to name a destructor}}
~F(){} // expected-error {{destructor must be a non-static member function}}

struct G {
  ~G();
};

G::~G() { }

// <rdar://problem/6841210>
struct H {
  ~H(void) { } 
};

struct X {};

struct Y {
  ~X(); // expected-error {{expected the class name after '~' to name the enclosing class}}
};

namespace PR6421 {
  class T; // expected-note{{forward declaration}}

  class QGenericArgument // expected-note{{declared here}}
  {
    template<typename U>
    void foo(T t) // expected-error{{variable has incomplete type}}
    { }
    
    void disconnect()
    {
      T* t;
      bob<QGenericArgument>(t); // expected-error{{undeclared identifier 'bob'}} \
      // expected-error{{does not refer to a value}}
    }
  };
}

namespace PR6709 {
#ifdef MSABI
  // This bug, "Clang instantiates destructor for function argument" is intended
  // behaviour in the Microsoft ABI because the callee needs to destruct the arguments.
  // expected-error@@+3 {{indirection requires pointer operand ('int' invalid)}}
  // expected-note@@+3 {{in instantiation of member function 'PR6709::X<int>::~X' requested here}}
#endif
  template<class T> class X { T v; ~X() { ++*v; } };
  void a(X<int> x) {}
}

struct X0 { virtual ~X0() throw(); };
struct X1 : public X0 { };

// Make sure we instantiate operator deletes when building a virtual
// destructor.
namespace test6 {
  template <class T> class A {
  public:
    void *operator new(__SIZE_TYPE__);
    void operator delete(void *p) {
      T::deleteIt(p); // expected-error {{type 'int' cannot be used prior to '::'}}
    }

#ifdef MSABI
    // expected-note@@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
#endif
    virtual ~A() {}
  };

#ifndef MSABI
    // expected-note@@+2 {{in instantiation of member function 'test6::A<int>::operator delete' requested here}}
#endif
  class B : A<int> { B(); };
  B::B() {}
}

// Make sure classes are marked invalid when they have invalid
// members.  This avoids a crash-on-invalid.
namespace test7 {
  struct A {
    ~A() const; // expected-error {{'const' qualifier is not allowed on a destructor}}
  };
  struct B : A {};

  void test() {
    B *b;
    b->~B();
  }
}

namespace nonvirtualdtor {
struct S1 { // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct S2 {
  ~S2(); // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct S3 : public S1 {  // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct S4 : public S2 {  // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void m();
};

struct B {
  virtual ~B();
  virtual void m();
};

struct S5 : public B {
  virtual void m();
};

struct S6 {
  virtual void m();
private:
  ~S6();
};

struct S7 {
  virtual void m();
protected:
  ~S7();
};

template<class T> class TS : public B {
  virtual void m();
};

TS<int> baz;

template<class T> class TS2 { // expected-warning {{'nonvirtualdtor::TS2<int>' has virtual functions but non-virtual destructor}}
  virtual void m();
};

TS2<int> foo; // expected-note {{instantiation}}
}

namespace dnvd { // delete-non-virtual-dtor warning
struct NP {};

struct B { // expected-warning {{has virtual functions but non-virtual destructor}}
  virtual void foo();
};

struct D: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}

struct F final: B {}; // expected-warning {{has virtual functions but non-virtual destructor}}

struct VB {
  virtual void foo();
  virtual ~VB();
};

struct VD: VB {};

struct VF final: VB {};

template <typename T>
class simple_ptr {
public:
  simple_ptr(T* t): _ptr(t) {}
  ~simple_ptr() { delete _ptr; } // \
    // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}} \
    // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}}
  T& operator*() const { return *_ptr; }
private:
  T* _ptr;
};

template <typename T>
class simple_ptr2 {
public:
  simple_ptr2(T* t): _ptr(t) {}
  ~simple_ptr2() { delete _ptr; } // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
  T& operator*() const { return *_ptr; }
private:
  T* _ptr;
};

void use(B&);
void use(VB&);

void nowarnstack() {
  B b; use(b);
  D d; use(d);
  F f; use(f);
  VB vb; use(vb);
  VD vd; use(vd);
  VF vf; use(vf);
}

void nowarnnonpoly() {
  {
    NP* np = new NP();
    delete np;
  }
  {
    NP* np = new NP[4];
    delete[] np;
  }
}

void nowarnarray() {
  {
    B* b = new B[4];
    delete[] b;
  }
  {
    D* d = new D[4];
    delete[] d;
  }
  {
    VB* vb = new VB[4];
    delete[] vb;
  }
  {
    VD* vd = new VD[4];
    delete[] vd;
  }
}

template <typename T>
void nowarntemplate() {
  {
    T* t = new T();
    delete t;
  }
  {
    T* t = new T[4];
    delete[] t;
  }
}

void nowarn0() {
  {
    F* f = new F();
    delete f;
  }
  {
    VB* vb = new VB();
    delete vb;
  }
  {
    VB* vb = new VD();
    delete vb;
  }
  {
    VD* vd = new VD();
    delete vd;
  }
  {
    VF* vf = new VF();
    delete vf;
  }
}

void warn0() {
  {
    B* b = new B();
    delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
  }
  {
    B* b = new D();
    delete b; // expected-warning {{delete called on 'dnvd::B' that has virtual functions but non-virtual destructor}}
  }
  {
    D* d = new D();
    delete d; // expected-warning {{delete called on 'dnvd::D' that has virtual functions but non-virtual destructor}}
  }
}

void nowarn1() {
  {
    simple_ptr<F> f(new F());
    use(*f);
  }
  {
    simple_ptr<VB> vb(new VB());
    use(*vb);
  }
  {
    simple_ptr<VB> vb(new VD());
    use(*vb);
  }
  {
    simple_ptr<VD> vd(new VD());
    use(*vd);
  }
  {
    simple_ptr<VF> vf(new VF());
    use(*vf);
  }
}

void warn1() {
  {
    simple_ptr<B> b(new B()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::B>::~simple_ptr' requested here}}
    use(*b);
  }
  {
    simple_ptr2<B> b(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr2<dnvd::B>::~simple_ptr2' requested here}}
    use(*b);
  }
  {
    simple_ptr<D> d(new D()); // expected-note {{in instantiation of member function 'dnvd::simple_ptr<dnvd::D>::~simple_ptr' requested here}}
    use(*d);
  }
}
}

namespace PR9238 {
  class B { public: ~B(); };
  class C : virtual B { public: ~C() { } };
}

namespace PR7900 {
  struct A { // expected-note 2{{type 'PR7900::A' is declared here}}
  };
  struct B : public A {
  };
  void foo() {
    B b;
    b.~B();
    b.~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
    (&b)->~A(); // expected-error{{destructor type 'PR7900::A' in object destruction expression does not match the type 'PR7900::B' of the object being destroyed}}
  }
}

namespace PR16892 {
  auto p = &A::~A; // expected-error{{taking the address of a destructor}}
}
@


