237 lines
8.0 KiB
C++
237 lines
8.0 KiB
C++
// 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 reference of type 'const int' to value of type 'const volatile int' drops 'volatile' qualifier}}
|
|
|
|
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));
|
|
}
|
|
}
|
|
|
|
namespace rdar13278115 {
|
|
struct X { };
|
|
struct Y : X { };
|
|
X &&f0(X &x) { return x; } // expected-error{{rvalue reference to type 'rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::X'}}
|
|
X &&f1(Y &y) { return y; } // expected-error{{rvalue reference to type 'rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::Y'}}
|
|
const X &&f2(Y &y) { return y; } // expected-error{{rvalue reference to type 'const rdar13278115::X' cannot bind to lvalue of type 'rdar13278115::Y'}}
|
|
}
|
|
|
|
namespace bitfields {
|
|
struct IntBitfield {
|
|
int i : 17; // expected-note 3 {{bit-field is declared here}}
|
|
};
|
|
|
|
// A simplified version of std::move.
|
|
template <typename T>
|
|
T &&move(T &obj) {
|
|
return static_cast<T &&>(obj);
|
|
}
|
|
|
|
void test() {
|
|
int & ir1 = (lvalue<IntBitfield>().i); // expected-error{{non-const reference cannot bind to bit-field 'i'}}
|
|
int & ir2 = (xvalue<IntBitfield>().i); // expected-error{{non-const lvalue reference to type 'int' cannot bind to a temporary of type 'int'}}
|
|
int && ir3 = (xvalue<IntBitfield>().i); // no-warning
|
|
int && ir4 = move(lvalue<IntBitfield>()).i; // no-warning
|
|
|
|
volatile int & vir1 = (lvalue<IntBitfield>().i); // expected-error{{non-const reference cannot bind to bit-field 'i'}}
|
|
volatile int & vir2 = (xvalue<IntBitfield>().i); // expected-error{{volatile lvalue reference to type 'volatile int' cannot bind to a temporary of type 'int'}}
|
|
volatile int && vir3 = (xvalue<IntBitfield>().i); // no-warning
|
|
volatile int && vir4 = move(lvalue<IntBitfield>()).i; // no-warning
|
|
|
|
const int & cir1 = (lvalue<IntBitfield>().i); // no-warning
|
|
const int & cir2 = (xvalue<IntBitfield>().i); // no-warning
|
|
const int && cir3 = (xvalue<IntBitfield>().i); // no-warning
|
|
const int && cir4 = move(lvalue<IntBitfield>()).i; // no-warning
|
|
|
|
const volatile int & cvir1 = (lvalue<IntBitfield>().i); // expected-error{{non-const reference cannot bind to bit-field 'i'}}
|
|
const volatile int & cvir2 = (xvalue<IntBitfield>().i); // expected-error{{volatile lvalue reference to type 'const volatile int' cannot bind to a temporary of type 'int'}}
|
|
const volatile int && cvir3 = (xvalue<IntBitfield>().i); // no-warning
|
|
const volatile int && cvir4 = move(lvalue<IntBitfield>()).i; // no-warning
|
|
}
|
|
}
|