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  };
57
58  struct B final : A {
59    virtual void f();
60  };
61
62  // CHECK-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: define i32 @_ZN5Test71fEPNS_3zedE
130  int f(zed *z) {
131    // CHECK: alloca
132    // CHECK-NEXT: store
133    // CHECK-NEXT: load
134    // CHECK-NEXT: call i32 @_ZN5Test73zed1fEv
135    // CHECK-NEXT: ret
136    return static_cast<bar*>(z)->f();
137  }
138}
139
140namespace Test8 {
141  struct A { virtual ~A() {} };
142  struct B {
143    int b;
144    virtual int foo() { return b; }
145  };
146  struct C final : A, B {  };
147  // CHECK-LABEL: define i32 @_ZN5Test84testEPNS_1CE
148  int test(C *c) {
149    // CHECK: %[[THIS:.*]] = phi
150    // CHECK-NEXT: call i32 @_ZN5Test81B3fooEv(%"struct.Test8::B"* %[[THIS]])
151    return static_cast<B*>(c)->foo();
152  }
153}
154
155namespace Test9 {
156  struct A {
157    int a;
158  };
159  struct B {
160    int b;
161  };
162  struct C : public B, public A {
163  };
164  struct RA {
165    virtual A *f() {
166      return 0;
167    }
168  };
169  struct RC final : public RA {
170    virtual C *f() {
171      C *x = new C();
172      x->a = 1;
173      x->b = 2;
174      return x;
175    }
176  };
177  // CHECK: define {{.*}} @_ZN5Test91fEPNS_2RCE
178  A *f(RC *x) {
179    // FIXME: It should be possible to devirtualize this case, but that is
180    // not implemented yet.
181    // CHECK: getelementptr
182    // CHECK-NEXT: %[[FUNC:.*]] = load
183    // CHECK-NEXT: bitcast
184    // CHECK-NEXT: = call {{.*}} %[[FUNC]]
185    return static_cast<RA*>(x)->f();
186  }
187}
188