| // RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s |
| struct A { |
| A(); |
| ~A(); |
| void f(); |
| }; |
| |
| void f1() { |
| // CHECK: call void @_ZN1AC1Ev |
| // CHECK: call void @_ZN1AD1Ev |
| (void)A(); |
| |
| // CHECK: call void @_ZN1AC1Ev |
| // CHECK: call void @_ZN1AD1Ev |
| A().f(); |
| } |
| |
| // Function calls |
| struct B { |
| B(); |
| ~B(); |
| }; |
| |
| B g(); |
| |
| void f2() { |
| // CHECK-NOT: call void @_ZN1BC1Ev |
| // CHECK: call void @_ZN1BD1Ev |
| (void)g(); |
| } |
| |
| // Member function calls |
| struct C { |
| C(); |
| ~C(); |
| |
| C f(); |
| }; |
| |
| void f3() { |
| // CHECK: call void @_ZN1CC1Ev |
| // CHECK: call void @_ZN1CD1Ev |
| // CHECK: call void @_ZN1CD1Ev |
| C().f(); |
| } |
| |
| // Function call operator |
| struct D { |
| D(); |
| ~D(); |
| |
| D operator()(); |
| }; |
| |
| void f4() { |
| // CHECK: call void @_ZN1DC1Ev |
| // CHECK: call void @_ZN1DD1Ev |
| // CHECK: call void @_ZN1DD1Ev |
| D()(); |
| } |
| |
| // Overloaded operators |
| struct E { |
| E(); |
| ~E(); |
| E operator+(const E&); |
| E operator!(); |
| }; |
| |
| void f5() { |
| // CHECK: call void @_ZN1EC1Ev |
| // CHECK: call void @_ZN1EC1Ev |
| // CHECK: call void @_ZN1ED1Ev |
| // CHECK: call void @_ZN1ED1Ev |
| // CHECK: call void @_ZN1ED1Ev |
| E() + E(); |
| |
| // CHECK: call void @_ZN1EC1Ev |
| // CHECK: call void @_ZN1ED1Ev |
| // CHECK: call void @_ZN1ED1Ev |
| !E(); |
| } |
| |
| struct F { |
| F(); |
| ~F(); |
| F& f(); |
| }; |
| |
| void f6() { |
| // CHECK: call void @_ZN1FC1Ev |
| // CHECK: call void @_ZN1FD1Ev |
| F().f(); |
| } |
| |
| struct G { |
| G(); |
| G(A); |
| ~G(); |
| operator A(); |
| }; |
| |
| void a(const A&); |
| |
| void f7() { |
| // CHECK: call void @_ZN1AC1Ev |
| // CHECK: call void @_Z1aRK1A |
| // CHECK: call void @_ZN1AD1Ev |
| a(A()); |
| |
| // CHECK: call void @_ZN1GC1Ev |
| // CHECK: call void @_ZN1Gcv1AEv |
| // CHECK: call void @_Z1aRK1A |
| // CHECK: call void @_ZN1AD1Ev |
| // CHECK: call void @_ZN1GD1Ev |
| a(G()); |
| } |
| |
| namespace PR5077 { |
| |
| struct A { |
| A(); |
| ~A(); |
| int f(); |
| }; |
| |
| void f(); |
| int g(const A&); |
| |
| struct B { |
| int a1; |
| int a2; |
| B(); |
| ~B(); |
| }; |
| |
| B::B() |
| // CHECK: call void @_ZN6PR50771AC1Ev |
| // CHECK: call i32 @_ZN6PR50771A1fEv |
| // CHECK: call void @_ZN6PR50771AD1Ev |
| : a1(A().f()) |
| // CHECK: call void @_ZN6PR50771AC1Ev |
| // CHECK: call i32 @_ZN6PR50771gERKNS_1AE |
| // CHECK: call void @_ZN6PR50771AD1Ev |
| , a2(g(A())) |
| { |
| // CHECK: call void @_ZN6PR50771fEv |
| f(); |
| } |
| |
| struct C { |
| C(); |
| |
| const B& b; |
| }; |
| |
| C::C() |
| // CHECK: call void @_ZN6PR50771BC1Ev |
| : b(B()) { |
| // CHECK: call void @_ZN6PR50771fEv |
| f(); |
| |
| // CHECK: call void @_ZN6PR50771BD1Ev |
| } |
| } |
| |
| A f8() { |
| // CHECK: call void @_ZN1AC1Ev |
| // CHECK-NOT: call void @_ZN1AD1Ev |
| return A(); |
| // CHECK: ret void |
| } |
| |
| struct H { |
| H(); |
| ~H(); |
| H(const H&); |
| }; |
| |
| void f9(H h) { |
| // CHECK: call void @_ZN1HC1Ev |
| // CHECK: call void @_Z2f91H |
| // CHECK: call void @_ZN1HD1Ev |
| f9(H()); |
| |
| // CHECK: call void @_ZN1HC1ERKS_ |
| // CHECK: call void @_Z2f91H |
| // CHECK: call void @_ZN1HD1Ev |
| f9(h); |
| } |
| |
| void f10(const H&); |
| |
| void f11(H h) { |
| // CHECK: call void @_ZN1HC1Ev |
| // CHECK: call void @_Z3f10RK1H |
| // CHECK: call void @_ZN1HD1Ev |
| f10(H()); |
| |
| // CHECK: call void @_Z3f10RK1H |
| // CHECK-NOT: call void @_ZN1HD1Ev |
| // CHECK: ret void |
| f10(h); |
| } |
| |
| // PR5808 |
| struct I { |
| I(const char *); |
| ~I(); |
| }; |
| |
| // CHECK: _Z3f12v |
| I f12() { |
| // CHECK: call void @_ZN1IC1EPKc |
| // CHECK-NOT: call void @_ZN1ID1Ev |
| // CHECK: ret void |
| return "Hello"; |
| } |
| |
| // PR5867 |
| namespace PR5867 { |
| struct S { |
| S(); |
| S(const S &); |
| ~S(); |
| }; |
| |
| void f(S, int); |
| // CHECK: define void @_ZN6PR58671gEv |
| void g() { |
| // CHECK: call void @_ZN6PR58671SC1Ev |
| // CHECK-NEXT: call void @_ZN6PR58671fENS_1SEi |
| // CHECK-NEXT: call void @_ZN6PR58671SD1Ev |
| // CHECK-NEXT: ret void |
| (f)(S(), 0); |
| } |
| |
| // CHECK: define linkonce_odr void @_ZN6PR58672g2IiEEvT_ |
| template<typename T> |
| void g2(T) { |
| // CHECK: call void @_ZN6PR58671SC1Ev |
| // CHECK-NEXT: call void @_ZN6PR58671fENS_1SEi |
| // CHECK-NEXT: call void @_ZN6PR58671SD1Ev |
| // CHECK-NEXT: ret void |
| (f)(S(), 0); |
| } |
| |
| void h() { |
| g2(17); |
| } |
| } |
| |
| // PR6199 |
| namespace PR6199 { |
| struct A { ~A(); }; |
| |
| struct B { operator A(); }; |
| |
| // CHECK: define weak_odr void @_ZN6PR61992f2IiEENS_1AET_ |
| template<typename T> A f2(T) { |
| B b; |
| // CHECK: call void @_ZN6PR61991BcvNS_1AEEv |
| // CHECK-NEXT: ret void |
| return b; |
| } |
| |
| template A f2<int>(int); |
| |
| } |
| |
| namespace T12 { |
| |
| struct A { |
| A(); |
| ~A(); |
| int f(); |
| }; |
| |
| int& f(int); |
| |
| // CHECK: define void @_ZN3T121gEv |
| void g() { |
| // CHECK: call void @_ZN3T121AC1Ev |
| // CHECK-NEXT: call i32 @_ZN3T121A1fEv( |
| // CHECK-NEXT: call i32* @_ZN3T121fEi( |
| // CHECK-NEXT: call void @_ZN3T121AD1Ev( |
| int& i = f(A().f()); |
| } |
| |
| } |
| |
| namespace PR6648 { |
| struct B { |
| ~B(); |
| }; |
| B foo; |
| struct D; |
| D& zed(B); |
| void foobar() { |
| // CHECK: call %"struct.PR6648::D"* @_ZN6PR66483zedENS_1BE |
| zed(foo); |
| } |
| } |
| |
| namespace UserConvertToValue { |
| struct X { |
| X(int); |
| X(const X&); |
| ~X(); |
| }; |
| |
| void f(X); |
| |
| // CHECK: void @_ZN18UserConvertToValue1gEv() |
| void g() { |
| // CHECK: call void @_ZN18UserConvertToValue1XC1Ei |
| // CHECK: call void @_ZN18UserConvertToValue1fENS_1XE |
| // CHECK: call void @_ZN18UserConvertToValue1XD1Ev |
| // CHECK: ret void |
| f(1); |
| } |
| } |
| |
| namespace PR7556 { |
| struct A { ~A(); }; |
| struct B { int i; ~B(); }; |
| struct C { int C::*pm; ~C(); }; |
| // CHECK: define void @_ZN6PR75563fooEv() |
| void foo() { |
| // CHECK: call void @_ZN6PR75561AD1Ev |
| A(); |
| // CHECK: call void @llvm.memset.p0i8.i64 |
| // CHECK: call void @_ZN6PR75561BD1Ev |
| B(); |
| // CHECK: call void @llvm.memcpy.p0i8.p0i8.i64 |
| // CHECK: call void @_ZN6PR75561CD1Ev |
| C(); |
| // CHECK-NEXT: ret void |
| } |
| } |
| |
| namespace Elision { |
| struct A { |
| A(); A(const A &); ~A(); |
| void *p; |
| void foo() const; |
| }; |
| |
| void foo(); |
| A fooA(); |
| void takeA(A a); |
| |
| // CHECK: define void @_ZN7Elision5test0Ev() |
| void test0() { |
| // CHECK: [[I:%.*]] = alloca [[A:%.*]], align 8 |
| // CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8 |
| // CHECK-NEXT: [[T0:%.*]] = alloca [[A]], align 8 |
| // CHECK-NEXT: [[K:%.*]] = alloca [[A]], align 8 |
| // CHECK-NEXT: [[T1:%.*]] = alloca [[A]], align 8 |
| |
| // CHECK-NEXT: call void @_ZN7Elision3fooEv() |
| // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[I]]) |
| A i = (foo(), A()); |
| |
| // CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret [[T0]]) |
| // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[J]]) |
| // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T0]]) |
| A j = (fooA(), A()); |
| |
| // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[T1]]) |
| // CHECK-NEXT: call void @_ZN7Elision4fooAEv([[A]]* sret [[K]]) |
| // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T1]]) |
| A k = (A(), fooA()); |
| |
| // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[K]]) |
| // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[J]]) |
| // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[I]]) |
| } |
| |
| |
| // CHECK: define void @_ZN7Elision5test1EbNS_1AE( |
| void test1(bool c, A x) { |
| // CHECK: [[I:%.*]] = alloca [[A]], align 8 |
| // CHECK-NEXT: [[J:%.*]] = alloca [[A]], align 8 |
| |
| // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[I]]) |
| // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[I]], [[A]]* [[X:%.*]]) |
| A i = (c ? A() : x); |
| |
| // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[J]], [[A]]* [[X]]) |
| // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[J]]) |
| A j = (c ? x : A()); |
| |
| // CHECK: call void @_ZN7Elision1AD1Ev([[A]]* [[J]]) |
| // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[I]]) |
| } |
| |
| // CHECK: define void @_ZN7Elision5test2Ev([[A]]* noalias sret |
| A test2() { |
| // CHECK: call void @_ZN7Elision3fooEv() |
| // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]]) |
| // CHECK-NEXT: ret void |
| return (foo(), A()); |
| } |
| |
| // CHECK: define void @_ZN7Elision5test3EiNS_1AE([[A]]* noalias sret |
| A test3(int v, A x) { |
| if (v < 5) |
| // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET:%.*]]) |
| // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* [[X:%.*]]) |
| return (v < 0 ? A() : x); |
| else |
| // CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* [[X]]) |
| // CHECK: call void @_ZN7Elision1AC1Ev([[A]]* [[RET]]) |
| return (v > 10 ? x : A()); |
| |
| // CHECK: ret void |
| } |
| |
| // CHECK: define void @_ZN7Elision5test4Ev() |
| void test4() { |
| // CHECK: [[X:%.*]] = alloca [[A]], align 8 |
| // CHECK-NEXT: [[XS:%.*]] = alloca [2 x [[A]]], align 16 |
| |
| // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[X]]) |
| A x; |
| |
| // CHECK-NEXT: [[XS0:%.*]] = getelementptr inbounds [2 x [[A]]]* [[XS]], i64 0, i64 0 |
| // CHECK-NEXT: call void @_ZN7Elision1AC1Ev([[A]]* [[XS0]]) |
| // CHECK-NEXT: [[XS1:%.*]] = getelementptr inbounds [[A]]* [[XS0]], i64 1 |
| // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[XS1]], [[A]]* [[X]]) |
| A xs[] = { A(), x }; |
| |
| // CHECK-NEXT: [[BEGIN:%.*]] = getelementptr inbounds [2 x [[A]]]* [[XS]], i32 0, i32 0 |
| // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]]* [[BEGIN]], i64 2 |
| // CHECK-NEXT: br label |
| // CHECK: [[AFTER:%.*]] = phi [[A]]* |
| // CHECK-NEXT: [[CUR:%.*]] = getelementptr inbounds [[A]]* [[AFTER]], i64 -1 |
| // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[CUR]]) |
| // CHECK-NEXT: [[T0:%.*]] = icmp eq [[A]]* [[CUR]], [[BEGIN]] |
| // CHECK-NEXT: br i1 [[T0]], |
| |
| // CHECK: call void @_ZN7Elision1AD1Ev([[A]]* [[X]]) |
| } |
| |
| // rdar://problem/8433352 |
| // CHECK: define void @_ZN7Elision5test5Ev([[A]]* noalias sret |
| struct B { A a; B(); }; |
| A test5() { |
| // CHECK: [[AT0:%.*]] = alloca [[A]], align 8 |
| // CHECK-NEXT: [[BT0:%.*]] = alloca [[B:%.*]], align 8 |
| // CHECK-NEXT: [[X:%.*]] = alloca [[A]], align 8 |
| // CHECK-NEXT: [[BT1:%.*]] = alloca [[B]], align 8 |
| // CHECK-NEXT: [[BT2:%.*]] = alloca [[B]], align 8 |
| |
| // CHECK: call void @_ZN7Elision1BC1Ev([[B]]* [[BT0]]) |
| // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT0]], i32 0, i32 0 |
| // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[AT0]], [[A]]* [[AM]]) |
| // CHECK-NEXT: call void @_ZN7Elision5takeAENS_1AE([[A]]* [[AT0]]) |
| // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[AT0]]) |
| // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT0]]) |
| takeA(B().a); |
| |
| // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT1]]) |
| // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT1]], i32 0, i32 0 |
| // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[X]], [[A]]* [[AM]]) |
| // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT1]]) |
| A x = B().a; |
| |
| // CHECK-NEXT: call void @_ZN7Elision1BC1Ev([[B]]* [[BT2]]) |
| // CHECK-NEXT: [[AM:%.*]] = getelementptr inbounds [[B]]* [[BT2]], i32 0, i32 0 |
| // CHECK-NEXT: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET:%.*]], [[A]]* [[AM]]) |
| // CHECK-NEXT: call void @_ZN7Elision1BD1Ev([[B]]* [[BT2]]) |
| return B().a; |
| |
| // CHECK: call void @_ZN7Elision1AD1Ev([[A]]* [[X]]) |
| } |
| |
| // Reduced from webkit. |
| // CHECK: define void @_ZN7Elision5test6EPKNS_1CE([[C:%.*]]* |
| struct C { operator A() const; }; |
| void test6(const C *x) { |
| // CHECK: [[T0:%.*]] = alloca [[A]], align 8 |
| // CHECK: [[X:%.*]] = load [[C]]** {{%.*}}, align 8 |
| // CHECK-NEXT: call void @_ZNK7Elision1CcvNS_1AEEv([[A]]* sret [[T0]], [[C]]* [[X]]) |
| // CHECK-NEXT: call void @_ZNK7Elision1A3fooEv([[A]]* [[T0]]) |
| // CHECK-NEXT: call void @_ZN7Elision1AD1Ev([[A]]* [[T0]]) |
| // CHECK-NEXT: ret void |
| A(*x).foo(); |
| } |
| } |
| |
| namespace PR8623 { |
| struct A { A(int); ~A(); }; |
| |
| // CHECK: define void @_ZN6PR86233fooEb( |
| void foo(bool b) { |
| // CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1 |
| // CHECK-NEXT: [[LCONS:%.*]] = alloca i1 |
| // CHECK-NEXT: [[RCONS:%.*]] = alloca i1 |
| // CHECK: store i1 false, i1* [[LCONS]] |
| // CHECK-NEXT: store i1 false, i1* [[RCONS]] |
| // CHECK-NEXT: br i1 |
| // CHECK: call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 2) |
| // CHECK-NEXT: store i1 true, i1* [[LCONS]] |
| // CHECK-NEXT: br label |
| // CHECK: call void @_ZN6PR86231AC1Ei([[A]]* [[TMP]], i32 3) |
| // CHECK-NEXT: store i1 true, i1* [[RCONS]] |
| // CHECK-NEXT: br label |
| // CHECK: load i1* [[RCONS]] |
| // CHECK-NEXT: br i1 |
| // CHECK: call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]]) |
| // CHECK-NEXT: br label |
| // CHECK: load i1* [[LCONS]] |
| // CHECK-NEXT: br i1 |
| // CHECK: call void @_ZN6PR86231AD1Ev([[A]]* [[TMP]]) |
| // CHECK-NEXT: br label |
| // CHECK: ret void |
| b ? A(2) : A(3); |
| } |
| } |