Files
clang-p2996/clang/test/CodeGenCXX/rvalue-references.cpp
John McCall 13a39c6f54 When devirtualizing the conversion to a virtual base subobject,
don't explode if the offset we get is zero.  This can happen if
you have an empty virtual base class.

While I'm at it, remove an unnecessary block from the IR-generation
of the null-check, mark the eventual GEP as inbounds, and generally
prettify.

llvm-svn: 161100
2012-08-01 05:04:58 +00:00

112 lines
2.3 KiB
C++

// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
struct Spacer { int x; };
struct A { double array[2]; };
struct B : Spacer, A { };
B &getB();
// CHECK: define %struct.A* @_Z4getAv()
// CHECK: call %struct.B* @_Z4getBv()
// CHECK-NEXT: bitcast %struct.B*
// CHECK-NEXT: getelementptr inbounds i8*
// CHECK-NEXT: bitcast i8* {{.*}} to %struct.A*
// CHECK-NEXT: ret %struct.A*
A &&getA() { return static_cast<A&&>(getB()); }
int &getIntLValue();
int &&getIntXValue();
int getIntPRValue();
// CHECK: define i32* @_Z2f0v()
// CHECK: call i32* @_Z12getIntLValuev()
// CHECK-NEXT: ret i32*
int &&f0() { return static_cast<int&&>(getIntLValue()); }
// CHECK: define i32* @_Z2f1v()
// CHECK: call i32* @_Z12getIntXValuev()
// CHECK-NEXT: ret i32*
int &&f1() { return static_cast<int&&>(getIntXValue()); }
// CHECK: define i32* @_Z2f2v
// CHECK: call i32 @_Z13getIntPRValuev()
// CHECK-NEXT: store i32 {{.*}}, i32*
// CHECK-NEXT: ret i32*
int &&f2() { return static_cast<int&&>(getIntPRValue()); }
bool ok;
class C
{
int* state_;
C(const C&) = delete;
C& operator=(const C&) = delete;
public:
C(int state) : state_(new int(state)) { }
C(C&& a) {
state_ = a.state_;
a.state_ = 0;
}
~C() {
delete state_;
state_ = 0;
}
};
C test();
// CHECK: define void @_Z15elide_copy_initv
void elide_copy_init() {
ok = false;
// CHECK: call void @_Z4testv
C a = test();
// CHECK-NEXT: call void @_ZN1CD1Ev
// CHECK-NEXT: ret void
}
// CHECK: define void @_Z16test_move_returnv
C test_move_return() {
// CHECK: call void @_ZN1CC1Ei
C a1(3);
// CHECK: call void @_ZN1CC1Ei
C a2(4);
if (ok)
// CHECK: call void @_ZN1CC1EOS_
return a1;
// CHECK: call void @_ZN1CC1EOS_
return a2;
// CHECK: call void @_ZN1CD1Ev
// CHECK: call void @_ZN1CD1Ev
//CHECK: ret void
}
// PR10800: don't crash
namespace test1 {
int &&move(int&);
struct A { A(int); };
struct B {
A a;
B(int i);
};
// CHECK: define void @_ZN5test11BC2Ei(
// CHECK: [[T0:%.*]] = call i32* @_ZN5test14moveERi(
// CHECK-NEXT: [[T1:%.*]] = load i32* [[T0]]
// CHECK-NEXT: call void @_ZN5test11AC1Ei({{.*}}, i32 [[T1]])
// CHECK-NEXT: ret void
B::B(int i) : a(move(i)) {}
}
// PR11009
struct MoveConvertible {
operator int&& () const;
};
void moveConstruct() {
(void)(int)MoveConvertible();
}