diff options
Diffstat (limited to 'clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref')
9 files changed, 599 insertions, 0 deletions
diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/basic.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/basic.cpp new file mode 100644 index 0000000..885d11b --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/basic.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +// PR5787 +class C { + public: +  ~C() {} +}; + +template <typename T> +class E { + public: +  E& Foo(const C&); +  E& Bar() { return Foo(C()); } +}; + +void Test() { +  E<int> e; +  e.Bar(); +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp new file mode 100644 index 0000000..20c059e --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p1.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +int g(int); +void f() { +  int i;  +  int& r = i; +  r = 1;  +  int* p = &r; +  int &rr=r;  +  int (&rg)(int) = g;  +  rg(i);  +  int a[3];  +  int (&ra)[3] = a;  +  ra[1] = i; +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp new file mode 100644 index 0000000..47e215a --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p3.cpp @@ -0,0 +1,3 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +int& r1;	// expected-error{{declaration of reference variable 'r1' requires an initializer}} +extern int& r2; diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp new file mode 100644 index 0000000..adbdff6 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-0x.cpp @@ -0,0 +1,194 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -pedantic %s + +// Test the c++0x-specific reference initialization rules, e.g., the +// rules for rvalue references. +template<typename T> T prvalue(); +template<typename T> T&& xvalue(); +template<typename T> T& lvalue(); + +struct Base { }; +struct Derived : Base { }; + +struct HasArray { +  int array[5]; +}; + +int f(int); + +template<typename T> +struct ConvertsTo { +  operator T(); // expected-note 2{{candidate function}} +}; + +void test_rvalue_refs() { +  // If the initializer expression... +  //   - is an xvalue, class prvalue, array prvalue or function lvalue +  //     and "cv1 T1" is reference-compatible with "cv2 T2", or + +  // xvalue case +  Base&& base0 = xvalue<Base>(); +  Base&& base1 = xvalue<Derived>(); +  int&& int0 = xvalue<int>(); + +  // class prvalue case +  Base&& base2 = prvalue<Base>(); +  Base&& base3 = prvalue<Derived>(); + +  // array prvalue case +  int (&&array0)[5] = HasArray().array; + +  // function lvalue case +  int (&&function0)(int) = f; + +  //   - has a class type (i.e., T2 is a class type), where T1 is not +  //     reference-related to T2, and can be implicitly converted to +  //     an xvalue, class prvalue, or function lvalue of type "cv3 +  //     T3", where "cv1 T1" is reference-compatible with "cv3 T3", + +  // xvalue +  Base&& base4 = ConvertsTo<Base&&>(); +  Base&& base5 = ConvertsTo<Derived&&>(); +  int && int1 = ConvertsTo<int&&>(); + +  // class prvalue +  Base&& base6 = ConvertsTo<Base>(); +  Base&& base7 = ConvertsTo<Derived>(); + +  // function lvalue +  int (&&function1)(int) = ConvertsTo<int(&)(int)>(); + +  // In the second case, if the reference is an rvalue reference and +  // the second standard conversion sequence of the user-defined +  // conversion sequence includes an lvalue-to-rvalue conversion, the +  // program is ill-formed. +  int &&int2 = ConvertsTo<int&>(); // expected-error{{no viable conversion from 'ConvertsTo<int &>' to 'int'}} +  int &&int3 = ConvertsTo<float&>(); // expected-error{{no viable conversion from 'ConvertsTo<float &>' to 'int'}} +} + +class NonCopyable { +  NonCopyable(const NonCopyable&); +}; + +class NonCopyableDerived : public NonCopyable { +  NonCopyableDerived(const NonCopyableDerived&); +}; + +// Make sure we get direct bindings with no copies. +void test_direct_binding() { +  NonCopyable &&nc0 = prvalue<NonCopyable>(); +  NonCopyable &&nc1 = prvalue<NonCopyableDerived>(); +  NonCopyable &&nc2 = xvalue<NonCopyable>(); +  NonCopyable &&nc3 = xvalue<NonCopyableDerived>(); +  const NonCopyable &nc4 = prvalue<NonCopyable>(); +  const NonCopyable &nc5 = prvalue<NonCopyableDerived>(); +  const NonCopyable &nc6 = xvalue<NonCopyable>(); +  const NonCopyable &nc7 = xvalue<NonCopyableDerived>(); +  NonCopyable &&nc8 = ConvertsTo<NonCopyable&&>(); +  NonCopyable &&nc9 = ConvertsTo<NonCopyableDerived&&>(); +  const NonCopyable &nc10 = ConvertsTo<NonCopyable&&>(); +  const NonCopyable &nc11 = ConvertsTo<NonCopyableDerived&&>(); +} + +namespace std_example_1 { +  double d = 2.0;  +  double& rd = d;  +  const double& rcd = d; +  struct A { };  +  struct B : A {  +    operator int&(); +  } b; +  A& ra = b;  +  const A& rca = b;  +  int& ir = B(); +} + +namespace std_example_2 { +  double& rd2 = 2.0; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a temporary of type 'double'}} +  int i = 2;  +  double& rd3 = i; // expected-error{{non-const lvalue reference to type 'double' cannot bind to a value of unrelated type 'int'}} +  struct A { };  +  struct B : A { } b;  +  extern B f();  +  const A& rca = f();  +  A&& rra = f(); +  struct X {  +    operator B();  // expected-note{{candidate function}} +    operator int&(); // expected-note{{candidate function}} +  } x; +  const A& r = x; +  int&& rri = static_cast<int&&>(i); +  B&& rrb = x; +  int&& rri2 = X(); // expected-error{{no viable conversion from 'std_example_2::X' to 'int'}} + +  const double& rcd2 = 2; +  double&& rrd = 2; +  const volatile int cvi = 1;  +  const int& r2 = cvi; // expected-error{{binding of reference to type 'const int' to a value of type 'const volatile int' drops qualifiers}} + +  double d; +  double&& rrd2 = d; // expected-error{{rvalue reference to type 'double' cannot bind to lvalue of type 'double'}} +  double&& rrd3 = i; +} + +namespace argument_passing { +  void base_rvalue_ref(Base&&); +  void int_rvalue_ref(int&&); // expected-note{{candidate function not viable: no known conversion from 'ConvertsTo<int &>' to 'int &&' for 1st argument}} \ +  // expected-note{{candidate function not viable: no known conversion from 'ConvertsTo<float &>' to 'int &&' for 1st argument}} + +  void array_rvalue_ref(int (&&)[5]); +  void function_rvalue_ref(int (&&)(int)); + +  void test() { +    base_rvalue_ref(xvalue<Base>()); +    base_rvalue_ref(xvalue<Derived>()); +    int_rvalue_ref(xvalue<int>()); +     +    base_rvalue_ref(prvalue<Base>()); +    base_rvalue_ref(prvalue<Derived>()); +     +    array_rvalue_ref(HasArray().array); +     +    function_rvalue_ref(f); +     +    base_rvalue_ref(ConvertsTo<Base&&>()); +    base_rvalue_ref(ConvertsTo<Derived&&>()); +    int_rvalue_ref(ConvertsTo<int&&>()); +     +    base_rvalue_ref(ConvertsTo<Base>()); +    base_rvalue_ref(ConvertsTo<Derived>()); + +    function_rvalue_ref(ConvertsTo<int(&)(int)>()); +     +    int_rvalue_ref(ConvertsTo<int&>()); // expected-error{{no matching function for call to 'int_rvalue_ref'}} +    int_rvalue_ref(ConvertsTo<float&>()); // expected-error{{no matching function for call to 'int_rvalue_ref'}} +  } + +} + +namespace pr10644 { +  struct string { +    string(const char* __s); +  }; +  class map { +    int& operator[](const string& __k); +  public: +    int& operator[](const string&& __k); +  }; +  void foo() { +    static map key_map; +    key_map["line"]; +  } +} + +namespace PR11003 { +  class Value { +  }; +  struct MoveRef { +    operator Value &() const ; +  }; +  MoveRef Move(int); +  void growTo() { +    Value x = Move(0); +    Value y(Move(0)); +  } +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp new file mode 100644 index 0000000..d58a129 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx03-extra-copy.cpp @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 -fsyntax-only -fdiagnostics-show-option -verify %s + +// C++03 requires that we check for a copy constructor when binding a +// reference to a temporary, since we are allowed to make a copy, Even +// though we don't actually make that copy, make sure that we diagnose +// cases where that copy constructor is somehow unavailable.  As an +// extension, this is only a warning. + +struct X1 { +  X1(); +  explicit X1(const X1&); +}; + +struct X2 { +  X2(); + +private: +  X2(const X2&); // expected-note{{declared private here}} +}; + +struct X3 { +  X3(); + +private: +  X3(X3&); // expected-note{{candidate constructor not viable: no known conversion from 'X3' to 'X3 &' for 1st argument}} +}; + +// Check for instantiation of default arguments +template<typename T> +T get_value_badly() { +  double *dp = 0; +  // The extension doesn't extend far enough to turn this error into a warning. +  T *tp = dp; // expected-error{{cannot initialize a variable of type 'int *' with an lvalue of type 'double *'}} +  return T(); +} + +template<typename T> +struct X4 { +  X4(); +  X4(const X4&, T = get_value_badly<T>()); // expected-note{{in instantiation of}} +};  + +// Check for "dangerous" default arguments that could cause recursion. +struct X5 { +  X5(); +  X5(const X5&, const X5& = X5()); // expected-warning{{no viable constructor copying parameter of type 'X5'}} +}; + +void g1(const X1&); +void g2(const X2&); +void g3(const X3&); +void g4(const X4<int>&); +void g5(const X5&); + +void test() { +  g1(X1()); +  g2(X2()); // expected-warning{{C++98 requires an accessible copy constructor for class 'X2' when binding a reference to a temporary; was private}} +  g3(X3()); // expected-warning{{no viable constructor copying parameter of type 'X3'}} +  g4(X4<int>()); +  g5(X5());  // Generates a warning in the default argument. +} + +// Check that unavailable copy constructors still cause SFINAE failures. +template<int> struct int_c { }; + +template<typename T> T f(const T&); + +// Would be ambiguous with the next g(), except the instantiation failure in +// sizeof() prevents that. +template<typename T> +int &g(int_c<sizeof(f(T()))> * = 0); + +template<typename T> float &g(); + +void h() { +  float &fp2 = g<X3>();  // Not ambiguous. +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx0x-no-extra-copy.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx0x-no-extra-copy.cpp new file mode 100644 index 0000000..27eb6d1 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-cxx0x-no-extra-copy.cpp @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +// C++03 requires that we check for a copy constructor when binding a +// reference to a reference-compatible rvalue, since we are allowed to +// make a copy. C++0x does not permit the copy, so ensure that we +// don't diagnose cases where the copy constructor is unavailable. + +struct X1 { +  X1(); +  explicit X1(const X1&); +}; + +struct X2 { +  X2(); + +private: +  X2(const X2&); +}; + +struct X3 { +  X3(); + +private: +  X3(X3&); +}; + +template<typename T> +T get_value_badly() { +  double *dp = 0; +  T *tp = dp; +  return T(); +} + +template<typename T> +struct X4 { +  X4(); +  X4(const X4&, T = get_value_badly<T>()); +}; + +void g1(const X1&); +void g2(const X2&); +void g3(const X3&); +void g4(const X4<int>&); + +void test() { +  g1(X1()); +  g2(X2()); +  g3(X3()); +  g4(X4<int>()); +} + +// Check that unavailable copy constructors do not cause SFINAE failures. +template<int> struct int_c { }; + +template<typename T> T f(const T&); + +template<typename T> +int &g(int_c<sizeof(f(T()))> * = 0);  // expected-note{{candidate function [with T = X3]}} + +template<typename T> float &g();  // expected-note{{candidate function [with T = X3]}} + +void h() { +  float &fp = g<X3>();  // expected-error{{call to 'g' is ambiguous}} +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp new file mode 100644 index 0000000..08d9639 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp @@ -0,0 +1,53 @@ +// RUN: %clang_cc1 -ast-dump %s 2>&1 | FileCheck %s + +// CHECK: example0 +void example0() { +  double d = 2.0; +  // CHECK: double &rd = +  // CHECK-NEXT: DeclRefExpr +  double &rd = d; +  // CHECK: const double &rcd = +  // CHECK-NEXT: ImplicitCastExpr{{.*}}'const double' lvalue <NoOp> +  const double &rcd = d; +} + +struct A { }; +struct B : A { } b; + +// CHECK: example1 +void example1() { +  // CHECK: A &ra = +  // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)> +  A &ra = b; +  // CHECK: const A &rca = +  // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue <NoOp> +  // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue <DerivedToBase (A)> +  const A& rca = b; +} + +extern B f(); + +struct X { +  operator B(); +} x; + +// CHECK: example2 +void example2() { +  // CHECK: const A &rca = +  // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp> +  // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> +  // CHECK: CallExpr{{.*}}B +  const A &rca = f();  +  // CHECK: const A &r = +  // CHECK: ImplicitCastExpr{{.*}}'const struct A' <NoOp> +  // CHECK: ImplicitCastExpr{{.*}}'struct A' <DerivedToBase (A)> +  // CHECK: CXXMemberCallExpr{{.*}}'struct B' +  const A& r = x; +} + +// CHECK: example3 +void example3() { +  // CHECK: const double &rcd2 = +  // CHECK: ImplicitCastExpr{{.*}} <IntegralToFloating> +  const double& rcd2 = 2;  +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp new file mode 100644 index 0000000..fee5f96 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-var.cpp @@ -0,0 +1,135 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +struct Base { }; +struct Derived : Base { }; // expected-note{{candidate constructor (the implicit copy constructor) not viable}} +struct Unrelated { }; +struct Derived2 : Base { }; +struct Diamond : Derived, Derived2 { }; + +struct ConvertibleToBaseRef { +  operator Base&() const; +}; + +struct ConvertibleToDerivedRef { +  operator Derived&() const; +}; + +struct ConvertibleToBothDerivedRef { +  operator Derived&(); // expected-note{{candidate function}} +  operator Derived2&(); // expected-note{{candidate function}} +}; + +struct ConvertibleToIntRef { +  operator int&(); +}; + +struct ConvertibleToBase { +  operator Base() const; +}; + +struct ConvertibleToDerived { +  operator Derived() const; +}; + +struct ConvertibleToBothDerived { +  operator Derived(); // expected-note{{candidate function}} +  operator Derived2(); // expected-note{{candidate function}} +}; + +struct ConvertibleToInt { +  operator int(); +}; + +template<typename T> T create(); + +// First bullet: lvalue references binding to lvalues (the simple cases). +void bind_lvalue_to_lvalue(Base b, Derived d,  +                           const Base bc, const Derived dc, +                           Diamond diamond, +                           int i) { +  // Reference-compatible +  Base &br1 = b; +  Base &br2 = d; +  Derived &dr1 = d; +  Derived &dr2 = b; // expected-error{{non-const lvalue reference to type 'Derived' cannot bind to a value of unrelated type 'Base'}} +  Base &br3 = bc; // expected-error{{drops qualifiers}} +  Base &br4 = dc; // expected-error{{drops qualifiers}} +  Base &br5 = diamond; // expected-error{{ambiguous conversion from derived class 'Diamond' to base class 'Base':}} +  int &ir = i; +  long &lr = i; // expected-error{{non-const lvalue reference to type 'long' cannot bind to a value of unrelated type 'int'}} +} + +void bind_lvalue_quals(volatile Base b, volatile Derived d, +                       volatile const Base bvc, volatile const Derived dvc, +                       volatile const int ivc) { +  volatile Base &bvr1 = b; +  volatile Base &bvr2 = d; +  volatile Base &bvr3 = bvc; // expected-error{{binding of reference to type 'volatile Base' to a value of type 'const volatile Base' drops qualifiers}} +  volatile Base &bvr4 = dvc; // expected-error{{binding of reference to type 'volatile Base' to a value of type 'const volatile Derived' drops qualifiers}} +   +  volatile int &ir = ivc; // expected-error{{binding of reference to type 'volatile int' to a value of type 'const volatile int' drops qualifiers}} + +  const volatile Base &bcvr1 = b; +  const volatile Base &bcvr2 = d; +} + +void bind_lvalue_to_rvalue() { +  Base &br1 = Base(); // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a temporary of type 'Base'}} +  Base &br2 = Derived(); // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a temporary of type 'Derived'}} +  const volatile Base &br3 = Base(); // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a temporary of type 'Base'}} +  const volatile Base &br4 = Derived(); // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a temporary of type 'Derived'}} + +  int &ir = 17; // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}} +} + +void bind_lvalue_to_unrelated(Unrelated ur) { +  Base &br1 = ur; // expected-error{{non-const lvalue reference to type 'Base' cannot bind to a value of unrelated type 'Unrelated'}} +  const volatile Base &br2 = ur; // expected-error{{volatile lvalue reference to type 'const volatile Base' cannot bind to a value of unrelated type 'Unrelated'}} +} + +void bind_lvalue_to_conv_lvalue() { +  // Not reference-related, but convertible +  Base &nbr1 = ConvertibleToBaseRef(); +  Base &nbr2 = ConvertibleToDerivedRef(); +  Derived &ndr1 = ConvertibleToDerivedRef(); +  int &ir = ConvertibleToIntRef(); +} + +void bind_lvalue_to_conv_lvalue_ambig(ConvertibleToBothDerivedRef both) { +  Derived &dr1 = both; +  Base &br1 = both; // expected-error{{reference initialization of type 'Base &' with initializer of type 'ConvertibleToBothDerivedRef' is ambiguous}} +} + +struct IntBitfield { +  int i : 17; // expected-note{{bit-field is declared here}} +}; + +void test_bitfield(IntBitfield ib) { +  int & ir1 = (ib.i); // expected-error{{non-const reference cannot bind to bit-field 'i'}} +} + +// Second bullet: const lvalue reference binding to an rvalue with +// similar type (both of which are class types). +void bind_const_lvalue_to_rvalue() { +  const Base &br1 = create<Base>(); +  const Base &br2 = create<Derived>(); +  const Derived &dr1 = create<Base>(); // expected-error{{no viable conversion}} + +  const Base &br3 = create<const Base>(); +  const Base &br4 = create<const Derived>(); + +  const Base &br5 = create<const volatile Base>(); // expected-error{{binding of reference to type 'const Base' to a value of type 'const volatile Base' drops qualifiers}} +  const Base &br6 = create<const volatile Derived>(); // expected-error{{binding of reference to type 'const Base' to a value of type 'const volatile Derived' drops qualifiers}} + +  const int &ir = create<int>(); +} + +// Second bullet: const lvalue reference binds to the result of a conversion. +void bind_const_lvalue_to_class_conv_temporary() { +  const Base &br1 = ConvertibleToBase(); +  const Base &br2 = ConvertibleToDerived(); +} +void bind_lvalue_to_conv_rvalue_ambig(ConvertibleToBothDerived both) { +  const Derived &dr1 = both; +  const Base &br1 = both; // expected-error{{reference initialization of type 'const Base &' with initializer of type 'ConvertibleToBothDerived' is ambiguous}} +} diff --git a/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp new file mode 100644 index 0000000..51d61a5 --- /dev/null +++ b/clang/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5.cpp @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +namespace PR5909 { +  struct Foo { +    int x : 20; +  }; +   +  bool Test(const int& foo); +   +  const Foo f = { 0 };  // It compiles without the 'const'. +  bool z = Test(f.x); +} + +namespace PR6264 { +  typedef int (&T)[3]; +  struct S +  { +    operator T (); +  }; +  void f() +  { +    T bar = S(); +  } +} + +namespace PR6066 { +  struct B { }; +  struct A : B { +    operator B*(); +    operator B&(); // expected-warning{{conversion function converting 'PR6066::A' to its base class 'PR6066::B' will never be used}} +  }; + +  void f(B&); // no rvalues accepted +  void f(B*); + +  int g() { +    f(A()); // calls f(B*) +    return 0; +  } +}  | 
