1 // RUN: %clang_cc1 -verify -std=c++11 %s
2 // expected-no-diagnostics
3 template <typename T> struct OwnPtr {
4   T *p;
5   ~OwnPtr() {
6     static_assert(sizeof(T) > 0, "incomplete T");
7     delete p;
8   }
9 };
10 
11 namespace use_vtable_for_vcall {
12 struct Incomplete;
13 struct A {
14   virtual ~A() {}
15   virtual void m() {}
16 };
17 struct B : A {
18   B();
19   virtual void m() { }
20   virtual void m2() { static_cast<A *>(this)->m(); }
21   OwnPtr<Incomplete> m_sqlError;
22 };
23 
24 void f() {
25   // Since B's constructor is declared out of line, nothing in this file
26   // references a vtable, so the destructor doesn't get built.
27   A *b = new B();
28   b->m();
29   delete b;
30 }
31 }
32 
33 namespace dont_mark_qualified_vcall {
34 struct Incomplete;
35 struct A {
36   virtual ~A() {}
37   virtual void m() {}
38 };
39 struct B : A {
40   B();
41   // Previously we would mark B's vtable referenced to devirtualize this call to
42   // A::m, even though it's not a virtual call.
43   virtual void m() { A::m(); }
44   OwnPtr<Incomplete> m_sqlError;
45 };
46 
47 B *f() {
48   return new B();
49 }
50 }
51