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

Reply via email to