On 23.09.2020 19:43, Puetz Kevin A wrote:
-----Original Message----- From: Jacek Caban jacek@codeweavers.com Sent: Wednesday, September 23, 2020 9:44 AM
In c++11 char16_t is a distinct fundamental type, but in c11 it is merely a typedef in <uchar.h>.
Explicitly mention char16_t only in c++11 (where it is built-in), otherwise define WCHAR to match u"...", without naming char16_t.
Remove WINE_UNICODE_CHAR16; it is now the default when supported.
I like the part that uses __cpp_unicode_literals, it would make our headers much more C++ friendly by default.
I'm less sure if we want __CHAR16_TYPE__. In practice, it will only affect C, which is much less strict about types anyway. We assume in Wine code base that WCHAR is 16-bit unsigned integer. If __CHAR16_TYPE__ is something else, we shouldn't use it. If it's the same, then there is little point in using it. I think that the original problem is fixed by __cpp_unicode_literals change alone, so how about doing just that?
__CHAR16_TYPE__ (per C11 standard) is always the same type as uint_least16_t. Which, in turn, is always a typedef for one of the ordinary integer types. So it is just a 16-bit unsigned integer, unless one doesn't exist at all , in which case it's the smallest unsigned integer that can hold 0...65535. It's never a distinct type like char16_t is for c++11/__cpp_unicode_literals.
What isn't guaranteed is that the only suitable type is `unsigned short`, it could legally be `unsigned int` (if that was also 16-bit).
I don't quite agree that ignoring this is preferable because C "is much less strict about types anyway."
- The __CHAR16_TYPE__ path applies to C++98 and C++03, which lack __cpp_unicode_literals but might have a C-ish char16_t. So its behavior shouldn't completely ignore c++.
It's not clear to me that we want to change the default in this case (and even if we do, it could be C++ only change).
- C has mostly the same strict-aliasing rules as C++, which would not permit `const unsigned short *` pointing to `unsigned int[]`, even if they are the same size. So when LPCTSTR = TEXT("...") becomes const WCHAR * = u"...", if WCHAR is `short` but __CHAR16_TYPE__ is e.g. `int`, there is a strict-aliasing violation (and undefined behavior) in C too.
Now, in practice wine probably doesn't support any platform with 16-bit `int`, So __CHAR16_TYPE__ is just going to be `unsigned short` anyway. This way is pedantically more portable (to various architectures, if they are using gcc or clang which provide __CHAR16_TYPE__) But in practice they will preprocess to the same thing, which makes both the arguments in favor and the arguments against moot.
So I'll drop it (after this last attempt to justify it) if that's what you want; I care about char16_t mostly in C++11, but was just trying to fix the C path to be portable too on general principle. Not a hill I need to die on :-)
I can see your point, but by changing C path, you put compatibility of Wine itself into the consideration. WCHAR is an important core type for Wine and we have a simple declaration that worked for years. If we were writing it from scratch, the consideration could be different. I think we agree the existing declaration works equally good in practice (esp. once WINE_UNICODE_CHAR16 handling is fixed in C), so I would prefer to avoid the additional complication. If we'd have 16-bit int, we would have much more problems than WCHAR declaration.
Thanks,
Jacek