[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