1// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 %s -emit-llvm -o - | FileCheck %s
2
3namespace Test1 {
4  struct A {
5    virtual int f() final;
6  };
7
8  // CHECK-LABEL: 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-LABEL: 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-LABEL: define i32 @_ZN5Test31fEPNS_1BE
35  int f(B *b) {
36    // CHECK: call i32 @_ZN5Test31A1fEv
37    return b->f();
38  }
39
40  // CHECK-LABEL: define i32 @_ZN5Test31fERNS_1BE
41  int f(B &b) {
42    // CHECK: call i32 @_ZN5Test31A1fEv
43    return b.f();
44  }
45
46  // CHECK-LABEL: 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    virtual int operator-();
57  };
58
59  struct B final : A {
60    virtual void f();
61    virtual int operator-();
62  };
63
64  // CHECK-LABEL: define void @_ZN5Test41fEPNS_1BE
65  void f(B* d) {
66    // CHECK: call void @_ZN5Test41B1fEv
67    static_cast<A*>(d)->f();
68    // CHECK: call i32 @_ZN5Test41BngEv
69    -static_cast<A&>(*d);
70  }
71}
72
73namespace Test5 {
74  struct A {
75    virtual void f();
76    virtual int operator-();
77  };
78
79  struct B : A {
80    virtual void f();
81    virtual int operator-();
82  };
83
84  struct C final : B {
85  };
86
87  // CHECK-LABEL: define void @_ZN5Test51fEPNS_1CE
88  void f(C* d) {
89    // FIXME: It should be possible to devirtualize this case, but that is
90    // not implemented yet.
91    // CHECK: getelementptr
92    // CHECK-NEXT: %[[FUNC:.*]] = load
93    // CHECK-NEXT: call void %[[FUNC]]
94    static_cast<A*>(d)->f();
95  }
96  // CHECK-LABEL: define void @_ZN5Test53fopEPNS_1CE
97  void fop(C* d) {
98    // FIXME: It should be possible to devirtualize this case, but that is
99    // not implemented yet.
100    // CHECK: getelementptr
101    // CHECK-NEXT: %[[FUNC:.*]] = load
102    // CHECK-NEXT: call i32 %[[FUNC]]
103    -static_cast<A&>(*d);
104  }
105}
106
107namespace Test6 {
108  struct A {
109    virtual ~A();
110  };
111
112  struct B : public A {
113    virtual ~B();
114  };
115
116  struct C {
117    virtual ~C();
118  };
119
120  struct D final : public C, public B {
121  };
122
123  // CHECK-LABEL: define void @_ZN5Test61fEPNS_1DE
124  void f(D* d) {
125    // CHECK: call void @_ZN5Test61DD1Ev
126    static_cast<A*>(d)->~A();
127  }
128}
129
130namespace Test7 {
131  struct foo {
132    virtual void g() {}
133  };
134
135  struct bar {
136    virtual int f() { return 0; }
137  };
138
139  struct zed final : public foo, public bar {
140    int z;
141    virtual int f() {return z;}
142  };
143
144  // CHECK-LABEL: define i32 @_ZN5Test71fEPNS_3zedE
145  int f(zed *z) {
146    // CHECK: alloca
147    // CHECK-NEXT: store
148    // CHECK-NEXT: load
149    // CHECK-NEXT: call i32 @_ZN5Test73zed1fEv
150    // CHECK-NEXT: ret
151    return static_cast<bar*>(z)->f();
152  }
153}
154
155namespace Test8 {
156  struct A { virtual ~A() {} };
157  struct B {
158    int b;
159    virtual int foo() { return b; }
160  };
161  struct C final : A, B {  };
162  // CHECK-LABEL: define i32 @_ZN5Test84testEPNS_1CE
163  int test(C *c) {
164    // CHECK: %[[THIS:.*]] = phi
165    // CHECK-NEXT: call i32 @_ZN5Test81B3fooEv(%"struct.Test8::B"* %[[THIS]])
166    return static_cast<B*>(c)->foo();
167  }
168}
169
170namespace Test9 {
171  struct A {
172    int a;
173  };
174  struct B {
175    int b;
176  };
177  struct C : public B, public A {
178  };
179  struct RA {
180    virtual A *f() {
181      return 0;
182    }
183    virtual A *operator-() {
184      return 0;
185    }
186  };
187  struct RC final : public RA {
188    virtual C *f() {
189      C *x = new C();
190      x->a = 1;
191      x->b = 2;
192      return x;
193    }
194    virtual C *operator-() {
195      C *x = new C();
196      x->a = 1;
197      x->b = 2;
198      return x;
199    }
200  };
201  // CHECK: define {{.*}} @_ZN5Test91fEPNS_2RCE
202  A *f(RC *x) {
203    // FIXME: It should be possible to devirtualize this case, but that is
204    // not implemented yet.
205    // CHECK: load
206    // CHECK: bitcast
207    // CHECK: [[F_PTR_RA:%.+]] = bitcast
208    // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]]
209    // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 0
210    // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]]
211    // CHECK-NEXT: = call {{.*}} %[[FUNC]]
212    return static_cast<RA*>(x)->f();
213  }
214  // CHECK: define {{.*}} @_ZN5Test93fopEPNS_2RCE
215  A *fop(RC *x) {
216    // FIXME: It should be possible to devirtualize this case, but that is
217    // not implemented yet.
218    // CHECK: load
219    // CHECK: bitcast
220    // CHECK: [[F_PTR_RA:%.+]] = bitcast
221    // CHECK: [[VTABLE:%.+]] = load {{.+}} [[F_PTR_RA]]
222    // CHECK: [[VFN:%.+]] = getelementptr inbounds {{.+}} [[VTABLE]], i{{[0-9]+}} 1
223    // CHECK-NEXT: %[[FUNC:.*]] = load {{.+}} [[VFN]]
224    // CHECK-NEXT: = call {{.*}} %[[FUNC]]
225    return -static_cast<RA&>(*x);
226  }
227}
228