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;