| // RUN: %clang_cc1 -verify -std=c++11 %s |
| // expected-no-diagnostics |
| template <typename T> struct OwnPtr { |
| T *p; |
| ~OwnPtr() { |
| static_assert(sizeof(T) > 0, "incomplete T"); |
| delete p; |
| } |
| }; |
| |
| namespace use_vtable_for_vcall { |
| struct Incomplete; |
| struct A { |
| virtual ~A() {} |
| virtual void m() {} |
| }; |
| struct B : A { |
| B(); |
| virtual void m() { } |
| virtual void m2() { static_cast<A *>(this)->m(); } |
| OwnPtr<Incomplete> m_sqlError; |
| }; |
| |
| void f() { |
| // Since B's constructor is declared out of line, nothing in this file |
| // references a vtable, so the destructor doesn't get built. |
| A *b = new B(); |
| b->m(); |
| delete b; |
| } |
| } |
| |
| namespace dont_mark_qualified_vcall { |
| struct Incomplete; |
| struct A { |
| virtual ~A() {} |
| virtual void m() {} |
| }; |
| struct B : A { |
| B(); |
| // Previously we would mark B's vtable referenced to devirtualize this call to |
| // A::m, even though it's not a virtual call. |
| virtual void m() { A::m(); } |
| OwnPtr<Incomplete> m_sqlError; |
| }; |
| |
| B *f() { |
| return new B(); |
| } |
| } |