Re: [Development] static constexpr in exported classes needs out-of-line definitions
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
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
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
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