1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 %s -fsyntax-only -verify -Wweak-vtables -Wweak-template-vtables 2*f4a2713aSLionel Sambuc 3*f4a2713aSLionel Sambuc struct A { // expected-warning {{'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} 4*f4a2713aSLionel Sambuc virtual void f() { } 5*f4a2713aSLionel Sambuc }; 6*f4a2713aSLionel Sambuc 7*f4a2713aSLionel Sambuc template<typename T> struct B { 8*f4a2713aSLionel Sambuc virtual void f() { } 9*f4a2713aSLionel Sambuc }; 10*f4a2713aSLionel Sambuc 11*f4a2713aSLionel Sambuc namespace { 12*f4a2713aSLionel Sambuc struct C { 13*f4a2713aSLionel Sambuc virtual void f() { } 14*f4a2713aSLionel Sambuc }; 15*f4a2713aSLionel Sambuc } 16*f4a2713aSLionel Sambuc 17*f4a2713aSLionel Sambuc void f() { 18*f4a2713aSLionel Sambuc struct A { 19*f4a2713aSLionel Sambuc virtual void f() { } 20*f4a2713aSLionel Sambuc }; 21*f4a2713aSLionel Sambuc 22*f4a2713aSLionel Sambuc A *a; 23*f4a2713aSLionel Sambuc a->f(); 24*f4a2713aSLionel Sambuc } 25*f4a2713aSLionel Sambuc 26*f4a2713aSLionel Sambuc // Use the vtables 27*f4a2713aSLionel Sambuc void uses(A &a, B<int> &b, C &c) { 28*f4a2713aSLionel Sambuc a.f(); 29*f4a2713aSLionel Sambuc b.f(); 30*f4a2713aSLionel Sambuc c.f(); 31*f4a2713aSLionel Sambuc } 32*f4a2713aSLionel Sambuc 33*f4a2713aSLionel Sambuc // <rdar://problem/9979458> 34*f4a2713aSLionel Sambuc class Parent { 35*f4a2713aSLionel Sambuc public: 36*f4a2713aSLionel Sambuc Parent() {} 37*f4a2713aSLionel Sambuc virtual ~Parent(); 38*f4a2713aSLionel Sambuc virtual void * getFoo() const = 0; 39*f4a2713aSLionel Sambuc }; 40*f4a2713aSLionel Sambuc 41*f4a2713aSLionel Sambuc class Derived : public Parent { 42*f4a2713aSLionel Sambuc public: 43*f4a2713aSLionel Sambuc Derived(); 44*f4a2713aSLionel Sambuc void * getFoo() const; 45*f4a2713aSLionel Sambuc }; 46*f4a2713aSLionel Sambuc 47*f4a2713aSLionel Sambuc class VeryDerived : public Derived { // expected-warning{{'VeryDerived' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} 48*f4a2713aSLionel Sambuc public: 49*f4a2713aSLionel Sambuc void * getFoo() const { return 0; } 50*f4a2713aSLionel Sambuc }; 51*f4a2713aSLionel Sambuc 52*f4a2713aSLionel Sambuc Parent::~Parent() {} 53*f4a2713aSLionel Sambuc 54*f4a2713aSLionel Sambuc void uses(Parent &p, Derived &d, VeryDerived &vd) { 55*f4a2713aSLionel Sambuc p.getFoo(); 56*f4a2713aSLionel Sambuc d.getFoo(); 57*f4a2713aSLionel Sambuc vd.getFoo(); 58*f4a2713aSLionel Sambuc } 59*f4a2713aSLionel Sambuc 60*f4a2713aSLionel Sambuc template<typename T> struct TemplVirt { 61*f4a2713aSLionel Sambuc virtual void f(); 62*f4a2713aSLionel Sambuc }; 63*f4a2713aSLionel Sambuc 64*f4a2713aSLionel Sambuc template class TemplVirt<float>; // expected-warning{{explicit template instantiation 'TemplVirt<float>' will emit a vtable in every translation unit}} 65*f4a2713aSLionel Sambuc 66*f4a2713aSLionel Sambuc template<> struct TemplVirt<bool> { 67*f4a2713aSLionel Sambuc virtual void f(); 68*f4a2713aSLionel Sambuc }; 69*f4a2713aSLionel Sambuc 70*f4a2713aSLionel Sambuc template<> struct TemplVirt<long> { // expected-warning{{'TemplVirt<long>' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit}} 71*f4a2713aSLionel Sambuc virtual void f() {} 72*f4a2713aSLionel Sambuc }; 73*f4a2713aSLionel Sambuc 74*f4a2713aSLionel Sambuc void uses(TemplVirt<float>& f, TemplVirt<bool>& b, TemplVirt<long>& l) { 75*f4a2713aSLionel Sambuc f.f(); 76*f4a2713aSLionel Sambuc b.f(); 77*f4a2713aSLionel Sambuc l.f(); 78*f4a2713aSLionel Sambuc } 79