[llvm] r283935 - Re-apply "Disallow ArrayRef assignment from temporaries."
Jordan Rose via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 11 13:39:17 PDT 2016
Author: jrose
Date: Tue Oct 11 15:39:16 2016
New Revision: 283935
URL: http://llvm.org/viewvc/llvm-project?rev=283935&view=rev
Log:
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
Modified:
llvm/trunk/include/llvm/ADT/ArrayRef.h
llvm/trunk/unittests/ADT/ArrayRefTest.cpp
Modified: llvm/trunk/include/llvm/ADT/ArrayRef.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ADT/ArrayRef.h?rev=283935&r1=283934&r2=283935&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ADT/ArrayRef.h (original)
+++ llvm/trunk/include/llvm/ADT/ArrayRef.h Tue Oct 11 15:39:16 2016
@@ -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
/// @{
Modified: llvm/trunk/unittests/ADT/ArrayRefTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ADT/ArrayRefTest.cpp?rev=283935&r1=283934&r2=283935&view=diff
==============================================================================
--- llvm/trunk/unittests/ADT/ArrayRefTest.cpp (original)
+++ llvm/trunk/unittests/ADT/ArrayRefTest.cpp Tue Oct 11 15:39:16 2016
@@ -31,6 +31,26 @@ 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.)
+//
+// Disable this check under MSVC; even MSVC 2015 isn't inconsistent between
+// std::is_assignable and actually writing such an assignment.
+#if !defined(_MSC_VER)
+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");
+#endif
+
namespace {
TEST(ArrayRefTest, AllocatorCopy) {
@@ -161,6 +181,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};
More information about the llvm-commits
mailing list