1 | // RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++11 -emit-llvm %s -o - | FileCheck %s |
2 | |
3 | struct A { |
4 | A(const A&); |
5 | A(); |
6 | ~A(); |
7 | }; |
8 | |
9 | struct B : public A { |
10 | B(); |
11 | B(const B& Other); |
12 | ~B(); |
13 | }; |
14 | |
15 | struct C : public B { |
16 | C(); |
17 | C(const C& Other); |
18 | ~C(); |
19 | }; |
20 | |
21 | struct X { |
22 | operator B&(); |
23 | operator C&(); |
24 | X(const X&); |
25 | X(); |
26 | ~X(); |
27 | B b; |
28 | C c; |
29 | }; |
30 | |
31 | void test0_helper(A); |
32 | void test0(X x) { |
33 | test0_helper(x); |
34 | // CHECK-LABEL: define void @_Z5test01X( |
35 | // CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align |
36 | // CHECK-NEXT: [[T0:%.*]] = call dereferenceable({{[0-9]+}}) [[B:%.*]]* @_ZN1XcvR1BEv( |
37 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]* [[T0]] to [[A]]* |
38 | // CHECK-NEXT: call void @_ZN1AC1ERKS_([[A]]* [[TMP]], [[A]]* dereferenceable({{[0-9]+}}) [[T1]]) |
39 | // CHECK-NEXT: call void @_Z12test0_helper1A([[A]]* [[TMP]]) |
40 | // CHECK-NEXT: call void @_ZN1AD1Ev([[A]]* [[TMP]]) |
41 | // CHECK-NEXT: ret void |
42 | } |
43 | |
44 | struct Base; |
45 | |
46 | struct Root { |
47 | operator Base&(); |
48 | }; |
49 | |
50 | struct Derived; |
51 | |
52 | struct Base : Root { |
53 | Base(const Base &); |
54 | Base(); |
55 | operator Derived &(); |
56 | }; |
57 | |
58 | struct Derived : Base { |
59 | }; |
60 | |
61 | void test1_helper(Base); |
62 | void test1(Derived bb) { |
63 | // CHECK-LABEL: define void @_Z5test17Derived( |
64 | // CHECK-NOT: call {{.*}} @_ZN4BasecvR7DerivedEv( |
65 | // CHECK: call void @_ZN4BaseC1ERKS_( |
66 | // CHECK-NOT: call {{.*}} @_ZN4BasecvR7DerivedEv( |
67 | // CHECK: call void @_Z12test1_helper4Base( |
68 | test1_helper(bb); |
69 | } |
70 | |
71 | // Don't crash after devirtualizing a derived-to-base conversion |
72 | // to an empty base allocated at offset zero. |
73 | // rdar://problem/11993704 |
74 | class Test2a {}; |
75 | class Test2b final : public virtual Test2a {}; |
76 | void test2(Test2b &x) { |
77 | Test2a &y = x; |
78 | // CHECK-LABEL: define void @_Z5test2R6Test2b( |
79 | // CHECK: [[X:%.*]] = alloca [[B:%.*]]*, align 8 |
80 | // CHECK-NEXT: [[Y:%.*]] = alloca [[A:%.*]]*, align 8 |
81 | // CHECK-NEXT: store [[B]]* {{%.*}}, [[B]]** [[X]], align 8 |
82 | // CHECK-NEXT: [[T0:%.*]] = load [[B]]*, [[B]]** [[X]], align 8 |
83 | // CHECK-NEXT: [[T1:%.*]] = bitcast [[B]]* [[T0]] to [[A]]* |
84 | // CHECK-NEXT: store [[A]]* [[T1]], [[A]]** [[Y]], align 8 |
85 | // CHECK-NEXT: ret void |
86 | } |
87 | |