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

            Bug ID: 127668
           Summary: GCC `__builtin_bitreverseg` ICEs (segfault in the C++
                    mangler) when applied to a dependent operand in a
                    template signature
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: bic60176 at gmail dot com
  Target Milestone: ---

## Summary

Using `__builtin_bitreverseg` on a dependent operand anywhere in a C++ function
template's *signature* (trailing return type, parameter type, alias template,
template argument, …) makes GCC segfault with an internal compiler error once
the template is instantiated. The C++ front end builds the dependent call with
`CALL_EXPR_FN == NULL_TREE` (an internal-function call), and `write_expression`
in `gcc/cp/mangle.cc` dereferences `CALL_EXPR_FN` unconditionally.
`__builtin_bswapg`, which shares the code path, crashes identically.


Reproducing the Bug

```python
import cc_harness

src = """
template <typename T>
auto f (T t) -> decltype (__builtin_bitreverseg (t)) { return t; }

template unsigned f<unsigned> (unsigned);
"""

r = cc_harness.compile_only(src, "c++")
print(r.compiled, r.crash_kind)
print(r.stderr)
```

Output:

```
False ice
prog.cc: In instantiation of 'decltype (BITREVERSE(t)) f(T) [with T = unsigned
int; ...]':
prog.cc:2:6: internal compiler error: Segmentation fault
0x1d9062b crash_signal(int)
0xf637cc  write_expression(tree_node*)
0xf6d5a2  write_type(tree_node*)
0xf70524  write_bare_function_type(tree_node*, int, tree_node*)
0xf7060c  write_encoding(tree_node*)
0xf72a0a  write_mangled_name(tree_node*, bool)
...
```

Fix

Handle the internal-function form of `CALL_EXPR` in `write_expression`,
mangling
it as an Itanium-ABI vendor extended expression (`u <source-name> <expr>* E`)
rather than falling into the ordinary `cl` path that assumes a callee tree.

```diff
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -4058,6 +4058,20 @@ write_expression (tree expr)
          return;
        }

+      /* Internal-function calls such as __builtin_bswapg and
+        __builtin_bitreverseg have a null CALL_EXPR_FN; mangle them as a
+        vendor extended expression instead of the ordinary "cl" form.  */
+      if (code == CALL_EXPR && CALL_EXPR_FN (expr) == NULL_TREE)
+       {
+         const char *fname = (CALL_EXPR_IFN (expr) == IFN_BSWAP
+                              ? "__builtin_bswapg"
+                              : "__builtin_bitreverseg");
+         write_char ('u');
+         write_source_name (get_identifier (fname));
+         for (i = 0; i < call_expr_nargs (expr); ++i)
+           write_expression (CALL_EXPR_ARG (expr, i));
+         write_char ('E');
+         return;
+       }
+

Reply via email to