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

Commit 3766c60

Browse files
authored
Merge pull request #32 from jrose-apple/swift-3.1-StringRef-temporaries
Disallow StringRef assignment from temporary std::strings
2 parents ab8e654 + 2544262 commit 3766c60

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

include/llvm/ADT/StringRef.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,15 @@ namespace llvm {
226226
return Data[Index];
227227
}
228228

229+
/// Disallow accidental assignment from a temporary std::string.
230+
///
231+
/// The declaration here is extra complicated so that `stringRef = {}`
232+
/// and `stringRef = "abc"` continue to select the move assignment operator.
233+
template <typename T>
234+
typename std::enable_if<std::is_same<T, std::string>::value,
235+
StringRef>::type &
236+
operator=(T &&Str) = delete;
237+
229238
/// @}
230239
/// @name Type Conversions
231240
/// @{

unittests/ADT/StringRefTest.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,34 @@ std::ostream &operator<<(std::ostream &OS,
3232

3333
}
3434

35+
// Check that we can't accidentally assign a temporary std::string to a
36+
// StringRef. (Unfortunately we can't make use of the same thing with
37+
// constructors.)
38+
//
39+
// Disable this check under MSVC; even MSVC 2015 isn't consistent between
40+
// std::is_assignable and actually writing such an assignment.
41+
#if !defined(_MSC_VER)
42+
static_assert(
43+
!std::is_assignable<StringRef, std::string>::value,
44+
"Assigning from prvalue std::string");
45+
static_assert(
46+
!std::is_assignable<StringRef, std::string &&>::value,
47+
"Assigning from xvalue std::string");
48+
static_assert(
49+
std::is_assignable<StringRef, std::string &>::value,
50+
"Assigning from lvalue std::string");
51+
static_assert(
52+
std::is_assignable<StringRef, const char *>::value,
53+
"Assigning from prvalue C string");
54+
static_assert(
55+
std::is_assignable<StringRef, const char * &&>::value,
56+
"Assigning from xvalue C string");
57+
static_assert(
58+
std::is_assignable<StringRef, const char * &>::value,
59+
"Assigning from lvalue C string");
60+
#endif
61+
62+
3563
namespace {
3664
TEST(StringRefTest, Construction) {
3765
EXPECT_EQ("", StringRef());
@@ -40,6 +68,14 @@ TEST(StringRefTest, Construction) {
4068
EXPECT_EQ("hello", StringRef(std::string("hello")));
4169
}
4270

71+
TEST(StringRefTest, EmptyInitializerList) {
72+
StringRef S = {};
73+
EXPECT_TRUE(S.empty());
74+
75+
S = {};
76+
EXPECT_TRUE(S.empty());
77+
}
78+
4379
TEST(StringRefTest, Iteration) {
4480
StringRef S("hello");
4581
const char *p = "hello";

0 commit comments

Comments
 (0)