Re: [Development] static constexpr in exported classes needs out-of-line definitions

2024-01-31 Thread Marc Mutz via Development
Thanks! Added to 
https://wiki.qt.io/Things_To_Look_Out_For_In_Reviews#Variables

On 18.01.24 04:35, Thiago Macieira wrote:
> See http://bugreports.qt.io/browse/QTBUG-121135 for the issue and
> https://codereview.qt-project.org/c/qt/qtbase/+/531251 for the solution.
> 
> TL;DR: if you define a static constexpr (which is implicitly inline) member
> variable in a class with export macro, you MUST add the definition of tha
> variable to the .cpp.
> 
> Alternatives:
> * move to a class that is not exported
> trick: add an empty base with the variable
> * change to enum (if primitive)
> 
> But this happens even for plain int variables. For example:
> 
> #include 
> #include 
> void f(std::vector &v)
> {
>  v.push_back(QLocale::FirstTwoDigitYear);
> }
> 
> This produced: with GCC 13 at -O2 optimisations:
> 
> _Z1fRSt6vectorIiSaIiEE:
>  movq8(%rcx), %rdx
>  cmpq16(%rcx), %rdx
>  je  .L29
>  movl$1900, (%rdx)
>  addq$4, %rdx
>  movq%rdx, 8(%rcx)
>  ret
> .L29:
>  movq__imp__ZN7QLocale17FirstTwoDigitYearE(%rip), %r8
>  jmp
> _ZNSt6vectorIiSaIiEE17_M_realloc_insertIJRKiEEEvN9__gnu_cxx17__normal_iteratorIPiS1_EEDpOT_
> 
> Interpretation: if the vector has enough pre-allocated space, it simply moves
> 1900 to the end of te array and adjusts the end. But if not, it calls
> std::vector_M_realloc_insert(), which takes the integer by reference, so
> the compiler emits an import from the DLL.
> 
> This appears to be a GCC bug/shortcoming. Clang and MSVC apparently
> automatically emit and export the variable for you:
> https://mingw.godbolt.org/z/q4dYdosjh
> 
> 
-- 
Marc Mutz 
Principal Software Engineer

The Qt Company
Erich-Thilo-Str. 10 12489
Berlin, Germany
www.qt.io

Geschäftsführer: Mika Pälsi, Juha Varelius, Jouni Lintunen
Sitz der Gesellschaft: Berlin,
Registergericht: Amtsgericht Charlottenburg,
HRB 144331 B

-- 
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] static constexpr in exported classes needs out-of-line definitions

2024-01-18 Thread Thiago Macieira
On Wednesday, 17 January 2024 19:35:17 PST Thiago Macieira wrote:
> Alternatives:
> * move to a class that is not exported
>trick: add an empty base with the variable
> * change to enum (if primitive)

* change to an static (inline) constexpr function

Then there's always a copy, because GCC either inlines or emits a copy for 
functions.
https://mingw.godbolt.org/z/bh95q8PKf

MSVC sucks at inlining dllimported functions, but there's no problem because 
it exported on the other side.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Cloud Software Architect - Intel DCAI Cloud Engineering


smime.p7s
Description: S/MIME cryptographic signature
-- 
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


Re: [Development] static constexpr in exported classes needs out-of-line definitions

2024-01-17 Thread Thiago Macieira
On Wednesday, 17 January 2024 19:35:17 PST Thiago Macieira wrote:
> This appears to be a GCC bug/shortcoming. Clang and MSVC apparently
> automatically emit and export the variable for you:
> https://mingw.godbolt.org/z/q4dYdosjh

Reported at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113465

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Cloud Software Architect - Intel DCAI Cloud Engineering


smime.p7s
Description: S/MIME cryptographic signature
-- 
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development


[Development] static constexpr in exported classes needs out-of-line definitions

2024-01-17 Thread Thiago Macieira
See http://bugreports.qt.io/browse/QTBUG-121135 for the issue and
https://codereview.qt-project.org/c/qt/qtbase/+/531251 for the solution.

TL;DR: if you define a static constexpr (which is implicitly inline) member 
variable in a class with export macro, you MUST add the definition of tha 
variable to the .cpp.

Alternatives:
* move to a class that is not exported
   trick: add an empty base with the variable
* change to enum (if primitive)

But this happens even for plain int variables. For example:

#include 
#include 
void f(std::vector &v) 
{ 
v.push_back(QLocale::FirstTwoDigitYear);
}

This produced: with GCC 13 at -O2 optimisations:

_Z1fRSt6vectorIiSaIiEE:
movq8(%rcx), %rdx
cmpq16(%rcx), %rdx
je  .L29
movl$1900, (%rdx)
addq$4, %rdx
movq%rdx, 8(%rcx)
ret
.L29:
movq__imp__ZN7QLocale17FirstTwoDigitYearE(%rip), %r8
jmp 
_ZNSt6vectorIiSaIiEE17_M_realloc_insertIJRKiEEEvN9__gnu_cxx17__normal_iteratorIPiS1_EEDpOT_

Interpretation: if the vector has enough pre-allocated space, it simply moves 
1900 to the end of te array and adjusts the end. But if not, it calls 
std::vector_M_realloc_insert(), which takes the integer by reference, so 
the compiler emits an import from the DLL.

This appears to be a GCC bug/shortcoming. Clang and MSVC apparently 
automatically emit and export the variable for you:
https://mingw.godbolt.org/z/q4dYdosjh

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Cloud Software Architect - Intel DCAI Cloud Engineering


smime.p7s
Description: S/MIME cryptographic signature
-- 
Development mailing list
Development@qt-project.org
https://lists.qt-project.org/listinfo/development