| // RUN: %clang_cc1 -std=c++20 -fblocks -Wno-return-stack-address -triple x86_64-unknown-unknown-gnu -emit-llvm -O1 -o - %s | FileCheck %s | 
 |  | 
 | struct alignas(4) X { | 
 |   X(); | 
 |   X(const X &); | 
 |   X(X &&); | 
 | }; | 
 |  | 
 | #define L(A, B, C) void l##A() {    \ | 
 |   auto t = []<class T = X>() -> C { \ | 
 |     T t;                            \ | 
 |     return B;                       \ | 
 |   }();                              \ | 
 | } | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2l1v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | L(1, t, X); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2l2v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | L(2, t, X&); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2l3v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | L(3, t, T); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2l4v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | L(4, t, T&); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2l5v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | L(5, t, auto); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2l6v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | L(6, t, auto&); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2l7v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | L(7, t, decltype(auto)); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2l8v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | L(8, (t), decltype(auto)); | 
 |  | 
 | #undef L | 
 |  | 
 | #define F(A, B, C) template<class T = X> static inline auto tf##A() -> C { \ | 
 |     T t;                                                                   \ | 
 |     return B;                                                              \ | 
 | }                                                                          \ | 
 | void f##A() { auto t = tf##A(); }                                          \ | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2f1v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | F(1, t, X); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2f2v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | F(2, t, X&); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2f3v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | F(3, t, T); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2f4v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | F(4, t, T&); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2f5v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | F(5, t, auto); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2f6v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | F(6, t, auto&); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2f7v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | F(7, t, decltype(auto)); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2f8v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | F(8, (t), decltype(auto)); | 
 |  | 
 | #undef F | 
 |  | 
 | #define B(A, B) void b##A() { \ | 
 |   auto t = []<class T = X>() { return ^ B () { \ | 
 |       T t;                                     \ | 
 |       return t;                                \ | 
 |   }; }()();                                    \ | 
 | } | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2b1v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | B(1, X); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2b2v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | B(2, X&); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2b3v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | B(3, T); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2b4v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1ERKS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | B(4, T&); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z2b5v | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | B(5, ); | 
 |  | 
 | #undef B | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z6f_attrv | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | template<class T = X> [[gnu::cdecl]] static inline auto tf_attr() -> X { | 
 |   T t; | 
 |   return t; | 
 | } | 
 | void f_attr() { auto t = tf_attr(); } | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_Z6b_attrv | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | // CHECK-NEXT:  ret void | 
 | void b_attr() { | 
 |   auto t = []<class T = X>() { | 
 |     return ^X() [[clang::vectorcall]] { | 
 |       T t; | 
 |       return t; | 
 |     }; | 
 |   }()(); | 
 | } | 
 |  | 
 | namespace test_alignas { | 
 |  | 
 | template <int A> X t1() { | 
 |   X a [[gnu::aligned(A)]]; | 
 |   return a; | 
 | } | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi1EEE1Xv | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  ret void | 
 | template X t1<1>(); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi4EEE1Xv | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  ret void | 
 | template X t1<4>(); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t1ILi8EEE1Xv | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | template X t1<8>(); | 
 |  | 
 | template <int A> X t2() { | 
 |   X a [[gnu::aligned(1)]] [[gnu::aligned(A)]] [[gnu::aligned(2)]]; | 
 |   return a; | 
 | } | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi1EEE1Xv | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  ret void | 
 | template X t2<1>(); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi4EEE1Xv | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  ret void | 
 | template X t2<4>(); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t2ILi8EEE1Xv | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | template X t2<8>(); | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t3Ev | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  ret void | 
 | X t3() { | 
 |   X a [[gnu::aligned(1)]]; | 
 |   return a; | 
 | } | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t4Ev | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | X t4() { | 
 |   X a [[gnu::aligned(8)]]; | 
 |   return a; | 
 | } | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_ZN12test_alignas2t5Ev | 
 | // CHECK:       call {{.*}} @_ZN1XC1Ev | 
 | // CHECK-NEXT:  call {{.*}} @_ZN1XC1EOS_ | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | X t5() { | 
 |   X a [[gnu::aligned(1)]] [[gnu::aligned(8)]]; | 
 |   return a; | 
 | } | 
 |  | 
 | } // namespace test_alignas | 
 |  | 
 | namespace PR51862 { | 
 |  | 
 | template <class T> T test() { | 
 |   T a; | 
 |   T b; | 
 |   if (0) | 
 |     return a; | 
 |   return b; | 
 | } | 
 |  | 
 | struct A { | 
 |   A(); | 
 |   A(A &); | 
 |   A(int); | 
 |   operator int(); | 
 | }; | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_ZN7PR518624testINS_1AEEET_v | 
 | // CHECK:       call noundef i32 @_ZN7PR518621AcviEv | 
 | // CHECK-NEXT:  call void @_ZN7PR518621AC1Ei | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | template A test<A>(); | 
 |  | 
 | struct BSub {}; | 
 | struct B : BSub { | 
 |   B(); | 
 |   B(B &); | 
 |   B(const BSub &); | 
 | }; | 
 |  | 
 | // CHECK-LABEL: define{{.*}} void @_ZN7PR518624testINS_1BEEET_v | 
 | // CHECK:       call void @_ZN7PR518621BC1ERKNS_4BSubE | 
 | // CHECK-NEXT:  call void @llvm.lifetime.end | 
 | template B test<B>(); | 
 |  | 
 | } // namespace PR51862 |