Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 2cb28b3

Browse files
authored
Re-apply "Disallow ArrayRef assignment from temporaries." (#28)
This re-applies r283798, disabled in r283803, with the static_assert tests disabled under MSVC. The deleted functions still seem to catch mistakes in MSVC, so it's not a significant loss. Part of rdar://problem/16375365 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@283935 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent e85c04a commit 2cb28b3

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

include/llvm/ADT/ArrayRef.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,22 @@ namespace llvm {
203203
return Data[Index];
204204
}
205205

206+
/// Disallow accidental assignment from a temporary.
207+
///
208+
/// The declaration here is extra complicated so that "arrayRef = {}"
209+
/// continues to select the move assignment operator.
210+
template <typename U>
211+
typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type &
212+
operator=(U &&Temporary) = delete;
213+
214+
/// Disallow accidental assignment from a temporary.
215+
///
216+
/// The declaration here is extra complicated so that "arrayRef = {}"
217+
/// continues to select the move assignment operator.
218+
template <typename U>
219+
typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type &
220+
operator=(std::initializer_list<U>) = delete;
221+
206222
/// @}
207223
/// @name Expensive Operations
208224
/// @{

unittests/ADT/ArrayRefTest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,26 @@ static_assert(
3131
!std::is_convertible<ArrayRef<volatile int *>, ArrayRef<int *>>::value,
3232
"Removing volatile");
3333

34+
// Check that we can't accidentally assign a temporary location to an ArrayRef.
35+
// (Unfortunately we can't make use of the same thing with constructors.)
36+
//
37+
// Disable this check under MSVC; even MSVC 2015 isn't inconsistent between
38+
// std::is_assignable and actually writing such an assignment.
39+
#if !defined(_MSC_VER)
40+
static_assert(
41+
!std::is_assignable<ArrayRef<int *>, int *>::value,
42+
"Assigning from single prvalue element");
43+
static_assert(
44+
!std::is_assignable<ArrayRef<int *>, int * &&>::value,
45+
"Assigning from single xvalue element");
46+
static_assert(
47+
std::is_assignable<ArrayRef<int *>, int * &>::value,
48+
"Assigning from single lvalue element");
49+
static_assert(
50+
!std::is_assignable<ArrayRef<int *>, std::initializer_list<int *>>::value,
51+
"Assigning from an initializer list");
52+
#endif
53+
3454
namespace {
3555

3656
TEST(ArrayRefTest, AllocatorCopy) {
@@ -146,6 +166,14 @@ TEST(ArrayRefTest, InitializerList) {
146166
ArgTest12({1, 2});
147167
}
148168

169+
TEST(ArrayRefTest, EmptyInitializerList) {
170+
ArrayRef<int> A = {};
171+
EXPECT_TRUE(A.empty());
172+
173+
A = {};
174+
EXPECT_TRUE(A.empty());
175+
}
176+
149177
// Test that makeArrayRef works on ArrayRef (no-op)
150178
TEST(ArrayRefTest, makeArrayRef) {
151179
static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8};

0 commit comments

Comments
 (0)