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.