https://gcc.gnu.org/g:6341d34747a6ac554e70ec1e0e39f1bece3506d3

commit r17-4856-g6341d34747a6ac554e70ec1e0e39f1bece3506d3
Author: Jakub Jelinek <[email protected]>
Date:   Sat Oct 3 21:29:06 2026 +0200

    c++: Fix up mangling of __builtin_{bswap,bitreverse}g calls [PR127668]
    
    The following testcases ICE during mangling, the dependent
    __builtin_{bswap,bitreverse}g calls (where those identifiers
    we treat as keywords and don't even have such builtins,
    given that those are the first type-generic builtins with the
    return type dependent on the argument type(s)) are emitted
    as internal fn calls (IFN_BSWAP or IFN_BITREVERSE), and
    during mangling we just ICE on any calls to internal functions.
    
    The following patch mangles those 2 calls like we mangle e.g.
    template <typename T>
    auto foo (T t) -> decltype (__builtin_popcountg (t)) { return t; }
    
    template int foo <unsigned> (unsigned);
    - _Z3fooIjEDTcl19__builtin_popcountgfp_EET_ .  In
    that case it is a type-generic builtin with a fixed return
    type and we trigger the
      /* Mangle a dependent name as the name, not whatever happens to
         be the first function in the overload set.  */
      if (OVL_P (fn)
          && type_dependent_expression_p_push (expr))
        fn = OVL_NAME (fn);
    case in the CALL_EXPR write_expression handling, so fn is
    then an identifier.
    
    2026-10-03  Jakub Jelinek  <[email protected]>
    
            PR c++/127668
            * mangle.cc (write_expression): Handle mangling of
            calls to IFN_BSWAP and IFN_BITREVERSE.
    
            * g++.dg/ext/builtin-bswapg-1.C: New test.
            * g++.dg/ext/builtin-bitreverseg-1.C: New test.
    
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/mangle.cc                                 | 39 ++++++++++++++++--------
 gcc/testsuite/g++.dg/ext/builtin-bitreverseg-1.C |  8 +++++
 gcc/testsuite/g++.dg/ext/builtin-bswapg-1.C      |  8 +++++
 3 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 739ab2afd60e..26da14ffc5e8 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -4094,20 +4094,35 @@ write_expression (tree expr)
       switch (code)
        {
        case CALL_EXPR:
-         {
-           tree fn = CALL_EXPR_FN (expr);
-
-           if (TREE_CODE (fn) == ADDR_EXPR)
-             fn = TREE_OPERAND (fn, 0);
+         if (tree fn = CALL_EXPR_FN (expr))
+           {
+             if (TREE_CODE (fn) == ADDR_EXPR)
+               fn = TREE_OPERAND (fn, 0);
 
-           /* Mangle a dependent name as the name, not whatever happens to
-              be the first function in the overload set.  */
-           if (OVL_P (fn)
-               && type_dependent_expression_p_push (expr))
-             fn = OVL_NAME (fn);
+             /* Mangle a dependent name as the name, not whatever happens to
+                be the first function in the overload set.  */
+             if (OVL_P (fn)
+                 && type_dependent_expression_p_push (expr))
+               fn = OVL_NAME (fn);
 
-           write_expression (fn);
-         }
+             write_expression (fn);
+           }
+         else
+           switch (CALL_EXPR_IFN (expr))
+             {
+             /* Calls to __builtin_bswapg/__builtin_bitreverseg are parsed
+                as IFN_BSWAP/IFN_BITREVERSE calls because we don't have
+                those builtins but instead keywords.  Pretend they are
+                builtin function template.  */
+             case IFN_BSWAP:
+               write_source_name (get_identifier ("__builtin_bswapg"));
+               break;
+             case IFN_BITREVERSE:
+               write_source_name (get_identifier ("__builtin_bitreverseg"));
+               break;
+             default:
+               gcc_unreachable ();
+             }
 
          for (i = 0; i < call_expr_nargs (expr); ++i)
            write_expression (CALL_EXPR_ARG (expr, i));
diff --git a/gcc/testsuite/g++.dg/ext/builtin-bitreverseg-1.C 
b/gcc/testsuite/g++.dg/ext/builtin-bitreverseg-1.C
new file mode 100644
index 000000000000..f6cd4a1ffa68
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/builtin-bitreverseg-1.C
@@ -0,0 +1,8 @@
+// PR c++/127668
+// { dg-do compile { target c++11 } }
+// { dg-final { scan-assembler "_Z3fooIjEDTcl21__builtin_bitreversegfp_EET_" } 
}
+
+template <typename T>
+auto foo (T t) -> decltype (__builtin_bitreverseg (t)) { return t; }
+
+template unsigned foo <unsigned> (unsigned);
diff --git a/gcc/testsuite/g++.dg/ext/builtin-bswapg-1.C 
b/gcc/testsuite/g++.dg/ext/builtin-bswapg-1.C
new file mode 100644
index 000000000000..d3ae993a3036
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/builtin-bswapg-1.C
@@ -0,0 +1,8 @@
+// PR c++/127668
+// { dg-do compile { target c++11 } }
+// { dg-final { scan-assembler "_Z3fooIjEDTcl16__builtin_bswapgfp_EET_" } }
+
+template <typename T>
+auto foo (T t) -> decltype (__builtin_bswapg (t)) { return t; }
+
+template unsigned foo <unsigned> (unsigned);

Reply via email to