On Tue, 15 Jul 2025 at 12:06, Tomasz Kaminski <tkami...@redhat.com> wrote: > > > > On Tue, Jul 15, 2025 at 12:37 PM Jonathan Wakely <jwak...@redhat.com> wrote: >> >> On Tue, 15 Jul 2025 at 08:10, Tomasz Kaminski <tkami...@redhat.com> wrote: >> > >> > >> > >> > On Mon, Jul 14, 2025 at 10:43 PM Jonathan Wakely <jwak...@redhat.com> >> > wrote: >> >> >> >> This makes it possible to use `new(std::nothrow) X` without linking to >> >> libsupc++ or libstdc++. >> >> >> >> To ensure we still export the symbol from the library we need to >> >> suppress the inline variable in libsupc++/new_handler.cc which is done >> >> by defining a macro. >> >> >> >> libstdc++-v3/ChangeLog: >> >> >> >> * libsupc++/new (nothrow): Define as inline variable. >> >> * libsupc++/new_handler.cc (_GLIBCXX_DEFINE_NOTHROW_OBJ): >> >> Define. >> >> --- >> >> >> >> Tested powerpc64le-linux. >> >> >> >> libstdc++-v3/libsupc++/new | 4 ++++ >> >> libstdc++-v3/libsupc++/new_handler.cc | 2 ++ >> >> 2 files changed, 6 insertions(+) >> >> >> >> diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new >> >> index fb36dae25a6d..85d28ff40769 100644 >> >> --- a/libstdc++-v3/libsupc++/new >> >> +++ b/libstdc++-v3/libsupc++/new >> >> @@ -125,7 +125,11 @@ namespace std >> >> #endif >> >> }; >> >> >> >> +#if defined __cpp_inline_variables && ! defined >> >> _GLIBCXX_DEFINE_NOTHROW_OBJ >> >> + inline constexpr nothrow_t nothrow{}; >> >> +#else >> >> extern const nothrow_t nothrow; >> >> +#endif >> > >> > If you move variable definition before include, this would become: >> > +#ifndef _GLIBCXX_DEFINE_NOTHROW_OBJ >> > +# ifdef __cpp_inline_variables >> > + inline constexpr nothrow_t nothrow{}; >> > + # else >> > extern const nothrow_t nothrow; >> > +# endif >> > +#endif >> > >> > GCC and clang also accepts, i.e. version when we always have extern >> > declaration: >> > +#if defined __cpp_inline_variables && ! defined >> > _GLIBCXX_DEFINE_NOTHROW_OBJ >> > + inline constexpr nothrow_t nothrow{}; >> > +#endif >> > extern const nothrow_t nothrow; >> > >> > >> >> >> >> /** If you write your own error handler to be called by @c new, it must >> >> * be of this type. */ >> >> diff --git a/libstdc++-v3/libsupc++/new_handler.cc >> >> b/libstdc++-v3/libsupc++/new_handler.cc >> >> index 7cd3e5a69fde..96dfb796c64a 100644 >> >> --- a/libstdc++-v3/libsupc++/new_handler.cc >> >> +++ b/libstdc++-v3/libsupc++/new_handler.cc >> >> @@ -23,6 +23,8 @@ >> >> // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see >> >> // <http://www.gnu.org/licenses/>. >> >> >> >> +#define _GLIBCXX_DEFINE_NOTHROW_OBJ 1 >> > >> > Could we also move the definition of nothrow here (before including new), >> > so entities in header new always see it's definition when it is constexpr? >> > I do not think there is any (even bening) ODR violation possibility here, >> > but >> > we can avoid the risk that way., >> >> We would need to also move the definition of the nothrow_t type there, >> otherwise you can't declare the variable. >> >> And wouldn't it have internal linkage if it's defined as constexpr >> const in new_handler.cc? >> It only has external linkage because the extern declaration in <new> >> was already seen. >> >> So in the <new> header we would need: >> >> #ifndef _GLIBCXX_DEFINED_NOTHROW_OBJ // defined by new_handler.cc >> struct nothrow_t >> { >> #if __cplusplus >= 201103L >> explicit nothrow_t() = default; >> #endif >> }; >> >> #if defined __cpp_inline_variables >> // Define as an inline variable when possible, so that std::nothrow can >> // be used without linking to libsupc++. >> inline constexpr nothrow_t nothrow{}; >> #endif >> extern const nothrow_t nothrow; >> #endif >> >> >> And then in new_handler.cc: >> >> namespace std >> { >> struct nothrow_t >> { >> explicit nothrow_t() = default; >> }; >> >> #ifdef __cpp_inline_variables >> // purposely match when header defines it as inline+constexpr >> constexpr >> #endif >> extern const nothrow_t nothrow{}; >> } >> >> // Prevent <new> from defining it again: >> #define _GLIBCXX_DEFINED_NOTHROW_OBJ 1 >> >> #include "new" >> >> >> But then I get multiple definition errors when linking libstdc++, so >> something is wrong here. > > We could define the nothrow in header if _GLIBCXX_DEFINE_NOTHROW_OBJ_IN_NEW > is defined: > #ifdef _GLIBCXX_DEFINE_NOTHROW_OBJ_IN_NEW > extern _GLIBCXX17_CONSTEXPR const nothrow_t nothrow = nothrow_t(); > #elifdef __cpp_inline_variables > // Define as an inline variable when possible, so that std::nothrow can > // be used without linking to libsupc++. > inline constexpr nothrow_t nothrow{}; > #else > extern const nothrow_t nothrow; > #endif > > And then in new_handler.cc, do: > // instruct <new> to provide definition of nothrow. > #define _GLIBCXX_DEFINE_NOTHROW_OBJ 1 > #include "new"
Ah yes, that's much cleaner and avoid repeating the type. I'll see if that works as expected. >> >> >> If all you're trying to do is ensure that 'constexpr' is seen >> consistently, I don't think it's worth it. It's already not going to >> be constexpr when combining C++98 and C++17 objects, because it can >> never be constexpr in C++98. > > That's true, so you can ship the original as is. > > Regards, > Tomasz