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

Commit f5d747c

Browse files
jrose-appletfiala
authored andcommitted
Re-apply "Disallow ArrayRef assignment from temporaries."
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 (cherry picked from commit 8f3f50a)
1 parent 3e3953a commit f5d747c

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
@@ -219,6 +219,22 @@ namespace llvm {
219219
return Data[Index];
220220
}
221221

222+
/// Disallow accidental assignment from a temporary.
223+
///
224+
/// The declaration here is extra complicated so that "arrayRef = {}"
225+
/// continues to select the move assignment operator.
226+
template <typename U>
227+
typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type &
228+
operator=(U &&Temporary) = delete;
229+
230+
/// Disallow accidental assignment from a temporary.
231+
///
232+
/// The declaration here is extra complicated so that "arrayRef = {}"
233+
/// continues to select the move assignment operator.
234+
template <typename U>
235+
typename std::enable_if<std::is_same<U, T>::value, ArrayRef<T>>::type &
236+
operator=(std::initializer_list<U>) = delete;
237+
222238
/// @}
223239
/// @name Expensive Operations
224240
/// @{

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) {
@@ -160,6 +180,14 @@ TEST(ArrayRefTest, InitializerList) {
160180
ArgTest12({1, 2});
161181
}
162182

183+
TEST(ArrayRefTest, EmptyInitializerList) {
184+
ArrayRef<int> A = {};
185+
EXPECT_TRUE(A.empty());
186+
187+
A = {};
188+
EXPECT_TRUE(A.empty());
189+
}
190+
163191
// Test that makeArrayRef works on ArrayRef (no-op)
164192
TEST(ArrayRefTest, makeArrayRef) {
165193
static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8};

0 commit comments

Comments
 (0)