text: // RUN: %clang_cc1 -triple x86_64-apple-darwin -verify -emit-llvm -o - %s | FileCheck %s
  void t1() {
    extern int& a;
    int b = a; 
  }
  
  void t2(int& a) {
    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(%"class.N2::X"* @_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(%"class.N2::X"* @_ZGRZN2N41fEvE2ar)
    // CHECK: call i32 @__cxa_atexit
    // CHECK: ret void
    static const A& ar = A();
    
  }
  }
  
  