Skip to content

Commit e861d51

Browse files
authored
libSyntax: implement the rule of five for OwnedString to ensure correct memory management. rdar://35116413 (#12610)
Thank you! @jrose-apple
1 parent 6d3fd90 commit e861d51

File tree

1 file changed

+45
-13
lines changed

1 file changed

+45
-13
lines changed

include/swift/Basic/OwnedString.h

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,17 @@ enum class StringOwnership {
4242
class OwnedString {
4343
const char *Data;
4444
size_t Length;
45-
StringOwnership Ownership;
45+
StringOwnership Ownership = StringOwnership::Unowned;
4646

47-
OwnedString(const char* Data, size_t Length, StringOwnership Ownership)
48-
: Length(Length), Ownership(Ownership) {
49-
assert(Length >= 0 && "expected length to be non-negative");
47+
void release() {
48+
if (Ownership == StringOwnership::Copied)
49+
free(const_cast<char *>(Data));
50+
}
5051

52+
void initialize(const char* Data, size_t Length, StringOwnership Ownership) {
53+
this->Length = Length;
54+
this->Ownership = Ownership;
55+
assert(Length >= 0 && "expected length to be non-negative");
5156
if (Ownership == StringOwnership::Copied && Data) {
5257
char *substring = static_cast<char *>(malloc(Length + 1));
5358
assert(substring && "expected successful malloc of copy");
@@ -60,20 +65,48 @@ class OwnedString {
6065
else
6166
this->Data = Data;
6267
}
63-
68+
OwnedString(const char* Data, size_t Length, StringOwnership Ownership) {
69+
initialize(Data, Length, Ownership);
70+
}
6471
public:
65-
OwnedString() : OwnedString(nullptr, 0, StringOwnership::Unowned) {}
72+
OwnedString(): OwnedString(nullptr, 0, StringOwnership::Unowned) {}
6673

67-
OwnedString(const char *Data, size_t Length)
68-
: OwnedString(Data, Length, StringOwnership::Unowned) {}
74+
OwnedString(const char *Data, size_t Length):
75+
OwnedString(Data, Length, StringOwnership::Unowned) {}
6976

7077
OwnedString(StringRef Str) : OwnedString(Str.data(), Str.size()) {}
7178

7279
OwnedString(const char *Data) : OwnedString(StringRef(Data)) {}
7380

74-
OwnedString(const OwnedString &Other)
75-
: OwnedString(Other.Data, Other.Length, Other.Ownership) {}
76-
81+
OwnedString(const OwnedString &Other):
82+
OwnedString(Other.Data, Other.Length, Other.Ownership) {}
83+
84+
OwnedString(OwnedString &&Other): Data(Other.Data), Length(Other.Length),
85+
Ownership(Other.Ownership) {
86+
Other.Data = nullptr;
87+
Other.Ownership = StringOwnership::Unowned;
88+
}
89+
90+
OwnedString& operator=(const OwnedString &Other) {
91+
if (&Other != this) {
92+
release();
93+
initialize(Other.Data, Other.Length, Other.Ownership);
94+
}
95+
return *this;
96+
}
97+
98+
OwnedString& operator=(OwnedString &&Other) {
99+
if (&Other != this) {
100+
release();
101+
this->Data = Other.Data;
102+
this->Length = Other.Length;
103+
this->Ownership = Other.Ownership;
104+
Other.Ownership = StringOwnership::Unowned;
105+
Other.Data = nullptr;
106+
}
107+
return *this;
108+
}
109+
77110
OwnedString copy() {
78111
return OwnedString(Data, Length, StringOwnership::Copied);
79112
}
@@ -99,8 +132,7 @@ class OwnedString {
99132
}
100133

101134
~OwnedString() {
102-
if (Ownership == StringOwnership::Copied)
103-
free(const_cast<char *>(Data));
135+
release();
104136
}
105137
};
106138

0 commit comments

Comments
 (0)