1// RUN: %clang_cc1 -std=c++11 %s -emit-llvm -o - | FileCheck %s
2
3namespace Test1 {
4  struct A {
5    virtual int f() final;
6  };
7
8  // CHECK: define i32 @_ZN5Test11fEPNS_1AE
9  int f(A *a) {
10    // CHECK: call i32 @_ZN5Test11A1fEv
11    return a->f();
12  }
13}
14
15namespace Test2 {
16  struct A final {
17    virtual int f();
18  };
19
20  // CHECK: define i32 @_ZN5Test21fEPNS_1AE
21  int f(A *a) {
22    // CHECK: call i32 @_ZN5Test21A1fEv
23    return a->f();
24  }
25}
26
27namespace Test3 {
28  struct A {
29    virtual int f();
30  };
31
32  struct B final : A { };
33
34  // CHECK: define i32 @_ZN5Test31fEPNS_1BE
35  int f(B *b) {
36    // CHECK: call i32 @_ZN5Test31A1fEv
37    return b->f();
38  }
39
40  // CHECK: define i32 @_ZN5Test31fERNS_1BE
41  int f(B &b) {
42    // CHECK: call i32 @_ZN5Test31A1fEv
43    return b.f();
44  }
45
46  // CHECK: define i32 @_ZN5Test31fEPv
47  int f(void *v) {
48    // CHECK: call i32 @_ZN5Test31A1fEv
49    return static_cast<B*>(v)->f();
50  }
51}
52
53namespace Test4 {
54  struct A {
55    virtual void f();
56  };
57
58  struct B final : A {
59    virtual void f();
60  };
61
62  // CHECK: define void @_ZN5Test41fEPNS_1BE
63  void f(B* d) {
64    // CHECK: call void @_ZN5Test41B1fEv
65    static_cast<A*>(d)->f();
66  }
67}
68
69namespace Test5 {
70  struct A {
71    virtual void f();
72  };
73
74  struct B : A {
75    virtual void f();
76  };
77
78  struct C final : B {
79  };
80
81  // CHECK: define void @_ZN5Test51fEPNS_1CE
82  void f(C* d) {
83    // FIXME: It should be possible to devirtualize this case, but that is
84    // not implemented yet.
85    // CHECK: getelementptr
86    // CHECK-NEXT: %[[FUNC:.*]] = load
87    // CHECK-NEXT: call void %[[FUNC]]
88    static_cast<A*>(d)->f();
89  }
90}
91
92namespace Test6 {
93  struct A {
94    virtual ~A();
95  };
96
97  struct B : public A {
98    virtual ~B();
99  };
100
101  struct C {
102    virtual ~C();
103  };
104
105  struct D final : public C, public B {
106  };
107
108  // CHECK: define void @_ZN5Test61fEPNS_1DE
109  void f(D* d) {
110    // CHECK: call void @_ZN5Test61DD1Ev
111    static_cast<A*>(d)->~A();
112  }
113}
114
115namespace Test7 {
116  struct foo {
117    virtual void g() {}
118  };
119
120  struct bar {
121    virtual int f() { return 0; }
122  };
123
124  struct zed final : public foo, public bar {
125    int z;
126    virtual int f() {return z;}
127  };
128
129  // CHECK: define i32 @_ZN5Test71fEPNS_3zedE
130  int f(zed *z) {
131    // CHECK: alloca
132    // CHECK-NEXT: store
133    // CHECK-NEXT: load
134    // CHECK-NEXT: bitcast
135    // CHECK-NEXT: call {{.*}} @_ZN5Test73zed1fEv
136    // CHECK-NEXT: ret
137    return static_cast<bar*>(z)->f();
138  }
139}
140
141namespace Test8 {
142  struct A { virtual ~A() {} };
143  struct B {
144    int b;
145    virtual int foo() { return b; }
146  };
147  struct C final : A, B {  };
148  // CHECK: define i32 @_ZN5Test84testEPNS_1CE
149  int test(C *c) {
150    // CHECK: %[[THIS:.*]] = phi
151    // CHECK-NEXT: call i32 @_ZN5Test81B3fooEv(%"struct.Test8::B"* %[[THIS]])
152    return static_cast<B*>(c)->foo();
153  }
154}
155
156namespace Test9 {
157  struct A {
158    int a;
159  };
160  struct B {
161    int b;
162  };
163  struct C : public B, public A {
164  };
165  struct RA {
166    virtual A *f() {
167      return 0;
168    }
169  };
170  struct RC final : public RA {
171    virtual C *f() {
172      C *x = new C();
173      x->a = 1;
174      x->b = 2;
175      return x;
176    }
177  };
178  // CHECK: define {{.*}} @_ZN5Test91fEPNS_2RCE
179  A *f(RC *x) {
180    // FIXME: It should be possible to devirtualize this case, but that is
181    // not implemented yet.
182    // CHECK: getelementptr
183    // CHECK-NEXT: %[[FUNC:.*]] = load
184    // CHECK-NEXT: bitcast
185    // CHECK-NEXT: = call {{.*}} %[[FUNC]]
186    return static_cast<RA*>(x)->f();
187  }
188}
189