On Tue, 13 May 2025, Ville Voutilainen wrote: > On Tue, 13 May 2025 at 23:34, Jason Merrill <ja...@redhat.com> wrote: > > > > On 5/13/25 4:29 PM, Ville Voutilainen wrote: > > > On Tue, 13 May 2025 at 23:23, Jason Merrill <ja...@redhat.com> wrote: > > >>> /* Check that the return and argument types are sane before > > >>> folding. */ > > >>> - if (INDIRECT_TYPE_P (TREE_TYPE (x)) > > >>> - && INDIRECT_TYPE_P (TREE_TYPE (r))) > > >>> + if (id_equal (DECL_NAME (callee), "to_underlying") > > >>> + || (INDIRECT_TYPE_P (TREE_TYPE (x)) > > >>> + && INDIRECT_TYPE_P (TREE_TYPE (r)))) > > >> > > >> Maybe instead of INDIRECT_TYPE_P, check ! AGGREGATE_TYPE_P ? I'm not > > >> sure how much sanity checking we need here, maybe we should just trust > > >> the library. > > > > > > I.. ..don't think AGGREGATE_TYPE_P is right? > > > > I was suggesting *not* AGGREGATE_TYPE_P, because build_nop doesn't work > > for such types. > > Ah, yes, got it. I did spot the 'not' but was wondering whether that > covers all the right cases, but for references and enumerators, I > guess > it would. > > > > It seems to me that this > > > sanity check is checking that it's a cast between > > > references for the other ones, and that's just unsuitable for > > > to_underlying. I would suggest just removing that sanity > > > check and trusting the library. > > > > That's fine too. > > I'll test the attached.
> diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc > index d2423fd1848..4e5d383daeb 100644 > --- a/gcc/cp/cp-gimplify.cc > +++ b/gcc/cp/cp-gimplify.cc > @@ -3343,19 +3343,16 @@ cp_fold (tree x, fold_flags_t flags) > || id_equal (DECL_NAME (callee), "addressof") > /* This addressof equivalent is used heavily in libstdc++. */ > || id_equal (DECL_NAME (callee), "__addressof") > + || id_equal (DECL_NAME (callee), "to_underlying") > || id_equal (DECL_NAME (callee), "as_const"))) > { > r = CALL_EXPR_ARG (x, 0); > /* Check that the return and argument types are sane before > folding. */ This comment should be removed too, along with the sanity check. > - if (INDIRECT_TYPE_P (TREE_TYPE (x)) > - && INDIRECT_TYPE_P (TREE_TYPE (r))) > - { > - if (!same_type_p (TREE_TYPE (x), TREE_TYPE (r))) > - r = build_nop (TREE_TYPE (x), r); > - x = cp_fold (r, flags); > - break; > - } > + if (!same_type_p (TREE_TYPE (x), TREE_TYPE (r))) > + r = build_nop (TREE_TYPE (x), r); > + x = cp_fold (r, flags); > + break; > } > > int sv = optimize, nw = sv; > diff --git a/gcc/testsuite/g++.dg/opt/pr96780_cpp23.C > b/gcc/testsuite/g++.dg/opt/pr96780_cpp23.C > new file mode 100644 > index 00000000000..ba4a837dded > --- /dev/null > +++ b/gcc/testsuite/g++.dg/opt/pr96780_cpp23.C > @@ -0,0 +1,16 @@ > +// PR c++/96780 > +// Verify calls to std::move/forward are folded away by the frontend. > +// { dg-do compile { target c++23 } } > +// { dg-additional-options "-ffold-simple-inlines -fdump-tree-gimple" } > + > +#include <utility> > + > +enum class A : char {a}; > + > +extern A& x; > + > +void f() { > + auto&& x1 = std::to_underlying(x); > +} > + > +// { dg-final { scan-tree-dump-not "= std::to_underlying" "gimple" } } > diff --git a/libstdc++-v3/include/std/utility > b/libstdc++-v3/include/std/utility > index 1c15c75f92b..8a85ccfd09b 100644 > --- a/libstdc++-v3/include/std/utility > +++ b/libstdc++-v3/include/std/utility > @@ -201,7 +201,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > #ifdef __cpp_lib_to_underlying // C++ >= 23 > /// Convert an object of enumeration type to its underlying type. > template<typename _Tp> > - [[nodiscard]] > + [[nodiscard, __gnu__::__always_inline__]] > constexpr underlying_type_t<_Tp> > to_underlying(_Tp __value) noexcept > { return static_cast<underlying_type_t<_Tp>>(__value); } > >