Files
clang-p2996/clang/test/CodeGenCXX/temporaries.cpp
Hal Finkel a2347baaec Mark C++ reference parameters as dereferenceable
Because references must be initialized using some evaluated expression, they
must point to something, and a callee can assume the reference parameter is
dereferenceable. Taking advantage of a new attribute just added to LLVM, mark
them as such.

Because dereferenceability in addrspace(0) implies nonnull in the backend, we
don't need both attributes. However, we need to know the size of the object to
use the dereferenceable attribute, so for incomplete types we still emit only
nonnull.

llvm-svn: 213386
2014-07-18 15:52:10 +00:00

795 lines
23 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
}
namespace PR20227 {
struct A { ~A(); };
struct B { virtual ~B(); };
struct C : B {};
A &&a = dynamic_cast<A&&>(A{});
// CHECK: @_ZGRN7PR202271aE_ = private global
B &&b = dynamic_cast<C&&>(dynamic_cast<B&&>(C{}));
// CHECK: @_ZGRN7PR202271bE_ = private global
B &&c = static_cast<C&&>(static_cast<B&&>(C{}));
// CHECK: @_ZGRN7PR202271cE_ = private global
}
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 dereferenceable({{[0-9]+}}) 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 nonnull %"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]]* dereferenceable({{[0-9]+}}) [[X:%.*]])
A i = (c ? A() : x);
// CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[J]], [[A]]* dereferenceable({{[0-9]+}}) [[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]]* dereferenceable({{[0-9]+}}) [[X:%.*]])
return (v < 0 ? A() : x);
else
// CHECK: call void @_ZN7Elision1AC1ERKS0_([[A]]* [[RET]], [[A]]* dereferenceable({{[0-9]+}}) [[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]]* dereferenceable({{[0-9]+}}) [[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]]* dereferenceable({{[0-9]+}}) [[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]]* dereferenceable({{[0-9]+}}) [[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]]* dereferenceable({{[0-9]+}}) [[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(
}