forked from OSchip/llvm-project
Disallow ArrayRef assignment from temporaries.
Without this, the following statements will create ArrayRefs that refer to temporary storage that goes out of scope by the end of the line: someArrayRef = getSingleElement(); someArrayRef = {elem1, elem2}; Note that the constructor still has this problem: ArrayRef<Element> someArrayRef = getSingleElement(); ArrayRef<Element> someArrayRef = {elem1, elem2}; but that's a little harder to get rid of because we want to be able to use this in calls: takesArrayRef(getSingleElement()); takesArrayRef({elem1, elem2}); Part of rdar://problem/16375365. Reviewed by Duncan Exon Smith. llvm-svn: 283798
This commit is contained in:
parent
fcd2421667
commit
d77cee3f54
|
@ -219,6 +219,22 @@ namespace llvm {
|
|||
return Data[Index];
|
||||
}
|
||||
|
||||
/// Disallow accidental assignment from a temporary.
|
||||
///
|
||||
/// The declaration here is extra complicated so that "arrayRef = {}"
|
||||
/// continues to select the move assignment operator.
|
||||
template <typename U>
|
||||
typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type &
|
||||
operator=(U &&Temporary) = delete;
|
||||
|
||||
/// Disallow accidental assignment from a temporary.
|
||||
///
|
||||
/// The declaration here is extra complicated so that "arrayRef = {}"
|
||||
/// continues to select the move assignment operator.
|
||||
template <typename U>
|
||||
typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type &
|
||||
operator=(std::initializer_list<U>) = delete;
|
||||
|
||||
/// @}
|
||||
/// @name Expensive Operations
|
||||
/// @{
|
||||
|
|
|
@ -31,6 +31,21 @@ static_assert(
|
|||
!std::is_convertible<ArrayRef<volatile int *>, ArrayRef<int *>>::value,
|
||||
"Removing volatile");
|
||||
|
||||
// Check that we can't accidentally assign a temporary location to an ArrayRef.
|
||||
// (Unfortunately we can't make use of the same thing with constructors.)
|
||||
static_assert(
|
||||
!std::is_assignable<ArrayRef<int *>, int *>::value,
|
||||
"Assigning from single prvalue element");
|
||||
static_assert(
|
||||
!std::is_assignable<ArrayRef<int *>, int * &&>::value,
|
||||
"Assigning from single xvalue element");
|
||||
static_assert(
|
||||
std::is_assignable<ArrayRef<int *>, int * &>::value,
|
||||
"Assigning from single lvalue element");
|
||||
static_assert(
|
||||
!std::is_assignable<ArrayRef<int *>, std::initializer_list<int *>>::value,
|
||||
"Assigning from an initializer list");
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(ArrayRefTest, AllocatorCopy) {
|
||||
|
@ -161,6 +176,14 @@ TEST(ArrayRefTest, InitializerList) {
|
|||
ArgTest12({1, 2});
|
||||
}
|
||||
|
||||
TEST(ArrayRefTest, EmptyInitializerList) {
|
||||
ArrayRef<int> A = {};
|
||||
EXPECT_TRUE(A.empty());
|
||||
|
||||
A = {};
|
||||
EXPECT_TRUE(A.empty());
|
||||
}
|
||||
|
||||
// Test that makeArrayRef works on ArrayRef (no-op)
|
||||
TEST(ArrayRefTest, makeArrayRef) {
|
||||
static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8};
|
||||
|
|
Loading…
Reference in New Issue