| // RUN: %clang_cc1 -triple x86_64-apple-darwin -verify -emit-llvm -o - %s | FileCheck %s |
| void t1() { |
| // CHECK: 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: 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: 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: 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: 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: 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: 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: 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 |
| } |