313 lines
5.7 KiB
C++
313 lines
5.7 KiB
C++
|
// RUN: not %clang_cc1 -triple x86_64-apple-darwin -verify -emit-llvm -o - %s | FileCheck %s
|
||
|
void t1() {
|
||
|
// CHECK-LABEL: define void @_Z2t1v
|
||
|
// CHECK: [[REFLOAD:%.*]] = load i32** @a, align 8
|
||
|
// CHECK: load i32* [[REFLOAD]], align 4
|
||
|
extern int& a;
|
||
|
int b = a;
|
||
|
}
|
||
|
|
||
|
void t2(int& a) {
|
||
|
// CHECK-LABEL: define void @_Z2t2Ri
|
||
|
// CHECK: [[REFLOAD2:%.*]] = load i32** {{.*}}, align 8
|
||
|
// CHECK: load i32* [[REFLOAD2]], align 4
|
||
|
int b = a;
|
||
|
}
|
||
|
|
||
|
int g;
|
||
|
int& gr = g;
|
||
|
int& grr = gr;
|
||
|
void t3() {
|
||
|
int b = gr;
|
||
|
}
|
||
|
|
||
|
// Test reference binding.
|
||
|
|
||
|
struct C { int a; };
|
||
|
void f(const bool&);
|
||
|
void f(const int&);
|
||
|
void f(const _Complex int&);
|
||
|
void f(const C&);
|
||
|
|
||
|
C aggregate_return();
|
||
|
|
||
|
bool& bool_reference_return();
|
||
|
int& int_reference_return();
|
||
|
_Complex int& complex_int_reference_return();
|
||
|
C& aggregate_reference_return();
|
||
|
|
||
|
void test_bool() {
|
||
|
bool a = true;
|
||
|
f(a);
|
||
|
|
||
|
f(true);
|
||
|
|
||
|
bool_reference_return() = true;
|
||
|
a = bool_reference_return();
|
||
|
|
||
|
struct { const bool& b; } b = { true };
|
||
|
}
|
||
|
|
||
|
void test_scalar() {
|
||
|
int a = 10;
|
||
|
f(a);
|
||
|
|
||
|
struct { int bitfield : 3; } s = { 3 };
|
||
|
f(s.bitfield);
|
||
|
|
||
|
f(10);
|
||
|
|
||
|
__attribute((vector_size(16))) typedef int vec4;
|
||
|
f((vec4){1,2,3,4}[0]);
|
||
|
|
||
|
int_reference_return() = 10;
|
||
|
a = int_reference_return();
|
||
|
|
||
|
struct { const int& a; } agg = { 10 };
|
||
|
}
|
||
|
|
||
|
void test_complex() {
|
||
|
_Complex int a = 10i;
|
||
|
f(a);
|
||
|
|
||
|
f(10i);
|
||
|
|
||
|
complex_int_reference_return() = 10i;
|
||
|
a = complex_int_reference_return();
|
||
|
|
||
|
struct { const _Complex int &a; } agg = { 10i };
|
||
|
}
|
||
|
|
||
|
void test_aggregate() {
|
||
|
C c;
|
||
|
f(c);
|
||
|
|
||
|
f(aggregate_return());
|
||
|
aggregate_reference_return().a = 10;
|
||
|
|
||
|
c = aggregate_reference_return();
|
||
|
|
||
|
struct { const C& a; } agg = { C() };
|
||
|
}
|
||
|
|
||
|
int& reference_return() {
|
||
|
return g;
|
||
|
}
|
||
|
|
||
|
int reference_decl() {
|
||
|
int& a = g;
|
||
|
const int& b = 1;
|
||
|
return a+b;
|
||
|
}
|
||
|
|
||
|
struct A {
|
||
|
int& b();
|
||
|
};
|
||
|
|
||
|
void f(A* a) {
|
||
|
int b = a->b();
|
||
|
}
|
||
|
|
||
|
// PR5122
|
||
|
void *foo = 0;
|
||
|
void * const & kFoo = foo;
|
||
|
|
||
|
struct D : C { D(); ~D(); };
|
||
|
|
||
|
void h() {
|
||
|
// CHECK: call void @_ZN1DD1Ev
|
||
|
const C& c = D();
|
||
|
}
|
||
|
|
||
|
namespace T {
|
||
|
struct A {
|
||
|
A();
|
||
|
~A();
|
||
|
};
|
||
|
|
||
|
struct B {
|
||
|
B();
|
||
|
~B();
|
||
|
A f();
|
||
|
};
|
||
|
|
||
|
void f() {
|
||
|
// CHECK: call void @_ZN1T1BC1Ev
|
||
|
// CHECK: call void @_ZN1T1B1fEv
|
||
|
// CHECK: call void @_ZN1T1BD1Ev
|
||
|
const A& a = B().f();
|
||
|
// CHECK: call void @_ZN1T1fEv
|
||
|
f();
|
||
|
// CHECK: call void @_ZN1T1AD1Ev
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// PR5227.
|
||
|
namespace PR5227 {
|
||
|
void f(int &a) {
|
||
|
(a = 10) = 20;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// PR5590
|
||
|
struct s0;
|
||
|
struct s1 { struct s0 &s0; };
|
||
|
void f0(s1 a) { s1 b = a; }
|
||
|
|
||
|
// PR6024
|
||
|
// CHECK: @_Z2f2v()
|
||
|
// CHECK: alloca i32,
|
||
|
// CHECK-NEXT: store
|
||
|
// CHECK-NEXT: ret
|
||
|
const int &f2() { return 0; }
|
||
|
|
||
|
// Don't constant fold const reference parameters with default arguments to
|
||
|
// their default arguments.
|
||
|
namespace N1 {
|
||
|
const int foo = 1;
|
||
|
// CHECK: @_ZN2N14test
|
||
|
void test(const int& arg = foo) {
|
||
|
// Ensure this array is on the stack where we can set values instead of
|
||
|
// being a global constant.
|
||
|
// CHECK: %args_array = alloca
|
||
|
const int* const args_array[] = { &arg };
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Bind to subobjects while extending the life of the complete object.
|
||
|
namespace N2 {
|
||
|
class X {
|
||
|
public:
|
||
|
X(const X&);
|
||
|
X &operator=(const X&);
|
||
|
~X();
|
||
|
};
|
||
|
|
||
|
struct P {
|
||
|
X first;
|
||
|
};
|
||
|
|
||
|
P getP();
|
||
|
|
||
|
// CHECK-LABEL: define void @_ZN2N21fEi
|
||
|
// CHECK: call void @_ZN2N24getPEv
|
||
|
// CHECK: getelementptr inbounds
|
||
|
// CHECK: store i32 17
|
||
|
// CHECK: call void @_ZN2N21PD1Ev
|
||
|
void f(int i) {
|
||
|
const X& xr = getP().first;
|
||
|
i = 17;
|
||
|
}
|
||
|
|
||
|
struct SpaceWaster {
|
||
|
int i, j;
|
||
|
};
|
||
|
|
||
|
struct ReallyHasX {
|
||
|
X x;
|
||
|
};
|
||
|
|
||
|
struct HasX : ReallyHasX { };
|
||
|
|
||
|
struct HasXContainer {
|
||
|
HasX has;
|
||
|
};
|
||
|
|
||
|
struct Y : SpaceWaster, HasXContainer { };
|
||
|
struct Z : SpaceWaster, Y { };
|
||
|
|
||
|
Z getZ();
|
||
|
|
||
|
// CHECK-LABEL: define void @_ZN2N21gEi
|
||
|
// CHECK: call void @_ZN2N24getZEv
|
||
|
// CHECK: {{getelementptr inbounds.*i32 0, i32 0}}
|
||
|
// CHECK: {{getelementptr inbounds.*i32 0, i32 0}}
|
||
|
// CHECK: store i32 19
|
||
|
// CHECK: call void @_ZN2N21ZD1Ev
|
||
|
// CHECK: ret void
|
||
|
void g(int i) {
|
||
|
const X &xr = getZ().has.x;
|
||
|
i = 19;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
namespace N3 {
|
||
|
|
||
|
// PR7326
|
||
|
|
||
|
struct A {
|
||
|
explicit A(int);
|
||
|
~A();
|
||
|
};
|
||
|
|
||
|
// CHECK-LABEL: define internal void @__cxx_global_var_init
|
||
|
// CHECK: call void @_ZN2N31AC1Ei(%"struct.N3::A"* @_ZGRN2N35sA123E, i32 123)
|
||
|
// CHECK: call i32 @__cxa_atexit
|
||
|
// CHECK: ret void
|
||
|
const A &sA123 = A(123);
|
||
|
}
|
||
|
|
||
|
namespace N4 {
|
||
|
|
||
|
struct A {
|
||
|
A();
|
||
|
~A();
|
||
|
};
|
||
|
|
||
|
void f() {
|
||
|
// CHECK-LABEL: define void @_ZN2N41fEv
|
||
|
// CHECK: call void @_ZN2N41AC1Ev(%"struct.N4::A"* @_ZGRZN2N41fEvE2ar)
|
||
|
// CHECK: call i32 @__cxa_atexit
|
||
|
// CHECK: ret void
|
||
|
static const A& ar = A();
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// PR9494
|
||
|
namespace N5 {
|
||
|
struct AnyS { bool b; };
|
||
|
void f(const bool&);
|
||
|
AnyS g();
|
||
|
void h() {
|
||
|
// CHECK: call i8 @_ZN2N51gEv()
|
||
|
// CHECK: call void @_ZN2N51fERKb(i8*
|
||
|
f(g().b);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// PR9565
|
||
|
namespace PR9565 {
|
||
|
struct a { int a : 10, b : 10; };
|
||
|
// CHECK-LABEL: define void @_ZN6PR95651fEv()
|
||
|
void f() {
|
||
|
// CHECK: call void @llvm.memcpy
|
||
|
a x = { 0, 0 };
|
||
|
// CHECK: [[WITH_SEVENTEEN:%[.a-zA-Z0-9]+]] = or i32 [[WITHOUT_SEVENTEEN:%[.a-zA-Z0-9]+]], 17
|
||
|
// CHECK: store i32 [[WITH_SEVENTEEN]], i32* [[XA:%[.a-zA-Z0-9]+]]
|
||
|
x.a = 17;
|
||
|
// CHECK-NEXT: bitcast
|
||
|
// CHECK-NEXT: load
|
||
|
// CHECK-NEXT: shl
|
||
|
// CHECK-NEXT: ashr
|
||
|
// CHECK-NEXT: store i32
|
||
|
// CHECK-NEXT: store i32*
|
||
|
const int &y = x.a;
|
||
|
// CHECK-NEXT: bitcast
|
||
|
// CHECK-NEXT: load
|
||
|
// CHECK-NEXT: and
|
||
|
// CHECK-NEXT: or i32 {{.*}}, 19456
|
||
|
// CHECK-NEXT: store i32
|
||
|
x.b = 19;
|
||
|
// CHECK-NEXT: ret void
|
||
|
}
|
||
|
}
|
||
|
|
||
|
namespace N6 {
|
||
|
extern struct x {char& x;}y;
|
||
|
int a() { return y.x; }
|
||
|
// CHECK-LABEL: define i32 @_ZN2N61aEv
|
||
|
// CHECK: [[REFLOAD3:%.*]] = load i8** getelementptr inbounds (%"struct.N6::x"* @_ZN2N61yE, i32 0, i32 0), align 8
|
||
|
// CHECK: load i8* [[REFLOAD3]], align 1
|
||
|
}
|