llvm-project/clang/test/CodeGenCXX/references.cpp

313 lines
5.8 KiB
C++

// RUN: not %clang_cc1 -no-opaque-pointers -triple x86_64-apple-darwin -verify -emit-llvm -o - %s | FileCheck %s
void t1() {
// CHECK-LABEL: define{{.*}} void @_Z2t1v
// CHECK: [[REFLOAD:%.*]] = load i32*, i32** @a, align 8
// CHECK: load i32, i32* [[REFLOAD]], align 4
extern int& a;
int b = a;
}
void t2(int& a) {
// CHECK-LABEL: define{{.*}} void @_Z2t2Ri
// CHECK: [[REFLOAD2:%.*]] = load i32*, i32** {{.*}}, align 8
// CHECK: load i32, 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 noundef 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*, i8** getelementptr inbounds (%"struct.N6::x", %"struct.N6::x"* @_ZN2N61yE, i32 0, i32 0), align 8
// CHECK: load i8, i8* [[REFLOAD3]], align 1
}