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.  */
-	    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); }

Reply via email to