Cherry-pick: ICU-21559 more guards for self-assignment
Upstream Bug: https://unicode-org.atlassian.net/browse/ICU-21559
Upstream CL: https://github.com/unicode-org/icu/commit/46720c412089c719556858af27f9b34a0d0f37a4
Fix: 181964296
Fix: 181964727
Test: atest CtsIcu4cTestCases
Change-Id: Idec1f0a1bfca0ba6dae8d46bb618869ce13740d2
diff --git a/icu4c/source/common/edits.cpp b/icu4c/source/common/edits.cpp
index 95f0c19..92ca36f 100644
--- a/icu4c/source/common/edits.cpp
+++ b/icu4c/source/common/edits.cpp
@@ -86,6 +86,7 @@
}
Edits &Edits::operator=(const Edits &other) {
+ if (this == &other) { return *this; } // self-assignment: no-op
length = other.length;
delta = other.delta;
numChanges = other.numChanges;
diff --git a/icu4c/source/i18n/cpdtrans.cpp b/icu4c/source/i18n/cpdtrans.cpp
index 82ee54a..dc0217b 100644
--- a/icu4c/source/i18n/cpdtrans.cpp
+++ b/icu4c/source/i18n/cpdtrans.cpp
@@ -282,6 +282,7 @@
CompoundTransliterator& CompoundTransliterator::operator=(
const CompoundTransliterator& t)
{
+ if (this == &t) { return *this; } // self-assignment: no-op
Transliterator::operator=(t);
int32_t i = 0;
UBool failed = FALSE;
diff --git a/icu4c/source/i18n/dtfmtsym.cpp b/icu4c/source/i18n/dtfmtsym.cpp
index 690f6a4..a0c7d21 100644
--- a/icu4c/source/i18n/dtfmtsym.cpp
+++ b/icu4c/source/i18n/dtfmtsym.cpp
@@ -450,6 +450,7 @@
*/
DateFormatSymbols& DateFormatSymbols::operator=(const DateFormatSymbols& other)
{
+ if (this == &other) { return *this; } // self-assignment: no-op
dispose();
copyData(other);
diff --git a/icu4c/source/i18n/number_decimfmtprops.h b/icu4c/source/i18n/number_decimfmtprops.h
index 1ce84d9..0ace241 100644
--- a/icu4c/source/i18n/number_decimfmtprops.h
+++ b/icu4c/source/i18n/number_decimfmtprops.h
@@ -38,7 +38,7 @@
// Exported as U_I18N_API because it is a public member field of exported DecimalFormatProperties
// Using this wrapper is rather unfortunate, but is needed on Windows platforms in order to allow
-// for DLL-exporting an fully specified template instantiation.
+// for DLL-exporting a fully specified template instantiation.
class U_I18N_API CurrencyPluralInfoWrapper {
public:
LocalPointer<CurrencyPluralInfo> fPtr;
@@ -52,7 +52,8 @@
}
CurrencyPluralInfoWrapper& operator=(const CurrencyPluralInfoWrapper& other) {
- if (!other.fPtr.isNull()) {
+ if (this != &other && // self-assignment: no-op
+ !other.fPtr.isNull()) {
fPtr.adoptInstead(new CurrencyPluralInfo(*other.fPtr));
}
return *this;
diff --git a/icu4c/source/i18n/number_fluent.cpp b/icu4c/source/i18n/number_fluent.cpp
index 8569a36..c173848 100644
--- a/icu4c/source/i18n/number_fluent.cpp
+++ b/icu4c/source/i18n/number_fluent.cpp
@@ -428,6 +428,7 @@
}
LocalizedNumberFormatter& LocalizedNumberFormatter::operator=(const LNF& other) {
+ if (this == &other) { return *this; } // self-assignment: no-op
NFS<LNF>::operator=(static_cast<const NFS<LNF>&>(other));
UErrorCode localStatus = U_ZERO_ERROR; // Can't bubble up the error
lnfCopyHelper(other, localStatus);
diff --git a/icu4c/source/i18n/number_multiplier.cpp b/icu4c/source/i18n/number_multiplier.cpp
index 8f07e54..58e1e44 100644
--- a/icu4c/source/i18n/number_multiplier.cpp
+++ b/icu4c/source/i18n/number_multiplier.cpp
@@ -46,6 +46,7 @@
}
Scale& Scale::operator=(const Scale& other) {
+ if (this == &other) { return *this; } // self-assignment: no-op
fMagnitude = other.fMagnitude;
if (other.fArbitrary != nullptr) {
UErrorCode localStatus = U_ZERO_ERROR;
diff --git a/icu4c/source/i18n/number_usageprefs.cpp b/icu4c/source/i18n/number_usageprefs.cpp
index 0d9cb06..0be1146 100644
--- a/icu4c/source/i18n/number_usageprefs.cpp
+++ b/icu4c/source/i18n/number_usageprefs.cpp
@@ -34,6 +34,7 @@
// Copy assignment operator
Usage &Usage::operator=(const Usage &other) {
+ if (this == &other) { return *this; } // self-assignment: no-op
fLength = 0;
fError = other.fError;
if (fUsage != nullptr) {
diff --git a/icu4c/source/i18n/numrange_fluent.cpp b/icu4c/source/i18n/numrange_fluent.cpp
index d9286d1..f1060b3 100644
--- a/icu4c/source/i18n/numrange_fluent.cpp
+++ b/icu4c/source/i18n/numrange_fluent.cpp
@@ -245,6 +245,7 @@
}
LocalizedNumberRangeFormatter& LocalizedNumberRangeFormatter::operator=(const LNF& other) {
+ if (this == &other) { return *this; } // self-assignment: no-op
NFS<LNF>::operator=(static_cast<const NFS<LNF>&>(other));
// Do not steal; just clear
delete fAtomicFormatter.exchange(nullptr);
diff --git a/icu4c/source/i18n/olsontz.cpp b/icu4c/source/i18n/olsontz.cpp
index 4873caa..ccf8d61 100644
--- a/icu4c/source/i18n/olsontz.cpp
+++ b/icu4c/source/i18n/olsontz.cpp
@@ -274,6 +274,7 @@
* Assignment operator
*/
OlsonTimeZone& OlsonTimeZone::operator=(const OlsonTimeZone& other) {
+ if (this == &other) { return *this; } // self-assignment: no-op
canonicalID = other.canonicalID;
transitionTimesPre32 = other.transitionTimesPre32;
diff --git a/icu4c/source/i18n/stsearch.cpp b/icu4c/source/i18n/stsearch.cpp
index 3e6ed46..7fcd2bd 100644
--- a/icu4c/source/i18n/stsearch.cpp
+++ b/icu4c/source/i18n/stsearch.cpp
@@ -184,7 +184,7 @@
// operator overloading ---------------------------------------------
StringSearch & StringSearch::operator=(const StringSearch &that)
{
- if ((*this) != that) {
+ if (this != &that) {
UErrorCode status = U_ZERO_ERROR;
m_text_ = that.m_text_;
m_breakiterator_ = that.m_breakiterator_;
diff --git a/icu4c/source/i18n/translit.cpp b/icu4c/source/i18n/translit.cpp
index ef44f42..9b2eaad 100644
--- a/icu4c/source/i18n/translit.cpp
+++ b/icu4c/source/i18n/translit.cpp
@@ -170,6 +170,7 @@
* Assignment operator.
*/
Transliterator& Transliterator::operator=(const Transliterator& other) {
+ if (this == &other) { return *this; } // self-assignment: no-op
ID = other.ID;
// NUL-terminate the ID string
ID.getTerminatedBuffer();
diff --git a/icu4c/source/i18n/windtfmt.cpp b/icu4c/source/i18n/windtfmt.cpp
index bcf272b..f6a990e 100644
--- a/icu4c/source/i18n/windtfmt.cpp
+++ b/icu4c/source/i18n/windtfmt.cpp
@@ -193,6 +193,7 @@
Win32DateFormat &Win32DateFormat::operator=(const Win32DateFormat &other)
{
+ if (this == &other) { return *this; } // self-assignment: no-op
// The following handles fCalendar
DateFormat::operator=(other);
diff --git a/icu4c/source/i18n/winnmfmt.cpp b/icu4c/source/i18n/winnmfmt.cpp
index 72da1be..8b2a9a4 100644
--- a/icu4c/source/i18n/winnmfmt.cpp
+++ b/icu4c/source/i18n/winnmfmt.cpp
@@ -268,6 +268,7 @@
Win32NumberFormat &Win32NumberFormat::operator=(const Win32NumberFormat &other)
{
+ if (this == &other) { return *this; } // self-assignment: no-op
NumberFormat::operator=(other);
this->fCurrency = other.fCurrency;
diff --git a/icu4c/source/test/intltest/tsdtfmsy.cpp b/icu4c/source/test/intltest/tsdtfmsy.cpp
index c1efcc2..2c1a183 100644
--- a/icu4c/source/test/intltest/tsdtfmsy.cpp
+++ b/icu4c/source/test/intltest/tsdtfmsy.cpp
@@ -149,6 +149,7 @@
dataerrln("ERROR: Couldn't create English DateFormatSymbols " + (UnicodeString)u_errorName(status));
return;
}
+ symbol->operator=(*symbol); // self-assignment should be a no-op
int32_t cntFmtAbbrev, cntFmtShort, cntStdAloneShort;
const UnicodeString * wdFmtAbbrev = symbol->getWeekdays(cntFmtAbbrev,DateFormatSymbols::FORMAT,DateFormatSymbols::ABBREVIATED);
const UnicodeString * wdFmtShort = symbol->getWeekdays(cntFmtShort,DateFormatSymbols::FORMAT,DateFormatSymbols::SHORT);
diff --git a/icu4c/source/test/intltest/tztest.cpp b/icu4c/source/test/intltest/tztest.cpp
index 93d992f..b877db5 100644
--- a/icu4c/source/test/intltest/tztest.cpp
+++ b/icu4c/source/test/intltest/tztest.cpp
@@ -1171,8 +1171,10 @@
TimeZone *zone = TimeZone::createTimeZone(id);
UnicodeString itsID, temp;
- if (dynamic_cast<OlsonTimeZone *>(zone) != NULL) {
+ OlsonTimeZone *ozone = dynamic_cast<OlsonTimeZone *>(zone);
+ if (ozone != nullptr) {
logln(id + " -> Olson time zone");
+ ozone->operator=(*ozone); // self-assignment should be a no-op
} else {
zone->getID(itsID);
int32_t ioffset = zone->getRawOffset()/1000;
diff --git a/libicu/cts_headers/number_decimfmtprops.h b/libicu/cts_headers/number_decimfmtprops.h
index 1ce84d9..0ace241 100644
--- a/libicu/cts_headers/number_decimfmtprops.h
+++ b/libicu/cts_headers/number_decimfmtprops.h
@@ -38,7 +38,7 @@
// Exported as U_I18N_API because it is a public member field of exported DecimalFormatProperties
// Using this wrapper is rather unfortunate, but is needed on Windows platforms in order to allow
-// for DLL-exporting an fully specified template instantiation.
+// for DLL-exporting a fully specified template instantiation.
class U_I18N_API CurrencyPluralInfoWrapper {
public:
LocalPointer<CurrencyPluralInfo> fPtr;
@@ -52,7 +52,8 @@
}
CurrencyPluralInfoWrapper& operator=(const CurrencyPluralInfoWrapper& other) {
- if (!other.fPtr.isNull()) {
+ if (this != &other && // self-assignment: no-op
+ !other.fPtr.isNull()) {
fPtr.adoptInstead(new CurrencyPluralInfo(*other.fPtr));
}
return *this;