| // 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 |