f4a2713ac8
Change-Id: Ia40e9ffdf29b5dab2f122f673ff6802a58bc690f
779 lines
22 KiB
C++
779 lines
22 KiB
C++
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -std=c++11 | FileCheck %s
|
|
|
|
namespace PR16263 {
|
|
const unsigned int n = 1234;
|
|
extern const int &r = (const int&)n;
|
|
// CHECK: @_ZGRN7PR162631rE = private constant i32 1234,
|
|
// CHECK: @_ZN7PR162631rE = constant i32* @_ZGRN7PR162631rE,
|
|
|
|
extern const int &s = reinterpret_cast<const int&>(n);
|
|
// CHECK: @_ZN7PR16263L1nE = internal constant i32 1234, align 4
|
|
// CHECK: @_ZN7PR162631sE = constant i32* @_ZN7PR16263L1nE, align 8
|
|
|
|
struct A { int n; };
|
|
struct B { int n; };
|
|
struct C : A, B {};
|
|
extern const A &&a = (A&&)(A&&)(C&&)(C{});
|
|
// CHECK: @_ZGRN7PR162631aE = private global {{.*}} zeroinitializer,
|
|
// CHECK: @_ZN7PR162631aE = constant {{.*}} bitcast ({{.*}}* @_ZGRN7PR162631aE to
|
|
|
|
extern const int &&t = ((B&&)C{}).n;
|
|
// CHECK: @_ZGRN7PR162631tE = private global {{.*}} zeroinitializer,
|
|
// CHECK: @_ZN7PR162631tE = constant i32* {{.*}}* @_ZGRN7PR162631tE {{.*}} 4
|
|
|
|
struct D { double d; C c; };
|
|
extern const int &&u = (123, static_cast<B&&>(0, ((D&&)D{}).*&D::c).n);
|
|
// CHECK: @_ZGRN7PR162631uE = private global {{.*}} zeroinitializer
|
|
// CHECK: @_ZN7PR162631uE = constant i32* {{.*}} @_ZGRN7PR162631uE {{.*}} 12
|
|
}
|
|
|
|
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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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-LABEL: 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);
|
|
}
|
|
}
|
|
|
|
namespace PR11365 {
|
|
struct A { A(); ~A(); };
|
|
|
|
// CHECK-LABEL: define void @_ZN7PR113653fooEv(
|
|
void foo() {
|
|
// CHECK: [[BEGIN:%.*]] = getelementptr inbounds [3 x [[A:%.*]]]* {{.*}}, i32 0, i32 0
|
|
// CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]]* [[BEGIN]], i64 3
|
|
// CHECK-NEXT: br label
|
|
|
|
// CHECK: [[PHI:%.*]] = phi
|
|
// CHECK-NEXT: [[ELEM:%.*]] = getelementptr inbounds [[A]]* [[PHI]], i64 -1
|
|
// CHECK-NEXT: call void @_ZN7PR113651AD1Ev([[A]]* [[ELEM]])
|
|
// CHECK-NEXT: icmp eq [[A]]* [[ELEM]], [[BEGIN]]
|
|
// CHECK-NEXT: br i1
|
|
(void) (A [3]) {};
|
|
}
|
|
}
|
|
|
|
namespace AssignmentOp {
|
|
struct A { ~A(); };
|
|
struct B { A operator=(const B&); };
|
|
struct C : B { B b1, b2; };
|
|
// CHECK-LABEL: define void @_ZN12AssignmentOp1fE
|
|
void f(C &c1, const C &c2) {
|
|
// CHECK: call {{.*}} @_ZN12AssignmentOp1CaSERKS0_(
|
|
c1 = c2;
|
|
}
|
|
|
|
// Ensure that each 'A' temporary is destroyed before the next subobject is
|
|
// copied.
|
|
// CHECK: define {{.*}} @_ZN12AssignmentOp1CaSERKS0_(
|
|
// CHECK: call {{.*}} @_ZN12AssignmentOp1BaSERKS
|
|
// CHECK: call {{.*}} @_ZN12AssignmentOp1AD1Ev(
|
|
// CHECK: call {{.*}} @_ZN12AssignmentOp1BaSERKS
|
|
// CHECK: call {{.*}} @_ZN12AssignmentOp1AD1Ev(
|
|
// CHECK: call {{.*}} @_ZN12AssignmentOp1BaSERKS
|
|
// CHECK: call {{.*}} @_ZN12AssignmentOp1AD1Ev(
|
|
}
|
|
|
|
namespace BindToSubobject {
|
|
struct A {
|
|
A();
|
|
~A();
|
|
int a;
|
|
};
|
|
|
|
void f(), g();
|
|
|
|
// CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1aE)
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1aE to i8*), i8* @__dso_handle)
|
|
// CHECK: store i32* getelementptr inbounds ({{.*}} @_ZGRN15BindToSubobject1aE, i32 0, i32 0), i32** @_ZN15BindToSubobject1aE, align 8
|
|
int &&a = A().a;
|
|
|
|
// CHECK: call void @_ZN15BindToSubobject1fEv()
|
|
// CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1bE)
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1bE to i8*), i8* @__dso_handle)
|
|
// CHECK: store i32* getelementptr inbounds ({{.*}} @_ZGRN15BindToSubobject1bE, i32 0, i32 0), i32** @_ZN15BindToSubobject1bE, align 8
|
|
int &&b = (f(), A().a);
|
|
|
|
int A::*h();
|
|
|
|
// CHECK: call void @_ZN15BindToSubobject1fEv()
|
|
// CHECK: call void @_ZN15BindToSubobject1gEv()
|
|
// CHECK: call void @_ZN15BindToSubobject1AC1Ev({{.*}} @_ZGRN15BindToSubobject1cE)
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1AD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1cE to i8*), i8* @__dso_handle)
|
|
// CHECK: call {{.*}} @_ZN15BindToSubobject1hE
|
|
// CHECK: getelementptr
|
|
// CHECK: store i32* {{.*}}, i32** @_ZN15BindToSubobject1cE, align 8
|
|
int &&c = (f(), (g(), A().*h()));
|
|
|
|
struct B {
|
|
int padding;
|
|
A a;
|
|
};
|
|
|
|
// CHECK: call void @_ZN15BindToSubobject1BC1Ev({{.*}} @_ZGRN15BindToSubobject1dE)
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} bitcast ({{.*}} @_ZN15BindToSubobject1BD1Ev to void (i8*)*), i8* bitcast ({{.*}} @_ZGRN15BindToSubobject1dE to i8*), i8* @__dso_handle)
|
|
// CHECK: call {{.*}} @_ZN15BindToSubobject1hE
|
|
// CHECK: getelementptr {{.*}} getelementptr
|
|
// CHECK: store i32* {{.*}}, i32** @_ZN15BindToSubobject1dE, align 8
|
|
int &&d = (B().a).*h();
|
|
}
|
|
|
|
namespace Bitfield {
|
|
struct S { int a : 5; ~S(); };
|
|
|
|
// Do not lifetime extend the S() temporary here.
|
|
// CHECK: alloca
|
|
// CHECK: call {{.*}}memset
|
|
// CHECK: store i32 {{.*}}, i32* @_ZGRN8Bitfield1rE
|
|
// CHECK: call void @_ZN8Bitfield1SD1
|
|
// CHECK: store i32* @_ZGRN8Bitfield1rE, i32** @_ZN8Bitfield1rE, align 8
|
|
int &&r = S().a;
|
|
}
|
|
|
|
namespace Vector {
|
|
typedef __attribute__((vector_size(16))) int vi4a;
|
|
typedef __attribute__((ext_vector_type(4))) int vi4b;
|
|
struct S {
|
|
vi4a v;
|
|
vi4b w;
|
|
};
|
|
// CHECK: alloca
|
|
// CHECK: extractelement
|
|
// CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1rE
|
|
// CHECK: store i32* @_ZGRN6Vector1rE, i32** @_ZN6Vector1rE,
|
|
int &&r = S().v[1];
|
|
|
|
// CHECK: alloca
|
|
// CHECK: extractelement
|
|
// CHECK: store i32 {{.*}}, i32* @_ZGRN6Vector1sE
|
|
// CHECK: store i32* @_ZGRN6Vector1sE, i32** @_ZN6Vector1sE,
|
|
int &&s = S().w[1];
|
|
// FIXME PR16204: The following code leads to an assertion in Sema.
|
|
//int &&s = S().w.y;
|
|
}
|
|
|
|
namespace ImplicitTemporaryCleanup {
|
|
struct A { A(int); ~A(); };
|
|
void g();
|
|
|
|
// CHECK-LABEL: define void @_ZN24ImplicitTemporaryCleanup1fEv(
|
|
void f() {
|
|
// CHECK: call {{.*}} @_ZN24ImplicitTemporaryCleanup1AC1Ei(
|
|
A &&a = 0;
|
|
|
|
// CHECK: call {{.*}} @_ZN24ImplicitTemporaryCleanup1gEv(
|
|
g();
|
|
|
|
// CHECK: call {{.*}} @_ZN24ImplicitTemporaryCleanup1AD1Ev(
|
|
}
|
|
}
|
|
|
|
namespace MultipleExtension {
|
|
struct A { A(); ~A(); };
|
|
struct B { B(); ~B(); };
|
|
struct C { C(); ~C(); };
|
|
struct D { D(); ~D(); int n; C c; };
|
|
struct E { const A &a; B b; const C &c; ~E(); };
|
|
|
|
E &&e1 = { A(), B(), D().c };
|
|
|
|
// CHECK: call void @_ZN17MultipleExtension1AC1Ev({{.*}} @[[TEMPA:_ZGRN17MultipleExtension2e1E.*]])
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1AD1Ev {{.*}} @[[TEMPA]]
|
|
// CHECK: store {{.*}} @[[TEMPA]], {{.*}} getelementptr inbounds ({{.*}} @[[TEMPE:_ZGRN17MultipleExtension2e1E.*]], i32 0, i32 0)
|
|
|
|
// CHECK: call void @_ZN17MultipleExtension1BC1Ev({{.*}} getelementptr inbounds ({{.*}} @[[TEMPE]], i32 0, i32 1))
|
|
|
|
// CHECK: call void @_ZN17MultipleExtension1DC1Ev({{.*}} @[[TEMPD:_ZGRN17MultipleExtension2e1E.*]])
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1DD1Ev {{.*}} @[[TEMPD]]
|
|
// CHECK: store {{.*}} @[[TEMPD]], {{.*}} getelementptr inbounds ({{.*}} @[[TEMPE]], i32 0, i32 2)
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1ED1Ev {{.*}} @[[TEMPE]]
|
|
// CHECK: store {{.*}} @[[TEMPE]], %"struct.MultipleExtension::E"** @_ZN17MultipleExtension2e1E, align 8
|
|
|
|
E e2 = { A(), B(), D().c };
|
|
|
|
// CHECK: call void @_ZN17MultipleExtension1AC1Ev({{.*}} @[[TEMPA:_ZGRN17MultipleExtension2e2E.*]])
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1AD1Ev {{.*}} @[[TEMPA]]
|
|
// CHECK: store {{.*}} @[[TEMPA]], {{.*}} getelementptr inbounds ({{.*}} @[[E:_ZN17MultipleExtension2e2E]], i32 0, i32 0)
|
|
|
|
// CHECK: call void @_ZN17MultipleExtension1BC1Ev({{.*}} getelementptr inbounds ({{.*}} @[[E]], i32 0, i32 1))
|
|
|
|
// CHECK: call void @_ZN17MultipleExtension1DC1Ev({{.*}} @[[TEMPD:_ZGRN17MultipleExtension2e2E.*]])
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1DD1Ev {{.*}} @[[TEMPD]]
|
|
// CHECK: store {{.*}} @[[TEMPD]], {{.*}} getelementptr inbounds ({{.*}} @[[E]], i32 0, i32 2)
|
|
// CHECK: call i32 @__cxa_atexit({{.*}} @_ZN17MultipleExtension1ED1Ev {{.*}} @[[E]]
|
|
|
|
|
|
void g();
|
|
// CHECK: define void @[[NS:_ZN17MultipleExtension]]1fEv(
|
|
void f() {
|
|
E &&e1 = { A(), B(), D().c };
|
|
// CHECK: %[[TEMPE1_A:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1:.*]], i32 0, i32 0
|
|
// CHECK: call void @[[NS]]1AC1Ev({{.*}} %[[TEMPA1:.*]])
|
|
// CHECK: store {{.*}} %[[TEMPA1]], {{.*}} %[[TEMPE1_A]]
|
|
// CHECK: %[[TEMPE1_B:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1]], i32 0, i32 1
|
|
// CHECK: call void @[[NS]]1BC1Ev({{.*}} %[[TEMPE1_B]])
|
|
// CHECK: %[[TEMPE1_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPE1]], i32 0, i32 2
|
|
// CHECK: call void @[[NS]]1DC1Ev({{.*}} %[[TEMPD1:.*]])
|
|
// CHECK: %[[TEMPD1_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPD1]], i32 0, i32 1
|
|
// CHECK: store {{.*}} %[[TEMPD1_C]], {{.*}} %[[TEMPE1_C]]
|
|
// CHECK: store {{.*}} %[[TEMPE1]], {{.*}} %[[E1:.*]]
|
|
|
|
g();
|
|
// CHECK: call void @[[NS]]1gEv()
|
|
|
|
E e2 = { A(), B(), D().c };
|
|
// CHECK: %[[TEMPE2_A:.*]] = getelementptr inbounds {{.*}} %[[E2:.*]], i32 0, i32 0
|
|
// CHECK: call void @[[NS]]1AC1Ev({{.*}} %[[TEMPA2:.*]])
|
|
// CHECK: store {{.*}} %[[TEMPA2]], {{.*}} %[[TEMPE2_A]]
|
|
// CHECK: %[[TEMPE2_B:.*]] = getelementptr inbounds {{.*}} %[[E2]], i32 0, i32 1
|
|
// CHECK: call void @[[NS]]1BC1Ev({{.*}} %[[TEMPE2_B]])
|
|
// CHECK: %[[TEMPE2_C:.*]] = getelementptr inbounds {{.*}} %[[E2]], i32 0, i32 2
|
|
// CHECK: call void @[[NS]]1DC1Ev({{.*}} %[[TEMPD2:.*]])
|
|
// CHECK: %[[TEMPD2_C:.*]] = getelementptr inbounds {{.*}} %[[TEMPD2]], i32 0, i32 1
|
|
// CHECK: store {{.*}} %[[TEMPD2_C]], {{.*}}* %[[TEMPE2_C]]
|
|
|
|
g();
|
|
// CHECK: call void @[[NS]]1gEv()
|
|
|
|
// CHECK: call void @[[NS]]1ED1Ev({{.*}} %[[E2]])
|
|
// CHECK: call void @[[NS]]1DD1Ev({{.*}} %[[TEMPD2]])
|
|
// CHECK: call void @[[NS]]1AD1Ev({{.*}} %[[TEMPA2]])
|
|
// CHECK: call void @[[NS]]1ED1Ev({{.*}} %[[TEMPE1]])
|
|
// CHECK: call void @[[NS]]1DD1Ev({{.*}} %[[TEMPD1]])
|
|
// CHECK: call void @[[NS]]1AD1Ev({{.*}} %[[TEMPA1]])
|
|
}
|
|
}
|
|
|
|
namespace PR14130 {
|
|
struct S { S(int); };
|
|
struct U { S &&s; };
|
|
U v { { 0 } };
|
|
// CHECK: call void @_ZN7PR141301SC1Ei({{.*}} @_ZGRN7PR141301vE, i32 0)
|
|
// CHECK: store {{.*}} @_ZGRN7PR141301vE, {{.*}} @_ZN7PR141301vE
|
|
}
|
|
|
|
namespace Ctor {
|
|
struct A { A(); ~A(); };
|
|
void f();
|
|
struct B {
|
|
A &&a;
|
|
B() : a{} { f(); }
|
|
} b;
|
|
// CHECK: define {{.*}}void @_ZN4Ctor1BC1Ev(
|
|
// CHECK: call void @_ZN4Ctor1AC1Ev(
|
|
// CHECK: call void @_ZN4Ctor1fEv(
|
|
// CHECK: call void @_ZN4Ctor1AD1Ev(
|
|
}
|