Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libicui18n fails to compile on Windows with MSVC 19.36.32502 due to P2468R2 #1

Open
wroyca opened this issue Mar 18, 2023 · 19 comments

Comments

@wroyca
Copy link

wroyca commented Mar 18, 2023

The meaning of == and != expressions has been altered in C++20 with the proposals P1185R2 and P2468R2, along with changes to how overload resolution is applied to them, resulting in previously valid code becoming invalid. As a result, ICU now produces error C2666 on certain overloaded functions and operators. Due to certain packages such as Qt being dependent on ICU, it also becomes infeasible to compile them.

    https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2468r2.html

b
c++ ..\echo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{fmtable} -> ..\echo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{fmtable}
c++ ..\echo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{fmtable} -> ..\echo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\obja{fmtable}
C:\Users\wroy\Desktop\echo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\fmtable.cpp(59): error C2666: 'icu_65::Measure::operator ==': overloaded functions have similar conversions
C:\Users\wroy\Desktop\echo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\unicode/measure.h(90): note: could be 'UBool icu_65::Measure::operator ==(const icu_65::UObject &) const'
C:\Users\wroy\Desktop\echo-msvc\libicuuc-65.1.0+6\libicu/uc\unicode/stringpiece.h(242): note: or       'UBool icu_65::operator ==(const icu_65::StringPiece &,const icu_65::StringPiece &)'
C:\Users\wroy\Desktop\echo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\unicode/measure.h(90): note: or 'UBool icu_65::Measure::operator ==(const icu_65::UObject &) const' [synthesized expression 'y == x']
C:\Users\wroy\Desktop\echo-msvc\libicuuc-65.1.0+6\libicu/uc\unicode/stringpiece.h(242): note: or 'UBool icu_65::operator ==(const icu_65::StringPiece &,const icu_65::StringPiece &)' [synthesized expression 'y == x']
C:\Users\wroy\Desktop\echo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\fmtable.cpp(59): note: while trying to match the argument list '(const icu_65::Measure, const icu_65::Measure)'
error: process cl exited with code 2
@boris-kolpackov
Copy link
Contributor

Thanks for the report. Do you know by any chance if this has been fixed in newer versions of ICU? We are overdue for an upgrade.

@wroyca
Copy link
Author

wroyca commented Mar 19, 2023

From what I understand, it seems like they've decided to use Wno-ambiguous-reversed-operator instead, but I wasn't able to see for myself as I had other things to focus on. However, I should have some free time on Monday to check it out.

Relevant discussions:

https://unicode-org.atlassian.net/browse/ICU-22014
https://unicode-org.atlassian.net/browse/ICU-20973

@wroyca
Copy link
Author

wroyca commented Mar 20, 2023

Here is a git patch that addresses the compilation issue. Note that it has not undergone extensive testing.

0001-Fix-P2468R2-with-MSVC-19.36.32502.patch

From 3fbe14993f0e2c4a1c6f490b71ba56d682069060 Mon Sep 17 00:00:00 2001
From: = <[email protected]>
Date: Mon, 20 Mar 2023 11:10:38 -0400
Subject: [PATCH] Fix P2468R2 with MSVC 19.36.32502

---
 icu4c/source/i18n/fmtable.cpp | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/icu4c/source/i18n/fmtable.cpp b/icu4c/source/i18n/fmtable.cpp
index dbfd3c26ba..33c0ad8505 100644
--- a/icu4c/source/i18n/fmtable.cpp
+++ b/icu4c/source/i18n/fmtable.cpp
@@ -56,7 +56,8 @@ using number::impl::DecimalQuantity;
 // Return TRUE if *a == *b.
 static inline UBool objectEquals(const UObject* a, const UObject* b) {
     // LATER: return *a == *b;
-    return *((const Measure*) a) == *((const Measure*) b);
+    return std::memcmp(static_cast<const Measure*>(a),
+                       static_cast<const Measure*>(b), sizeof(Measure)) == 0;
 }
 
 // Return a clone of *a.
-- 
2.40.0.windows.1

@boris-kolpackov
Copy link
Contributor

No, I am 99% sure this patch is wrong (you are most likely comparing padding bytes inside Measure). I think it's best to just wait until upstream releases a fix (whatever it might be) and then we find time to release a new version. If you can ping this issue when that happens (that is, upstream releases a fixed version), that would be helpful.

@wroyca
Copy link
Author

wroyca commented Mar 20, 2023

No, I am 99% sure this patch is wrong (you are most likely comparing padding bytes inside Measure).

I don't believe the compiler would insert padding for the measure object - Even if it did, the code should still be accurate since we are already comparing the entire type, aren't we?

*((any type ptr)param) == *((any type ptr)param)

In any case, I am hesitant to rely on "waiting for upstream to release a fix," especially given their decision to use the flag approach. It could take a considerable amount of time to resolve the issue, and in the meantime, we are unable to compile certain packages because they depend on the ICU package, which happens to be a single point of failure on Windows.

Should this patch cause issues as you have indicated, adding the overload to the Measure class itself would be the suitable solution - however, this could result in more significant consequences than the objectEquals method ever would

@wroyca
Copy link
Author

wroyca commented Mar 21, 2023

@boris-kolpackov Here's the Patch that add the overload to the Measure class itself:

0001-Add-operator-for-P2468R2.patch

From f37efc2c29d25ac774890e272b7accd712448631 Mon Sep 17 00:00:00 2001
From: William Roy <[email protected]>
Date: Tue, 21 Mar 2023 11:49:00 -0400
Subject: [PATCH] Add operator!= for P2468R2

---
 icu4c/source/i18n/unicode/measure.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/icu4c/source/i18n/unicode/measure.h b/icu4c/source/i18n/unicode/measure.h
index fa9c29351e..186751074a 100644
--- a/icu4c/source/i18n/unicode/measure.h
+++ b/icu4c/source/i18n/unicode/measure.h
@@ -88,6 +88,7 @@ class U_I18N_API Measure: public UObject {
      * @stable ICU 3.0
      */
     UBool operator==(const UObject& other) const;
+    UBool operator!=(const UObject& other) const;
 
     /**
      * Return a reference to the numeric value of this object.  The
-- 
2.40.0.windows.1

FYI we still need to create the definition in measure.cpp, e.g:

0001-Add-operator-definition-for-P2468R2.patch

From b07978eef67ba613d83c57fca3ec12ecebf599eb Mon Sep 17 00:00:00 2001
From: William Roy <[email protected]>
Date: Tue, 21 Mar 2023 12:00:32 -0400
Subject: [PATCH] Add operator != definition for P2468R2

---
 icu4c/source/i18n/measure.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/icu4c/source/i18n/measure.cpp b/icu4c/source/i18n/measure.cpp
index bffa44215e..e73f92d81b 100644
--- a/icu4c/source/i18n/measure.cpp
+++ b/icu4c/source/i18n/measure.cpp
@@ -69,6 +69,10 @@ UBool Measure::operator==(const UObject& other) const {
         (unit == NULL || *unit == *m.unit);
 }
 
+UBool Measure::operator!=(const UObject& other) const {
+  return !(this->operator==(other));
+}
+
 U_NAMESPACE_END
 
 #endif // !UCONFIG_NO_FORMATTING
-- 
2.40.0.windows.1

@boris-kolpackov
Copy link
Contributor

This looks better. Can you confirm that this fixes all the compilation errors in this MSVC version?

@wroyca
Copy link
Author

wroyca commented Mar 22, 2023

This looks better. Can you confirm that this fixes all the compilation errors in this MSVC version?

It does, I use it currently👍

@boris-kolpackov
Copy link
Contributor

@wroyca Do you know if there is an upstream's official fix/patch for this yet?

@boris-kolpackov
Copy link
Contributor

Also, 19.36.32502 is (currently) the preview version of MSVC 17.6, correct?

@wroyca
Copy link
Author

wroyca commented Apr 5, 2023

Also, 19.36.32502 is (currently) the preview version of MSVC 17.6, correct?

Sorry late answer (timezone) but that's correct, as for upstream I didn't have a chance to look again, but you can quickly check for the overload upstream, if it's missing then the issue is still present - I'll be home a bit later today to check again

@boris-kolpackov
Copy link
Contributor

I just checked 72.1 and while they didn't add the != overload, they did change the return type to bool. I've also checked the current development version (the main branch) and there is nothing new there in this regard. So perhaps that's enough? It would have been helpful if you could test this change (i.e., change UBool to bool instead of adding the != overload) and confirm it helps (we don't deploy preview versions of MSVC to our CI so we cannot test this ourselves).

@wroyca
Copy link
Author

wroyca commented Apr 5, 2023

I just checked 72.1 and while they didn't add the != overload, they did change the return type to bool. I've also checked the current development version (the main branch) and there is nothing new there in this regard. So perhaps that's enough? It would have been helpful if you could test this change (i.e., change UBool to bool instead of adding the != overload) and confirm it helps (we don't deploy preview versions of MSVC to our CI so we cannot test this ourselves).

Thank, I'll take a look and come back to you as soon as possible 👍

@wroyca
Copy link
Author

wroyca commented Apr 5, 2023

@boris-kolpackov Confirmed that the issue is still present, but at a different location this time 👍

PS C:\Users\wroy\Desktop\foo> b
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{fmtable} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{fmtable}
C:\Users\wroy\Desktop\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\fmtable.cpp(59): error C2666: 'icu_65::Measure::operator ==': overloaded functions have similar conversions
C:\Users\wroy\Desktop\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\unicode/measure.h(90): note: could be 'UBool icu_65::Measure::operator ==(const icu_65::UObject &) const'
C:\Users\wroy\Desktop\foo-msvc\libicuuc-65.1.0+6\libicu/uc\unicode/stringpiece.h(242): note: or       'UBool icu_65::operator ==(const icu_65::StringPiece &,const icu_65::StringPiece &)'
C:\Users\wroy\Desktop\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\unicode/measure.h(90): note: or 'UBool icu_65::Measure::operator ==(const icu_65::UObject &) const' [synthesized expression 'y == x']
C:\Users\wroy\Desktop\foo-msvc\libicuuc-65.1.0+6\libicu/uc\unicode/stringpiece.h(242): note: or 'UBool icu_65::operator ==(const icu_65::StringPiece &,const icu_65::StringPiece &)' [synthesized expression 'y == x']
C:\Users\wroy\Desktop\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\fmtable.cpp(59): note: while trying to match the argument list '(const icu_65::Measure, const icu_65::Measure)'
error: process C:\Program Files\Microsoft Visual Studio\2022\Preview\VC\Tools\MSVC\14.36.32502\bin\Hostx64\x64\cl exited with code 2
  info: command line: "C:\Program Files\Microsoft Visual Studio\2022\Preview\VC\Tools\MSVC\14.36.32502\bin\Hostx64\x64\cl" -IC:\Users\wroy\Desktop\foo-msvc\libicui18n-65.1.0+6\libicui18n/i18n -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS -DU_I18N_IMPLEMENTATION -DU_ATTRIBUTE_DEPRECATED= -DU_HAVE_STRTOD_L=0 -DHAVE_DLOPEN=0 -DU_HAVE_MMAP=0 -DWIN32 -DU_HAVE_DIRENT_H=0 -DU_HAVE_POPEN=0 -DU_HAVE_TZNAME=0 -IC:\Users\wroy\Desktop\foo-msvc\libicuuc-65.1.0+6\libicu/uc /wd4251 /wd4275 /wd4800 /utf-8 /Zc:wchar_t /GF /Gy /wd4244 /wd4996 /nologo /std:c++20 /Zc:__cplusplus /I "C:\Program Files\Microsoft Visual Studio\2022\Preview\VC\Tools\MSVC\14.36.32502\include" /I "C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\ucrt" /I "C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\shared" /I "C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\um" /I "C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\winrt" /utf-8 /EHsc /MD /Fo: ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\fmtable.dll.obj /c /TP C:\Users\wroy\Desktop\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\fmtable.cpp
  info: while updating ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{fmtable}
  info: while updating ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\libs{icui18n}
  info: while updating ..\foo-msvc\libQt6Core-6.4.3-a.0.20230329144408.6712fd545990\QtCore\libs{Qt6Core}
  info: while updating ..\foo-msvc\foo\foo\exe{foo}
  info: while updating ..\foo-msvc\foo\dir{foo\}
  info: while updating ..\foo-msvc\dir{foo\}

However, my patch is still applicable and resolve it:

0001-Add-operator-for-P2468R2.patch
0001-Add-operator-definition-for-P2468R2.patch

b
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{fmtable} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{fmtable}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{choicfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{choicfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{compactdecimalformat} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{compactdecimalformat}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{curramt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{curramt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{dtptngen} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{dtptngen}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{dcfmtsym} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{dcfmtsym}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{currfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{currfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{dtitvinf} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{dtitvinf}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{decimfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{decimfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{datefmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{datefmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{dtfmtsym} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{dtfmtsym}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{currpinf} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{currpinf}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{formattedval_sbimpl} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{formattedval_sbimpl}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{quantityformatter} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{quantityformatter}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{measure} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{measure}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{measfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{measfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{nfrs} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{nfrs}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{msgfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{msgfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{nfrule} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{nfrule}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{nfsubs} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{nfsubs}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_affixutils} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_affixutils}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_asformat} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_asformat}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_capi} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_capi}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_compact} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_compact}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_currencysymbols} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_currencysymbols}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_decimalquantity} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_decimalquantity}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_decimfmtprops} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_decimfmtprops}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_fluent} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_fluent}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_formatimpl} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_formatimpl}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_grouping} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_grouping}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_integerwidth} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_integerwidth}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{tmutamt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{tmutamt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_longnames} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_longnames}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_mapper} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_mapper}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_modifiers} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_modifiers}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_multiplier} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_multiplier}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_notation} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_notation}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_output} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_output}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_padding} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_padding}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_patternmodifier} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_patternmodifier}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_patternstring} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_patternstring}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_rounding} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_rounding}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_scientific} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_scientific}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{udat} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{udat}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_skeletons} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_skeletons}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{number_utils} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{number_utils}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numparse_affixes} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numparse_affixes}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numparse_compositions} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numparse_compositions}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numparse_currency} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numparse_currency}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numparse_decimal} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numparse_decimal}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numparse_impl} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numparse_impl}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numparse_parsednumber} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numparse_parsednumber}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numparse_scientific} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numparse_scientific}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numparse_symbols} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numparse_symbols}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numparse_validators} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numparse_validators}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numrange_fluent} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numrange_fluent}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{numrange_impl} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{numrange_impl}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{windtfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{windtfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{plurfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{plurfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{plurrule} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{plurrule}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{rbnf} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{rbnf}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{reldatefmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{reldatefmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{reldtfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{reldtfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{scientificnumberformatter} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{scientificnumberformatter}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{selfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{selfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{simpletz} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{simpletz}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{smpdtfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{smpdtfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{string_segment} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{string_segment}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{timezone} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{timezone}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{tmutfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{tmutfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{translit} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{translit}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{udateintervalformat} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{udateintervalformat}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\cxx{dtitvfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\objs{dtitvfmt}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{udatpg} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{udatpg}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{umsg} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{umsg}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{unum} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{unum}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{upluralrules} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{upluralrules}
c++ ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\cxx{winnmfmt} -> ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\i18n\objs{winnmfmt}
ld ..\foo-msvc\libicui18n-65.1.0+6\libicui18n\libs{icui18n}
ld ..\foo-msvc\libQt6Core-6.4.3-a.0.20230329144408.6712fd545990\QtCore\libs{Qt6Core}
ld ..\foo-msvc\libQt6Gui-6.4.3-a.0.20230329144408.6712fd545990\QtGui\libs{Qt6Gui}
ld ..\foo-msvc\libQt6Widgets-6.4.3-a.0.20230329144408.6712fd545990\QtWidgets\libs{Qt6Widgets}
ld ..\foo-msvc\foo\foo\exe{foo}
ln ..\foo-msvc\foo\foo\exe{foo} -> foo\
ld ..\foo-msvc\libQt6Gui-6.4.3-a.0.20230329144408.6712fd545990\QtGuiPlugins\imageformats\libs{qgif}
ld ..\foo-msvc\libQt6Gui-6.4.3-a.0.20230329144408.6712fd545990\QtGuiPlugins\imageformats\libs{qico}
ld ..\foo-msvc\libQt6Gui-6.4.3-a.0.20230329144408.6712fd545990\QtGuiPlugins\imageformats\libs{qjpeg}
ld ..\foo-msvc\libQt6Gui-6.4.3-a.0.20230329144408.6712fd545990\QtGuiPlugins\platforms\libs{qwindows}
ld ..\foo-msvc\libQt6Widgets-6.4.3-a.0.20230329144408.6712fd545990\QtWidgetsPlugins\styles\libs{qwindowsvistastyle}

@boris-kolpackov
Copy link
Contributor

Confirmed that the issue is still present [...]

measure.h(90): note: could be 'UBool icu_65::Measure::operator ==(const icu_65::UObject &) const'

Not sure what this is confirming since it still seems to use UBool. Can you: (1) revert your patch (or rebuild from scratch), (2) replace Ubool with bool (both in declaration and definition) and see if that helps.

@wroyca
Copy link
Author

wroyca commented Apr 5, 2023

Confirmed that the issue is still present [...]

measure.h(90): note: could be 'UBool icu_65::Measure::operator ==(const icu_65::UObject &) const'

Not sure what this is confirming since it still seems to use UBool. Can you: (1) revert your patch (or rebuild from scratch), (2) replace Ubool with bool (both in declaration and definition) and see if that helps.

I have tested both without my patch first, and then applied my patch, unfortunately we hit compile errors without my patch (UBool and bool alike)

@boris-kolpackov
Copy link
Contributor

boris-kolpackov commented Apr 5, 2023

Ok, thanks for testing. Do you know if there is a bug report upstream for this exact problem? If not, maybe it makes sense to submit it and see what they say/plan?

While your patch is sensible, because it affects a header, it will be quite messy to apply in our package. So I was hoping we could just upgrade to latest upstream and sidestep the whole mess.

Another option to try would be to fix the call site in fmtable.cpp:59. It is currently:

return *((const Measure*) a) == *((const Measure*) b);

We could try explicitly calling the correct operator==:

diff --git a/icu4c/source/i18n/fmtable.cpp b/icu4c/source/i18n/fmtable.cpp
index dbfd3c26..00fa750a 100644
--- a/icu4c/source/i18n/fmtable.cpp
+++ b/icu4c/source/i18n/fmtable.cpp
@@ -56,7 +56,8 @@ using number::impl::DecimalQuantity;
 // Return TRUE if *a == *b.
 static inline UBool objectEquals(const UObject* a, const UObject* b) {
     // LATER: return *a == *b;
-    return *((const Measure*) a) == *((const Measure*) b);
+    //return *((const Measure*) a) == *((const Measure*) b);
+    return ((const Measure*) a)->operator== (*((const Measure*) b));
 }
 
 // Return a clone of *a.

Do you think you can try that (without your patch) and see if it helps?

@wroyca
Copy link
Author

wroyca commented Apr 5, 2023

Ok, thanks for testing. Do you know if there is a bug report upstream for this exact problem? If not, maybe it makes sense to submit it and see what they say/plan?

While your patch is sensible, because it affects a header, it will be quite messy to apply in our package. So I was hoping we could just upgrade to latest upstream and sidestep the whole mess.

Another option to try would be to fix the call site in fmtable.cpp:59. It is currently:

return *((const Measure*) a) == *((const Measure*) b);

We could try explicitly calling the correct operator==:

diff --git a/icu4c/source/i18n/fmtable.cpp b/icu4c/source/i18n/fmtable.cpp
index dbfd3c26..00fa750a 100644
--- a/icu4c/source/i18n/fmtable.cpp
+++ b/icu4c/source/i18n/fmtable.cpp
@@ -56,7 +56,8 @@ using number::impl::DecimalQuantity;
 // Return TRUE if *a == *b.
 static inline UBool objectEquals(const UObject* a, const UObject* b) {
     // LATER: return *a == *b;
-    return *((const Measure*) a) == *((const Measure*) b);
+    //return *((const Measure*) a) == *((const Measure*) b);
+    return ((const Measure*) a)->operator== (*((const Measure*) b));
 }
 
 // Return a clone of *a.

Do you think you can try that (without your patch) and see if it helps?

The issue with this is that anything that relies on measures, for example, will eventually encounter problems with the operator. We are fortunate that currently, only objectEquals is affected by this. That said, yes, using operator== explicitly will work! :)

EDIT:

Last I've check there was effectively a open issue for it but they side-stepped with Wno-ambiguous-reversed-operator on clang for now so MSVC afaik is not there yet, let me see if I can find it back

EDIT:

Ah yes, I've referenced it above,
https://unicode-org.atlassian.net/browse/ICU-22014
https://unicode-org.atlassian.net/browse/ICU-20973

build2-bot pushed a commit that referenced this issue Apr 6, 2023
Patch upstream issue with operator== ambiguity described in GH issue #1.
@boris-kolpackov
Copy link
Contributor

boris-kolpackov commented Apr 6, 2023

Ok, I've published a revision with the patch to the call site. Please let me know if there are any issues. Let's also keep this bug open until a proper fix is released by upstream.

The issue with this is that anything that relies on measures, for example, will eventually encounter problems with the operator.

While true, this is a stop-gap measure until upstream releases a proper fix. And, as I said, it saves us from wading into a big header patching mess in our package.

Last I've check there was effectively a open issue for it but they side-stepped with Wno-ambiguous-reversed-operator on clang for now so MSVC afaik is not there yet [...]

None of the bug reports you've linked talk about a compile error in MSVC, so I think ICU folks are unaware of this (likely because this is a preview version of MSVC). I would suggest that you report this as a separate issue, if you can.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants