1 | // RUN: %clang_cc1 -std=c++1z -emit-llvm -triple x86_64-linux-gnu -o - %s | FileCheck %s |
2 | |
3 | struct A { |
4 | A(int); |
5 | A(A&&); |
6 | A(const A&); |
7 | ~A(); |
8 | |
9 | operator bool(); |
10 | |
11 | int arr[10]; |
12 | }; |
13 | |
14 | A f(); |
15 | void h(); |
16 | |
17 | // CHECK-LABEL: define {{.*}} @_Z1gv( |
18 | void g() { |
19 | // CHECK: %[[A:.*]] = alloca |
20 | // CHECK-NOT: alloca |
21 | // CHECK-NOT: call |
22 | // CHECK: call {{.*}} @_Z1fv({{.*}}* sret %[[A]]) |
23 | A a = A( A{ f() } ); |
24 | // CHECK-NOT: call |
25 | |
26 | // CHECK: call void @_Z1hv( |
27 | h(); |
28 | // CHECK-NOT: call |
29 | |
30 | // CHECK: call void @_ZN1AD1Ev({{.*}}* %[[A]]) |
31 | // CHECK-NOT: call |
32 | // CHECK-LABEL: } |
33 | } |
34 | |
35 | void f(A); |
36 | |
37 | // CHECK-LABEL: define {{.*}} @_Z1hv( |
38 | void h() { |
39 | // CHECK: %[[A:.*]] = alloca |
40 | // CHECK-NOT: alloca |
41 | // CHECK-NOT: call |
42 | |
43 | // CHECK: call {{.*}} @_Z1fv({{.*}}* sret %[[A]]) |
44 | // CHECK-NOT: call |
45 | // CHECK: call {{.*}} @_Z1f1A({{.*}}* %[[A]]) |
46 | f(f()); |
47 | // CHECK-NOT: call |
48 | // CHECK: call void @_ZN1AD1Ev({{.*}}* %[[A]]) |
49 | |
50 | // CHECK: call void @_Z1hv( |
51 | h(); |
52 | |
53 | // CHECK-NOT: call |
54 | // CHECK-LABEL: } |
55 | } |
56 | |
57 | // We still pass classes with trivial copy/move constructors and destructors in |
58 | // registers, even if the copy is formally omitted. |
59 | struct B { |
60 | B(int); |
61 | int n; |
62 | }; |
63 | |
64 | B fB(); |
65 | void fB(B); |
66 | |
67 | // CHECK-LABEL: define {{.*}} @_Z1iv( |
68 | void i() { |
69 | // CHECK: %[[B:.*]] = alloca |
70 | // CHECK-NOT: alloca |
71 | // CHECK-NOT: call |
72 | |
73 | // CHECK: %[[B_N:.*]] = call i32 @_Z2fBv() |
74 | // CHECK-NOT: call |
75 | // CHECK: store i32 %[[B_N]], |
76 | // CHECK-NOT: call |
77 | // CHECK: %[[B_N:.*]] = load i32 |
78 | // CHECK-NOT: call |
79 | // CHECK: call void @_Z2fB1B(i32 %[[B_N]]) |
80 | fB(fB()); |
81 | |
82 | // CHECK-LABEL: } |
83 | } |
84 | |
85 | // CHECK-LABEL: define {{.*}} @_Z1jv( |
86 | void j() { |
87 | // CHECK: alloca %{{.*}}* |
88 | // CHECK: %[[OUTERTEMP:.*]] = alloca %{{.*}} |
89 | // CHECK: %[[INNERTEMP:.*]] = alloca %{{.*}} |
90 | // CHECK: call void @_ZN1AC1Ei(%{{.*}} %[[INNERTEMP]], i32 1) |
91 | // CHECK: call zeroext i1 @_ZN1AcvbEv(%{{.*}} %[[INNERTEMP]]) |
92 | // CHECK: br i1 |
93 | // |
94 | // CHECK: call void @_ZN1AC1EOS_(%{{.*}} %[[OUTERTEMP]], %{{.*}} %[[INNERTEMP]]) |
95 | // CHECK: br label |
96 | // |
97 | // CHECK: call void @_ZN1AC1Ei(%{{.*}} %[[OUTERTEMP]], i32 2) |
98 | // CHECK: br label |
99 | // |
100 | // CHECK: call void @_ZN1AD1Ev(%{{.*}} %[[INNERTEMP]]) |
101 | A &&a = A(1) ?: A(2); |
102 | |
103 | // CHECK: call void @_Z1iv() |
104 | i(); |
105 | |
106 | // CHECK: call void @_ZN1AD1Ev(%{{.*}} %[[OUTERTEMP]]) |
107 | } |
108 | |