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