https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119064

--- Comment #3 from Jason Merrill <jason at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #2)
> The patch is on top of the
> https://gcc.gnu.org/pipermail/gcc-patches/2025-June/686210.html
> https://gcc.gnu.org/pipermail/gcc-patches/2025-June/686211.html
> https://gcc.gnu.org/pipermail/gcc-patches/2025-June/686212.html
> patches.
> 
> Jason, could I ask for guidance on 4 issues?
> 
> 1) https://eel.is/c++draft/diff.cpp23.dcl.dcl#1 notes that
>    struct C {}; struct C replaceable_if_eligible {};
>    and
>    struct C {}; struct C trivially_relocatable_if_eligible {};
>    are valid in C++11 to C++23.  Seems clang 21 didn't bother with this
>    when implementing P2786R13 and just made those invalid even in the
>    older modes (similarly how we've tried override in C++98
>    for years until the pending patch).
>    What should I do about that:
>    a) ignore like clang and make those invalid
>    b) only support __replaceable_if_eligible and
> __trivially_relocatable_if_eligible
>       contextual keywords in C++11 to C++23 and leave the non-__ prefixed
> ones to
>       C++26 and later

This sounds fine, perhaps with a -Wc++26-compat warning about those names in
earlier modes.

> 2) naming question for the builtin traits;  the patch uses
>    __is_trivially_relocatable, __is_nothrow_relocatable and __is_replaceable
>    builtin traits; looking at clang which implemented this paper recently
>    in https://github.com/llvm/llvm-project/pull/127636
>    clang seems to use wild __builtin_is_cpp_trivially_relocatable
>    and __builtin_is_replaceable (apparently because they've implemented it
> too
>    early with different semantics; why one has the _cpp infix and the other
>    one doesn't is unclear); at least for libstdc++-v3 I think there are
>    no reasons to be afraid of older __is_trivially_relocatable or
> __is_replaceable
>    or __is_nothrow_relocatable non-builtin traits

I'd like to get back to using __builtin for builtins.

> 3) for the
>    https://eel.is/c++draft/class.prop#2.1
>    https://eel.is/c++draft/class.prop#2.2
>    https://eel.is/c++draft/class.prop#6.3
>    https://eel.is/c++draft/class.prop#6.4
>    the patch tries hard to avoid synthetizing lazy move or copy ctors and
>    move or copy assignment operators when trying to determine if a class type
>    is default-movable or not eligible for replacement because of my fear that
>    when this is done at the check_bases_and_members time at least for classes
>    which aren't trivially relocatable or replaceable for other reasons it
> will
>    basically kill the lazy stuff; is that doable that way at all?
>    Initially I didn't have the classtype_has_const_or_ref_members hack in
> there
>    and then e.g. struct S { const int s; }; __is_trivially_relocatable (S)
> was
>    incorrectly true, even when the lazily declared implicit move assignment
> operator
>    is deleted; the hack fixes that, but I think e.g. walk_field_subobs has
> also
>    deleted case for copy/move ctor if there are rvalue reference type
> non-static
>    data members; maybe that will be covered also by the same function, and
> perhaps
>    e.g. using deleted special member functions on the bases or members;
>    on one side, at least without the new contextual keywords being present
> and
>    with the exception of the union exception, trivially relocatable or
> replaceable
>    types should imply default-movable on the base types and in those cases
> those
>    shouldn't have the deleted special member functions.
> 
>    Anyway, perhaps another option would be stop computing this during type
> completion,
>    and instead compute it on demand with caching, so either have 2 bits for
> the
>    trivially_relocatable and replaceable bitfields, 0 unknown, 1 no, 2 yes,
> or
>    just add one bit and compute both trivial relocatability and
> replaceability
>    at the same time; in that case synthetize whatever lazy methods we
> actually
>    need to check for deletion

Computing it on demand makes sense to me.

> 4) so far I've been only concentrating on the new traits, seems clang has
> also
>    __builtin_trivially_relocate type-generic builtin which acts similarly to
>    __builtin_memmove, just perhaps works differently during constant
> expression
>    evaluation and has some extra checks plus the third argument is count, so
>    for memmove needs to be multiplied by sizeof (T); do you think we need
> this
>    too?

I would think we could just make __builtin_memmove work in constant-evaluation.

Reply via email to