[RFC] libstdc++: fix declaration and definition mismatch for _GLIBCXX20_CONSTEXPR
Jonathan Wakely
jwakely.gcc@gmail.com
Mon May 19 15:12:02 GMT 2025
On Mon, 19 May 2025 at 12:39, Alexey Lapshin
<alexey.lapshin@espressif.com> wrote:
>
> I mean __resize_and_overwrite is defined with "_GLIBCXX20_CONSTEXPR":
>
> https://github.com/gcc-mirror/gcc/blob/025374559b22f5d9148f227b3df800a8e0231f59/libstdc%2B%2B-v3/include/bits/basic_string.h#L1267-L1268
>
> But if __glibcxx_string_resize_and_overwrite is enabled, it now harcoded with "constexpr"
>
> https://github.com/gcc-mirror/gcc/blob/1197f896ae5558f27baa929a10f66447aaafb681/libstdc%2B%2B-v3/include/bits/basic_string.tcc#L604-L606
Looks a few lines further down. There are two definitions of
__resize_and_overwrite.
The first definition is for C++23 (and later) and is defined with
always_inline. For C++23 _GLIBCXX20_CONSTEXPR always means 'constexpr'
so the definitions are consistent. It's only a problem because *you*
are breaking the meaning of _GLIBCXX20_CONSTEXPR, so don't do that
then. It's not a macro you're allowed to mess with, see
https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_macros.html
The second definition is for C++20 and earlier, and uses
_GLIBCXX20_CONSTEXPR so that the definition matches the declaration.
We /could/ use _GLIBCXX20_CONSTEXPR for the C++23 definition, but
since _GLIBCXX20_CONSTEXPR always means 'constexpr' for C++23, it
doesn't matter.
What matters is that the code is consistent **after preprocessing*,
and that is true.
> Or the same for "find":
>
> https://github.com/gcc-mirror/gcc/blob/025374559b22f5d9148f227b3df800a8e0231f59/libstdc%2B%2B-v3/include/bits/basic_string.h#L2922-L2924
> https://github.com/gcc-mirror/gcc/blob/1197f896ae5558f27baa929a10f66447aaafb681/libstdc%2B%2B-v3/include/bits/basic_string.tcc#L649-L658
In practice, the code is correct and consistent after preprocessing.
But I agree that this case would be better if the same preprocessor
macro was used.
The reason it isn't used is because those definitions in
bits/basic_string.tcc are shared by the declarations in
bits/basic_string.h and the declarations in cow_string.h, and only the
former ones are constexpr.
So the definition of _GLIBCXX_STRING_CONSTEXPR could be like this instead:
#if _GLIBCXX_USE_CXX11_ABI
# define _GLIBCXX_STRING_CONSTEXPR constexpr
#else
# define _GLIBCXX_STRING_CONSTEXPR
#endif
> > because that will break *everything*.
>
> I hope it's not true, unless constexpr functions are used for defining array sizes or something similar.
> In any case, a compile-time error will occur.
> I mean, if the program compiles successfully without the constexpr specifier, it should run normally.
Yes, but many valid C++ programs will not compile successfully. That's
not acceptable. Feel free to break that in your own copy of the
headers if you wish, but a patch doing that can not be accepted into
GCC.
> Or did you mean something else?
I mean that removing 'constexpr' from functions that the C++ standard
says are constexpr will break programs. We will not do that.
I understand what you're trying to do, but redefining
_GLIBCXX20_CONSTEXPR is the wrong way to do it. You should find
another approach.
It seems pretty obvious to me that a better solution would be
something like this (e.g. in bits/c++config)
#ifdef __OPTIMIZE_SIZE__
# define _GLIBCXX_MAYBE_COLD __attribute__((__cold__))
#else
# define _GLIBCXX_MAYBE_COLD
#endif
Then add that where you want it. Do not change the meaning of
_GLIBCXX20_CONSTEXPR.
More information about the Libstdc++
mailing list