1 // RUN: %clang_cc1 -std=c++20 -fblocks -Wno-return-stack-address -triple x86_64-unknown-unknown-gnu -emit-llvm -O1 -fexperimental-new-pass-manager -o - %s | FileCheck %s
2 
3 struct X {
4     X();
5     X(const X&);
6     X(X&&);
7 };
8 
9 #define L(A, B, C) void l##A() {    \
10   auto t = []<class T = X>() -> C { \
11     T t;                            \
12     return B;                       \
13   }();                              \
14 }
15 
16 // CHECK-LABEL: define{{.*}} void @_Z2l1v
17 // CHECK:       call {{.*}} @_ZN1XC1Ev
18 // CHECK-NEXT:  call void @llvm.lifetime.end
19 // CHECK-NEXT:  ret void
20 L(1, t, X);
21 
22 // CHECK-LABEL: define{{.*}} void @_Z2l2v
23 // CHECK:       call {{.*}} @_ZN1XC1Ev
24 // CHECK-NEXT:  call void @llvm.lifetime.end
25 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
26 // CHECK-NEXT:  call void @llvm.lifetime.end
27 // CHECK-NEXT:  ret void
28 L(2, t, X&);
29 
30 // CHECK-LABEL: define{{.*}} void @_Z2l3v
31 // CHECK:       call {{.*}} @_ZN1XC1Ev
32 // CHECK-NEXT:  call void @llvm.lifetime.end
33 // CHECK-NEXT:  ret void
34 L(3, t, T);
35 
36 // CHECK-LABEL: define{{.*}} void @_Z2l4v
37 // CHECK:       call {{.*}} @_ZN1XC1Ev
38 // CHECK-NEXT:  call void @llvm.lifetime.end
39 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
40 // CHECK-NEXT:  call void @llvm.lifetime.end
41 // CHECK-NEXT:  ret void
42 L(4, t, T&);
43 
44 // CHECK-LABEL: define{{.*}} void @_Z2l5v
45 // CHECK:       call {{.*}} @_ZN1XC1Ev
46 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
47 // CHECK-NEXT:  call void @llvm.lifetime.end
48 // CHECK-NEXT:  call void @llvm.lifetime.end
49 // CHECK-NEXT:  ret void
50 L(5, t, auto);
51 
52 // CHECK-LABEL: define{{.*}} void @_Z2l6v
53 // CHECK:       call {{.*}} @_ZN1XC1Ev
54 // CHECK-NEXT:  call void @llvm.lifetime.end
55 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
56 // CHECK-NEXT:  call void @llvm.lifetime.end
57 // CHECK-NEXT:  ret void
58 L(6, t, auto&);
59 
60 // CHECK-LABEL: define{{.*}} void @_Z2l7v
61 // CHECK:       call {{.*}} @_ZN1XC1Ev
62 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
63 // CHECK-NEXT:  call void @llvm.lifetime.end
64 // CHECK-NEXT:  call void @llvm.lifetime.end
65 // CHECK-NEXT:  ret void
66 L(7, t, decltype(auto));
67 
68 // CHECK-LABEL: define{{.*}} void @_Z2l8v
69 // CHECK:       call {{.*}} @_ZN1XC1Ev
70 // CHECK-NEXT:  call void @llvm.lifetime.end
71 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
72 // CHECK-NEXT:  call void @llvm.lifetime.end
73 // CHECK-NEXT:  ret void
74 L(8, (t), decltype(auto));
75 
76 #undef L
77 
78 #define F(A, B, C) template<class T = X> static inline auto tf##A() -> C { \
79     T t;                                                                   \
80     return B;                                                              \
81 }                                                                          \
82 void f##A() { auto t = tf##A(); }                                          \
83 
84 // CHECK-LABEL: define{{.*}} void @_Z2f1v
85 // CHECK:       call {{.*}} @_ZN1XC1Ev
86 // CHECK-NEXT:  call void @llvm.lifetime.end
87 // CHECK-NEXT:  ret void
88 F(1, t, X);
89 
90 // CHECK-LABEL: define{{.*}} void @_Z2f2v
91 // CHECK:       call {{.*}} @_ZN1XC1Ev
92 // CHECK-NEXT:  call void @llvm.lifetime.end
93 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
94 // CHECK-NEXT:  call void @llvm.lifetime.end
95 // CHECK-NEXT:  ret void
96 F(2, t, X&);
97 
98 // CHECK-LABEL: define{{.*}} void @_Z2f3v
99 // CHECK:       call {{.*}} @_ZN1XC1Ev
100 // CHECK-NEXT:  call void @llvm.lifetime.end
101 // CHECK-NEXT:  ret void
102 F(3, t, T);
103 
104 // CHECK-LABEL: define{{.*}} void @_Z2f4v
105 // CHECK:       call {{.*}} @_ZN1XC1Ev
106 // CHECK-NEXT:  call void @llvm.lifetime.end
107 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
108 // CHECK-NEXT:  call void @llvm.lifetime.end
109 // CHECK-NEXT:  ret void
110 F(4, t, T&);
111 
112 // CHECK-LABEL: define{{.*}} void @_Z2f5v
113 // CHECK:       call {{.*}} @_ZN1XC1Ev
114 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
115 // CHECK-NEXT:  call void @llvm.lifetime.end
116 // CHECK-NEXT:  call void @llvm.lifetime.end
117 // CHECK-NEXT:  ret void
118 F(5, t, auto);
119 
120 // CHECK-LABEL: define{{.*}} void @_Z2f6v
121 // CHECK:       call {{.*}} @_ZN1XC1Ev
122 // CHECK-NEXT:  call void @llvm.lifetime.end
123 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
124 // CHECK-NEXT:  call void @llvm.lifetime.end
125 // CHECK-NEXT:  ret void
126 F(6, t, auto&);
127 
128 // CHECK-LABEL: define{{.*}} void @_Z2f7v
129 // CHECK:       call {{.*}} @_ZN1XC1Ev
130 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
131 // CHECK-NEXT:  call void @llvm.lifetime.end
132 // CHECK-NEXT:  call void @llvm.lifetime.end
133 // CHECK-NEXT:  ret void
134 F(7, t, decltype(auto));
135 
136 // CHECK-LABEL: define{{.*}} void @_Z2f8v
137 // CHECK:       call {{.*}} @_ZN1XC1Ev
138 // CHECK-NEXT:  call void @llvm.lifetime.end
139 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
140 // CHECK-NEXT:  call void @llvm.lifetime.end
141 // CHECK-NEXT:  ret void
142 F(8, (t), decltype(auto));
143 
144 #undef F
145 
146 #define B(A, B) void b##A() { \
147   auto t = []<class T = X>() { return ^ B () { \
148       T t;                                     \
149       return t;                                \
150   }; }()();                                    \
151 }
152 
153 // CHECK-LABEL: define{{.*}} void @_Z2b1v
154 // CHECK:       call {{.*}} @_ZN1XC1Ev
155 // CHECK-NEXT:  call void @llvm.lifetime.end
156 // CHECK-NEXT:  ret void
157 B(1, X);
158 
159 // CHECK-LABEL: define{{.*}} void @_Z2b2v
160 // CHECK:       call {{.*}} @_ZN1XC1Ev
161 // CHECK-NEXT:  call void @llvm.lifetime.end
162 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
163 // CHECK-NEXT:  call void @llvm.lifetime.end
164 // CHECK-NEXT:  ret void
165 B(2, X&);
166 
167 // CHECK-LABEL: define{{.*}} void @_Z2b3v
168 // CHECK:       call {{.*}} @_ZN1XC1Ev
169 // CHECK-NEXT:  call void @llvm.lifetime.end
170 // CHECK-NEXT:  ret void
171 B(3, T);
172 
173 // CHECK-LABEL: define{{.*}} void @_Z2b4v
174 // CHECK:       call {{.*}} @_ZN1XC1Ev
175 // CHECK-NEXT:  call void @llvm.lifetime.end
176 // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_
177 // CHECK-NEXT:  call void @llvm.lifetime.end
178 // CHECK-NEXT:  ret void
179 B(4, T&);
180 
181 // CHECK-LABEL: define{{.*}} void @_Z2b5v
182 // CHECK:       call {{.*}} @_ZN1XC1Ev
183 // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_
184 // CHECK-NEXT:  call void @llvm.lifetime.end
185 // CHECK-NEXT:  call void @llvm.lifetime.end
186 // CHECK-NEXT:  ret void
187 B(5, );
188 
189 #undef B
190 
191 // CHECK-LABEL: define{{.*}} void @_Z6f_attrv
192 // CHECK:       call {{.*}} @_ZN1XC1Ev
193 // CHECK-NEXT:  call void @llvm.lifetime.end
194 // CHECK-NEXT:  ret void
195 template<class T = X> [[gnu::cdecl]] static inline auto tf_attr() -> X {
196     T t;
197     return t;
198 }
199 void f_attr() { auto t = tf_attr(); }
200 
201 // CHECK-LABEL: define{{.*}} void @_Z6b_attrv
202 // CHECK:       call {{.*}} @_ZN1XC1Ev
203 // CHECK-NEXT:  call void @llvm.lifetime.end
204 // CHECK-NEXT:  ret void
205 void b_attr() {
206   auto t = []<class T = X>() { return ^ X () [[clang::vectorcall]] {
207       T t;
208       return t;
209   }; }()();
210 }
211